-
Notifications
You must be signed in to change notification settings - Fork 7.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
playbackRate support #1132
playbackRate support #1132
Changes from 3 commits
524b253
6ebb5ac
61eb54a
8630248
1100ce3
3082afa
c5d46c1
778d56f
2ea98af
20798aa
a5bc688
adf4e50
269f7b1
ef25557
dbff62e
61696c0
10c5aea
2f4c619
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
/** | ||
* The component for controlling the playback rate | ||
* | ||
* @param {vjs.Player|Object} player | ||
* @param {Object=} options | ||
* @constructor | ||
*/ | ||
vjs.PlaybackRateMenuButton = vjs.MenuButton.extend({ | ||
/** @constructor */ | ||
init: function(player, options){ | ||
vjs.MenuButton.call(this, player, options); | ||
|
||
player.on('loadstart', vjs.bind(this, function(){ | ||
// hide playback rate controls when they're no playback rate options to select | ||
if (( player.tech.features && player.tech.features['playbackRate'] === false) || | ||
this.player_.options_.playbackRates.length === 0) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Any var with an underscore at the end is a private var, so you should really never have two in the same reference. i.e. this should be |
||
this.addClass('vjs-hidden'); | ||
} else { | ||
this.removeClass('vjs-hidden'); | ||
} | ||
})); | ||
|
||
player.on('ratechange', vjs.bind(this, this.rateChange)); | ||
} | ||
}); | ||
|
||
|
||
vjs.PlaybackRateMenuButton.prototype.createEl = function(){ | ||
var rate = this.player_.tech.playbackRate() + 'x'; | ||
return vjs.Component.prototype.createEl.call(this, 'div', { | ||
className: 'vjs-playback-rate vjs-menu-button vjs-control', | ||
innerHTML:'<div class="vjs-playaback-rate-value">' + rate + '</div>' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
}); | ||
}; | ||
|
||
// Menu creation | ||
vjs.PlaybackRateMenuButton.prototype.createMenu = function(){ | ||
var menu = new vjs.Menu(this.player_); | ||
var rates = this.player_.options_.playbackRates; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this should be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
for (var i = rates.length - 1; i >= 0; i--) { | ||
menu.addChild( | ||
new vjs.PlaybackRateMenuItem(this.player_, {rate: rates[i] + 'x'}) | ||
); | ||
}; | ||
|
||
return menu; | ||
}; | ||
|
||
vjs.PlaybackRateMenuButton.prototype.updateARIAAttributes = function(){ | ||
// Current playback rate | ||
this.el_.setAttribute('aria-valuenow',this.player_.playbackRate()); | ||
}; | ||
|
||
vjs.PlaybackRateMenuButton.prototype.onClick = function(){ | ||
// select next rate option | ||
var current_rate = this.player_.playbackRate(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. please use camel case here, |
||
var rates = this.player_.options_.playbackRates; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this.player_.options(). playbackRates; |
||
// wthis will select first if last currently selected | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 'wthis' |
||
var new_rate = rates[0]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. camelCase here please |
||
for (var i = 0; i <rates.length ; i++) { | ||
if (rates[i] > current_rate) { | ||
new_rate = rates[i]; | ||
break; | ||
} | ||
}; | ||
this.player_.playbackRate( new_rate ); | ||
}; | ||
|
||
// Update button label when rate changed | ||
vjs.PlaybackRateMenuButton.prototype.rateChange = function(){ | ||
this.el_.children[0].innerHTML = this.player_.playbackRate() + 'x'; | ||
}; | ||
|
||
/** | ||
* The specific menu item type for selecting a playback rate | ||
* | ||
* @constructor | ||
*/ | ||
vjs.PlaybackRateMenuItem = vjs.MenuItem.extend({ | ||
contentElType: 'button', | ||
/** @constructor */ | ||
init: function(player, options){ | ||
var label = this.label = options['rate']; | ||
var rate = this.rate = parseFloat(label, 10); | ||
|
||
// Modify options for parent MenuItem class's init. | ||
options['label'] = label; | ||
options['selected'] = rate === 1; | ||
vjs.MenuItem.call(this, player, options); | ||
|
||
this.player_.on('ratechange', vjs.bind(this, this.update)); | ||
} | ||
}); | ||
|
||
vjs.PlaybackRateMenuItem.prototype.onClick = function(){ | ||
vjs.MenuItem.prototype.onClick.call(this); | ||
this.player_.playbackRate(this.rate); | ||
}; | ||
|
||
vjs.PlaybackRateMenuItem.prototype.update = function(){ | ||
this.selected(this.player_.playbackRate() == this.rate); | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1382,6 +1382,19 @@ vjs.Player.prototype.listenForUserActivity = function(){ | |
clearInterval(activityCheck); | ||
clearTimeout(inactivityTimeout); | ||
}); | ||
|
||
vjs.Player.prototype.playbackRate = function(rate) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is actually being defined inside the |
||
if (rate !== undefined) { | ||
|
||
this.techCall('setPlaybackRate', rate); | ||
|
||
this.trigger('ratechange'); | ||
|
||
return this; | ||
} | ||
|
||
return this.techGet('playbackRate') || 1.0; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is what's causing the tests to break. The tests use a mock tech that doesn't support a lot of things, and this call assumes that the features should exist. I think we should change this to protect against the case where where playbackRate is not defined.
|
||
}; | ||
}; | ||
|
||
// Methods to add support for | ||
|
@@ -1396,7 +1409,6 @@ vjs.Player.prototype.listenForUserActivity = function(){ | |
// videoWidth: function(){ return this.techCall('videoWidth'); }, | ||
// videoHeight: function(){ return this.techCall('videoHeight'); }, | ||
// defaultPlaybackRate: function(){ return this.techCall('defaultPlaybackRate'); }, | ||
// playbackRate: function(){ return this.techCall('playbackRate'); }, | ||
// mediaGroup: function(){ return this.techCall('mediaGroup'); }, | ||
// controller: function(){ return this.techCall('controller'); }, | ||
// defaultMuted: function(){ return this.techCall('defaultMuted'); } | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The tech should really be a private thing, so I don't love the idea of accessing it directly from a UI component, but I know this is how the volume control currently does it too and I can't think of a better existing way to do this yet. I created issue #1147 to fix this later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would actually change this line to be
That way a tech isn't required to define any of that, and it assumes playback rate is not supported, which is the safer route.