aboutsummaryrefslogtreecommitdiff
path: root/ext/bg/js
diff options
context:
space:
mode:
Diffstat (limited to 'ext/bg/js')
-rw-r--r--ext/bg/js/api.js4
-rw-r--r--ext/bg/js/audio.js14
-rw-r--r--ext/bg/js/backend.js16
-rw-r--r--ext/bg/js/settings/audio.js25
4 files changed, 34 insertions, 25 deletions
diff --git a/ext/bg/js/api.js b/ext/bg/js/api.js
index 93e43a7d..4e5d81db 100644
--- a/ext/bg/js/api.js
+++ b/ext/bg/js/api.js
@@ -21,10 +21,6 @@ function apiTemplateRender(template, data) {
return _apiInvoke('templateRender', {data, template});
}
-function apiAudioGetUrl(definition, source, optionsContext) {
- return _apiInvoke('audioGetUrl', {definition, source, optionsContext});
-}
-
function _apiInvoke(action, params={}) {
const data = {action, params};
return new Promise((resolve, reject) => {
diff --git a/ext/bg/js/audio.js b/ext/bg/js/audio.js
index 972e2b8b..c94121ae 100644
--- a/ext/bg/js/audio.js
+++ b/ext/bg/js/audio.js
@@ -16,7 +16,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-/*global jpIsStringEntirelyKana, audioGetFromSources*/
+/*global jpIsStringEntirelyKana*/
const audioUrlBuilders = new Map([
['jpod101', async (definition) => {
@@ -154,7 +154,7 @@ function audioBuildFilename(definition) {
return null;
}
-async function audioInject(definition, fields, sources, optionsContext) {
+async function audioInject(definition, fields, sources, optionsContext, audioSystem) {
let usesAudio = false;
for (const fieldValue of Object.values(fields)) {
if (fieldValue.includes('{audio}')) {
@@ -171,12 +171,10 @@ async function audioInject(definition, fields, sources, optionsContext) {
const expressions = definition.expressions;
const audioSourceDefinition = Array.isArray(expressions) ? expressions[0] : definition;
- const {url} = await audioGetFromSources(audioSourceDefinition, sources, optionsContext, true);
- if (url !== null) {
- const filename = audioBuildFilename(audioSourceDefinition);
- if (filename !== null) {
- definition.audio = {url, filename};
- }
+ const {uri} = await audioSystem.getDefinitionAudio(audioSourceDefinition, sources, {tts: false, optionsContext});
+ const filename = audioBuildFilename(audioSourceDefinition);
+ if (filename !== null) {
+ definition.audio = {url: uri, filename};
}
return true;
diff --git a/ext/bg/js/backend.js b/ext/bg/js/backend.js
index 04bf240d..60a87916 100644
--- a/ext/bg/js/backend.js
+++ b/ext/bg/js/backend.js
@@ -23,7 +23,7 @@ requestText, requestJson, optionsLoad
dictConfigured, dictTermsSort, dictEnabledSet, dictNoteFormat
audioGetUrl, audioInject
jpConvertReading, jpDistributeFuriganaInflected, jpKatakanaToHiragana
-Translator, AnkiConnect, AnkiNull, Mecab, BackendApiForwarder, JsonSchema, ClipboardMonitor*/
+AudioSystem, Translator, AnkiConnect, AnkiNull, Mecab, BackendApiForwarder, JsonSchema, ClipboardMonitor*/
class Backend {
constructor() {
@@ -34,6 +34,7 @@ class Backend {
this.options = null;
this.optionsSchema = null;
this.defaultAnkiFieldTemplates = null;
+ this.audioSystem = new AudioSystem({getAudioUri: this._getAudioUri.bind(this)});
this.optionsContext = {
depth: 0,
url: window.location.href
@@ -436,7 +437,8 @@ class Backend {
definition,
options.anki.terms.fields,
options.audio.sources,
- optionsContext
+ optionsContext,
+ this.audioSystem
);
}
@@ -762,6 +764,16 @@ class Backend {
// Utilities
+ async _getAudioUri(definition, source, details) {
+ let optionsContext = (typeof details === 'object' && details !== null ? details.optionsContext : null);
+ if (!(typeof optionsContext === 'object' && optionsContext !== null)) {
+ optionsContext = this.optionsContext;
+ }
+
+ const options = this.getOptions(optionsContext);
+ return await audioGetUrl(definition, source, options);
+ }
+
async _injectScreenshot(definition, fields, screenshot) {
let usesScreenshot = false;
for (const fieldValue of Object.values(fields)) {
diff --git a/ext/bg/js/settings/audio.js b/ext/bg/js/settings/audio.js
index 6d183a43..6f581d9b 100644
--- a/ext/bg/js/settings/audio.js
+++ b/ext/bg/js/settings/audio.js
@@ -16,12 +16,20 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-/*global getOptionsContext, getOptionsMutable, settingsSaveOptions
-AudioSourceUI, audioGetTextToSpeechVoice*/
+/*global getOptionsContext, getOptionsMutable, settingsSaveOptions, apiAudioGetUrl
+AudioSystem, AudioSourceUI*/
let audioSourceUI = null;
+let audioSystem = null;
async function audioSettingsInitialize() {
+ audioSystem = new AudioSystem({
+ getAudioUri: async (definition, source) => {
+ const optionsContext = getOptionsContext();
+ return await apiAudioGetUrl(definition, source, optionsContext);
+ }
+ });
+
const optionsContext = getOptionsContext();
const options = await getOptionsMutable(optionsContext);
audioSourceUI = new AudioSourceUI.Container(
@@ -100,16 +108,11 @@ function textToSpeechVoiceCompare(a, b) {
function textToSpeechTest() {
try {
const text = document.querySelector('#text-to-speech-voice-test').dataset.speechText || '';
- const voiceURI = document.querySelector('#text-to-speech-voice').value;
- const voice = audioGetTextToSpeechVoice(voiceURI);
- if (voice === null) { return; }
-
- const utterance = new SpeechSynthesisUtterance(text);
- utterance.lang = 'ja-JP';
- utterance.voice = voice;
- utterance.volume = 1.0;
+ const voiceUri = document.querySelector('#text-to-speech-voice').value;
- speechSynthesis.speak(utterance);
+ const audio = audioSystem.createTextToSpeechAudio({text, voiceUri});
+ audio.volume = 1.0;
+ audio.play();
} catch (e) {
// NOP
}