Use dependency injection for getAudioUri implementation

This commit is contained in:
toasted-nutbread 2020-03-07 14:10:43 -05:00
parent 75eac153d6
commit a8eb50d96f
6 changed files with 31 additions and 16 deletions

View File

@ -21,10 +21,6 @@ function apiTemplateRender(template, data) {
return _apiInvoke('templateRender', {data, template}); return _apiInvoke('templateRender', {data, template});
} }
function apiAudioGetUrl(definition, source, optionsContext) {
return _apiInvoke('audioGetUrl', {definition, source, optionsContext});
}
function _apiInvoke(action, params={}) { function _apiInvoke(action, params={}) {
const data = {action, params}; const data = {action, params};
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {

View File

@ -171,7 +171,7 @@ async function audioInject(definition, fields, sources, optionsContext, audioSys
const expressions = definition.expressions; const expressions = definition.expressions;
const audioSourceDefinition = Array.isArray(expressions) ? expressions[0] : definition; const audioSourceDefinition = Array.isArray(expressions) ? expressions[0] : definition;
const {uri} = await audioSystem.getExpressionAudio(audioSourceDefinition, sources, optionsContext, {tts: false}); const {uri} = await audioSystem.getExpressionAudio(audioSourceDefinition, sources, {tts: false, optionsContext});
const filename = audioBuildFilename(audioSourceDefinition); const filename = audioBuildFilename(audioSourceDefinition);
if (filename !== null) { if (filename !== null) {
definition.audio = {url: uri, filename}; definition.audio = {url: uri, filename};

View File

@ -34,7 +34,7 @@ class Backend {
this.options = null; this.options = null;
this.optionsSchema = null; this.optionsSchema = null;
this.defaultAnkiFieldTemplates = null; this.defaultAnkiFieldTemplates = null;
this.audioSystem = new AudioSystem(); this.audioSystem = new AudioSystem({getAudioUri: this._getAudioUri.bind(this)});
this.optionsContext = { this.optionsContext = {
depth: 0, depth: 0,
url: window.location.href url: window.location.href
@ -764,6 +764,16 @@ class Backend {
// Utilities // 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) { async _injectScreenshot(definition, fields, screenshot) {
let usesScreenshot = false; let usesScreenshot = false;
for (const fieldValue of Object.values(fields)) { for (const fieldValue of Object.values(fields)) {

View File

@ -16,14 +16,19 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
/*global getOptionsContext, getOptionsMutable, settingsSaveOptions /*global getOptionsContext, getOptionsMutable, settingsSaveOptions, apiAudioGetUrl
AudioSystem, AudioSourceUI*/ AudioSystem, AudioSourceUI*/
let audioSourceUI = null; let audioSourceUI = null;
let audioSystem = null; let audioSystem = null;
async function audioSettingsInitialize() { async function audioSettingsInitialize() {
audioSystem = new AudioSystem(); audioSystem = new AudioSystem({
getAudioUri: async (definition, source) => {
const optionsContext = getOptionsContext();
return await apiAudioGetUrl(definition, source, optionsContext);
}
});
const optionsContext = getOptionsContext(); const optionsContext = getOptionsContext();
const options = await getOptionsMutable(optionsContext); const options = await getOptionsMutable(optionsContext);

View File

@ -16,8 +16,6 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
/*global apiAudioGetUrl*/
class TextToSpeechAudio { class TextToSpeechAudio {
constructor(text, voice) { constructor(text, voice) {
this.text = text; this.text = text;
@ -69,9 +67,10 @@ class TextToSpeechAudio {
} }
class AudioSystem { class AudioSystem {
constructor() { constructor({getAudioUri}) {
this._cache = new Map(); this._cache = new Map();
this._cacheSizeMaximum = 32; this._cacheSizeMaximum = 32;
this._getAudioUri = getAudioUri;
if (typeof speechSynthesis !== 'undefined') { if (typeof speechSynthesis !== 'undefined') {
// speechSynthesis.getVoices() will not be populated unless some API call is made. // speechSynthesis.getVoices() will not be populated unless some API call is made.
@ -79,7 +78,7 @@ class AudioSystem {
} }
} }
async getExpressionAudio(expression, sources, optionsContext, details) { async getExpressionAudio(expression, sources, details) {
const key = `${expression.expression}:${expression.reading}`; const key = `${expression.expression}:${expression.reading}`;
const cacheValue = this._cache.get(expression); const cacheValue = this._cache.get(expression);
if (typeof cacheValue !== 'undefined') { if (typeof cacheValue !== 'undefined') {
@ -88,7 +87,7 @@ class AudioSystem {
} }
for (const source of sources) { for (const source of sources) {
const uri = await apiAudioGetUrl(expression, source, optionsContext); const uri = await this._getAudioUri(expression, source, details);
if (uri === null) { continue; } if (uri === null) { continue; }
try { try {

View File

@ -18,7 +18,7 @@
/*global docRangeFromPoint, docSentenceExtract /*global docRangeFromPoint, docSentenceExtract
apiKanjiFind, apiTermsFind, apiNoteView, apiOptionsGet, apiDefinitionsAddable, apiDefinitionAdd apiKanjiFind, apiTermsFind, apiNoteView, apiOptionsGet, apiDefinitionsAddable, apiDefinitionAdd
apiScreenshotGet, apiForward apiScreenshotGet, apiForward, apiAudioGetUrl
AudioSystem, DisplayGenerator, WindowScroll, DisplayContext, DOM*/ AudioSystem, DisplayGenerator, WindowScroll, DisplayContext, DOM*/
class Display { class Display {
@ -31,7 +31,7 @@ class Display {
this.index = 0; this.index = 0;
this.audioPlaying = null; this.audioPlaying = null;
this.audioFallback = null; this.audioFallback = null;
this.audioSystem = new AudioSystem(); this.audioSystem = new AudioSystem({getAudioUri: this._getAudioUri.bind(this)});
this.styleNode = null; this.styleNode = null;
this.eventListeners = new EventListenerCollection(); this.eventListeners = new EventListenerCollection();
@ -775,7 +775,7 @@ class Display {
const sources = this.options.audio.sources; const sources = this.options.audio.sources;
let audio, source, info; let audio, source, info;
try { try {
({audio, source} = await this.audioSystem.getExpressionAudio(expression, sources, this.getOptionsContext())); ({audio, source} = await this.audioSystem.getExpressionAudio(expression, sources));
info = `From source ${1 + sources.indexOf(source)}: ${source}`; info = `From source ${1 + sources.indexOf(source)}: ${source}`;
} catch (e) { } catch (e) {
if (this.audioFallback === null) { if (this.audioFallback === null) {
@ -916,4 +916,9 @@ class Display {
const key = event.key; const key = event.key;
return (typeof key === 'string' ? (key.length === 1 ? key.toUpperCase() : key) : ''); return (typeof key === 'string' ? (key.length === 1 ? key.toUpperCase() : key) : '');
} }
async _getAudioUri(definition, source) {
const optionsContext = this.getOptionsContext();
return await apiAudioGetUrl(definition, source, optionsContext);
}
} }