-
Notifications
You must be signed in to change notification settings - Fork 7.5k
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
Add option to have remoteTextTracks automatically 'garbage-collected' when sources change #3736
Changes from all commits
cb0df09
08a1eb6
8a5fd49
402a126
b65b872
ad7008a
9359fa3
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 |
---|---|---|
|
@@ -85,9 +85,11 @@ class Tech extends Component { | |
} | ||
|
||
if (!this.featuresNativeTextTracks) { | ||
this.on('ready', this.emulateTextTracks); | ||
this.emulateTextTracks(); | ||
} | ||
|
||
this.autoRemoteTextTracks_ = new TextTrackList(); | ||
|
||
this.initTextTrackListeners(); | ||
this.initTrackListeners(); | ||
|
||
|
@@ -291,6 +293,23 @@ class Tech extends Component { | |
}); | ||
} | ||
|
||
/** | ||
* Remove any TextTracks added via addRemoteTextTrack that are | ||
* flagged for automatic garbage collection | ||
* | ||
* @method cleanupAutoTextTracks | ||
*/ | ||
cleanupAutoTextTracks() { | ||
const list = this.autoRemoteTextTracks_ || []; | ||
let i = list.length; | ||
|
||
while (i--) { | ||
const track = list[i]; | ||
|
||
this.removeRemoteTextTrack(track); | ||
} | ||
} | ||
|
||
/** | ||
* Reset the tech. Removes all sources and resets readyState. | ||
* | ||
|
@@ -394,17 +413,11 @@ class Tech extends Component { | |
} | ||
|
||
/** | ||
* Emulate texttracks | ||
* Add vtt.js if necessary | ||
* | ||
* @method emulateTextTracks | ||
* @private | ||
*/ | ||
emulateTextTracks() { | ||
const tracks = this.textTracks(); | ||
|
||
if (!tracks) { | ||
return; | ||
} | ||
|
||
addWebVttScript_() { | ||
if (!window.WebVTT && this.el().parentNode !== null && this.el().parentNode !== undefined) { | ||
const script = document.createElement('script'); | ||
|
||
|
@@ -424,6 +437,32 @@ class Tech extends Component { | |
window.WebVTT = true; | ||
this.el().parentNode.appendChild(script); | ||
} | ||
} | ||
|
||
/** | ||
* Emulate texttracks | ||
* | ||
* @method emulateTextTracks | ||
*/ | ||
emulateTextTracks() { | ||
const tracks = this.textTracks(); | ||
|
||
if (!tracks) { | ||
return; | ||
} | ||
|
||
this.remoteTextTracks().on('addtrack', (e) => { | ||
this.textTracks().addTrack_(e.track); | ||
}); | ||
|
||
this.remoteTextTracks().on('removetrack', (e) => { | ||
this.textTracks().removeTrack_(e.track); | ||
}); | ||
|
||
// Initially, Tech.el_ is a child of a dummy-div wait until the Component system | ||
// signals that the Tech is ready at which point Tech.el_ is part of the DOM | ||
// before inserting the WebVTT script | ||
this.on('ready', this.addWebVttScript_); | ||
|
||
const updateDisplay = () => this.trigger('texttrackchange'); | ||
const textTracksChanges = () => { | ||
|
@@ -527,26 +566,51 @@ class Tech extends Component { | |
} | ||
|
||
/** | ||
* Creates a remote text track object and returns a emulated html track element | ||
* Create an emulated TextTrack for use by addRemoteTextTrack | ||
* | ||
* This is intended to be overridden by classes that inherit from | ||
* Tech in order to create native or custom TextTracks. | ||
* | ||
* @param {Object} options The object should contain values for | ||
* kind, language, label and src (location of the WebVTT file) | ||
* @return {HTMLTrackElement} | ||
* @method addRemoteTextTrack | ||
*/ | ||
addRemoteTextTrack(options) { | ||
createRemoteTextTrack(options) { | ||
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. private |
||
const track = mergeOptions(options, { | ||
tech: this | ||
}); | ||
|
||
const htmlTrackElement = new HTMLTrackElement(track); | ||
return new HTMLTrackElement(track); | ||
} | ||
|
||
/** | ||
* Creates a remote text track object and returns an html track element. | ||
* | ||
* @param {Object} options The object should contain values for | ||
* kind, language, label, and src (location of the WebVTT file) | ||
* @param {Boolean} [manualCleanup=true] if set to false, the TextTrack will be | ||
* automatically removed from the video element whenever the source changes | ||
* @return {HTMLTrackElement} An Html Track Element. | ||
* This can be an emulated {@link HTMLTrackElement} or a native one. | ||
* @deprecated The default value of the "manualCleanup" parameter will default | ||
* to "false" in upcoming versions of Video.js | ||
*/ | ||
addRemoteTextTrack(options = {}, manualCleanup) { | ||
const htmlTrackElement = this.createRemoteTextTrack(options); | ||
|
||
if (manualCleanup !== true && manualCleanup !== false) { | ||
// deprecation warning | ||
log.warn('Calling addRemoteTextTrack without explicitly setting the "manualCleanup" parameter to `true` is deprecated and default to `false` in future version of video.js'); | ||
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. I am open to some nice word-smithing here. I feel like coming up with error/warnings is not my strong suit. 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. is there any reason why we need to deprecate this and not just make the change? This almost seems like a bug. If we decide not to deprecate and to just make the change we can probably make this change much smaller. 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 because currently, you have to manually cleanup, we're wanting to change it so that by default tracks are cleaned up automatically. |
||
manualCleanup = true; | ||
} | ||
|
||
// store HTMLTrackElement and TextTrack to remote list | ||
this.remoteTextTrackEls().addTrackElement_(htmlTrackElement); | ||
this.remoteTextTracks().addTrack_(htmlTrackElement.track); | ||
|
||
// must come after remoteTextTracks() | ||
this.textTracks().addTrack_(htmlTrackElement.track); | ||
if (manualCleanup !== true) { | ||
// create the TextTrackList if it doesn't exist | ||
this.autoRemoteTextTracks_.addTrack_(htmlTrackElement.track); | ||
} | ||
|
||
return htmlTrackElement; | ||
} | ||
|
@@ -558,13 +622,12 @@ class Tech extends Component { | |
* @method removeRemoteTextTrack | ||
*/ | ||
removeRemoteTextTrack(track) { | ||
this.textTracks().removeTrack_(track); | ||
|
||
const trackElement = this.remoteTextTrackEls().getTrackElementByTrack_(track); | ||
|
||
// remove HTMLTrackElement and TextTrack from remote list | ||
this.remoteTextTrackEls().removeTrackElement_(trackElement); | ||
this.remoteTextTracks().removeTrack_(track); | ||
this.autoRemoteTextTracks_.removeTrack_(track); | ||
} | ||
|
||
/** | ||
|
@@ -685,7 +748,7 @@ Tech.prototype.featuresNativeTextTracks = false; | |
* | ||
* ##### EXAMPLE: | ||
* | ||
* Tech.withSourceHandlers.call(MyTech); | ||
* Tech.withSourceHandlers(MyTech); | ||
* | ||
*/ | ||
Tech.withSourceHandlers = function(_Tech) { | ||
|
@@ -820,25 +883,14 @@ Tech.withSourceHandlers = function(_Tech) { | |
this.disposeSourceHandler(); | ||
this.off('dispose', this.disposeSourceHandler); | ||
|
||
// if we have a source and get another one | ||
// then we are loading something new | ||
// than clear all of our current tracks | ||
if (this.currentSource_) { | ||
this.clearTracks(['audio', 'video']); | ||
|
||
this.currentSource_ = null; | ||
} | ||
|
||
if (sh !== _Tech.nativeSourceHandler) { | ||
|
||
this.currentSource_ = source; | ||
|
||
// Catch if someone replaced the src without calling setSource. | ||
// If they do, set currentSource_ to null and dispose our source handler. | ||
this.off(this.el_, 'loadstart', _Tech.prototype.firstLoadStartListener_); | ||
this.off(this.el_, 'loadstart', _Tech.prototype.successiveLoadStartListener_); | ||
this.one(this.el_, 'loadstart', _Tech.prototype.firstLoadStartListener_); | ||
|
||
} | ||
|
||
this.sourceHandler_ = sh.handleSource(source, this, this.options_); | ||
|
@@ -854,7 +906,6 @@ Tech.withSourceHandlers = function(_Tech) { | |
|
||
// On successive loadstarts when setSource has not been called again | ||
_Tech.prototype.successiveLoadStartListener_ = function() { | ||
this.currentSource_ = null; | ||
this.disposeSourceHandler(); | ||
this.one(this.el_, 'loadstart', _Tech.prototype.successiveLoadStartListener_); | ||
}; | ||
|
@@ -863,10 +914,25 @@ Tech.withSourceHandlers = function(_Tech) { | |
* Clean up any existing source handler | ||
*/ | ||
_Tech.prototype.disposeSourceHandler = function() { | ||
if (this.sourceHandler_ && this.sourceHandler_.dispose) { | ||
// if we have a source and get another one | ||
// then we are loading something new | ||
// than clear all of our current tracks | ||
if (this.currentSource_) { | ||
this.clearTracks(['audio', 'video']); | ||
this.currentSource_ = null; | ||
} | ||
|
||
// always clean up auto-text tracks | ||
this.cleanupAutoTextTracks(); | ||
|
||
if (this.sourceHandler_) { | ||
this.off(this.el_, 'loadstart', _Tech.prototype.firstLoadStartListener_); | ||
this.off(this.el_, 'loadstart', _Tech.prototype.successiveLoadStartListener_); | ||
this.sourceHandler_.dispose(); | ||
|
||
if (this.sourceHandler_.dispose) { | ||
this.sourceHandler_.dispose(); | ||
} | ||
|
||
this.sourceHandler_ = null; | ||
} | ||
}; | ||
|
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.
this should probably be private.