diff --git a/src/streaming/MediaPlayer.js b/src/streaming/MediaPlayer.js index ad4b7454fd..91a9a751dd 100644 --- a/src/streaming/MediaPlayer.js +++ b/src/streaming/MediaPlayer.js @@ -83,7 +83,7 @@ import CustomParametersModel from './models/CustomParametersModel'; /** * The media types - * @typedef {("video" | "audio" | "text" | "image")} MediaType + * @typedef {('video' | 'audio' | 'text' | 'image')} MediaType */ /** @@ -1435,10 +1435,13 @@ function MediaPlayer() { } if (playbackInitialized) { //Reset if we have been playing before, so this is a new element. - _resetPlaybackControllers(); + _resetPlaybackControllers() + .then(() => { + _initializePlayback(providedStartTime); + }) + } else { + _initializePlayback(providedStartTime); } - - _initializePlayback(providedStartTime); } /** @@ -1899,9 +1902,16 @@ function MediaPlayer() { source = urlOrManifest; if (streamingInitialized || playbackInitialized) { - _resetPlaybackControllers(); + _resetPlaybackControllers() + .then(() => { + _initializePlaybackIfReady() + }) + } else { + _initializePlaybackIfReady() } + } + function _initializePlaybackIfReady() { if (isReady()) { _initializePlayback(providedStartTime); } @@ -2150,18 +2160,32 @@ function MediaPlayer() { abrController.reset(); mediaController.reset(); segmentBaseController.reset(); - if (protectionController) { - if (settings.get().streaming.protection.keepProtectionMediaKeys) { - protectionController.stop(); - } else { - protectionController.reset(); - protectionController = null; - _detectProtection(); - } - } textController.reset(); cmcdModel.reset(); cmsdModel.reset(); + return _resetProtectionController() + } + + function _resetProtectionController() { + return new Promise((resolve) => { + if (!protectionController) { + resolve() + return + } + if (settings.get().streaming.protection.keepProtectionMediaKeys) { + protectionController.stop() + .finally(() => { + resolve() + }) + } else { + protectionController.reset() + .finally(() => { + protectionController = null; + _detectProtection(); + resolve() + }) + } + }) } function _createPlaybackControllers() { diff --git a/src/streaming/protection/controllers/ProtectionController.js b/src/streaming/protection/controllers/ProtectionController.js index d6d0919eeb..a4a412a6cc 100644 --- a/src/streaming/protection/controllers/ProtectionController.js +++ b/src/streaming/protection/controllers/ProtectionController.js @@ -574,8 +574,9 @@ function ProtectionController(config) { function stop() { _abortLicenseRequest(); if (protectionModel) { - protectionModel.stop(); + return protectionModel.stop(); } + return Promise.resolve; } /** @@ -585,27 +586,38 @@ function ProtectionController(config) { * associated with a HTMLMediaElement, it will be detached from that element. * * @memberof module:ProtectionController - * @instance - * @ignore - */ + * @instanceignore + * + **/ function reset() { - eventBus.off(events.INTERNAL_KEY_MESSAGE, _onKeyMessage, instance); - eventBus.off(events.INTERNAL_KEY_STATUS_CHANGED, _onKeyStatusChanged, instance); + return new Promise((resolve) => { + eventBus.off(events.INTERNAL_KEY_MESSAGE, _onKeyMessage, instance); + eventBus.off(events.INTERNAL_KEY_STATUS_CHANGED, _onKeyStatusChanged, instance); - checkConfig(); + checkConfig(); - _abortLicenseRequest(); + _abortLicenseRequest(); - setMediaElement(null); + setMediaElement(null); - selectedKeySystem = null; - keySystemSelectionInProgress = false; + selectedKeySystem = null; + keySystemSelectionInProgress = false; - if (protectionModel) { - protectionModel.reset(); - protectionModel = null; - } + if (protectionModel) { + protectionModel.reset() + .then(() => { + protectionModel = null; + _resetVariablesAfterReset(); + resolve(); + }) + } else { + _resetVariablesAfterReset() + resolve(); + } + }) + } + function _resetVariablesAfterReset() { needkeyRetries.forEach(retryTimeout => clearTimeout(retryTimeout)); needkeyRetries = []; diff --git a/src/streaming/protection/models/ProtectionModel_21Jan2015.js b/src/streaming/protection/models/ProtectionModel_21Jan2015.js index abd5c53db5..e3cee5cb04 100644 --- a/src/streaming/protection/models/ProtectionModel_21Jan2015.js +++ b/src/streaming/protection/models/ProtectionModel_21Jan2015.js @@ -78,11 +78,24 @@ function ProtectionModel_21Jan2015(config) { } function reset() { - const numSessions = sessions.length; - let session; + return new Promise((resolve, reject) => { + if (sessions.length === 0) { + eventBus.trigger(events.TEARDOWN_COMPLETE); + resolve(); + return; + } - if (numSessions !== 0) { - // Called when we are done closing a session. Success or fail + const promises = []; + for (let i = sessions.length - 1; i >= 0; i--) { + promises.push(_resetSingleSession(sessions[i])); + } + + return Promise.all(promises); + }) + } + + function _resetSingleSession(session) { + return new Promise((resolve) => { const done = function (session) { removeSession(session); if (sessions.length === 0) { @@ -96,28 +109,36 @@ function ProtectionModel_21Jan2015(config) { } } }; - for (let i = 0; i < numSessions; i++) { - session = sessions[i]; - (function (s) { - _closeKeySessionInternal(session) - done(s); - })(session); - } - } else { - eventBus.trigger(events.TEARDOWN_COMPLETE); - } + + _closeKeySessionInternal(session) + .finally(() => { + done(session); + resolve(); + }) + }) } function stop() { - // Close and remove not usable sessions - let session; - for (let i = 0; i < sessions.length; i++) { - session = sessions[i]; + const promises = [] + for (let i = sessions.length - 1; i >= 0; i--) { + promises.push(_stopSingleSession(sessions[i])); + } + + return Promise.all(promises) + } + + function _stopSingleSession(session) { + return new Promise((resolve) => { if (!session.getUsable()) { _closeKeySessionInternal(session) - removeSession(session); + .finally(() => { + removeSession(session); + resolve(); + }) + } else { + resolve() } - } + }) } function getAllInitData() { @@ -413,7 +434,11 @@ function ProtectionModel_21Jan2015(config) { session.removeEventListener('message', sessionToken); // Send our request to the key session - return session.close(); + return Promise.race([ + session.close(), + new Promise((resolve, reject) => { + setTimeout(reject, 500) + })]); } // This is our main event handler for all desired HTMLMediaElement events