diff --git a/src/js/media/media.js b/src/js/media/media.js index 3c6f7588c7..67dca61703 100644 --- a/src/js/media/media.js +++ b/src/js/media/media.js @@ -36,6 +36,8 @@ vjs.MediaTechController = vjs.Component.extend({ this.emulateTextTracks(); } + this.on('loadstart', this.updateCurrentSource_); + this.initTextTrackListeners(); } }); @@ -168,6 +170,24 @@ vjs.MediaTechController.prototype.onTap = function(){ this.player().userActive(!this.player().userActive()); }; +/** + * Set currentSource_ asynchronously to simulate the media element's + * asynchronous execution of the `resource selection algorithm` + * + * currentSource_ is set either as the first loadstart event OR + * in a timeout to make sure it is set asynchronously before anything else + * but before other loadstart handlers have had a chance to execute + */ +vjs.MediaTechController.prototype.updateCurrentSource_ = function () { + // We could have been called with a 0-ms setTimeout OR via loadstart (which ever + // happens first) so we should clear the timeout to be a good citizen + this.clearTimeout(this.updateSourceTimer_); + + if (this.pendingSource_) { + this.currentSource_ = this.pendingSource_; + } +}; + /* Fallbacks for unsupported event types ================================================================================ */ // Manually trigger progress events based on changes to the buffered amount @@ -426,6 +446,8 @@ vjs.MediaTechController.prototype['featuresNativeTextTracks'] = false; * */ vjs.MediaTechController.withSourceHandlers = function(Tech){ + Tech.prototype.currentSource_ = {src: ''}; + /** * Register a source handler * Source handlers are scripts for handling specific formats. @@ -510,13 +532,11 @@ vjs.MediaTechController.withSourceHandlers = function(Tech){ this.disposeSourceHandler(); this.off('dispose', this.disposeSourceHandler); - // Set currentSource_ asynchronously to simulate the media element's - // asynchronous execution of the `resource selection algorithm` - this.setTimeout(vjs.bind(this, function () { - if (source && source.src !== '') { - this.currentSource_ = source; - } - }), 0); + // Schedule currentSource_ to be set asynchronously + if (source && source.src !== '') { + this.pendingSource_ = source; + this.updateSourceTimer_ = this.setTimeout(vjs.bind(this, this.updateCurrentSource_), 0); + } this.sourceHandler_ = sh.handleSource(source, this); this.on('dispose', this.disposeSourceHandler); diff --git a/src/js/player.js b/src/js/player.js index 899de475d9..8d919f6a3c 100644 --- a/src/js/player.js +++ b/src/js/player.js @@ -1228,7 +1228,12 @@ vjs.Player.prototype.load = function(){ * @return {String} The current source */ vjs.Player.prototype.currentSrc = function(){ - return this.techGet('currentSrc') || this.cache_.src || ''; + var techSrc = this.techGet('currentSrc'); + + if (techSrc === undefined) { + return this.cache_.src || ''; + } + return techSrc; }; /** diff --git a/test/unit/media.js b/test/unit/media.js index fd22119d22..054976a180 100644 --- a/test/unit/media.js +++ b/test/unit/media.js @@ -287,7 +287,7 @@ test('should emulate the video element\'s behavior for currentSrc when src is se tech.setSource(sourceA); // Test that currentSource_ is not immediately specified - strictEqual(tech.currentSource_, undefined, 'sourceA was not stored immediately'); + deepEqual(tech.currentSource_, {src:''}, 'sourceA was not stored immediately'); this.clock.tick(1);