mirror of
https://github.com/shaka-project/shaka-player.git
synced 2026-06-13 15:46:46 +03:00
refactor(Cast): Simplify CastProxy internals (#10187)
This commit is contained in:
committed by
GitHub
parent
b8982567b9
commit
378011fa4e
+74
-95
@@ -93,14 +93,18 @@ shaka.cast.CastProxy = class extends shaka.util.FakeEventTarget {
|
||||
/** @private {boolean} */
|
||||
this.androidReceiverCompatible_ = androidReceiverCompatible;
|
||||
|
||||
/** @private {!Array<?>} */
|
||||
this.addThumbnailsTrackCalls_ = [];
|
||||
|
||||
/** @private {!Array<?>} */
|
||||
this.addTextTrackAsyncCalls_ = [];
|
||||
|
||||
/** @private {!Array<?>} */
|
||||
this.addChaptersTrackCalls_ = [];
|
||||
/**
|
||||
* @private {{
|
||||
* addThumbnailsTrack: !Array<?>,
|
||||
* addTextTrackAsync: !Array<?>,
|
||||
* addChaptersTrack: !Array<?>,
|
||||
* }}
|
||||
*/
|
||||
this.trackedCalls_ = {
|
||||
addThumbnailsTrack: [],
|
||||
addTextTrackAsync: [],
|
||||
addChaptersTrack: [],
|
||||
};
|
||||
|
||||
/** @private {!Map} */
|
||||
this.playerCompiledToExternNames_ = new Map();
|
||||
@@ -411,8 +415,12 @@ shaka.cast.CastProxy = class extends shaka.util.FakeEventTarget {
|
||||
}
|
||||
|
||||
if (COMPILED) {
|
||||
this.mapCompiledToUncompiledPlayerMethodNames_();
|
||||
this.mapCompiledToUncompiledAdManagerMethodNames_();
|
||||
this.mapCompiledToUncompiledMethodNames_(
|
||||
(op) => this.iterateOverPlayerMethods_(op),
|
||||
this.playerCompiledToExternNames_);
|
||||
this.mapCompiledToUncompiledMethodNames_(
|
||||
(op) => this.iterateOverAdManagerMethods_(op),
|
||||
this.adManagerCompiledToExternNames_);
|
||||
}
|
||||
|
||||
this.videoEventTarget_ = new shaka.util.FakeEventTarget();
|
||||
@@ -438,53 +446,28 @@ shaka.cast.CastProxy = class extends shaka.util.FakeEventTarget {
|
||||
|
||||
|
||||
/**
|
||||
* Maps compiled to uncompiled player names so we can figure out
|
||||
* Maps compiled to uncompiled names for a given object so we can figure out
|
||||
* which method to call in compiled build, while casting.
|
||||
* @param {function(function(string, function()))} iterateFn Accepts an
|
||||
* operation callback and calls iterateOver*Methods_ with it.
|
||||
* @param {!Map} compiledMap
|
||||
* @private
|
||||
*/
|
||||
mapCompiledToUncompiledPlayerMethodNames_() {
|
||||
// In compiled mode, UI tries to access player methods by their internal
|
||||
// renamed names, but the proxy object doesn't know about those. See
|
||||
mapCompiledToUncompiledMethodNames_(iterateFn, compiledMap) {
|
||||
// In compiled mode, UI tries to access methods by their internal renamed
|
||||
// names, but the proxy object doesn't know about those. See
|
||||
// https://github.com/shaka-project/shaka-player/issues/2130 for details.
|
||||
const methodsToNames = new Map();
|
||||
this.iterateOverPlayerMethods_((name, method) => {
|
||||
iterateFn((name, method) => {
|
||||
if (methodsToNames.has(method)) {
|
||||
// If two method names, point to the same method, add them to the
|
||||
// If two method names point to the same method, add them to the
|
||||
// map as aliases of each other.
|
||||
const name2 = methodsToNames.get(method);
|
||||
// Assumes that the compiled name is shorter
|
||||
if (name.length < name2.length) {
|
||||
this.playerCompiledToExternNames_.set(name, name2);
|
||||
compiledMap.set(name, name2);
|
||||
} else {
|
||||
this.playerCompiledToExternNames_.set(name2, name);
|
||||
}
|
||||
} else {
|
||||
methodsToNames.set(method, name);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Maps compiled to uncompiled ad manager names so we can figure out
|
||||
* which method to call in compiled build, while casting.
|
||||
* @private
|
||||
*/
|
||||
mapCompiledToUncompiledAdManagerMethodNames_() {
|
||||
// In compiled mode, UI tries to access ad methods by their internal
|
||||
// renamed names, but the proxy object doesn't know about those. See
|
||||
// https://github.com/shaka-project/shaka-player/issues/2130 for details.
|
||||
const methodsToNames = new Map();
|
||||
this.iterateOverAdManagerMethods_((name, method) => {
|
||||
if (methodsToNames.has(method)) {
|
||||
// If two method names, point to the same method, add them to the
|
||||
// map as aliases of each other.
|
||||
const name2 = methodsToNames.get(method);
|
||||
// Assumes that the compiled name is shorter
|
||||
if (name.length < name2.length) {
|
||||
this.adManagerCompiledToExternNames_.set(name, name2);
|
||||
} else {
|
||||
this.adManagerCompiledToExternNames_.set(name2, name);
|
||||
compiledMap.set(name2, name);
|
||||
}
|
||||
} else {
|
||||
methodsToNames.set(method, name);
|
||||
@@ -583,9 +566,9 @@ shaka.cast.CastProxy = class extends shaka.util.FakeEventTarget {
|
||||
'manifest': this.localPlayer_.getAssetUri(),
|
||||
'startTime': null,
|
||||
'mimeType': this.localPlayer_.getMimeType(),
|
||||
'addThumbnailsTrackCalls': this.addThumbnailsTrackCalls_,
|
||||
'addTextTrackAsyncCalls': this.addTextTrackAsyncCalls_,
|
||||
'addChaptersTrackCalls': this.addChaptersTrackCalls_,
|
||||
'addThumbnailsTrackCalls': this.trackedCalls_.addThumbnailsTrack,
|
||||
'addTextTrackAsyncCalls': this.trackedCalls_.addTextTrackAsync,
|
||||
'addChaptersTrackCalls': this.trackedCalls_.addChaptersTrack,
|
||||
};
|
||||
|
||||
// Pause local playback before capturing state.
|
||||
@@ -645,9 +628,9 @@ shaka.cast.CastProxy = class extends shaka.util.FakeEventTarget {
|
||||
/** @type {Object} */(this.localPlayer_)[setter](value);
|
||||
}
|
||||
|
||||
const addThumbnailsTrackCalls = this.addThumbnailsTrackCalls_;
|
||||
const addTextTrackAsyncCalls = this.addTextTrackAsyncCalls_;
|
||||
const addChaptersTrackCalls = this.addChaptersTrackCalls_;
|
||||
const addThumbnailsTrackCalls = this.trackedCalls_.addThumbnailsTrack;
|
||||
const addTextTrackAsyncCalls = this.trackedCalls_.addTextTrackAsync;
|
||||
const addChaptersTrackCalls = this.trackedCalls_.addChaptersTrack;
|
||||
|
||||
this.resetExternalTracks();
|
||||
|
||||
@@ -736,6 +719,33 @@ shaka.cast.CastProxy = class extends shaka.util.FakeEventTarget {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the local value/method for |name| on |localTarget| when not
|
||||
* casting, or delegates to the sender for the given |targetName|.
|
||||
* Centralises the repeated "use local if not casting" pattern shared by
|
||||
* videoProxyGet_, playerProxyGet_, and adManagerProxyGet_.
|
||||
* @param {!Object} localTarget
|
||||
* @param {string} targetName
|
||||
* @param {string} name
|
||||
* @return {?}
|
||||
* @private
|
||||
*/
|
||||
getLocalOrRemote_(localTarget, targetName, name) {
|
||||
if (!this.sender_.isCasting()) {
|
||||
const value = localTarget[name];
|
||||
if (typeof value == 'function') {
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
return value.bind(localTarget);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
// getCurrentAd is special: it must return the proxy, not the local ad.
|
||||
if (name == 'getCurrentAd') {
|
||||
return () => this.currentAdProxy_;
|
||||
}
|
||||
return this.sender_.get(targetName, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} name
|
||||
* @return {?}
|
||||
@@ -763,17 +773,8 @@ shaka.cast.CastProxy = class extends shaka.util.FakeEventTarget {
|
||||
}
|
||||
}
|
||||
|
||||
// Use local values and methods if we are not casting.
|
||||
if (!this.sender_.isCasting()) {
|
||||
let value = this.localVideo_[name];
|
||||
if (typeof value == 'function') {
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
value = value.bind(this.localVideo_);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
return this.sender_.get('video', name);
|
||||
return this.getLocalOrRemote_(
|
||||
/** @type {!Object} */(this.localVideo_), 'video', name);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -882,21 +883,21 @@ shaka.cast.CastProxy = class extends shaka.util.FakeEventTarget {
|
||||
if (!dontRecordCalls) {
|
||||
if (name == 'addThumbnailsTrack') {
|
||||
return (...args) => {
|
||||
this.addThumbnailsTrackCalls_.push(args);
|
||||
this.trackedCalls_.addThumbnailsTrack.push(args);
|
||||
return this.playerProxyGet_(
|
||||
name, /* dontRecordCalls= */ true)(...args);
|
||||
};
|
||||
}
|
||||
if (name == 'addTextTrackAsync') {
|
||||
return (...args) => {
|
||||
this.addTextTrackAsyncCalls_.push(args);
|
||||
this.trackedCalls_.addTextTrackAsync.push(args);
|
||||
return this.playerProxyGet_(
|
||||
name, /* dontRecordCalls= */ true)(...args);
|
||||
};
|
||||
}
|
||||
if (name == 'addChaptersTrack') {
|
||||
return (...args) => {
|
||||
this.addChaptersTrackCalls_.push(args);
|
||||
this.trackedCalls_.addChaptersTrack.push(args);
|
||||
return this.playerProxyGet_(
|
||||
name, /* dontRecordCalls= */ true)(...args);
|
||||
};
|
||||
@@ -934,17 +935,8 @@ shaka.cast.CastProxy = class extends shaka.util.FakeEventTarget {
|
||||
}
|
||||
}
|
||||
|
||||
// Use local getters and methods if we are not casting.
|
||||
if (!this.sender_.isCasting()) {
|
||||
const value = /** @type {Object} */(this.localPlayer_)[name];
|
||||
if (typeof value != 'function') {
|
||||
return value;
|
||||
}
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
return value.bind(this.localPlayer_);
|
||||
}
|
||||
|
||||
return this.sender_.get('player', name);
|
||||
return this.getLocalOrRemote_(
|
||||
/** @type {!Object} */(this.localPlayer_), 'player', name);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -985,21 +977,8 @@ shaka.cast.CastProxy = class extends shaka.util.FakeEventTarget {
|
||||
};
|
||||
}
|
||||
|
||||
// Use local getters and methods if we are not casting.
|
||||
if (!this.sender_.isCasting()) {
|
||||
const value = /** @type {Object} */(this.localAdManager_)[name];
|
||||
if (typeof value != 'function') {
|
||||
return value;
|
||||
}
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
return value.bind(this.localAdManager_);
|
||||
}
|
||||
|
||||
if (name == 'getCurrentAd') {
|
||||
return () => this.currentAdProxy_;
|
||||
}
|
||||
|
||||
return this.sender_.get('adManager', name);
|
||||
return this.getLocalOrRemote_(
|
||||
/** @type {!Object} */(this.localAdManager_), 'adManager', name);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1070,9 +1049,9 @@ shaka.cast.CastProxy = class extends shaka.util.FakeEventTarget {
|
||||
* Reset external tracks
|
||||
*/
|
||||
resetExternalTracks() {
|
||||
this.addThumbnailsTrackCalls_ = [];
|
||||
this.addTextTrackAsyncCalls_ = [];
|
||||
this.addChaptersTrackCalls_ = [];
|
||||
this.trackedCalls_.addThumbnailsTrack = [];
|
||||
this.trackedCalls_.addTextTrackAsync = [];
|
||||
this.trackedCalls_.addChaptersTrack = [];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+15
-13
@@ -173,11 +173,7 @@ shaka.cast.CastReceiver = class extends shaka.util.FakeEventTarget {
|
||||
* @export
|
||||
*/
|
||||
setContentTitle(title) {
|
||||
if (!this.metadata_) {
|
||||
this.metadata_ = {
|
||||
'metadataType': cast.receiver.media.MetadataType.GENERIC,
|
||||
};
|
||||
}
|
||||
this.ensureMetadata_();
|
||||
this.metadata_['title'] = title;
|
||||
}
|
||||
|
||||
@@ -189,11 +185,7 @@ shaka.cast.CastReceiver = class extends shaka.util.FakeEventTarget {
|
||||
* @export
|
||||
*/
|
||||
setContentImage(imageUrl) {
|
||||
if (!this.metadata_) {
|
||||
this.metadata_ = {
|
||||
'metadataType': cast.receiver.media.MetadataType.GENERIC,
|
||||
};
|
||||
}
|
||||
this.ensureMetadata_();
|
||||
this.metadata_['images'] = [
|
||||
{
|
||||
'url': imageUrl,
|
||||
@@ -210,14 +202,24 @@ shaka.cast.CastReceiver = class extends shaka.util.FakeEventTarget {
|
||||
* @export
|
||||
*/
|
||||
setContentArtist(artist) {
|
||||
if (!this.metadata_) {
|
||||
this.metadata_ = {};
|
||||
}
|
||||
this.ensureMetadata_();
|
||||
this.metadata_['artist'] = artist;
|
||||
this.metadata_['metadataType'] =
|
||||
cast.receiver.media.MetadataType.MUSIC_TRACK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures this.metadata_ exists, initialising it with GENERIC type if not.
|
||||
* @private
|
||||
*/
|
||||
ensureMetadata_() {
|
||||
if (!this.metadata_) {
|
||||
this.metadata_ = {
|
||||
'metadataType': cast.receiver.media.MetadataType.GENERIC,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys the underlying Player, then terminates the cast receiver app.
|
||||
*
|
||||
|
||||
+45
-43
@@ -347,52 +347,54 @@ shaka.cast.CastSender = class {
|
||||
targetName == 'adManager' || targetName == 'currentAd',
|
||||
'Unexpected target name');
|
||||
const CastUtils = shaka.cast.CastUtils;
|
||||
if (targetName == 'video') {
|
||||
if (CastUtils.VideoVoidMethods.includes(property)) {
|
||||
return (...args) => this.remoteCall_(targetName, property, ...args);
|
||||
}
|
||||
} else if (targetName == 'player') {
|
||||
if (CastUtils.PlayerGetterMethodsThatRequireLive.has(property)) {
|
||||
const isLive = this.get('player', 'isLive')();
|
||||
goog.asserts.assert(isLive,
|
||||
property + ' should be called on a live stream!');
|
||||
// If the property shouldn't exist, return a fake function so that the
|
||||
// user doesn't call an undefined function and get a second error.
|
||||
if (!isLive) {
|
||||
return () => undefined;
|
||||
}
|
||||
}
|
||||
if (CastUtils.PlayerVoidMethods.includes(property)) {
|
||||
return (...args) => this.remoteCall_(targetName, property, ...args);
|
||||
}
|
||||
if (CastUtils.PlayerPromiseMethods.includes(property)) {
|
||||
return (...args) =>
|
||||
this.remoteAsyncCall_(targetName, property, ...args);
|
||||
}
|
||||
if (CastUtils.PlayerGetterMethods.has(property) ||
|
||||
CastUtils.LargePlayerGetterMethods.has(property)) {
|
||||
return () => this.propertyGetter_(targetName, property);
|
||||
}
|
||||
} else if (targetName == 'adManager') {
|
||||
if (CastUtils.AdManagerVoidMethods.includes(property)) {
|
||||
return (...args) => this.remoteCall_(targetName, property, ...args);
|
||||
}
|
||||
if (CastUtils.AdManagerPromiseMethods.includes(property)) {
|
||||
return (...args) =>
|
||||
this.remoteAsyncCall_(targetName, property, ...args);
|
||||
}
|
||||
if (CastUtils.LargeAdManagerGetterMethods.has(property)) {
|
||||
return () => this.propertyGetter_(targetName, property);
|
||||
}
|
||||
} else if (targetName == 'currentAd') {
|
||||
if (CastUtils.CurrentAdVoidMethods.includes(property)) {
|
||||
return (...args) => this.remoteCall_(targetName, property, ...args);
|
||||
}
|
||||
if (CastUtils.CurrentAdGetterMethods.has(property)) {
|
||||
return () => this.propertyGetter_(targetName, property);
|
||||
|
||||
// Config table: for each target, which lists/maps govern dispatch.
|
||||
const config = {
|
||||
'video': {
|
||||
voidMethods: CastUtils.VideoVoidMethods,
|
||||
},
|
||||
'player': {
|
||||
voidMethods: CastUtils.PlayerVoidMethods,
|
||||
promiseMethods: CastUtils.PlayerPromiseMethods,
|
||||
getterMethods: [CastUtils.PlayerGetterMethods,
|
||||
CastUtils.LargePlayerGetterMethods],
|
||||
requiresLiveMap: CastUtils.PlayerGetterMethodsThatRequireLive,
|
||||
},
|
||||
'adManager': {
|
||||
voidMethods: CastUtils.AdManagerVoidMethods,
|
||||
promiseMethods: CastUtils.AdManagerPromiseMethods,
|
||||
getterMethods: [CastUtils.LargeAdManagerGetterMethods],
|
||||
},
|
||||
'currentAd': {
|
||||
voidMethods: CastUtils.CurrentAdVoidMethods,
|
||||
getterMethods: [CastUtils.CurrentAdGetterMethods],
|
||||
},
|
||||
};
|
||||
|
||||
const cfg = config[targetName];
|
||||
|
||||
// Live-only guard (player only).
|
||||
if (cfg.requiresLiveMap && cfg.requiresLiveMap.has(property)) {
|
||||
const isLive = this.get('player', 'isLive')();
|
||||
goog.asserts.assert(isLive,
|
||||
property + ' should be called on a live stream!');
|
||||
if (!isLive) {
|
||||
return () => undefined;
|
||||
}
|
||||
}
|
||||
|
||||
if (cfg.voidMethods && cfg.voidMethods.includes(property)) {
|
||||
return (...args) => this.remoteCall_(targetName, property, ...args);
|
||||
}
|
||||
if (cfg.promiseMethods && cfg.promiseMethods.includes(property)) {
|
||||
return (...args) =>
|
||||
this.remoteAsyncCall_(targetName, property, ...args);
|
||||
}
|
||||
if (cfg.getterMethods &&
|
||||
cfg.getterMethods.some((map) => map.has(property))) {
|
||||
return () => this.propertyGetter_(targetName, property);
|
||||
}
|
||||
|
||||
return this.propertyGetter_(targetName, property);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user