Merge pull request #1027 from friday/quality

Minor code improvements for quality switching
This commit is contained in:
Sam Potts 2018-06-12 11:13:34 +10:00 committed by GitHub
commit 0b09b8ee6f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 55 additions and 133 deletions

6
src/js/controls.js vendored
View File

@ -632,7 +632,6 @@ const controls = {
}, },
// Set the quality menu // Set the quality menu
// TODO: Vimeo support
setQualityMenu(options) { setQualityMenu(options) {
// Menu required // Menu required
if (!utils.is.element(this.elements.settings.panes.quality)) { if (!utils.is.element(this.elements.settings.panes.quality)) {
@ -642,9 +641,10 @@ const controls = {
const type = 'quality'; const type = 'quality';
const list = this.elements.settings.panes.quality.querySelector('ul'); const list = this.elements.settings.panes.quality.querySelector('ul');
// Set options if passed and filter based on config // Set options if passed and filter based on uniqueness and config
if (utils.is.array(options)) { if (utils.is.array(options)) {
this.options.quality = options.filter(quality => this.config.quality.options.includes(quality)); this.options.quality = utils.dedupe(options)
.filter(quality => this.config.quality.options.includes(quality));
} }
// Toggle the pane and tab // Toggle the pane and tab

View File

@ -8,35 +8,21 @@ import utils from './utils';
const html5 = { const html5 = {
getSources() { getSources() {
if (!this.isHTML5) { if (!this.isHTML5) {
return null; return [];
} }
return this.media.querySelectorAll('source'); const sources = Array.from(this.media.querySelectorAll('source'));
// Filter out unsupported sources
return sources.filter(source => support.mime.call(this, source.getAttribute('type')));
}, },
// Get quality levels // Get quality levels
getQualityOptions() { getQualityOptions() {
if (!this.isHTML5) { // Get sizes from <source> elements
return null; return html5.getSources.call(this)
} .map(source => Number(source.getAttribute('size')))
.filter(Boolean);
// Get sources
const sources = html5.getSources.call(this);
if (utils.is.empty(sources)) {
return null;
}
// Get <source> with size attribute
const sizes = Array.from(sources).filter(source => !utils.is.empty(source.getAttribute('size')));
// If none, bail
if (utils.is.empty(sizes)) {
return null;
}
// Reduce to unique list
return utils.dedupe(sizes.map(source => Number(source.getAttribute('size'))));
}, },
extend() { extend() {
@ -51,53 +37,28 @@ const html5 = {
get() { get() {
// Get sources // Get sources
const sources = html5.getSources.call(player); const sources = html5.getSources.call(player);
const [source] = sources.filter(source => source.getAttribute('src') === player.source);
if (utils.is.empty(sources)) { // Return size, if match is found
return null; return source && Number(source.getAttribute('size'));
}
const matches = Array.from(sources).filter(source => source.getAttribute('src') === player.source);
if (utils.is.empty(matches)) {
return null;
}
return Number(matches[0].getAttribute('size'));
}, },
set(input) { set(input) {
// Get sources // Get sources
const sources = html5.getSources.call(player); const sources = html5.getSources.call(player);
if (utils.is.empty(sources)) { // Get first match for requested size
const source = sources.find(source => Number(source.getAttribute('size')) === input);
// No matching source found
if (!source) {
return; return;
} }
// Get matches for requested size
const matches = Array.from(sources).filter(source => Number(source.getAttribute('size')) === input);
// No matches for requested size
if (utils.is.empty(matches)) {
return;
}
// Get supported sources
const supported = matches.filter(source => support.mime.call(player, source.getAttribute('type')));
// No supported sources
if (utils.is.empty(supported)) {
return;
}
// Trigger change event
utils.dispatchEvent.call(player, player.media, 'qualityrequested', false, {
quality: input,
});
// Get current state // Get current state
const { currentTime, playing } = player; const { currentTime, playing } = player;
// Set new source // Set new source
player.media.src = supported[0].getAttribute('src'); player.media.src = source.getAttribute('src');
// Restore time // Restore time
const onLoadedMetaData = () => { const onLoadedMetaData = () => {

View File

@ -8,52 +8,26 @@ import utils from './../utils';
// Standardise YouTube quality unit // Standardise YouTube quality unit
function mapQualityUnit(input) { function mapQualityUnit(input) {
switch (input) { const qualities = {
case 'hd2160': hd2160: 2160,
return 2160; hd1440: 1440,
hd1080: 1080,
hd720: 720,
large: 480,
medium: 360,
small: 240,
tiny: 144,
};
case 2160: const entry = Object.entries(qualities)
return 'hd2160'; .find(entry => entry.includes(input));
case 'hd1440': if (entry) {
return 1440; // Get the match corresponding to the input
return entry.find(value => value !== input);
case 1440:
return 'hd1440';
case 'hd1080':
return 1080;
case 1080:
return 'hd1080';
case 'hd720':
return 720;
case 720:
return 'hd720';
case 'large':
return 480;
case 480:
return 'large';
case 'medium':
return 360;
case 360:
return 'medium';
case 'small':
return 240;
case 240:
return 'small';
default:
return 'default';
} }
return 'default';
} }
function mapQualityUnits(levels) { function mapQualityUnits(levels) {
@ -328,15 +302,7 @@ const youtube = {
return mapQualityUnit(instance.getPlaybackQuality()); return mapQualityUnit(instance.getPlaybackQuality());
}, },
set(input) { set(input) {
const quality = input; instance.setPlaybackQuality(mapQualityUnit(input));
// Set via API
instance.setPlaybackQuality(mapQualityUnit(quality));
// Trigger request event
utils.dispatchEvent.call(player, player.media, 'qualityrequested', false, {
quality,
});
}, },
}); });

View File

@ -669,36 +669,31 @@ class Plyr {
* @param {number} input - Quality level * @param {number} input - Quality level
*/ */
set quality(input) { set quality(input) {
let quality = null; const config = this.config.quality;
const options = this.options.quality;
if (!utils.is.empty(input)) { if (!options.length) {
quality = Number(input);
}
if (!utils.is.number(quality)) {
quality = this.storage.get('quality');
}
if (!utils.is.number(quality)) {
quality = this.config.quality.selected;
}
if (!utils.is.number(quality)) {
quality = this.config.quality.default;
}
if (!this.options.quality.length) {
return; return;
} }
if (!this.options.quality.includes(quality)) { let quality = ([
const closest = utils.closest(this.options.quality, quality); !utils.is.empty(input) && Number(input),
this.storage.get('quality'),
config.selected,
config.default,
]).find(utils.is.number);
if (!options.includes(quality)) {
const closest = utils.closest(options, quality);
this.debug.warn(`Unsupported quality option: ${quality}, using ${closest} instead`); this.debug.warn(`Unsupported quality option: ${quality}, using ${closest} instead`);
quality = closest; quality = closest;
} }
// Trigger request event
utils.dispatchEvent.call(this, this.media, 'qualityrequested', false, { quality });
// Update config // Update config
this.config.quality.selected = quality; config.selected = quality;
// Set quality // Set quality
this.media.quality = quality; this.media.quality = quality;