diff --git a/src/js/controls.js b/src/js/controls.js index 058e636f..8fb2b7b7 100644 --- a/src/js/controls.js +++ b/src/js/controls.js @@ -632,7 +632,6 @@ const controls = { }, // Set the quality menu - // TODO: Vimeo support setQualityMenu(options) { // Menu required if (!utils.is.element(this.elements.settings.panes.quality)) { @@ -642,9 +641,10 @@ const controls = { const type = 'quality'; 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)) { - 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 diff --git a/src/js/html5.js b/src/js/html5.js index 63596cfc..fb2bc359 100644 --- a/src/js/html5.js +++ b/src/js/html5.js @@ -8,35 +8,21 @@ import utils from './utils'; const html5 = { getSources() { 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 getQualityOptions() { - if (!this.isHTML5) { - return null; - } - - // Get sources - const sources = html5.getSources.call(this); - - if (utils.is.empty(sources)) { - return null; - } - - // Get 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')))); + // Get sizes from elements + return html5.getSources.call(this) + .map(source => Number(source.getAttribute('size'))) + .filter(Boolean); }, extend() { @@ -51,53 +37,28 @@ const html5 = { get() { // Get sources const sources = html5.getSources.call(player); + const [source] = sources.filter(source => source.getAttribute('src') === player.source); - if (utils.is.empty(sources)) { - return null; - } - - 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')); + // Return size, if match is found + return source && Number(source.getAttribute('size')); }, set(input) { // Get sources 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; } - // 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 const { currentTime, playing } = player; // Set new source - player.media.src = supported[0].getAttribute('src'); + player.media.src = source.getAttribute('src'); // Restore time const onLoadedMetaData = () => { diff --git a/src/js/plugins/youtube.js b/src/js/plugins/youtube.js index 9b067c8a..f7458bcb 100644 --- a/src/js/plugins/youtube.js +++ b/src/js/plugins/youtube.js @@ -8,52 +8,26 @@ import utils from './../utils'; // Standardise YouTube quality unit function mapQualityUnit(input) { - switch (input) { - case 'hd2160': - return 2160; + const qualities = { + hd2160: 2160, + hd1440: 1440, + hd1080: 1080, + hd720: 720, + large: 480, + medium: 360, + small: 240, + tiny: 144, + }; - case 2160: - return 'hd2160'; + const entry = Object.entries(qualities) + .find(entry => entry.includes(input)); - case 'hd1440': - return 1440; - - 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'; + if (entry) { + // Get the match corresponding to the input + return entry.find(value => value !== input); } + + return 'default'; } function mapQualityUnits(levels) { @@ -328,15 +302,7 @@ const youtube = { return mapQualityUnit(instance.getPlaybackQuality()); }, set(input) { - const quality = input; - - // Set via API - instance.setPlaybackQuality(mapQualityUnit(quality)); - - // Trigger request event - utils.dispatchEvent.call(player, player.media, 'qualityrequested', false, { - quality, - }); + instance.setPlaybackQuality(mapQualityUnit(input)); }, }); diff --git a/src/js/plyr.js b/src/js/plyr.js index 0786334d..71ca363e 100644 --- a/src/js/plyr.js +++ b/src/js/plyr.js @@ -669,36 +669,31 @@ class Plyr { * @param {number} input - Quality level */ set quality(input) { - let quality = null; + const config = this.config.quality; + const options = this.options.quality; - if (!utils.is.empty(input)) { - 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) { + if (!options.length) { return; } - if (!this.options.quality.includes(quality)) { - const closest = utils.closest(this.options.quality, quality); + let 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`); quality = closest; } + // Trigger request event + utils.dispatchEvent.call(this, this.media, 'qualityrequested', false, { quality }); + // Update config - this.config.quality.selected = quality; + config.selected = quality; // Set quality this.media.quality = quality;