Skip to content

Commit 4c9e09d

Browse files
misteroneillgkatsev
authored andcommitted
fix: make sure sources, volume, and playback rate are reset along with the player (videojs#5676)
Clear out the player cache_ on reset. Fixes videojs#5675
1 parent b02181b commit 4c9e09d

File tree

3 files changed

+115
-14
lines changed

3 files changed

+115
-14
lines changed

src/js/player.js

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -401,18 +401,14 @@ class Player extends Component {
401401
this.languages_ = Player.prototype.options_.languages;
402402
}
403403

404-
// Cache for video property values.
405-
this.cache_ = {};
404+
this.resetCache_();
406405

407406
// Set poster
408407
this.poster_ = options.poster || '';
409408

410409
// Set controls
411410
this.controls_ = !!options.controls;
412411

413-
// Set default values for lastVolume
414-
this.cache_.lastVolume = 1;
415-
416412
// Original tag settings stored in options
417413
// now remove immediately so native controls don't flash.
418414
// May be turned back on by HTML5 tech if nativeControlsForTouch is true
@@ -438,9 +434,6 @@ class Player extends Component {
438434

439435
this.el_ = this.createEl();
440436

441-
// Set default value for lastPlaybackRate
442-
this.cache_.lastPlaybackRate = this.defaultPlaybackRate();
443-
444437
// Make this an evented object and use `el_` as its event bus.
445438
evented(this, {eventBusKey: 'el_'});
446439

@@ -2011,6 +2004,33 @@ class Player extends Component {
20112004
return this.cache_;
20122005
}
20132006

2007+
/**
2008+
* Resets the internal cache object.
2009+
*
2010+
* Using this function outside the player constructor or reset method may
2011+
* have unintended side-effects.
2012+
*
2013+
* @private
2014+
*/
2015+
resetCache_() {
2016+
this.cache_ = {
2017+
2018+
// Right now, the currentTime is not _really_ cached because it is always
2019+
// retrieved from the tech (see: currentTime). However, for completeness,
2020+
// we set it to zero here to ensure that if we do start actually caching
2021+
// it, we reset it along with everything else.
2022+
currentTime: 0,
2023+
duration: NaN,
2024+
lastVolume: 1,
2025+
lastPlaybackRate: this.defaultPlaybackRate(),
2026+
media: null,
2027+
src: '',
2028+
source: {},
2029+
sources: [],
2030+
volume: 1
2031+
};
2032+
}
2033+
20142034
/**
20152035
* Pass values to the playback tech
20162036
*
@@ -2933,9 +2953,7 @@ class Player extends Component {
29332953
if (this.tech_) {
29342954
this.tech_.clearTracks('text');
29352955
}
2936-
if (this.cache_) {
2937-
this.cache_.media = null;
2938-
}
2956+
this.resetCache_();
29392957
this.poster('');
29402958
this.loadTech_(this.options_.techOrder[0], null);
29412959
this.techCall_('reset');

test/unit/player.test.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1436,6 +1436,7 @@ QUnit.test('player#reset loads the Html5 tech and then techCalls reset', functio
14361436
options_: {
14371437
techOrder: ['html5', 'flash']
14381438
},
1439+
resetCache_() {},
14391440
loadTech_(tech, source) {
14401441
loadedTech = tech;
14411442
loadedSource = source;
@@ -1462,6 +1463,7 @@ QUnit.test('player#reset loads the first item in the techOrder and then techCall
14621463
options_: {
14631464
techOrder: ['flash', 'html5']
14641465
},
1466+
resetCache_() {},
14651467
loadTech_(tech, source) {
14661468
loadedTech = tech;
14671469
loadedSource = source;
@@ -1479,6 +1481,48 @@ QUnit.test('player#reset loads the first item in the techOrder and then techCall
14791481
assert.equal(techCallMethod, 'reset', 'we then reset the tech');
14801482
});
14811483

1484+
QUnit.test('player#reset clears the player cache', function(assert) {
1485+
const player = TestHelpers.makePlayer();
1486+
const sources = [{
1487+
src: '//vjs.zencdn.net/v/oceans.mp4',
1488+
type: 'video/mp4'
1489+
}, {
1490+
src: '//vjs.zencdn.net/v/oceans.webm',
1491+
type: 'video/webm'
1492+
}];
1493+
1494+
this.clock.tick(1);
1495+
1496+
player.src(sources);
1497+
player.duration(10);
1498+
player.playbackRate(0.5);
1499+
player.volume(0.2);
1500+
1501+
assert.strictEqual(player.currentSrc(), sources[0].src, 'currentSrc is correct');
1502+
assert.deepEqual(player.currentSource(), sources[0], 'currentSource is correct');
1503+
assert.deepEqual(player.currentSources(), sources, 'currentSources is correct');
1504+
assert.strictEqual(player.duration(), 10, 'duration is correct');
1505+
assert.strictEqual(player.playbackRate(), 0.5, 'playbackRate is correct');
1506+
assert.strictEqual(player.volume(), 0.2, 'volume is correct');
1507+
assert.strictEqual(player.lastVolume_(), 0.2, 'lastVolume_ is correct');
1508+
1509+
player.reset();
1510+
1511+
assert.strictEqual(player.currentSrc(), '', 'currentSrc is correct');
1512+
assert.deepEqual(player.currentSource(), {}, 'currentSource is correct');
1513+
assert.deepEqual(player.currentSources(), [], 'currentSources is correct');
1514+
1515+
// Right now, the currentTime is not _really_ cached because it is always
1516+
// retrieved from the tech. However, for completeness, we set it to zero in
1517+
// the `resetCache_` method to ensure that if we do start actually caching it,
1518+
// we reset it along with everything else.
1519+
assert.strictEqual(player.getCache().currentTime, 0, 'currentTime is correct');
1520+
assert.ok(isNaN(player.duration()), 'duration is correct');
1521+
assert.strictEqual(player.playbackRate(), 1, 'playbackRate is correct');
1522+
assert.strictEqual(player.volume(), 1, 'volume is correct');
1523+
assert.strictEqual(player.lastVolume_(), 1, 'lastVolume_ is correct');
1524+
});
1525+
14821526
QUnit.test('player#reset removes the poster', function(assert) {
14831527
const player = TestHelpers.makePlayer();
14841528

test/unit/tech/tech-faker.js

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ class TechFaker extends Tech {
1010
constructor(options, handleReady) {
1111
super(options, handleReady);
1212

13+
this.featuresPlaybackRate = true;
14+
this.defaultPlaybackRate_ = 1;
15+
this.playbackRate_ = 1;
16+
this.currentTime_ = 0;
17+
1318
if (this.options_ && this.options_.sourceset) {
1419
this.fakeSourceset();
1520
}
@@ -37,7 +42,9 @@ class TechFaker extends Tech {
3742

3843
setControls(val) {}
3944

40-
setVolume(newVolume) {}
45+
setVolume(value) {
46+
this.volume_ = value;
47+
}
4148

4249
setMuted() {}
4350

@@ -49,9 +56,41 @@ class TechFaker extends Tech {
4956
this.options_.autoplay = true;
5057
}
5158

59+
defaultPlaybackRate(value) {
60+
if (value !== undefined) {
61+
this.defaultPlaybackRate_ = parseFloat(value);
62+
}
63+
return this.defaultPlaybackRate_;
64+
}
65+
66+
setPlaybackRate(value) {
67+
const last = this.playbackRate_;
68+
69+
this.playbackRate_ = parseFloat(value);
70+
71+
if (value !== last) {
72+
this.trigger('ratechange');
73+
}
74+
}
75+
76+
playbackRate() {
77+
return this.playbackRate_;
78+
}
79+
80+
setCurrentTime(value) {
81+
const last = this.currentTime_;
82+
83+
this.currentTime_ = parseFloat(value);
84+
85+
if (value !== last) {
86+
this.trigger('timeupdate');
87+
}
88+
}
89+
5290
currentTime() {
53-
return 0;
91+
return this.currentTime_;
5492
}
93+
5594
seekable() {
5695
return createTimeRanges(0, 0);
5796
}
@@ -73,7 +112,7 @@ class TechFaker extends Tech {
73112
return 'movie.mp4';
74113
}
75114
volume() {
76-
return 0;
115+
return this.volume_ || 0;
77116
}
78117
muted() {
79118
return false;

0 commit comments

Comments
 (0)