mirror of
https://github.com/videojs/video.js.git
synced 2025-07-15 01:34:23 +02:00
refactor: unify all Track and TrackList APIs (#3783)
Unify all track-related usage internally. BREAKING CHANGE: some externally accessibly functions for tracks are now private.
This commit is contained in:
committed by
Gary Katsevman
parent
7bafcc2a55
commit
49bed07039
@ -22,7 +22,7 @@ class AudioTrackButton extends TrackButton {
|
|||||||
* The key/value store of player options.
|
* The key/value store of player options.
|
||||||
*/
|
*/
|
||||||
constructor(player, options = {}) {
|
constructor(player, options = {}) {
|
||||||
options.tracks = player.audioTracks && player.audioTracks();
|
options.tracks = player.audioTracks();
|
||||||
|
|
||||||
super(player, options);
|
super(player, options);
|
||||||
|
|
||||||
@ -49,11 +49,7 @@ class AudioTrackButton extends TrackButton {
|
|||||||
* An array of menu items
|
* An array of menu items
|
||||||
*/
|
*/
|
||||||
createItems(items = []) {
|
createItems(items = []) {
|
||||||
const tracks = this.player_.audioTracks && this.player_.audioTracks();
|
const tracks = this.player_.audioTracks();
|
||||||
|
|
||||||
if (!tracks) {
|
|
||||||
return items;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < tracks.length; i++) {
|
for (let i = 0; i < tracks.length; i++) {
|
||||||
const track = tracks[i];
|
const track = tracks[i];
|
||||||
|
@ -33,14 +33,12 @@ class AudioTrackMenuItem extends MenuItem {
|
|||||||
|
|
||||||
this.track = track;
|
this.track = track;
|
||||||
|
|
||||||
if (tracks) {
|
const changeHandler = Fn.bind(this, this.handleTracksChange);
|
||||||
const changeHandler = Fn.bind(this, this.handleTracksChange);
|
|
||||||
|
|
||||||
tracks.addEventListener('change', changeHandler);
|
tracks.addEventListener('change', changeHandler);
|
||||||
this.on('dispose', () => {
|
this.on('dispose', () => {
|
||||||
tracks.removeEventListener('change', changeHandler);
|
tracks.removeEventListener('change', changeHandler);
|
||||||
});
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -59,10 +57,6 @@ class AudioTrackMenuItem extends MenuItem {
|
|||||||
|
|
||||||
super.handleClick(event);
|
super.handleClick(event);
|
||||||
|
|
||||||
if (!tracks) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < tracks.length; i++) {
|
for (let i = 0; i < tracks.length; i++) {
|
||||||
const track = tracks[i];
|
const track = tracks[i];
|
||||||
|
|
||||||
|
@ -29,15 +29,12 @@ class DescriptionsButton extends TextTrackButton {
|
|||||||
this.el_.setAttribute('aria-label', 'Descriptions Menu');
|
this.el_.setAttribute('aria-label', 'Descriptions Menu');
|
||||||
|
|
||||||
const tracks = player.textTracks();
|
const tracks = player.textTracks();
|
||||||
|
const changeHandler = Fn.bind(this, this.handleTracksChange);
|
||||||
|
|
||||||
if (tracks) {
|
tracks.addEventListener('change', changeHandler);
|
||||||
const changeHandler = Fn.bind(this, this.handleTracksChange);
|
this.on('dispose', function() {
|
||||||
|
tracks.removeEventListener('change', changeHandler);
|
||||||
tracks.addEventListener('change', changeHandler);
|
});
|
||||||
this.on('dispose', function() {
|
|
||||||
tracks.removeEventListener('change', changeHandler);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -43,10 +43,6 @@ class TextTrackButton extends TrackButton {
|
|||||||
|
|
||||||
const tracks = this.player_.textTracks();
|
const tracks = this.player_.textTracks();
|
||||||
|
|
||||||
if (!tracks) {
|
|
||||||
return items;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < tracks.length; i++) {
|
for (let i = 0; i < tracks.length; i++) {
|
||||||
const track = tracks[i];
|
const track = tracks[i];
|
||||||
|
|
||||||
|
@ -34,15 +34,12 @@ class TextTrackMenuItem extends MenuItem {
|
|||||||
super(player, options);
|
super(player, options);
|
||||||
|
|
||||||
this.track = track;
|
this.track = track;
|
||||||
|
const changeHandler = Fn.bind(this, this.handleTracksChange);
|
||||||
|
|
||||||
if (tracks) {
|
tracks.addEventListener('change', changeHandler);
|
||||||
const changeHandler = Fn.bind(this, this.handleTracksChange);
|
this.on('dispose', function() {
|
||||||
|
tracks.removeEventListener('change', changeHandler);
|
||||||
tracks.addEventListener('change', changeHandler);
|
});
|
||||||
this.on('dispose', function() {
|
|
||||||
tracks.removeEventListener('change', changeHandler);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// iOS7 doesn't dispatch change events to TextTrackLists when an
|
// iOS7 doesn't dispatch change events to TextTrackLists when an
|
||||||
// associated track's mode changes. Without something like
|
// associated track's mode changes. Without something like
|
||||||
@ -50,7 +47,7 @@ class TextTrackMenuItem extends MenuItem {
|
|||||||
// possible to detect changes to the mode attribute and polyfill
|
// possible to detect changes to the mode attribute and polyfill
|
||||||
// the change event. As a poor substitute, we manually dispatch
|
// the change event. As a poor substitute, we manually dispatch
|
||||||
// change events whenever the controls modify the mode.
|
// change events whenever the controls modify the mode.
|
||||||
if (tracks && tracks.onchange === undefined) {
|
if (tracks.onchange === undefined) {
|
||||||
let event;
|
let event;
|
||||||
|
|
||||||
this.on(['tap', 'click'], function() {
|
this.on(['tap', 'click'], function() {
|
||||||
|
186
src/js/player.js
186
src/js/player.js
@ -25,8 +25,7 @@ import mergeOptions from './utils/merge-options.js';
|
|||||||
import textTrackConverter from './tracks/text-track-list-converter.js';
|
import textTrackConverter from './tracks/text-track-list-converter.js';
|
||||||
import ModalDialog from './modal-dialog';
|
import ModalDialog from './modal-dialog';
|
||||||
import Tech from './tech/tech.js';
|
import Tech from './tech/tech.js';
|
||||||
import AudioTrackList from './tracks/audio-track-list.js';
|
import {ALL as TRACK_TYPES} from './tracks/track-types';
|
||||||
import VideoTrackList from './tracks/video-track-list.js';
|
|
||||||
|
|
||||||
// The following imports are used only to ensure that the corresponding modules
|
// The following imports are used only to ensure that the corresponding modules
|
||||||
// are always included in the video.js package. Importing the modules will
|
// are always included in the video.js package. Importing the modules will
|
||||||
@ -809,14 +808,11 @@ class Player extends Component {
|
|||||||
this.isReady_ = false;
|
this.isReady_ = false;
|
||||||
|
|
||||||
// Grab tech-specific options from player options and add source and parent element to use.
|
// Grab tech-specific options from player options and add source and parent element to use.
|
||||||
const techOptions = assign({
|
const techOptions = {
|
||||||
source,
|
source,
|
||||||
'nativeControlsForTouch': this.options_.nativeControlsForTouch,
|
'nativeControlsForTouch': this.options_.nativeControlsForTouch,
|
||||||
'playerId': this.id(),
|
'playerId': this.id(),
|
||||||
'techId': `${this.id()}_${techName}_api`,
|
'techId': `${this.id()}_${techName}_api`,
|
||||||
'videoTracks': this.videoTracks_,
|
|
||||||
'textTracks': this.textTracks_,
|
|
||||||
'audioTracks': this.audioTracks_,
|
|
||||||
'autoplay': this.options_.autoplay,
|
'autoplay': this.options_.autoplay,
|
||||||
'preload': this.options_.preload,
|
'preload': this.options_.preload,
|
||||||
'loop': this.options_.loop,
|
'loop': this.options_.loop,
|
||||||
@ -825,7 +821,15 @@ class Player extends Component {
|
|||||||
'language': this.language(),
|
'language': this.language(),
|
||||||
'playerElIngest': this.playerElIngest_ || false,
|
'playerElIngest': this.playerElIngest_ || false,
|
||||||
'vtt.js': this.options_['vtt.js']
|
'vtt.js': this.options_['vtt.js']
|
||||||
}, this.options_[techName.toLowerCase()]);
|
};
|
||||||
|
|
||||||
|
TRACK_TYPES.names.forEach((name) => {
|
||||||
|
const props = TRACK_TYPES[name];
|
||||||
|
|
||||||
|
techOptions[props.getterName] = this[props.privateName];
|
||||||
|
});
|
||||||
|
|
||||||
|
assign(techOptions, this.options_[techName.toLowerCase()]);
|
||||||
|
|
||||||
if (this.tag) {
|
if (this.tag) {
|
||||||
techOptions.tag = this.tag;
|
techOptions.tag = this.tag;
|
||||||
@ -906,9 +910,11 @@ class Player extends Component {
|
|||||||
*/
|
*/
|
||||||
unloadTech_() {
|
unloadTech_() {
|
||||||
// Save the current text tracks so that we can reuse the same text tracks with the next tech
|
// Save the current text tracks so that we can reuse the same text tracks with the next tech
|
||||||
this.videoTracks_ = this.videoTracks();
|
TRACK_TYPES.names.forEach((name) => {
|
||||||
this.textTracks_ = this.textTracks();
|
const props = TRACK_TYPES[name];
|
||||||
this.audioTracks_ = this.audioTracks();
|
|
||||||
|
this[props.privateName] = this[props.getterName]();
|
||||||
|
});
|
||||||
this.textTracksJson_ = textTrackConverter.textTracksToJson(this.tech_);
|
this.textTracksJson_ = textTrackConverter.textTracksToJson(this.tech_);
|
||||||
|
|
||||||
this.isReady_ = false;
|
this.isReady_ = false;
|
||||||
@ -2841,102 +2847,6 @@ class Player extends Component {
|
|||||||
return !!this.isAudio_;
|
return !!this.isAudio_;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the {@link VideoTrackList}
|
|
||||||
*
|
|
||||||
* @see https://html.spec.whatwg.org/multipage/embedded-content.html#videotracklist
|
|
||||||
*
|
|
||||||
* @return {VideoTrackList}
|
|
||||||
* the current video track list
|
|
||||||
*/
|
|
||||||
videoTracks() {
|
|
||||||
// if we have not yet loadTech_, we create videoTracks_
|
|
||||||
// these will be passed to the tech during loading
|
|
||||||
if (!this.tech_) {
|
|
||||||
this.videoTracks_ = this.videoTracks_ || new VideoTrackList();
|
|
||||||
return this.videoTracks_;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.tech_.videoTracks();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the {@link AudioTrackList}
|
|
||||||
*
|
|
||||||
* @see https://html.spec.whatwg.org/multipage/embedded-content.html#audiotracklist
|
|
||||||
*
|
|
||||||
* @return {AudioTrackList}
|
|
||||||
* the current audio track list
|
|
||||||
*/
|
|
||||||
audioTracks() {
|
|
||||||
// if we have not yet loadTech_, we create videoTracks_
|
|
||||||
// these will be passed to the tech during loading
|
|
||||||
if (!this.tech_) {
|
|
||||||
this.audioTracks_ = this.audioTracks_ || new AudioTrackList();
|
|
||||||
return this.audioTracks_;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.tech_.audioTracks();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the {@link TextTrackList}
|
|
||||||
*
|
|
||||||
* Text tracks are tracks of timed text events.
|
|
||||||
* - Captions: text displayed over the video
|
|
||||||
* for the hearing impaired
|
|
||||||
* - Subtitles: text displayed over the video for
|
|
||||||
* those who don't understand language in the video
|
|
||||||
* - Chapters: text displayed in a menu allowing the user to jump
|
|
||||||
* to particular points (chapters) in the video
|
|
||||||
* - Descriptions: (not yet implemented) audio descriptions that are read back to
|
|
||||||
* the user by a screen reading device
|
|
||||||
*
|
|
||||||
* @see http://www.w3.org/html/wg/drafts/html/master/embedded-content-0.html#dom-media-texttracks
|
|
||||||
*
|
|
||||||
* @return {TextTrackList|undefined}
|
|
||||||
* The current TextTrackList or undefined if
|
|
||||||
* or undefined if we don't have a tech
|
|
||||||
*/
|
|
||||||
textTracks() {
|
|
||||||
// cannot use techGet_ directly because it checks to see whether the tech is ready.
|
|
||||||
// Flash is unlikely to be ready in time but textTracks should still work.
|
|
||||||
if (this.tech_) {
|
|
||||||
return this.tech_.textTracks();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the "remote" {@link TextTrackList}. Remote Text Tracks
|
|
||||||
* are tracks that were added to the HTML video element and can
|
|
||||||
* be removed, whereas normal texttracks cannot be removed.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @return {TextTrackList|undefined}
|
|
||||||
* The current remote text track list or undefined
|
|
||||||
* if we don't have a tech
|
|
||||||
*/
|
|
||||||
remoteTextTracks() {
|
|
||||||
if (this.tech_) {
|
|
||||||
return this.tech_.remoteTextTracks();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the "remote" {@link HTMLTrackElementList}.
|
|
||||||
* This gives the user all of the DOM elements that match up
|
|
||||||
* with the remote {@link TextTrackList}.
|
|
||||||
*
|
|
||||||
* @return {HTMLTrackElementList}
|
|
||||||
* The current remote text track list elements
|
|
||||||
* or undefined if we don't have a tech
|
|
||||||
*/
|
|
||||||
remoteTextTrackEls() {
|
|
||||||
if (this.tech_) {
|
|
||||||
return this.tech_.remoteTextTrackEls();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A helper method for adding a {@link TextTrack} to our
|
* A helper method for adding a {@link TextTrack} to our
|
||||||
* {@link TextTrackList}.
|
* {@link TextTrackList}.
|
||||||
@ -3194,6 +3104,70 @@ class Player extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the {@link VideoTrackList}
|
||||||
|
* @link https://html.spec.whatwg.org/multipage/embedded-content.html#videotracklist
|
||||||
|
*
|
||||||
|
* @return {VideoTrackList}
|
||||||
|
* the current video track list
|
||||||
|
*
|
||||||
|
* @method Player.prototype.videoTracks
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the {@link AudioTrackList}
|
||||||
|
* @link https://html.spec.whatwg.org/multipage/embedded-content.html#audiotracklist
|
||||||
|
*
|
||||||
|
* @return {AudioTrackList}
|
||||||
|
* the current audio track list
|
||||||
|
*
|
||||||
|
* @method Player.prototype.audioTracks
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the {@link TextTrackList}
|
||||||
|
*
|
||||||
|
* @link http://www.w3.org/html/wg/drafts/html/master/embedded-content-0.html#dom-media-texttracks
|
||||||
|
*
|
||||||
|
* @return {TextTrackList}
|
||||||
|
* the current text track list
|
||||||
|
*
|
||||||
|
* @method Player.prototype.textTracks
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the remote {@link TextTrackList}
|
||||||
|
*
|
||||||
|
* @return {TextTrackList}
|
||||||
|
* The current remote text track list
|
||||||
|
*
|
||||||
|
* @method Player.prototype.textTracks
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the remote {@link HTMLTrackElementList} tracks.
|
||||||
|
*
|
||||||
|
* @return {HTMLTrackElementList}
|
||||||
|
* The current remote text track element list
|
||||||
|
*
|
||||||
|
* @method Player.prototype.remoteTextTrackEls
|
||||||
|
*/
|
||||||
|
|
||||||
|
TRACK_TYPES.names.forEach(function(name) {
|
||||||
|
const props = TRACK_TYPES[name];
|
||||||
|
|
||||||
|
Player.prototype[props.getterName] = function() {
|
||||||
|
if (this.tech_) {
|
||||||
|
return this.tech_[props.getterName]();
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we have not yet loadTech_, we create {video,audio,text}Tracks_
|
||||||
|
// these will be passed to the tech during loading
|
||||||
|
this[props.privateName] = this[props.privateName] || new props.ListClass();
|
||||||
|
return this[props.privateName];
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Global player list
|
* Global player list
|
||||||
*
|
*
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
import Tech from './tech.js';
|
import Tech from './tech.js';
|
||||||
import * as Dom from '../utils/dom.js';
|
import * as Dom from '../utils/dom.js';
|
||||||
import * as Url from '../utils/url.js';
|
import * as Url from '../utils/url.js';
|
||||||
import * as Fn from '../utils/fn.js';
|
|
||||||
import log from '../utils/log.js';
|
import log from '../utils/log.js';
|
||||||
import tsml from 'tsml';
|
import tsml from 'tsml';
|
||||||
import * as browser from '../utils/browser.js';
|
import * as browser from '../utils/browser.js';
|
||||||
@ -13,6 +12,7 @@ import window from 'global/window';
|
|||||||
import {assign} from '../utils/obj';
|
import {assign} from '../utils/obj';
|
||||||
import mergeOptions from '../utils/merge-options.js';
|
import mergeOptions from '../utils/merge-options.js';
|
||||||
import toTitleCase from '../utils/to-title-case.js';
|
import toTitleCase from '../utils/to-title-case.js';
|
||||||
|
import {NORMAL as TRACK_TYPES} from '../tracks/track-types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HTML5 Media Controller - Wrapper for HTML5 Media API
|
* HTML5 Media Controller - Wrapper for HTML5 Media API
|
||||||
@ -67,7 +67,7 @@ class Html5 extends Tech {
|
|||||||
} else {
|
} else {
|
||||||
// store HTMLTrackElement and TextTrack to remote list
|
// store HTMLTrackElement and TextTrack to remote list
|
||||||
this.remoteTextTrackEls().addTrackElement_(node);
|
this.remoteTextTrackEls().addTrackElement_(node);
|
||||||
this.remoteTextTracks().addTrack_(node.track);
|
this.remoteTextTracks().addTrack(node.track);
|
||||||
if (!crossoriginTracks &&
|
if (!crossoriginTracks &&
|
||||||
!this.el_.hasAttribute('crossorigin') &&
|
!this.el_.hasAttribute('crossorigin') &&
|
||||||
Url.isCrossOrigin(node.src)) {
|
Url.isCrossOrigin(node.src)) {
|
||||||
@ -82,52 +82,10 @@ class Html5 extends Tech {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: add text tracks into this list
|
this.proxyNativeTracks_();
|
||||||
const trackTypes = ['audio', 'video'];
|
if (this.featuresNativeTextTracks && crossoriginTracks) {
|
||||||
|
log.warn(tsml`Text Tracks are being loaded from another origin but the crossorigin attribute isn't used.
|
||||||
// ProxyNative Video/Audio Track
|
|
||||||
trackTypes.forEach((type) => {
|
|
||||||
const elTracks = this.el()[`${type}Tracks`];
|
|
||||||
const techTracks = this[`${type}Tracks`]();
|
|
||||||
const capitalType = toTitleCase(type);
|
|
||||||
|
|
||||||
if (!this[`featuresNative${capitalType}Tracks`] ||
|
|
||||||
!elTracks ||
|
|
||||||
!elTracks.addEventListener) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this[`handle${capitalType}TrackChange_`] = (e) => {
|
|
||||||
techTracks.trigger({
|
|
||||||
type: 'change',
|
|
||||||
target: techTracks,
|
|
||||||
currentTarget: techTracks,
|
|
||||||
srcElement: techTracks
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
this[`handle${capitalType}TrackAdd_`] = (e) => techTracks.addTrack(e.track);
|
|
||||||
this[`handle${capitalType}TrackRemove_`] = (e) => techTracks.removeTrack(e.track);
|
|
||||||
|
|
||||||
elTracks.addEventListener('change', this[`handle${capitalType}TrackChange_`]);
|
|
||||||
elTracks.addEventListener('addtrack', this[`handle${capitalType}TrackAdd_`]);
|
|
||||||
elTracks.addEventListener('removetrack', this[`handle${capitalType}TrackRemove_`]);
|
|
||||||
this[`removeOld${capitalType}Tracks_`] = (e) => this.removeOldTracks_(techTracks, elTracks);
|
|
||||||
|
|
||||||
// Remove (native) tracks that are not used anymore
|
|
||||||
this.on('loadstart', this[`removeOld${capitalType}Tracks_`]);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (this.featuresNativeTextTracks) {
|
|
||||||
if (crossoriginTracks) {
|
|
||||||
log.warn(tsml`Text Tracks are being loaded from another origin but the crossorigin attribute isn't used.
|
|
||||||
This may prevent text tracks from loading.`);
|
This may prevent text tracks from loading.`);
|
||||||
}
|
|
||||||
|
|
||||||
this.handleTextTrackChange_ = Fn.bind(this, this.handleTextTrackChange);
|
|
||||||
this.handleTextTrackAdd_ = Fn.bind(this, this.handleTextTrackAdd);
|
|
||||||
this.handleTextTrackRemove_ = Fn.bind(this, this.handleTextTrackRemove);
|
|
||||||
this.proxyNativeTextTracks_();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine if native controls should be used
|
// Determine if native controls should be used
|
||||||
@ -150,28 +108,81 @@ class Html5 extends Tech {
|
|||||||
* Dispose of `HTML5` media element and remove all tracks.
|
* Dispose of `HTML5` media element and remove all tracks.
|
||||||
*/
|
*/
|
||||||
dispose() {
|
dispose() {
|
||||||
// Un-ProxyNativeTracks
|
|
||||||
['audio', 'video', 'text'].forEach((type) => {
|
|
||||||
const capitalType = toTitleCase(type);
|
|
||||||
const tl = this.el_[`${type}Tracks`];
|
|
||||||
|
|
||||||
if (tl && tl.removeEventListener) {
|
|
||||||
tl.removeEventListener('change', this[`handle${capitalType}TrackChange_`]);
|
|
||||||
tl.removeEventListener('addtrack', this[`handle${capitalType}TrackAdd_`]);
|
|
||||||
tl.removeEventListener('removetrack', this[`handle${capitalType}TrackRemove_`]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stop removing old text tracks
|
|
||||||
if (tl) {
|
|
||||||
this.off('loadstart', this[`removeOld${capitalType}Tracks_`]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Html5.disposeMediaElement(this.el_);
|
Html5.disposeMediaElement(this.el_);
|
||||||
// tech will handle clearing of the emulated track list
|
// tech will handle clearing of the emulated track list
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Proxy all native track list events to our track lists if the browser we are playing
|
||||||
|
* in supports that type of track list.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
proxyNativeTracks_() {
|
||||||
|
TRACK_TYPES.names.forEach((name) => {
|
||||||
|
const props = TRACK_TYPES[name];
|
||||||
|
const elTracks = this.el()[props.getterName];
|
||||||
|
const techTracks = this[props.getterName]();
|
||||||
|
|
||||||
|
if (!this[`featuresNative${props.capitalName}Tracks`] ||
|
||||||
|
!elTracks ||
|
||||||
|
!elTracks.addEventListener) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const listeners = {
|
||||||
|
change(e) {
|
||||||
|
techTracks.trigger({
|
||||||
|
type: 'change',
|
||||||
|
target: techTracks,
|
||||||
|
currentTarget: techTracks,
|
||||||
|
srcElement: techTracks
|
||||||
|
});
|
||||||
|
},
|
||||||
|
addtrack(e) {
|
||||||
|
techTracks.addTrack(e.track);
|
||||||
|
},
|
||||||
|
removetrack(e) {
|
||||||
|
techTracks.removeTrack(e.track);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const removeOldTracks = function() {
|
||||||
|
const removeTracks = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < techTracks.length; i++) {
|
||||||
|
let found = false;
|
||||||
|
|
||||||
|
for (let j = 0; j < elTracks.length; j++) {
|
||||||
|
if (elTracks[j] === techTracks[i]) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
removeTracks.push(techTracks[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (removeTracks.length) {
|
||||||
|
techTracks.removeTrack(removeTracks.shift());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Object.keys(listeners).forEach((eventName) => {
|
||||||
|
const listener = listeners[eventName];
|
||||||
|
|
||||||
|
elTracks.addEventListener(eventName, listener);
|
||||||
|
this.on('dispose', (e) => elTracks.removeEventListener(eventName, listener));
|
||||||
|
});
|
||||||
|
|
||||||
|
// Remove (native) tracks that are not used anymore
|
||||||
|
this.on('loadstart', removeOldTracks);
|
||||||
|
this.on('dispose', (e) => this.off('loadstart', removeOldTracks));
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create the `Html5` Tech's DOM element.
|
* Create the `Html5` Tech's DOM element.
|
||||||
*
|
*
|
||||||
@ -331,130 +342,18 @@ class Html5 extends Tech {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add event listeners to native text track events. This adds the native text tracks
|
* Called by {@link Player#play} to play using the `Html5` `Tech`.
|
||||||
* to our emulated {@link TextTrackList}.
|
|
||||||
*/
|
*/
|
||||||
proxyNativeTextTracks_() {
|
play() {
|
||||||
const tt = this.el().textTracks;
|
const playPromise = this.el_.play();
|
||||||
|
|
||||||
if (tt) {
|
// Catch/silence error when a pause interrupts a play request
|
||||||
// Add tracks - if player is initialised after DOM loaded, textTracks
|
// on browsers which return a promise
|
||||||
// will not trigger addtrack
|
if (playPromise !== undefined && typeof playPromise.then === 'function') {
|
||||||
for (let i = 0; i < tt.length; i++) {
|
playPromise.then(null, (e) => {});
|
||||||
this.textTracks().addTrack_(tt[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tt.addEventListener) {
|
|
||||||
tt.addEventListener('change', this.handleTextTrackChange_);
|
|
||||||
tt.addEventListener('addtrack', this.handleTextTrackAdd_);
|
|
||||||
tt.addEventListener('removetrack', this.handleTextTrackRemove_);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove (native) texttracks that are not used anymore
|
|
||||||
this.on('loadstart', this.removeOldTextTracks_);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle any {@link TextTrackList} `change` event.
|
|
||||||
*
|
|
||||||
* @param {EventTarget~Event} e
|
|
||||||
* The `change` event that caused this to run.
|
|
||||||
*
|
|
||||||
* @listens TextTrackList#change
|
|
||||||
*/
|
|
||||||
handleTextTrackChange(e) {
|
|
||||||
const tt = this.textTracks();
|
|
||||||
|
|
||||||
this.textTracks().trigger({
|
|
||||||
type: 'change',
|
|
||||||
target: tt,
|
|
||||||
currentTarget: tt,
|
|
||||||
srcElement: tt
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle any {@link TextTrackList} `addtrack` event.
|
|
||||||
*
|
|
||||||
* @param {EventTarget~Event} e
|
|
||||||
* The `addtrack` event that caused this to run.
|
|
||||||
*
|
|
||||||
* @listens TextTrackList#addtrack
|
|
||||||
*/
|
|
||||||
handleTextTrackAdd(e) {
|
|
||||||
this.textTracks().addTrack_(e.track);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle any {@link TextTrackList} `removetrack` event.
|
|
||||||
*
|
|
||||||
* @param {EventTarget~Event} e
|
|
||||||
* The `removetrack` event that caused this to run.
|
|
||||||
*
|
|
||||||
* @listens TextTrackList#removetrack
|
|
||||||
*/
|
|
||||||
handleTextTrackRemove(e) {
|
|
||||||
this.textTracks().removeTrack_(e.track);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function removes any {@link AudioTrack}s, {@link VideoTrack}s, or
|
|
||||||
* {@link TextTrack}s that are not in the media elements TrackList.
|
|
||||||
*
|
|
||||||
* @param {TrackList} techTracks
|
|
||||||
* HTML5 Tech's TrackList to search through
|
|
||||||
*
|
|
||||||
* @param {TrackList} elTracks
|
|
||||||
* HTML5 media elements TrackList to search trough.
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
removeOldTracks_(techTracks, elTracks) {
|
|
||||||
// This will loop over the techTracks and check if they are still used by the HTML5 media element
|
|
||||||
// If not, they will be removed from the emulated list
|
|
||||||
const removeTracks = [];
|
|
||||||
|
|
||||||
if (!elTracks) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < techTracks.length; i++) {
|
|
||||||
const techTrack = techTracks[i];
|
|
||||||
let found = false;
|
|
||||||
|
|
||||||
for (let j = 0; j < elTracks.length; j++) {
|
|
||||||
if (elTracks[j] === techTrack) {
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found) {
|
|
||||||
removeTracks.push(techTrack);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < removeTracks.length; i++) {
|
|
||||||
const track = removeTracks[i];
|
|
||||||
|
|
||||||
techTracks.removeTrack_(track);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove {@link TextTrack}s that dont exist in the native track list from our
|
|
||||||
* emulated {@link TextTrackList}.
|
|
||||||
*
|
|
||||||
* @listens Tech#loadstart
|
|
||||||
*/
|
|
||||||
removeOldTextTracks_(e) {
|
|
||||||
const techTracks = this.textTracks();
|
|
||||||
const elTracks = this.el().textTracks;
|
|
||||||
|
|
||||||
this.removeOldTracks_(techTracks, elTracks);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set current time for the `HTML5` tech.
|
* Set current time for the `HTML5` tech.
|
||||||
*
|
*
|
||||||
|
@ -3,13 +3,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import Component from '../component';
|
import Component from '../component';
|
||||||
import HTMLTrackElement from '../tracks/html-track-element';
|
|
||||||
import HTMLTrackElementList from '../tracks/html-track-element-list';
|
|
||||||
import mergeOptions from '../utils/merge-options.js';
|
import mergeOptions from '../utils/merge-options.js';
|
||||||
import TextTrack from '../tracks/text-track';
|
|
||||||
import TextTrackList from '../tracks/text-track-list';
|
|
||||||
import VideoTrackList from '../tracks/video-track-list';
|
|
||||||
import AudioTrackList from '../tracks/audio-track-list';
|
|
||||||
import * as Fn from '../utils/fn.js';
|
import * as Fn from '../utils/fn.js';
|
||||||
import log from '../utils/log.js';
|
import log from '../utils/log.js';
|
||||||
import { createTimeRange } from '../utils/time-ranges.js';
|
import { createTimeRange } from '../utils/time-ranges.js';
|
||||||
@ -18,6 +12,7 @@ import MediaError from '../media-error.js';
|
|||||||
import window from 'global/window';
|
import window from 'global/window';
|
||||||
import document from 'global/document';
|
import document from 'global/document';
|
||||||
import {isPlain} from '../utils/obj';
|
import {isPlain} from '../utils/obj';
|
||||||
|
import * as TRACK_TYPES from '../tracks/track-types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An Object containing a structure like: `{src: 'url', type: 'mimetype'}` or string
|
* An Object containing a structure like: `{src: 'url', type: 'mimetype'}` or string
|
||||||
@ -68,9 +63,9 @@ function createTrackHelper(self, kind, label, language, options = {}) {
|
|||||||
}
|
}
|
||||||
options.tech = self;
|
options.tech = self;
|
||||||
|
|
||||||
const track = new TextTrack(options);
|
const track = new TRACK_TYPES.ALL.text.TrackClass(options);
|
||||||
|
|
||||||
tracks.addTrack_(track);
|
tracks.addTrack(track);
|
||||||
|
|
||||||
return track;
|
return track;
|
||||||
}
|
}
|
||||||
@ -108,9 +103,13 @@ class Tech extends Component {
|
|||||||
this.hasStarted_ = false;
|
this.hasStarted_ = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.textTracks_ = options.textTracks;
|
TRACK_TYPES.ALL.names.forEach((name) => {
|
||||||
this.videoTracks_ = options.videoTracks;
|
const props = TRACK_TYPES.ALL[name];
|
||||||
this.audioTracks_ = options.audioTracks;
|
|
||||||
|
if (options && options[props.getterName]) {
|
||||||
|
this[props.privateName] = options[props.getterName];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Manually track progress in cases where the browser/flash player doesn't report it.
|
// Manually track progress in cases where the browser/flash player doesn't report it.
|
||||||
if (!this.featuresProgressEvents) {
|
if (!this.featuresProgressEvents) {
|
||||||
@ -136,9 +135,8 @@ class Tech extends Component {
|
|||||||
this.emulateTextTracks();
|
this.emulateTextTracks();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.autoRemoteTextTracks_ = new TextTrackList();
|
this.autoRemoteTextTracks_ = new TRACK_TYPES.ALL.text.ListClass();
|
||||||
|
|
||||||
this.initTextTrackListeners();
|
|
||||||
this.initTrackListeners();
|
this.initTrackListeners();
|
||||||
|
|
||||||
// Turn on component tap events only if not using native controls
|
// Turn on component tap events only if not using native controls
|
||||||
@ -332,7 +330,7 @@ class Tech extends Component {
|
|||||||
dispose() {
|
dispose() {
|
||||||
|
|
||||||
// clear out all tracks because we can't reuse them between techs
|
// clear out all tracks because we can't reuse them between techs
|
||||||
this.clearTracks(['audio', 'video', 'text']);
|
this.clearTracks(TRACK_TYPES.NORMAL.names);
|
||||||
|
|
||||||
// Turn off any manual progress or timeupdate tracking
|
// Turn off any manual progress or timeupdate tracking
|
||||||
if (this.manualProgress) {
|
if (this.manualProgress) {
|
||||||
@ -369,7 +367,7 @@ class Tech extends Component {
|
|||||||
if (type === 'text') {
|
if (type === 'text') {
|
||||||
this.removeRemoteTextTrack(track);
|
this.removeRemoteTextTrack(track);
|
||||||
}
|
}
|
||||||
list.removeTrack_(track);
|
list.removeTrack(track);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -450,49 +448,16 @@ class Tech extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Turn on listeners for {@link TextTrackList} events. This adds
|
* Turn on listeners for {@link VideoTrackList}, {@link {AudioTrackList}, and
|
||||||
* {@link EventTarget~EventListeners} for `texttrackchange`, `addtrack` and
|
* {@link TextTrackList} events.
|
||||||
* `removetrack`.
|
|
||||||
*
|
*
|
||||||
* @fires Tech#texttrackchange
|
|
||||||
*/
|
|
||||||
initTextTrackListeners() {
|
|
||||||
const textTrackListChanges = Fn.bind(this, function() {
|
|
||||||
/**
|
|
||||||
* Triggered when tracks are added or removed on the Tech {@link TextTrackList}
|
|
||||||
*
|
|
||||||
* @event Tech#texttrackchange
|
|
||||||
* @type {EventTarget~Event}
|
|
||||||
*/
|
|
||||||
this.trigger('texttrackchange');
|
|
||||||
});
|
|
||||||
|
|
||||||
const tracks = this.textTracks();
|
|
||||||
|
|
||||||
if (!tracks) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
tracks.addEventListener('removetrack', textTrackListChanges);
|
|
||||||
tracks.addEventListener('addtrack', textTrackListChanges);
|
|
||||||
|
|
||||||
this.on('dispose', Fn.bind(this, function() {
|
|
||||||
tracks.removeEventListener('removetrack', textTrackListChanges);
|
|
||||||
tracks.removeEventListener('addtrack', textTrackListChanges);
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Turn on listeners for {@link VideoTrackList} and {@link {AudioTrackList} events.
|
|
||||||
* This adds {@link EventTarget~EventListeners} for `addtrack`, and `removetrack`.
|
* This adds {@link EventTarget~EventListeners} for `addtrack`, and `removetrack`.
|
||||||
*
|
*
|
||||||
* @fires Tech#audiotrackchange
|
* @fires Tech#audiotrackchange
|
||||||
* @fires Tech#videotrackchange
|
* @fires Tech#videotrackchange
|
||||||
|
* @fires Tech#texttrackchange
|
||||||
*/
|
*/
|
||||||
initTrackListeners() {
|
initTrackListeners() {
|
||||||
const trackTypes = ['video', 'audio'];
|
|
||||||
|
|
||||||
trackTypes.forEach((type) => {
|
|
||||||
/**
|
/**
|
||||||
* Triggered when tracks are added or removed on the Tech {@link AudioTrackList}
|
* Triggered when tracks are added or removed on the Tech {@link AudioTrackList}
|
||||||
*
|
*
|
||||||
@ -506,11 +471,20 @@ class Tech extends Component {
|
|||||||
* @event Tech#videotrackchange
|
* @event Tech#videotrackchange
|
||||||
* @type {EventTarget~Event}
|
* @type {EventTarget~Event}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggered when tracks are added or removed on the Tech {@link TextTrackList}
|
||||||
|
*
|
||||||
|
* @event Tech#texttrackchange
|
||||||
|
* @type {EventTarget~Event}
|
||||||
|
*/
|
||||||
|
TRACK_TYPES.NORMAL.names.forEach((name) => {
|
||||||
|
const props = TRACK_TYPES.NORMAL[name];
|
||||||
const trackListChanges = () => {
|
const trackListChanges = () => {
|
||||||
this.trigger(`${type}trackchange`);
|
this.trigger(`${name}trackchange`);
|
||||||
};
|
};
|
||||||
|
|
||||||
const tracks = this[`${type}Tracks`]();
|
const tracks = this[props.getterName]();
|
||||||
|
|
||||||
tracks.addEventListener('removetrack', trackListChanges);
|
tracks.addEventListener('removetrack', trackListChanges);
|
||||||
tracks.addEventListener('addtrack', trackListChanges);
|
tracks.addEventListener('addtrack', trackListChanges);
|
||||||
@ -585,16 +559,12 @@ class Tech extends Component {
|
|||||||
emulateTextTracks() {
|
emulateTextTracks() {
|
||||||
const tracks = this.textTracks();
|
const tracks = this.textTracks();
|
||||||
|
|
||||||
if (!tracks) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.remoteTextTracks().on('addtrack', (e) => {
|
this.remoteTextTracks().on('addtrack', (e) => {
|
||||||
this.textTracks().addTrack_(e.track);
|
tracks.addTrack(e.track);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.remoteTextTracks().on('removetrack', (e) => {
|
this.remoteTextTracks().on('removetrack', (e) => {
|
||||||
this.textTracks().removeTrack_(e.track);
|
tracks.removeTrack(e.track);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Initially, Tech.el_ is a child of a dummy-div wait until the Component system
|
// Initially, Tech.el_ is a child of a dummy-div wait until the Component system
|
||||||
@ -624,63 +594,6 @@ class Tech extends Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the `Tech`s {@link VideoTrackList}.
|
|
||||||
*
|
|
||||||
* @return {VideoTrackList}
|
|
||||||
* The video track list that the Tech is currently using.
|
|
||||||
*/
|
|
||||||
videoTracks() {
|
|
||||||
this.videoTracks_ = this.videoTracks_ || new VideoTrackList();
|
|
||||||
return this.videoTracks_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the `Tech`s {@link AudioTrackList}.
|
|
||||||
*
|
|
||||||
* @return {AudioTrackList}
|
|
||||||
* The audio track list that the Tech is currently using.
|
|
||||||
*/
|
|
||||||
audioTracks() {
|
|
||||||
this.audioTracks_ = this.audioTracks_ || new AudioTrackList();
|
|
||||||
return this.audioTracks_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the `Tech`s {@link TextTrackList}.
|
|
||||||
*
|
|
||||||
* @return {TextTrackList}
|
|
||||||
* The text track list that the Tech is currently using.
|
|
||||||
*/
|
|
||||||
textTracks() {
|
|
||||||
this.textTracks_ = this.textTracks_ || new TextTrackList();
|
|
||||||
return this.textTracks_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the `Tech`s remote {@link TextTrackList}, which is created from elements
|
|
||||||
* that were added to the DOM.
|
|
||||||
*
|
|
||||||
* @return {TextTrackList}
|
|
||||||
* The remote text track list that the Tech is currently using.
|
|
||||||
*/
|
|
||||||
remoteTextTracks() {
|
|
||||||
this.remoteTextTracks_ = this.remoteTextTracks_ || new TextTrackList();
|
|
||||||
return this.remoteTextTracks_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get The `Tech`s {HTMLTrackElementList}, which are the elements in the DOM that are
|
|
||||||
* being used as TextTracks.
|
|
||||||
*
|
|
||||||
* @return {HTMLTrackElementList}
|
|
||||||
* The current HTML track elements that exist for the tech.
|
|
||||||
*/
|
|
||||||
remoteTextTrackEls() {
|
|
||||||
this.remoteTextTrackEls_ = this.remoteTextTrackEls_ || new HTMLTrackElementList();
|
|
||||||
return this.remoteTextTrackEls_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create and returns a remote {@link TextTrack} object.
|
* Create and returns a remote {@link TextTrack} object.
|
||||||
*
|
*
|
||||||
@ -730,7 +643,7 @@ class Tech extends Component {
|
|||||||
tech: this
|
tech: this
|
||||||
});
|
});
|
||||||
|
|
||||||
return new HTMLTrackElement(track);
|
return new TRACK_TYPES.REMOTE.remoteTextEl.TrackClass(track);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -764,11 +677,11 @@ class Tech extends Component {
|
|||||||
|
|
||||||
// store HTMLTrackElement and TextTrack to remote list
|
// store HTMLTrackElement and TextTrack to remote list
|
||||||
this.remoteTextTrackEls().addTrackElement_(htmlTrackElement);
|
this.remoteTextTrackEls().addTrackElement_(htmlTrackElement);
|
||||||
this.remoteTextTracks().addTrack_(htmlTrackElement.track);
|
this.remoteTextTracks().addTrack(htmlTrackElement.track);
|
||||||
|
|
||||||
if (manualCleanup !== true) {
|
if (manualCleanup !== true) {
|
||||||
// create the TextTrackList if it doesn't exist
|
// create the TextTrackList if it doesn't exist
|
||||||
this.autoRemoteTextTracks_.addTrack_(htmlTrackElement.track);
|
this.autoRemoteTextTracks_.addTrack(htmlTrackElement.track);
|
||||||
}
|
}
|
||||||
|
|
||||||
return htmlTrackElement;
|
return htmlTrackElement;
|
||||||
@ -785,8 +698,8 @@ class Tech extends Component {
|
|||||||
|
|
||||||
// remove HTMLTrackElement and TextTrack from remote list
|
// remove HTMLTrackElement and TextTrack from remote list
|
||||||
this.remoteTextTrackEls().removeTrackElement_(trackElement);
|
this.remoteTextTrackEls().removeTrackElement_(trackElement);
|
||||||
this.remoteTextTracks().removeTrack_(track);
|
this.remoteTextTracks().removeTrack(track);
|
||||||
this.autoRemoteTextTracks_.removeTrack_(track);
|
this.autoRemoteTextTracks_.removeTrack(track);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -878,28 +791,72 @@ class Tech extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of associated text tracks.
|
* Get the {@link VideoTrackList}
|
||||||
|
*
|
||||||
|
* @returns {VideoTrackList}
|
||||||
|
* @method Tech.prototype.videoTracks
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the {@link AudioTrackList}
|
||||||
|
*
|
||||||
|
* @returns {AudioTrackList}
|
||||||
|
* @method Tech.prototype.audioTracks
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the {@link TextTrackList}
|
||||||
|
*
|
||||||
|
* @returns {TextTrackList}
|
||||||
|
* @method Tech.prototype.textTracks
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the remote element {@link TextTrackList}
|
||||||
|
*
|
||||||
|
* @returns {TextTrackList}
|
||||||
|
* @method Tech.prototype.remoteTextTracks
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the remote element {@link HTMLTrackElementList}
|
||||||
|
*
|
||||||
|
* @returns {HTMLTrackElementList}
|
||||||
|
* @method Tech.prototype.remoteTextTrackEls
|
||||||
|
*/
|
||||||
|
|
||||||
|
TRACK_TYPES.ALL.names.forEach(function(name) {
|
||||||
|
const props = TRACK_TYPES.ALL[name];
|
||||||
|
|
||||||
|
Tech.prototype[props.getterName] = function() {
|
||||||
|
this[props.privateName] = this[props.privateName] || new props.ListClass();
|
||||||
|
return this[props.privateName];
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of associated text tracks
|
||||||
*
|
*
|
||||||
* @type {TextTrackList}
|
* @type {TextTrackList}
|
||||||
* @private
|
* @private
|
||||||
|
* @property Tech#textTracks_
|
||||||
*/
|
*/
|
||||||
Tech.prototype.textTracks_; // eslint-disable-line
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of associated audio tracks.
|
* List of associated audio tracks.
|
||||||
*
|
*
|
||||||
* @type {AudioTrackList}
|
* @type {AudioTrackList}
|
||||||
* @private
|
* @private
|
||||||
|
* @property Tech#audioTracks_
|
||||||
*/
|
*/
|
||||||
Tech.prototype.audioTracks_; // eslint-disable-line
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of associated video tracks.
|
* List of associated video tracks.
|
||||||
*
|
*
|
||||||
* @type {VideoTrackList}
|
* @type {VideoTrackList}
|
||||||
* @private
|
* @private
|
||||||
|
* @property Tech#videoTracks_
|
||||||
*/
|
*/
|
||||||
Tech.prototype.videoTracks_; // eslint-disable-line
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Boolean indicating wether the `Tech` supports volume control.
|
* Boolean indicating wether the `Tech` supports volume control.
|
||||||
|
@ -81,15 +81,14 @@ class AudioTrackList extends TrackList {
|
|||||||
* @param {AudioTrack} track
|
* @param {AudioTrack} track
|
||||||
* The AudioTrack to add to the list
|
* The AudioTrack to add to the list
|
||||||
*
|
*
|
||||||
* @fires Track#addtrack
|
* @fires TrackList#addtrack
|
||||||
* @private
|
|
||||||
*/
|
*/
|
||||||
addTrack_(track) {
|
addTrack(track) {
|
||||||
if (track.enabled) {
|
if (track.enabled) {
|
||||||
disableOthers(this, track);
|
disableOthers(this, track);
|
||||||
}
|
}
|
||||||
|
|
||||||
super.addTrack_(track);
|
super.addTrack(track);
|
||||||
// native tracks don't have this
|
// native tracks don't have this
|
||||||
if (!track.addEventListener) {
|
if (!track.addEventListener) {
|
||||||
return;
|
return;
|
||||||
@ -112,31 +111,6 @@ class AudioTrackList extends TrackList {
|
|||||||
this.trigger('change');
|
this.trigger('change');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Add an {@link AudioTrack} to the `AudioTrackList`.
|
|
||||||
*
|
|
||||||
* @param {AudioTrack} track
|
|
||||||
* The AudioTrack to add to the list
|
|
||||||
*
|
|
||||||
* @fires Track#addtrack
|
|
||||||
*/
|
|
||||||
addTrack(track) {
|
|
||||||
this.addTrack_(track);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove an {@link AudioTrack} from the `AudioTrackList`.
|
|
||||||
*
|
|
||||||
* @param {AudioTrack} track
|
|
||||||
* The AudioTrack to remove from the list
|
|
||||||
*
|
|
||||||
* @fires Track#removetrack
|
|
||||||
*/
|
|
||||||
removeTrack(track) {
|
|
||||||
super.removeTrack_(track);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default AudioTrackList;
|
export default AudioTrackList;
|
||||||
|
@ -114,28 +114,26 @@ class TextTrackDisplay extends Component {
|
|||||||
let firstDesc;
|
let firstDesc;
|
||||||
let firstCaptions;
|
let firstCaptions;
|
||||||
|
|
||||||
if (trackList) {
|
for (let i = 0; i < trackList.length; i++) {
|
||||||
for (let i = 0; i < trackList.length; i++) {
|
const track = trackList[i];
|
||||||
const track = trackList[i];
|
|
||||||
|
|
||||||
if (track.default) {
|
if (track.default) {
|
||||||
if (track.kind === 'descriptions' && !firstDesc) {
|
if (track.kind === 'descriptions' && !firstDesc) {
|
||||||
firstDesc = track;
|
firstDesc = track;
|
||||||
} else if (track.kind in modes && !firstCaptions) {
|
} else if (track.kind in modes && !firstCaptions) {
|
||||||
firstCaptions = track;
|
firstCaptions = track;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// We want to show the first default track but captions and subtitles
|
// We want to show the first default track but captions and subtitles
|
||||||
// take precedence over descriptions.
|
// take precedence over descriptions.
|
||||||
// So, display the first default captions or subtitles track
|
// So, display the first default captions or subtitles track
|
||||||
// and otherwise the first default descriptions track.
|
// and otherwise the first default descriptions track.
|
||||||
if (firstCaptions) {
|
if (firstCaptions) {
|
||||||
firstCaptions.mode = 'showing';
|
firstCaptions.mode = 'showing';
|
||||||
} else if (firstDesc) {
|
} else if (firstDesc) {
|
||||||
firstDesc.mode = 'showing';
|
firstDesc.mode = 'showing';
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@ -192,17 +190,12 @@ class TextTrackDisplay extends Component {
|
|||||||
|
|
||||||
this.clearDisplay();
|
this.clearDisplay();
|
||||||
|
|
||||||
if (!tracks) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Track display prioritization model: if multiple tracks are 'showing',
|
// Track display prioritization model: if multiple tracks are 'showing',
|
||||||
// display the first 'subtitles' or 'captions' track which is 'showing',
|
// display the first 'subtitles' or 'captions' track which is 'showing',
|
||||||
// otherwise display the first 'descriptions' track which is 'showing'
|
// otherwise display the first 'descriptions' track which is 'showing'
|
||||||
|
|
||||||
let descriptionsTrack = null;
|
let descriptionsTrack = null;
|
||||||
let captionsSubtitlesTrack = null;
|
let captionsSubtitlesTrack = null;
|
||||||
|
|
||||||
let i = tracks.length;
|
let i = tracks.length;
|
||||||
|
|
||||||
while (i--) {
|
while (i--) {
|
||||||
|
@ -50,10 +50,9 @@ class TextTrackList extends TrackList {
|
|||||||
* The text track to add to the list.
|
* The text track to add to the list.
|
||||||
*
|
*
|
||||||
* @fires TrackList#addtrack
|
* @fires TrackList#addtrack
|
||||||
* @private
|
|
||||||
*/
|
*/
|
||||||
addTrack_(track) {
|
addTrack(track) {
|
||||||
super.addTrack_(track);
|
super.addTrack(track);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @listens TextTrack#modechange
|
* @listens TextTrack#modechange
|
||||||
|
@ -331,11 +331,9 @@ class TextTrack extends Track {
|
|||||||
addCue(cue) {
|
addCue(cue) {
|
||||||
const tracks = this.tech_.textTracks();
|
const tracks = this.tech_.textTracks();
|
||||||
|
|
||||||
if (tracks) {
|
for (let i = 0; i < tracks.length; i++) {
|
||||||
for (let i = 0; i < tracks.length; i++) {
|
if (tracks[i] !== this) {
|
||||||
if (tracks[i] !== this) {
|
tracks[i].removeCue(cue);
|
||||||
tracks[i].removeCue(cue);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ class TrackList extends EventTarget {
|
|||||||
});
|
});
|
||||||
|
|
||||||
for (let i = 0; i < tracks.length; i++) {
|
for (let i = 0; i < tracks.length; i++) {
|
||||||
list.addTrack_(tracks[i]);
|
list.addTrack(tracks[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// must return the object, as for ie8 it will not be this
|
// must return the object, as for ie8 it will not be this
|
||||||
@ -65,9 +65,8 @@ class TrackList extends EventTarget {
|
|||||||
* The audio, video, or text track to add to the list.
|
* The audio, video, or text track to add to the list.
|
||||||
*
|
*
|
||||||
* @fires TrackList#addtrack
|
* @fires TrackList#addtrack
|
||||||
* @private
|
|
||||||
*/
|
*/
|
||||||
addTrack_(track) {
|
addTrack(track) {
|
||||||
const index = this.tracks_.length;
|
const index = this.tracks_.length;
|
||||||
|
|
||||||
if (!('' + index in this)) {
|
if (!('' + index in this)) {
|
||||||
@ -99,13 +98,12 @@ class TrackList extends EventTarget {
|
|||||||
/**
|
/**
|
||||||
* Remove a {@link Track} from the `TrackList`
|
* Remove a {@link Track} from the `TrackList`
|
||||||
*
|
*
|
||||||
* @param {Track} track
|
* @param {Track} rtrack
|
||||||
* The audio, video, or text track to remove from the list.
|
* The audio, video, or text track to remove from the list.
|
||||||
*
|
*
|
||||||
* @fires TrackList#removetrack
|
* @fires TrackList#removetrack
|
||||||
* @private
|
|
||||||
*/
|
*/
|
||||||
removeTrack_(rtrack) {
|
removeTrack(rtrack) {
|
||||||
let track;
|
let track;
|
||||||
|
|
||||||
for (let i = 0, l = this.length; i < l; i++) {
|
for (let i = 0, l = this.length; i < l; i++) {
|
||||||
|
68
src/js/tracks/track-types.js
Normal file
68
src/js/tracks/track-types.js
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import AudioTrackList from './audio-track-list';
|
||||||
|
import VideoTrackList from './video-track-list';
|
||||||
|
import TextTrackList from './text-track-list';
|
||||||
|
import HTMLTrackElementList from './html-track-element-list';
|
||||||
|
|
||||||
|
import TextTrack from './text-track';
|
||||||
|
import AudioTrack from './audio-track';
|
||||||
|
import VideoTrack from './video-track';
|
||||||
|
import HTMLTrackElement from './html-track-element';
|
||||||
|
|
||||||
|
import mergeOptions from '../utils/merge-options';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This file contains all track properties that are used in
|
||||||
|
* player.js, tech.js, html5.js and possibly other techs in the future.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const NORMAL = {
|
||||||
|
audio: {
|
||||||
|
ListClass: AudioTrackList,
|
||||||
|
TrackClass: AudioTrack,
|
||||||
|
capitalName: 'Audio'
|
||||||
|
},
|
||||||
|
video: {
|
||||||
|
ListClass: VideoTrackList,
|
||||||
|
TrackClass: VideoTrack,
|
||||||
|
capitalName: 'Video'
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
ListClass: TextTrackList,
|
||||||
|
TrackClass: TextTrack,
|
||||||
|
capitalName: 'Text'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Object.keys(NORMAL).forEach(function(type) {
|
||||||
|
NORMAL[type].getterName = `${type}Tracks`;
|
||||||
|
NORMAL[type].privateName = `${type}Tracks_`;
|
||||||
|
});
|
||||||
|
|
||||||
|
const REMOTE = {
|
||||||
|
remoteText: {
|
||||||
|
ListClass: TextTrackList,
|
||||||
|
TrackClass: TextTrack,
|
||||||
|
capitalName: 'RemoteText',
|
||||||
|
getterName: 'remoteTextTracks',
|
||||||
|
privateName: 'remoteTextTracks_'
|
||||||
|
},
|
||||||
|
remoteTextEl: {
|
||||||
|
ListClass: HTMLTrackElementList,
|
||||||
|
TrackClass: HTMLTrackElement,
|
||||||
|
capitalName: 'RemoteTextTrackEls',
|
||||||
|
getterName: 'remoteTextTrackEls',
|
||||||
|
privateName: 'remoteTextTrackEls_'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const ALL = mergeOptions(NORMAL, REMOTE);
|
||||||
|
|
||||||
|
REMOTE.names = Object.keys(REMOTE);
|
||||||
|
NORMAL.names = Object.keys(NORMAL);
|
||||||
|
ALL.names = [].concat(REMOTE.names).concat(NORMAL.names);
|
||||||
|
|
||||||
|
export {
|
||||||
|
NORMAL,
|
||||||
|
REMOTE,
|
||||||
|
ALL
|
||||||
|
};
|
@ -97,14 +97,13 @@ class VideoTrackList extends TrackList {
|
|||||||
* The VideoTrack to add to the list
|
* The VideoTrack to add to the list
|
||||||
*
|
*
|
||||||
* @fires TrackList#addtrack
|
* @fires TrackList#addtrack
|
||||||
* @private
|
|
||||||
*/
|
*/
|
||||||
addTrack_(track) {
|
addTrack(track) {
|
||||||
if (track.selected) {
|
if (track.selected) {
|
||||||
disableOthers(this, track);
|
disableOthers(this, track);
|
||||||
}
|
}
|
||||||
|
|
||||||
super.addTrack_(track);
|
super.addTrack(track);
|
||||||
// native tracks don't have this
|
// native tracks don't have this
|
||||||
if (!track.addEventListener) {
|
if (!track.addEventListener) {
|
||||||
return;
|
return;
|
||||||
@ -124,31 +123,6 @@ class VideoTrackList extends TrackList {
|
|||||||
this.trigger('change');
|
this.trigger('change');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a {@link VideoTrack} to the `VideoTrackList`.
|
|
||||||
*
|
|
||||||
* @param {VideoTrack} track
|
|
||||||
* The VideoTrack to add to the list
|
|
||||||
*
|
|
||||||
* @fires TrackList#addtrack
|
|
||||||
*/
|
|
||||||
addTrack(track) {
|
|
||||||
this.addTrack_(track);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove a {@link VideoTrack} to the `VideoTrackList`.
|
|
||||||
*
|
|
||||||
* @param {VideoTrack} track
|
|
||||||
* The VideoTrack to remove from the list.
|
|
||||||
*
|
|
||||||
* @fires TrackList#removetrack
|
|
||||||
*/
|
|
||||||
removeTrack(track) {
|
|
||||||
super.removeTrack_(track);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default VideoTrackList;
|
export default VideoTrackList;
|
||||||
|
@ -139,11 +139,11 @@ QUnit.test('dispose() should clear all tracks that are added after creation', fu
|
|||||||
tech.addRemoteTextTrack({}, true);
|
tech.addRemoteTextTrack({}, true);
|
||||||
tech.addRemoteTextTrack({}, true);
|
tech.addRemoteTextTrack({}, true);
|
||||||
|
|
||||||
tech.audioTracks().addTrack_(new AudioTrack());
|
tech.audioTracks().addTrack(new AudioTrack());
|
||||||
tech.audioTracks().addTrack_(new AudioTrack());
|
tech.audioTracks().addTrack(new AudioTrack());
|
||||||
|
|
||||||
tech.videoTracks().addTrack_(new VideoTrack());
|
tech.videoTracks().addTrack(new VideoTrack());
|
||||||
tech.videoTracks().addTrack_(new VideoTrack());
|
tech.videoTracks().addTrack(new VideoTrack());
|
||||||
|
|
||||||
assert.equal(tech.audioTracks().length, 2, 'should have two audio tracks at the start');
|
assert.equal(tech.audioTracks().length, 2, 'should have two audio tracks at the start');
|
||||||
assert.equal(tech.videoTracks().length, 2, 'should have two video tracks at the start');
|
assert.equal(tech.videoTracks().length, 2, 'should have two video tracks at the start');
|
||||||
@ -354,11 +354,11 @@ QUnit.test('should add the source handler interface to a tech', function(assert)
|
|||||||
tech.addRemoteTextTrack({}, true);
|
tech.addRemoteTextTrack({}, true);
|
||||||
tech.addRemoteTextTrack({}, true);
|
tech.addRemoteTextTrack({}, true);
|
||||||
|
|
||||||
tech.audioTracks().addTrack_(new AudioTrack());
|
tech.audioTracks().addTrack(new AudioTrack());
|
||||||
tech.audioTracks().addTrack_(new AudioTrack());
|
tech.audioTracks().addTrack(new AudioTrack());
|
||||||
|
|
||||||
tech.videoTracks().addTrack_(new VideoTrack());
|
tech.videoTracks().addTrack(new VideoTrack());
|
||||||
tech.videoTracks().addTrack_(new VideoTrack());
|
tech.videoTracks().addTrack(new VideoTrack());
|
||||||
|
|
||||||
assert.equal(tech.audioTracks().length, 2, 'should have two audio tracks at the start');
|
assert.equal(tech.audioTracks().length, 2, 'should have two audio tracks at the start');
|
||||||
assert.equal(tech.videoTracks().length, 2, 'should have two video tracks at the start');
|
assert.equal(tech.videoTracks().length, 2, 'should have two video tracks at the start');
|
||||||
@ -586,4 +586,3 @@ QUnit.test('setSource after previous setSource should dispose source handler onc
|
|||||||
assert.equal(disposeCount, 2, 'did dispose for third setSource');
|
assert.equal(disposeCount, 2, 'did dispose for third setSource');
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ QUnit.test('only one track is ever enabled', function(assert) {
|
|||||||
assert.equal(track.enabled, true, 'track is enabled');
|
assert.equal(track.enabled, true, 'track is enabled');
|
||||||
assert.equal(track2.enabled, false, 'track2 is disabled');
|
assert.equal(track2.enabled, false, 'track2 is disabled');
|
||||||
|
|
||||||
list.addTrack_(track3);
|
list.addTrack(track3);
|
||||||
assert.equal(track.enabled, false, 'track is disabled');
|
assert.equal(track.enabled, false, 'track is disabled');
|
||||||
assert.equal(track2.enabled, false, 'track2 is disabled');
|
assert.equal(track2.enabled, false, 'track2 is disabled');
|
||||||
assert.equal(track3.enabled, true, 'track3 is enabled');
|
assert.equal(track3.enabled, true, 'track3 is enabled');
|
||||||
@ -50,7 +50,7 @@ QUnit.test('only one track is ever enabled', function(assert) {
|
|||||||
assert.equal(track2.enabled, false, 'track2 is disabled');
|
assert.equal(track2.enabled, false, 'track2 is disabled');
|
||||||
assert.equal(track3.enabled, false, 'track3 is disabled');
|
assert.equal(track3.enabled, false, 'track3 is disabled');
|
||||||
|
|
||||||
list.addTrack_(track4);
|
list.addTrack(track4);
|
||||||
assert.equal(track.enabled, true, 'track is enabled');
|
assert.equal(track.enabled, true, 'track is enabled');
|
||||||
assert.equal(track2.enabled, false, 'track2 is disabled');
|
assert.equal(track2.enabled, false, 'track2 is disabled');
|
||||||
assert.equal(track3.enabled, false, 'track3 is disabled');
|
assert.equal(track3.enabled, false, 'track3 is disabled');
|
||||||
@ -92,7 +92,7 @@ QUnit.test('trigger a change event per enabled change', function(assert) {
|
|||||||
track.enabled = true;
|
track.enabled = true;
|
||||||
assert.equal(change, 1, 'one change triggered');
|
assert.equal(change, 1, 'one change triggered');
|
||||||
|
|
||||||
list.addTrack_(track3);
|
list.addTrack(track3);
|
||||||
assert.equal(change, 2, 'another change triggered by adding an enabled track');
|
assert.equal(change, 2, 'another change triggered by adding an enabled track');
|
||||||
|
|
||||||
track.enabled = true;
|
track.enabled = true;
|
||||||
@ -101,7 +101,7 @@ QUnit.test('trigger a change event per enabled change', function(assert) {
|
|||||||
track.enabled = false;
|
track.enabled = false;
|
||||||
assert.equal(change, 4, 'another change trigger by changing enabled');
|
assert.equal(change, 4, 'another change trigger by changing enabled');
|
||||||
|
|
||||||
list.addTrack_(track4);
|
list.addTrack(track4);
|
||||||
assert.equal(change, 4, 'no change triggered by adding a disabled track');
|
assert.equal(change, 4, 'no change triggered by adding a disabled track');
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
/* eslint-env qunit */
|
/* eslint-env qunit */
|
||||||
import HTMLTrackElement from '../../../src/js/tracks/html-track-element.js';
|
import HTMLTrackElement from '../../../src/js/tracks/html-track-element.js';
|
||||||
|
import TextTrackList from '../../../src/js/tracks/text-track-list.js';
|
||||||
|
|
||||||
const defaultTech = {
|
const defaultTech = {
|
||||||
textTracks() {},
|
textTracks() {
|
||||||
|
return new TextTrackList();
|
||||||
|
},
|
||||||
on() {},
|
on() {},
|
||||||
off() {},
|
off() {},
|
||||||
currentTime() {}
|
currentTime() {}
|
||||||
|
@ -56,8 +56,8 @@ if (Html5.supportsNativeTextTracks()) {
|
|||||||
|
|
||||||
const tt = new TextTrackList();
|
const tt = new TextTrackList();
|
||||||
|
|
||||||
tt.addTrack_(nativeTrack.track);
|
tt.addTrack(nativeTrack.track);
|
||||||
tt.addTrack_(emulatedTrack);
|
tt.addTrack(emulatedTrack);
|
||||||
|
|
||||||
const tech = {
|
const tech = {
|
||||||
$$() {
|
$$() {
|
||||||
@ -107,8 +107,8 @@ if (Html5.supportsNativeTextTracks()) {
|
|||||||
|
|
||||||
const tt = new TextTrackList();
|
const tt = new TextTrackList();
|
||||||
|
|
||||||
tt.addTrack_(nativeTrack.track);
|
tt.addTrack(nativeTrack.track);
|
||||||
tt.addTrack_(emulatedTrack);
|
tt.addTrack(emulatedTrack);
|
||||||
|
|
||||||
let addRemotes = 0;
|
let addRemotes = 0;
|
||||||
const tech = {
|
const tech = {
|
||||||
@ -177,8 +177,8 @@ QUnit.test('textTracksToJson produces good json output for emulated only', funct
|
|||||||
|
|
||||||
const tt = new TextTrackList();
|
const tt = new TextTrackList();
|
||||||
|
|
||||||
tt.addTrack_(anotherTrack);
|
tt.addTrack(anotherTrack);
|
||||||
tt.addTrack_(emulatedTrack);
|
tt.addTrack(emulatedTrack);
|
||||||
|
|
||||||
const tech = {
|
const tech = {
|
||||||
$$() {
|
$$() {
|
||||||
@ -231,8 +231,8 @@ QUnit.test('jsonToTextTracks calls addRemoteTextTrack on the tech with emulated
|
|||||||
|
|
||||||
const tt = new TextTrackList();
|
const tt = new TextTrackList();
|
||||||
|
|
||||||
tt.addTrack_(anotherTrack);
|
tt.addTrack(anotherTrack);
|
||||||
tt.addTrack_(emulatedTrack);
|
tt.addTrack(emulatedTrack);
|
||||||
|
|
||||||
let addRemotes = 0;
|
let addRemotes = 0;
|
||||||
const tech = {
|
const tech = {
|
||||||
|
@ -7,10 +7,13 @@ import TextTrack from '../../../src/js/tracks/text-track.js';
|
|||||||
import TestHelpers from '../test-helpers.js';
|
import TestHelpers from '../test-helpers.js';
|
||||||
import proxyquireify from 'proxyquireify';
|
import proxyquireify from 'proxyquireify';
|
||||||
import sinon from 'sinon';
|
import sinon from 'sinon';
|
||||||
|
import TextTrackList from '../../../src/js/tracks/text-track-list.js';
|
||||||
|
|
||||||
const proxyquire = proxyquireify(require);
|
const proxyquire = proxyquireify(require);
|
||||||
const defaultTech = {
|
const defaultTech = {
|
||||||
textTracks() {},
|
textTracks() {
|
||||||
|
return new TextTrackList();
|
||||||
|
},
|
||||||
on() {},
|
on() {},
|
||||||
off() {},
|
off() {},
|
||||||
currentTime() {}
|
currentTime() {}
|
||||||
|
@ -370,7 +370,7 @@ QUnit.test('removes cuechange event when text track is hidden for emulated track
|
|||||||
startTime: 2,
|
startTime: 2,
|
||||||
endTime: 5
|
endTime: 5
|
||||||
});
|
});
|
||||||
player.tech_.textTracks().addTrack_(tt);
|
player.tech_.textTracks().addTrack(tt);
|
||||||
|
|
||||||
let numTextTrackChanges = 0;
|
let numTextTrackChanges = 0;
|
||||||
|
|
||||||
|
@ -33,20 +33,20 @@ QUnit.test('can get tracks by int and string id', function(assert) {
|
|||||||
QUnit.test('length is updated when new tracks are added or removed', function(assert) {
|
QUnit.test('length is updated when new tracks are added or removed', function(assert) {
|
||||||
const trackList = new TrackList(this.tracks);
|
const trackList = new TrackList(this.tracks);
|
||||||
|
|
||||||
trackList.addTrack_(newTrack('100'));
|
trackList.addTrack(newTrack('100'));
|
||||||
assert.equal(trackList.length,
|
assert.equal(trackList.length,
|
||||||
this.tracks.length + 1,
|
this.tracks.length + 1,
|
||||||
'the length is ' + (this.tracks.length + 1));
|
'the length is ' + (this.tracks.length + 1));
|
||||||
trackList.addTrack_(newTrack('101'));
|
trackList.addTrack(newTrack('101'));
|
||||||
assert.equal(trackList.length,
|
assert.equal(trackList.length,
|
||||||
this.tracks.length + 2,
|
this.tracks.length + 2,
|
||||||
'the length is ' + (this.tracks.length + 2));
|
'the length is ' + (this.tracks.length + 2));
|
||||||
|
|
||||||
trackList.removeTrack_(trackList.getTrackById('101'));
|
trackList.removeTrack(trackList.getTrackById('101'));
|
||||||
assert.equal(trackList.length,
|
assert.equal(trackList.length,
|
||||||
this.tracks.length + 1,
|
this.tracks.length + 1,
|
||||||
'the length is ' + (this.tracks.length + 1));
|
'the length is ' + (this.tracks.length + 1));
|
||||||
trackList.removeTrack_(trackList.getTrackById('100'));
|
trackList.removeTrack(trackList.getTrackById('100'));
|
||||||
assert.equal(trackList.length,
|
assert.equal(trackList.length,
|
||||||
this.tracks.length,
|
this.tracks.length,
|
||||||
'the length is ' + this.tracks.length);
|
'the length is ' + this.tracks.length);
|
||||||
@ -68,23 +68,23 @@ QUnit.test('can access items by index', function(assert) {
|
|||||||
QUnit.test('can access new items by index', function(assert) {
|
QUnit.test('can access new items by index', function(assert) {
|
||||||
const trackList = new TrackList(this.tracks);
|
const trackList = new TrackList(this.tracks);
|
||||||
|
|
||||||
trackList.addTrack_(newTrack('100'));
|
trackList.addTrack(newTrack('100'));
|
||||||
assert.equal(trackList[3].id, '100', 'id of item at index 3 is 100');
|
assert.equal(trackList[3].id, '100', 'id of item at index 3 is 100');
|
||||||
|
|
||||||
trackList.addTrack_(newTrack('101'));
|
trackList.addTrack(newTrack('101'));
|
||||||
assert.equal(trackList[4].id, '101', 'id of item at index 4 is 101');
|
assert.equal(trackList[4].id, '101', 'id of item at index 4 is 101');
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('cannot access removed items by index', function(assert) {
|
QUnit.test('cannot access removed items by index', function(assert) {
|
||||||
const trackList = new TrackList(this.tracks);
|
const trackList = new TrackList(this.tracks);
|
||||||
|
|
||||||
trackList.addTrack_(newTrack('100'));
|
trackList.addTrack(newTrack('100'));
|
||||||
trackList.addTrack_(newTrack('101'));
|
trackList.addTrack(newTrack('101'));
|
||||||
assert.equal(trackList[3].id, '100', 'id of item at index 3 is 100');
|
assert.equal(trackList[3].id, '100', 'id of item at index 3 is 100');
|
||||||
assert.equal(trackList[4].id, '101', 'id of item at index 4 is 101');
|
assert.equal(trackList[4].id, '101', 'id of item at index 4 is 101');
|
||||||
|
|
||||||
trackList.removeTrack_(trackList.getTrackById('101'));
|
trackList.removeTrack(trackList.getTrackById('101'));
|
||||||
trackList.removeTrack_(trackList.getTrackById('100'));
|
trackList.removeTrack(trackList.getTrackById('100'));
|
||||||
|
|
||||||
assert.ok(!trackList[3], 'nothing at index 3');
|
assert.ok(!trackList[3], 'nothing at index 3');
|
||||||
assert.ok(!trackList[4], 'nothing at index 4');
|
assert.ok(!trackList[4], 'nothing at index 4');
|
||||||
@ -93,13 +93,13 @@ QUnit.test('cannot access removed items by index', function(assert) {
|
|||||||
QUnit.test('new item available at old index', function(assert) {
|
QUnit.test('new item available at old index', function(assert) {
|
||||||
const trackList = new TrackList(this.tracks);
|
const trackList = new TrackList(this.tracks);
|
||||||
|
|
||||||
trackList.addTrack_(newTrack('100'));
|
trackList.addTrack(newTrack('100'));
|
||||||
assert.equal(trackList[3].id, '100', 'id of item at index 3 is 100');
|
assert.equal(trackList[3].id, '100', 'id of item at index 3 is 100');
|
||||||
|
|
||||||
trackList.removeTrack_(trackList.getTrackById('100'));
|
trackList.removeTrack(trackList.getTrackById('100'));
|
||||||
assert.ok(!trackList[3], 'nothing at index 3');
|
assert.ok(!trackList[3], 'nothing at index 3');
|
||||||
|
|
||||||
trackList.addTrack_(newTrack('101'));
|
trackList.addTrack(newTrack('101'));
|
||||||
assert.equal(trackList[3].id, '101', 'id of new item at index 3 is now 101');
|
assert.equal(trackList[3].id, '101', 'id of new item at index 3 is now 101');
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -116,14 +116,14 @@ QUnit.test('a "addtrack" event is triggered when new tracks are added', function
|
|||||||
|
|
||||||
trackList.on('addtrack', addHandler);
|
trackList.on('addtrack', addHandler);
|
||||||
|
|
||||||
trackList.addTrack_(newTrack('100'));
|
trackList.addTrack(newTrack('100'));
|
||||||
trackList.addTrack_(newTrack('101'));
|
trackList.addTrack(newTrack('101'));
|
||||||
|
|
||||||
trackList.off('addtrack', addHandler);
|
trackList.off('addtrack', addHandler);
|
||||||
trackList.onaddtrack = addHandler;
|
trackList.onaddtrack = addHandler;
|
||||||
|
|
||||||
trackList.addTrack_(newTrack('102'));
|
trackList.addTrack(newTrack('102'));
|
||||||
trackList.addTrack_(newTrack('103'));
|
trackList.addTrack(newTrack('103'));
|
||||||
|
|
||||||
assert.equal(adds, 4, 'we got ' + adds + ' "addtrack" events');
|
assert.equal(adds, 4, 'we got ' + adds + ' "addtrack" events');
|
||||||
assert.equal(tracks, 4, 'we got a track with every event');
|
assert.equal(tracks, 4, 'we got a track with every event');
|
||||||
@ -141,12 +141,12 @@ QUnit.test('a "removetrack" event is triggered when tracks are removed', functio
|
|||||||
};
|
};
|
||||||
|
|
||||||
trackList.on('removetrack', rmHandler);
|
trackList.on('removetrack', rmHandler);
|
||||||
trackList.removeTrack_(trackList.getTrackById('1'));
|
trackList.removeTrack(trackList.getTrackById('1'));
|
||||||
trackList.removeTrack_(trackList.getTrackById('2'));
|
trackList.removeTrack(trackList.getTrackById('2'));
|
||||||
|
|
||||||
trackList.off('removetrack', rmHandler);
|
trackList.off('removetrack', rmHandler);
|
||||||
trackList.onremovetrack = rmHandler;
|
trackList.onremovetrack = rmHandler;
|
||||||
trackList.removeTrack_(trackList.getTrackById('3'));
|
trackList.removeTrack(trackList.getTrackById('3'));
|
||||||
|
|
||||||
assert.equal(rms, 3, 'we got ' + rms + ' "removetrack" events');
|
assert.equal(rms, 3, 'we got ' + rms + ' "removetrack" events');
|
||||||
assert.equal(tracks, 3, 'we got a track with every event');
|
assert.equal(tracks, 3, 'we got a track with every event');
|
||||||
|
@ -2,9 +2,12 @@
|
|||||||
import TechFaker from '../tech/tech-faker';
|
import TechFaker from '../tech/tech-faker';
|
||||||
import TrackBaseline from './track-baseline';
|
import TrackBaseline from './track-baseline';
|
||||||
import Track from '../../../src/js/tracks/track.js';
|
import Track from '../../../src/js/tracks/track.js';
|
||||||
|
import TextTrackList from '../../../src/js/tracks/text-track-list.js';
|
||||||
|
|
||||||
const defaultTech = {
|
const defaultTech = {
|
||||||
textTracks() {},
|
textTracks() {
|
||||||
|
return new TextTrackList();
|
||||||
|
},
|
||||||
on() {},
|
on() {},
|
||||||
off() {},
|
off() {},
|
||||||
currentTime() {}
|
currentTime() {}
|
||||||
|
@ -40,7 +40,7 @@ QUnit.test('only one track is ever selected', function(assert) {
|
|||||||
assert.equal(track.selected, true, 'track is selected');
|
assert.equal(track.selected, true, 'track is selected');
|
||||||
assert.equal(track2.selected, false, 'track2 is unselected');
|
assert.equal(track2.selected, false, 'track2 is unselected');
|
||||||
|
|
||||||
list.addTrack_(track3);
|
list.addTrack(track3);
|
||||||
assert.equal(track.selected, false, 'track is unselected');
|
assert.equal(track.selected, false, 'track is unselected');
|
||||||
assert.equal(track2.selected, false, 'track2 is unselected');
|
assert.equal(track2.selected, false, 'track2 is unselected');
|
||||||
assert.equal(track3.selected, true, 'track3 is selected');
|
assert.equal(track3.selected, true, 'track3 is selected');
|
||||||
@ -50,7 +50,7 @@ QUnit.test('only one track is ever selected', function(assert) {
|
|||||||
assert.equal(track2.selected, false, 'track2 is unselected');
|
assert.equal(track2.selected, false, 'track2 is unselected');
|
||||||
assert.equal(track3.selected, false, 'track3 is unselected');
|
assert.equal(track3.selected, false, 'track3 is unselected');
|
||||||
|
|
||||||
list.addTrack_(track4);
|
list.addTrack(track4);
|
||||||
assert.equal(track.selected, true, 'track is selected');
|
assert.equal(track.selected, true, 'track is selected');
|
||||||
assert.equal(track2.selected, false, 'track2 is unselected');
|
assert.equal(track2.selected, false, 'track2 is unselected');
|
||||||
assert.equal(track3.selected, false, 'track3 is unselected');
|
assert.equal(track3.selected, false, 'track3 is unselected');
|
||||||
@ -89,7 +89,7 @@ QUnit.test('trigger a change event per selected change', function(assert) {
|
|||||||
track.selected = true;
|
track.selected = true;
|
||||||
assert.equal(change, 1, 'one change triggered');
|
assert.equal(change, 1, 'one change triggered');
|
||||||
|
|
||||||
list.addTrack_(track3);
|
list.addTrack(track3);
|
||||||
assert.equal(change, 2, 'another change triggered by adding an selected track');
|
assert.equal(change, 2, 'another change triggered by adding an selected track');
|
||||||
|
|
||||||
track.selected = true;
|
track.selected = true;
|
||||||
@ -98,6 +98,6 @@ QUnit.test('trigger a change event per selected change', function(assert) {
|
|||||||
track.selected = false;
|
track.selected = false;
|
||||||
assert.equal(change, 4, 'another change trigger by changing selected');
|
assert.equal(change, 4, 'another change trigger by changing selected');
|
||||||
|
|
||||||
list.addTrack_(track4);
|
list.addTrack(track4);
|
||||||
assert.equal(change, 4, 'no change triggered by adding a unselected track');
|
assert.equal(change, 4, 'no change triggered by adding a unselected track');
|
||||||
});
|
});
|
||||||
|
Reference in New Issue
Block a user