Skip to content

Commit

Permalink
Merge pull request #658 from golddranks/master
Browse files Browse the repository at this point in the history
Fixed an edge case with Safari ("infinite" html5 audio -> the end event won't run)
  • Loading branch information
goldfire authored Oct 25, 2020
2 parents 289bcda + 2e5c752 commit 0629f9e
Showing 1 changed file with 32 additions and 0 deletions.
32 changes: 32 additions & 0 deletions src/howler.core.js
Original file line number Diff line number Diff line change
Expand Up @@ -1746,6 +1746,7 @@
// Remove any event listeners.
sounds[i]._node.removeEventListener('error', sounds[i]._errorFn, false);
sounds[i]._node.removeEventListener(Howler._canPlayEvent, sounds[i]._loadFn, false);
sounds[i]._node.removeEventListener('ended', sounds[i]._endFn, false);

// Release the Audio object back to the pool.
Howler._releaseHtml5Audio(sounds[i]._node);
Expand Down Expand Up @@ -2242,6 +2243,11 @@
self._loadFn = self._loadListener.bind(self);
self._node.addEventListener(Howler._canPlayEvent, self._loadFn, false);

// Listen for the 'ended' event on the sound to account for edge-case where
// a finite sound has a duration of Infinity.
self._endFn = self._endListener.bind(self);
self._node.addEventListener('ended', self._endFn, false);

// Setup the new audio node.
self._node.src = parent._src;
self._node.preload = parent._preload === true ? 'auto' : parent._preload;
Expand Down Expand Up @@ -2315,6 +2321,32 @@

// Clear the event listener.
self._node.removeEventListener(Howler._canPlayEvent, self._loadFn, false);
},

/**
* HTML5 Audio ended listener callback.
*/
_endListener: function() {
var self = this;
var parent = self._parent;

// Only handle the `ended`` event if the duration is Infinity.
if (parent._duration === Infinity) {
// Update the parent duration to match the real audio duration.
// Round up the duration to account for the lower precision in HTML5 Audio.
parent._duration = Math.ceil(self._node.duration * 10) / 10;

// Update the sprite that corresponds to the real duration.
if (parent._sprite.__default[1] === Infinity) {
parent._sprite.__default[1] = parent._duration * 1000;
}

// Run the regular ended method.
parent._ended(self);
}

// Clear the event listener since the duration is now correct.
self._node.removeEventListener('ended', self._endFn, false);
}
};

Expand Down

0 comments on commit 0629f9e

Please sign in to comment.