diff options
Diffstat (limited to 'ext')
-rw-r--r-- | ext/bg/js/settings/audio.js | 102 | ||||
-rw-r--r-- | ext/bg/js/settings/main.js | 89 | ||||
-rw-r--r-- | ext/bg/settings.html | 1 |
3 files changed, 103 insertions, 89 deletions
diff --git a/ext/bg/js/settings/audio.js b/ext/bg/js/settings/audio.js new file mode 100644 index 00000000..f63551ed --- /dev/null +++ b/ext/bg/js/settings/audio.js @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2019 Alex Yatskov <alex@foosoft.net> + * Author: Alex Yatskov <alex@foosoft.net> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + + +let audioSourceUI = null; + +async function audioSettingsInitialize() { + const optionsContext = getOptionsContext(); + const options = await apiOptionsGet(optionsContext); + audioSourceUI = new AudioSourceUI.Container(options.audio.sources, $('.audio-source-list'), $('.audio-source-add')); + audioSourceUI.save = () => settingsSaveOptions(); + + textToSpeechInitialize(); +} + +function textToSpeechInitialize() { + if (typeof speechSynthesis === 'undefined') { return; } + + speechSynthesis.addEventListener('voiceschanged', () => updateTextToSpeechVoices(), false); + updateTextToSpeechVoices(); + + $('#text-to-speech-voice-test').on('click', () => textToSpeechTest()); +} + +function updateTextToSpeechVoices() { + const voices = Array.prototype.map.call(speechSynthesis.getVoices(), (voice, index) => ({voice, index})); + voices.sort(textToSpeechVoiceCompare); + if (voices.length > 0) { + $('#text-to-speech-voice-container').css('display', ''); + } + + const select = $('#text-to-speech-voice'); + select.empty(); + select.append($('<option>').val('').text('None')); + for (const {voice} of voices) { + select.append($('<option>').val(voice.voiceURI).text(`${voice.name} (${voice.lang})`)); + } + + select.val(select.attr('data-value')); +} + +function languageTagIsJapanese(languageTag) { + return ( + languageTag.startsWith('ja-') || + languageTag.startsWith('jpn-') + ); +} + +function textToSpeechVoiceCompare(a, b) { + const aIsJapanese = languageTagIsJapanese(a.voice.lang); + const bIsJapanese = languageTagIsJapanese(b.voice.lang); + if (aIsJapanese) { + if (!bIsJapanese) { return -1; } + } else { + if (bIsJapanese) { return 1; } + } + + const aIsDefault = a.voice.default; + const bIsDefault = b.voice.default; + if (aIsDefault) { + if (!bIsDefault) { return -1; } + } else { + if (bIsDefault) { return 1; } + } + + if (a.index < b.index) { return -1; } + if (a.index > b.index) { return 1; } + return 0; +} + +function textToSpeechTest() { + try { + const text = $('#text-to-speech-voice-test').attr('data-speech-text') || ''; + const voiceURI = $('#text-to-speech-voice').val(); + const voice = audioGetTextToSpeechVoice(voiceURI); + if (voice === null) { return; } + + const utterance = new SpeechSynthesisUtterance(text); + utterance.lang = 'ja-JP'; + utterance.voice = voice; + utterance.volume = 1.0; + + speechSynthesis.speak(utterance); + } catch (e) { + // NOP + } +} diff --git a/ext/bg/js/settings/main.js b/ext/bg/js/settings/main.js index 9e9604e2..adf74df3 100644 --- a/ext/bg/js/settings/main.js +++ b/ext/bg/js/settings/main.js @@ -272,95 +272,6 @@ function showAppearancePreview() { /* - * Audio - */ - -let audioSourceUI = null; - -async function audioSettingsInitialize() { - const optionsContext = getOptionsContext(); - const options = await apiOptionsGet(optionsContext); - audioSourceUI = new AudioSourceUI.Container(options.audio.sources, $('.audio-source-list'), $('.audio-source-add')); - audioSourceUI.save = () => settingsSaveOptions(); - - textToSpeechInitialize(); -} - -function textToSpeechInitialize() { - if (typeof speechSynthesis === 'undefined') { return; } - - speechSynthesis.addEventListener('voiceschanged', () => updateTextToSpeechVoices(), false); - updateTextToSpeechVoices(); - - $('#text-to-speech-voice-test').on('click', () => textToSpeechTest()); -} - -function updateTextToSpeechVoices() { - const voices = Array.prototype.map.call(speechSynthesis.getVoices(), (voice, index) => ({voice, index})); - voices.sort(textToSpeechVoiceCompare); - if (voices.length > 0) { - $('#text-to-speech-voice-container').css('display', ''); - } - - const select = $('#text-to-speech-voice'); - select.empty(); - select.append($('<option>').val('').text('None')); - for (const {voice} of voices) { - select.append($('<option>').val(voice.voiceURI).text(`${voice.name} (${voice.lang})`)); - } - - select.val(select.attr('data-value')); -} - -function languageTagIsJapanese(languageTag) { - return ( - languageTag.startsWith('ja-') || - languageTag.startsWith('jpn-') - ); -} - -function textToSpeechVoiceCompare(a, b) { - const aIsJapanese = languageTagIsJapanese(a.voice.lang); - const bIsJapanese = languageTagIsJapanese(b.voice.lang); - if (aIsJapanese) { - if (!bIsJapanese) { return -1; } - } else { - if (bIsJapanese) { return 1; } - } - - const aIsDefault = a.voice.default; - const bIsDefault = b.voice.default; - if (aIsDefault) { - if (!bIsDefault) { return -1; } - } else { - if (bIsDefault) { return 1; } - } - - if (a.index < b.index) { return -1; } - if (a.index > b.index) { return 1; } - return 0; -} - -function textToSpeechTest() { - try { - const text = $('#text-to-speech-voice-test').attr('data-speech-text') || ''; - const voiceURI = $('#text-to-speech-voice').val(); - const voice = audioGetTextToSpeechVoice(voiceURI); - if (voice === null) { return; } - - const utterance = new SpeechSynthesisUtterance(text); - utterance.lang = 'ja-JP'; - utterance.voice = voice; - utterance.volume = 1.0; - - speechSynthesis.speak(utterance); - } catch (e) { - // NOP - } -} - - -/* * Remote options updates */ diff --git a/ext/bg/settings.html b/ext/bg/settings.html index 8ce647b1..7671dbc4 100644 --- a/ext/bg/settings.html +++ b/ext/bg/settings.html @@ -882,6 +882,7 @@ <script src="/bg/js/util.js"></script> <script src="/mixed/js/audio.js"></script> + <script src="/bg/js/settings/audio.js"></script> <script src="/bg/js/settings/dictionaries.js"></script> <script src="/bg/js/settings/profiles.js"></script> |