Skip to content

Commit

Permalink
[mainui][WIP] Attempts a workaround to #1717 where Safari requires a …
Browse files Browse the repository at this point in the history
…user interaction after a web audio stream has been requested.

Signed-off-by: Dan Cunningham <dan@digitaldan.com>
  • Loading branch information
digitaldan committed Mar 5, 2023
1 parent 737427f commit a8e1d12
Showing 1 changed file with 24 additions and 7 deletions.
31 changes: 24 additions & 7 deletions bundles/org.openhab.ui/web/src/components/app.vue
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@ export default {
init: false,
ready: false,
eventSource: null,
context: null,
// Framework7 Parameters
f7params: {
Expand Down Expand Up @@ -624,30 +625,46 @@ export default {
this.eventSource = null
},
playAudioUrl (audioUrl) {
let context
try {
window.AudioContext = window.AudioContext || window.webkitAudioContext
if (typeof (window.AudioContext) !== 'undefined') {
context = new AudioContext()
if(!this.context){
window.AudioContext = window.AudioContext || window.webkitAudioContext
if (typeof (window.AudioContext) !== 'undefined') {
this.context = new AudioContext()
unlockAudioContext(this.context);
}
}
let context = this.context
console.log('Playing audio URL: ' + audioUrl)
this.$oh.api.getPlain(audioUrl, '', '*/*', 'arraybuffer').then((data) => {
context.decodeAudioData(data, function (buffer) {
let source = context.createBufferSource()
source.buffer = buffer
source.connect(context.destination)
source.onended = function () {
context.close()
context.suspend()
}
if(context.state == 'suspended'){
context.resume()
}
source.start(0)
})
})
} catch (e) {
console.warn('Error while playing audio URL: ' + e.toString())
if (context) {
context.close()
if (this.context) {
this.context.suspend()
}
}
//Safari requires a touch event after the stream has started, hence this workaround
//Credit: https://www.mattmontag.com/web/unlock-web-audio-in-safari-for-ios-and-macos
function unlockAudioContext(audioCtx) {
if (audioCtx.state !== 'suspended') return;
const b = document.body;
const events = ['touchstart','touchend', 'mousedown','keydown'];
events.forEach(e => b.addEventListener(e, unlock, false));
function unlock() { audioCtx.resume().then(clean); }
function clean() { events.forEach(e => b.removeEventListener(e, unlock)); }
}
}
},
created () {
Expand Down

0 comments on commit a8e1d12

Please sign in to comment.