diff options
Diffstat (limited to 'src/js/html5.js')
-rw-r--r-- | src/js/html5.js | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/src/js/html5.js b/src/js/html5.js new file mode 100644 index 00000000..3818a441 --- /dev/null +++ b/src/js/html5.js @@ -0,0 +1,146 @@ +// ========================================================================== +// Plyr HTML5 helpers +// ========================================================================== + +import support from './support'; +import utils from './utils'; + +const html5 = { + getSources() { + if (!this.isHTML5) { + return null; + } + + return this.media.querySelectorAll('source'); + }, + + // 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 <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() { + if (!this.isHTML5) { + return; + } + + const player = this; + + // Quality + Object.defineProperty(player.media, 'quality', { + get() { + // Get sources + const sources = html5.getSources.call(player); + + 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')); + }, + set(input) { + // Get sources + const sources = html5.getSources.call(player); + + if (utils.is.empty(sources)) { + 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'); + + // Load new source + player.media.load(); + + // Resume playing + if (playing) { + player.play(); + } + + // Restore time + player.currentTime = currentTime; + + // Trigger change event + utils.dispatchEvent.call(player, player.media, 'qualitychange', false, { + quality: input, + }); + }, + }); + }, + + // Cancel current network requests + // See https://github.com/sampotts/plyr/issues/174 + cancelRequests() { + if (!this.isHTML5) { + return; + } + + // Remove child sources + utils.removeElement(html5.getSources()); + + // Set blank video src attribute + // This is to prevent a MEDIA_ERR_SRC_NOT_SUPPORTED error + // Info: http://stackoverflow.com/questions/32231579/how-to-properly-dispose-of-an-html5-video-and-close-socket-or-connection + this.media.setAttribute('src', this.config.blankVideo); + + // Load the new empty source + // This will cancel existing requests + // See https://github.com/sampotts/plyr/issues/174 + this.media.load(); + + // Debugging + this.debug.log('Cancelled network requests'); + }, +}; + +export default html5; |