diff options
| author | toasted-nutbread <toasted-nutbread@users.noreply.github.com> | 2019-10-10 19:58:06 -0400 | 
|---|---|---|
| committer | toasted-nutbread <toasted-nutbread@users.noreply.github.com> | 2019-10-10 21:30:38 -0400 | 
| commit | 1d516b3b24eb6b89aa3a345341b6c1c35e24dfed (patch) | |
| tree | d32c926ab268f73142f8672ce9b115a5610c04e5 /ext/mixed/js | |
| parent | 8ae1da427756a9a1e057b3518c4069ac7d5b4b3a (diff) | |
Implement audio fallbacks
Diffstat (limited to 'ext/mixed/js')
| -rw-r--r-- | ext/mixed/js/audio.js | 60 | ||||
| -rw-r--r-- | ext/mixed/js/display.js | 39 | 
2 files changed, 76 insertions, 23 deletions
| diff --git a/ext/mixed/js/audio.js b/ext/mixed/js/audio.js new file mode 100644 index 00000000..b905140c --- /dev/null +++ b/ext/mixed/js/audio.js @@ -0,0 +1,60 @@ +/* + * 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/>. + */ + + +function audioGetFromUrl(url) { +    return new Promise((resolve, reject) => { +        const audio = new Audio(url); +        audio.addEventListener('loadeddata', () => { +            if (audio.duration === 5.694694 || audio.duration === 5.720718) { +                // Hardcoded values for invalid audio +                reject(new Error('Could not retrieve audio')); +            } else { +                resolve(audio); +            } +        }); +        audio.addEventListener('error', () => reject(audio.error)); +    }); +} + +async function audioGetFromSources(expression, sources, optionsContext, createAudioObject, cache=null) { +    const key = `${expression.expression}:${expression.reading}`; +    if (cache !== null && cache.hasOwnProperty(expression)) { +        return cache[key]; +    } + +    for (let i = 0, ii = sources.length; i < ii; ++i) { +        const source = sources[i]; +        const url = await apiAudioGetUrl(expression, source, optionsContext); +        if (url === null) { +            continue; +        } + +        try { +            const audio = createAudioObject ? await audioGetFromUrl(url) : null; +            const result = {audio, url, source}; +            if (cache !== null) { +                cache[key] = result; +            } +            return result; +        } catch (e) { +            // NOP +        } +    } +    return {audio: null, source: null}; +} diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index c1224084..8d4e1e68 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -26,6 +26,8 @@ class Display {          this.context = null;          this.sequence = 0;          this.index = 0; +        this.audioPlaying = null; +        this.audioFallback = null;          this.audioCache = {};          this.optionsContext = {};          this.eventListeners = []; @@ -404,33 +406,24 @@ class Display {              this.setSpinnerVisible(true);              const expression = expressionIndex === -1 ? definition : definition.expressions[expressionIndex]; -            let url = await apiAudioGetUrl(expression, this.options.audio.sources[0], this.optionsContext); -            if (!url) { -                url = '/mixed/mp3/button.mp3'; -            } -            for (const key in this.audioCache) { -                this.audioCache[key].pause(); +            if (this.audioPlaying !== null) { +                this.audioPlaying.pause(); +                this.audioPlaying = null;              } -            const volume = this.options.audio.volume / 100.0; -            let audio = this.audioCache[url]; -            if (audio) { -                audio.currentTime = 0; -                audio.volume = volume; -                audio.play(); -            } else { -                audio = new Audio(url); -                audio.onloadeddata = () => { -                    if (audio.duration === 5.694694 || audio.duration === 5.720718) { -                        audio = new Audio('/mixed/mp3/button.mp3'); -                    } - -                    this.audioCache[url] = audio; -                    audio.volume = volume; -                    audio.play(); -                }; +            let {audio} = await audioGetFromSources(expression, this.options.audio.sources, this.optionsContext, true, this.audioCache); +            if (audio === null) { +                if (this.audioFallback === null) { +                    this.audioFallback = new Audio('/mixed/mp3/button.mp3'); +                } +                audio = this.audioFallback;              } + +            this.audioPlaying = audio; +            audio.currentTime = 0; +            audio.volume = this.options.audio.volume / 100.0; +            audio.play();          } catch (e) {              this.onError(e);          } finally { |