diff --git a/ext/bg/search.html b/ext/bg/search.html index 609387e5..c08ad9cf 100644 --- a/ext/bg/search.html +++ b/ext/bg/search.html @@ -79,7 +79,6 @@ - diff --git a/ext/fg/float.html b/ext/fg/float.html index 512818bd..505bce81 100644 --- a/ext/fg/float.html +++ b/ext/fg/float.html @@ -93,7 +93,6 @@ - diff --git a/ext/mixed/js/display-audio.js b/ext/mixed/js/display-audio.js index cc7e9e93..ea919d14 100644 --- a/ext/mixed/js/display-audio.js +++ b/ext/mixed/js/display-audio.js @@ -17,7 +17,6 @@ /* global * AudioSystem - * CacheMap * api */ @@ -29,7 +28,7 @@ class DisplayAudio { this._autoPlayAudioTimer = null; this._autoPlayAudioDelay = 400; this._eventListeners = new EventListenerCollection(); - this._cache = new CacheMap(32); + this._cache = new Map(); } get autoPlayAudioDelay() { @@ -50,6 +49,7 @@ class DisplayAudio { } cleanupEntries() { + this._cache.clear(); this.clearAutoPlayTimer(); this._eventListeners.removeAllEventListeners(); } @@ -118,15 +118,16 @@ class DisplayAudio { try { // Create audio let audio; - let info; - try { + let title; + const info = await this._createExpressionAudio(sources, expression, reading, {textToSpeechVoice, customSourceUrl}); + if (info !== null) { let source; - ({audio, source} = await this._createExpressionAudio(sources, expression, reading, {textToSpeechVoice, customSourceUrl})); + ({audio, source} = info); const sourceIndex = sources.indexOf(source); - info = `From source ${1 + sourceIndex}: ${source}`; - } catch (e) { + title = `From source ${1 + sourceIndex}: ${source}`; + } else { audio = this._audioSystem.getFallbackAudio(); - info = 'Could not find audio'; + title = 'Could not find audio'; } // Stop any currently playing audio @@ -135,7 +136,7 @@ class DisplayAudio { // Update details for (const button of this._getAudioPlayButtons(definitionIndex, expressionIndex)) { const titleDefault = button.dataset.titleDefault || ''; - button.title = `${titleDefault}\n${info}`; + button.title = `${titleDefault}\n${title}`; } // Play @@ -189,30 +190,43 @@ class DisplayAudio { async _createExpressionAudio(sources, expression, reading, details) { const key = JSON.stringify([expression, reading]); - const cacheValue = this._cache.get(key); - if (typeof cacheValue !== 'undefined') { - return cacheValue; + let sourceMap = this._cache.get(key); + if (typeof sourceMap === 'undefined') { + sourceMap = new Map(); + this._cache.set(key, sourceMap); } for (let i = 0, ii = sources.length; i < ii; ++i) { const source = sources[i]; - const infoList = await await api.getExpressionAudioInfoList(source, expression, reading, details); + + let infoListPromise = sourceMap.get(source); + if (typeof infoListPromise === 'undefined') { + infoListPromise = this._getExpressionAudioInfoList(source, expression, reading, details); + sourceMap.set(source, infoListPromise); + } + const infoList = await infoListPromise; + for (let j = 0, jj = infoList.length; j < jj; ++j) { - const info = infoList[j]; + const item = infoList[j]; + + let {audioPromise} = item; + if (audioPromise === null) { + audioPromise = this._createAudioFromInfo(item.info, source); + item.audioPromise = audioPromise; + } + let audio; try { - audio = await this._createAudioFromInfo(info, source); + audio = await audioPromise; } catch (e) { continue; } - const result = {audio, source, infoList, infoListIndex: j}; - this._cache.set(key, result); - return result; + return {audio, source, infoListIndex: j}; } } - throw new Error('Could not create audio'); + return null; } async _createAudioFromInfo(info, source) { @@ -225,4 +239,9 @@ class DisplayAudio { throw new Error(`Unsupported type: ${info.type}`); } } + + async _getExpressionAudioInfoList(source, expression, reading, details) { + const infoList = await api.getExpressionAudioInfoList(source, expression, reading, details); + return infoList.map((info) => ({info, audioPromise: null})); + } }