Update audio controller (#904)
* Remove redundant assignment of select value * Update TTS preparation * Don't hide options * Improve voice sorting * Update event handler * Apply options to all selects targeting audio.textToSpeechVoice * Update selector * Use IDs * Move test text to a hidden text input
This commit is contained in:
parent
6799b87cc6
commit
3174f3c657
@ -28,18 +28,25 @@ class AudioController {
|
|||||||
this._audioSourceContainer = null;
|
this._audioSourceContainer = null;
|
||||||
this._audioSourceAddButton = null;
|
this._audioSourceAddButton = null;
|
||||||
this._audioSourceEntries = [];
|
this._audioSourceEntries = [];
|
||||||
|
this._ttsVoiceTestTextInput = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
async prepare() {
|
async prepare() {
|
||||||
this._audioSystem.prepare();
|
this._audioSystem.prepare();
|
||||||
|
|
||||||
this._audioSourceContainer = document.querySelector('.audio-source-list');
|
this._ttsVoiceTestTextInput = document.querySelector('#text-to-speech-voice-test-text');
|
||||||
this._audioSourceAddButton = document.querySelector('.audio-source-add');
|
this._audioSourceContainer = document.querySelector('#audio-source-list');
|
||||||
|
this._audioSourceAddButton = document.querySelector('#audio-source-add');
|
||||||
this._audioSourceContainer.textContent = '';
|
this._audioSourceContainer.textContent = '';
|
||||||
|
|
||||||
this._audioSourceAddButton.addEventListener('click', this._onAddAudioSource.bind(this), false);
|
this._audioSourceAddButton.addEventListener('click', this._onAddAudioSource.bind(this), false);
|
||||||
|
|
||||||
this._prepareTextToSpeech();
|
if (typeof speechSynthesis !== 'undefined') {
|
||||||
|
speechSynthesis.addEventListener('voiceschanged', this._updateTextToSpeechVoices.bind(this), false);
|
||||||
|
}
|
||||||
|
this._updateTextToSpeechVoices();
|
||||||
|
|
||||||
|
document.querySelector('#text-to-speech-voice-test').addEventListener('click', this._onTestTextToSpeech.bind(this), false);
|
||||||
|
|
||||||
this._settingsController.on('optionsChanged', this._onOptionsChanged.bind(this));
|
this._settingsController.on('optionsChanged', this._onOptionsChanged.bind(this));
|
||||||
|
|
||||||
@ -59,22 +66,32 @@ class AudioController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_prepareTextToSpeech() {
|
_onTestTextToSpeech() {
|
||||||
if (typeof speechSynthesis === 'undefined') { return; }
|
try {
|
||||||
|
const text = this._ttsVoiceTestTextInput.value || '';
|
||||||
|
const voiceUri = document.querySelector('[data-setting="audio.textToSpeechVoice"]').value;
|
||||||
|
|
||||||
speechSynthesis.addEventListener('voiceschanged', this._updateTextToSpeechVoices.bind(this), false);
|
const audio = this._audioSystem.createTextToSpeechAudio(text, voiceUri);
|
||||||
this._updateTextToSpeechVoices();
|
audio.volume = 1.0;
|
||||||
|
audio.play();
|
||||||
document.querySelector('#text-to-speech-voice').addEventListener('change', this._onTextToSpeechVoiceChange.bind(this), false);
|
} catch (e) {
|
||||||
document.querySelector('#text-to-speech-voice-test').addEventListener('click', this._testTextToSpeech.bind(this), false);
|
// NOP
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_updateTextToSpeechVoices() {
|
_updateTextToSpeechVoices() {
|
||||||
const voices = Array.prototype.map.call(speechSynthesis.getVoices(), (voice, index) => ({voice, index}));
|
const voices = (
|
||||||
|
typeof speechSynthesis !== 'undefined' ?
|
||||||
|
[...speechSynthesis.getVoices()].map((voice, index) => ({
|
||||||
|
voice,
|
||||||
|
isJapanese: this._languageTagIsJapanese(voice.lang),
|
||||||
|
index
|
||||||
|
})) :
|
||||||
|
[]
|
||||||
|
);
|
||||||
voices.sort(this._textToSpeechVoiceCompare.bind(this));
|
voices.sort(this._textToSpeechVoiceCompare.bind(this));
|
||||||
|
|
||||||
document.querySelector('#text-to-speech-voice-container').hidden = (voices.length === 0);
|
for (const select of document.querySelectorAll('[data-setting="audio.textToSpeechVoice"]')) {
|
||||||
|
|
||||||
const fragment = document.createDocumentFragment();
|
const fragment = document.createDocumentFragment();
|
||||||
|
|
||||||
let option = document.createElement('option');
|
let option = document.createElement('option');
|
||||||
@ -89,27 +106,22 @@ class AudioController {
|
|||||||
fragment.appendChild(option);
|
fragment.appendChild(option);
|
||||||
}
|
}
|
||||||
|
|
||||||
const select = document.querySelector('#text-to-speech-voice');
|
|
||||||
select.textContent = '';
|
select.textContent = '';
|
||||||
select.appendChild(fragment);
|
select.appendChild(fragment);
|
||||||
select.value = select.dataset.value;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_textToSpeechVoiceCompare(a, b) {
|
_textToSpeechVoiceCompare(a, b) {
|
||||||
const aIsJapanese = this._languageTagIsJapanese(a.voice.lang);
|
if (a.isJapanese) {
|
||||||
const bIsJapanese = this._languageTagIsJapanese(b.voice.lang);
|
if (!b.isJapanese) { return -1; }
|
||||||
if (aIsJapanese) {
|
|
||||||
if (!bIsJapanese) { return -1; }
|
|
||||||
} else {
|
} else {
|
||||||
if (bIsJapanese) { return 1; }
|
if (b.isJapanese) { return 1; }
|
||||||
}
|
}
|
||||||
|
|
||||||
const aIsDefault = a.voice.default;
|
if (a.voice.default) {
|
||||||
const bIsDefault = b.voice.default;
|
if (!b.voice.default) { return -1; }
|
||||||
if (aIsDefault) {
|
|
||||||
if (!bIsDefault) { return -1; }
|
|
||||||
} else {
|
} else {
|
||||||
if (bIsDefault) { return 1; }
|
if (b.voice.default) { return 1; }
|
||||||
}
|
}
|
||||||
|
|
||||||
return a.index - b.index;
|
return a.index - b.index;
|
||||||
@ -123,19 +135,6 @@ class AudioController {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_testTextToSpeech() {
|
|
||||||
try {
|
|
||||||
const text = document.querySelector('#text-to-speech-voice-test').dataset.speechText || '';
|
|
||||||
const voiceUri = document.querySelector('#text-to-speech-voice').value;
|
|
||||||
|
|
||||||
const audio = this._audioSystem.createTextToSpeechAudio(text, voiceUri);
|
|
||||||
audio.volume = 1.0;
|
|
||||||
audio.play();
|
|
||||||
} catch (e) {
|
|
||||||
// NOP
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_getUnusedAudioSource() {
|
_getUnusedAudioSource() {
|
||||||
const audioSourcesAvailable = [
|
const audioSourcesAvailable = [
|
||||||
'jpod101',
|
'jpod101',
|
||||||
@ -195,10 +194,6 @@ class AudioController {
|
|||||||
this._audioSourceEntries.splice(index, 1);
|
this._audioSourceEntries.splice(index, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onTextToSpeechVoiceChange(e) {
|
|
||||||
e.currentTarget.dataset.value = e.currentTarget.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
async _onAddAudioSource() {
|
async _onAddAudioSource() {
|
||||||
const audioSource = this._getUnusedAudioSource();
|
const audioSource = this._getUnusedAudioSource();
|
||||||
const index = this._audioSourceEntries.length;
|
const index = this._audioSourceEntries.length;
|
||||||
|
@ -346,14 +346,15 @@
|
|||||||
<input type="number" min="0" max="100" id="audio-playback-volume" class="form-control" data-setting="audio.volume">
|
<input type="number" min="0" max="100" id="audio-playback-volume" class="form-control" data-setting="audio.volume">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group" id="text-to-speech-voice-container" hidden>
|
<div class="form-group" id="text-to-speech-voice-container">
|
||||||
<label for="text-to-speech-voice">Text-to-speech voice</label>
|
<label for="text-to-speech-voice">Text-to-speech voice</label>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<select class="form-control" id="text-to-speech-voice" data-setting="audio.textToSpeechVoice"></select>
|
<select class="form-control" id="text-to-speech-voice" data-setting="audio.textToSpeechVoice"></select>
|
||||||
<div class="input-group-btn">
|
<div class="input-group-btn">
|
||||||
<button class="btn btn-default" id="text-to-speech-voice-test" title="Test voice" data-speech-text="よみちゃん"><span class="glyphicon glyphicon-volume-up"></span></button>
|
<button class="btn btn-default" id="text-to-speech-voice-test" title="Test voice"><span class="glyphicon glyphicon-volume-up"></span></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<input type="text" value="よみちゃん" id="text-to-speech-voice-test-text" hidden>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group options-advanced">
|
<div class="form-group options-advanced">
|
||||||
@ -363,9 +364,9 @@
|
|||||||
|
|
||||||
<div class="form-group ignore-form-changes">
|
<div class="form-group ignore-form-changes">
|
||||||
<label>Audio playback sources</label>
|
<label>Audio playback sources</label>
|
||||||
<div class="audio-source-list generic-input-list"></div>
|
<div class="audio-source-list generic-input-list" id="audio-source-list"></div>
|
||||||
<div class="input-group audio-source-options">
|
<div class="input-group audio-source-options">
|
||||||
<button class="btn btn-default audio-source-add" title="Add audio playback source"><span class="glyphicon glyphicon-plus"></span></button>
|
<button class="btn btn-default audio-source-add" title="Add audio playback source" id="audio-source-add"><span class="glyphicon glyphicon-plus"></span></button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<template id="audio-source-template"><div class="input-group audio-source">
|
<template id="audio-source-template"><div class="input-group audio-source">
|
||||||
|
Loading…
Reference in New Issue
Block a user