Skip to content

Commit

Permalink
Add a temporary fix to enable casting.
Browse files Browse the repository at this point in the history
Issue #1948

Change-Id: Id3953cdc32f1cdd02729c1a3f08c522b2ee376f1
  • Loading branch information
ismena authored and TheModMaker committed Jul 11, 2019
1 parent 02bd8f2 commit 8c37740
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 23 deletions.
117 changes: 94 additions & 23 deletions lib/cast/cast_proxy.js
Expand Up @@ -69,14 +69,28 @@ shaka.cast.CastProxy = function(video, player, receiverAppId) {
/** @private {shaka.util.EventManager} */
this.eventManager_ = null;

/** @private {shaka.cast.CastSender} */
this.sender_ = new shaka.cast.CastSender(
receiverAppId,
this.onCastStatusChanged_.bind(this),
this.onFirstCastStateUpdate_.bind(this),
this.onRemoteEvent_.bind(this),
this.onResumeLocal_.bind(this),
this.getInitState_.bind(this));
/** @private {string} */
this.receiverAppId_ = receiverAppId;

if (this.receiverAppId_) {
// TODO: This is temporary fix to get casting working.
// It masks the fact that we're at the moment unable to
// change the receiver id sucessfully.
// It relies on the assumption that changing one actual
// id to another is a very edgy use case (usually apps have
// only one receiver app).
// It unblocks casting in the world where UI can be configured,
// but it's hacky and must be changed to a permanent solution
// allowing to change Receiver App ID for reals.
/** @private {shaka.cast.CastSender} */
this.sender_ = new shaka.cast.CastSender(
receiverAppId,
() => this.onCastStatusChanged_(),
() => this.onFirstCastStateUpdate_(),
(targetName, event) => this.onRemoteEvent_(targetName, event),
() => this.onResumeLocal_(),
() => this.getInitState_());
}

this.init_();
};
Expand Down Expand Up @@ -191,6 +205,13 @@ shaka.cast.CastProxy.prototype.receiverName = function() {
* @export
*/
shaka.cast.CastProxy.prototype.cast = function() {
if (!this.sender_) {
throw new shaka.util.Error(
shaka.util.Error.Severity.RECOVERABLE,
shaka.util.Error.Category.CAST,
shaka.util.Error.Code.CAST_RECEIVER_APP_ID_MISSING);
}

let initState = this.getInitState_();

// TODO: transfer manually-selected tracks?
Expand All @@ -215,7 +236,9 @@ shaka.cast.CastProxy.prototype.cast = function() {
* @export
*/
shaka.cast.CastProxy.prototype.setAppData = function(appData) {
this.sender_.setAppData(appData);
if (this.sender_) {
this.sender_.setAppData(appData);
}
};


Expand All @@ -224,7 +247,44 @@ shaka.cast.CastProxy.prototype.setAppData = function(appData) {
* @export
*/
shaka.cast.CastProxy.prototype.suggestDisconnect = function() {
this.sender_.showDisconnectDialog();
if (this.sender_) {
this.sender_.showDisconnectDialog();
}
};


/**
* @param {string} newAppId
* @export
*/
shaka.cast.CastProxy.prototype.changeReceiverId = async function(newAppId) {
if (newAppId == this.receiverAppId_) {
// Nothing to change
return;
}

this.receiverAppId_ = newAppId;

// TODO: This code doesn't work correctly at the moment. Changing
// one working receiver id to another needs to be figured out.
// Destroy the old sender
if (this.sender_) {
this.sender_.forceDisconnect();
await this.sender_.destroy();
this.sender_ = null;
}


// Create the new one
this.sender_ = new shaka.cast.CastSender(
newAppId,
() => this.onCastStatusChanged_(),
() => this.onFirstCastStateUpdate_(),
(targetName, event) => this.onRemoteEvent_(targetName, event),
() => this.onResumeLocal_(),
() => this.getInitState_());

this.sender_.init();
};


Expand All @@ -233,7 +293,9 @@ shaka.cast.CastProxy.prototype.suggestDisconnect = function() {
* @export
*/
shaka.cast.CastProxy.prototype.forceDisconnect = function() {
this.sender_.forceDisconnect();
if (this.sender_) {
this.sender_.forceDisconnect();
}
};


Expand All @@ -242,7 +304,9 @@ shaka.cast.CastProxy.prototype.forceDisconnect = function() {
* @private
*/
shaka.cast.CastProxy.prototype.init_ = function() {
this.sender_.init();
if (this.sender_) {
this.sender_.init();
}

this.eventManager_ = new shaka.util.EventManager();

Expand Down Expand Up @@ -360,6 +424,9 @@ shaka.cast.CastProxy.prototype.onFirstCastStateUpdate_ = function() {
* @private
*/
shaka.cast.CastProxy.prototype.onResumeLocal_ = function() {
goog.asserts.assert(this.sender_,
'Cast sender should not be null!');

// Transfer back the player state.
shaka.cast.CastUtils.PlayerInitState.forEach(function(pair) {
let getter = pair[0];
Expand Down Expand Up @@ -447,15 +514,16 @@ shaka.cast.CastProxy.prototype.videoProxyGet_ = function(name) {

// If we are casting, but the first update has not come in yet, use local
// values, but not local methods.
if (this.sender_.isCasting() && !this.sender_.hasRemoteProperties()) {
if (this.sender_ && this.sender_.isCasting() &&
!this.sender_.hasRemoteProperties()) {
let value = this.localVideo_[name];
if (typeof value != 'function') {
return value;
}
}

// Use local values and methods if we are not casting.
if (!this.sender_.isCasting()) {
if (!this.sender_ || !this.sender_.isCasting()) {
let value = this.localVideo_[name];
if (typeof value == 'function') {
value = value.bind(this.localVideo_);
Expand All @@ -473,7 +541,7 @@ shaka.cast.CastProxy.prototype.videoProxyGet_ = function(name) {
* @private
*/
shaka.cast.CastProxy.prototype.videoProxySet_ = function(name, value) {
if (!this.sender_.isCasting()) {
if (!this.sender_ || !this.sender_.isCasting()) {
this.localVideo_[name] = value;
return;
}
Expand All @@ -487,7 +555,7 @@ shaka.cast.CastProxy.prototype.videoProxySet_ = function(name, value) {
* @private
*/
shaka.cast.CastProxy.prototype.videoProxyLocalEvent_ = function(event) {
if (this.sender_.isCasting()) {
if (this.sender_ && this.sender_.isCasting()) {
// Ignore any unexpected local events while casting. Events can still be
// fired by the local video and Player when we unload() after the Cast
// connection is complete.
Expand Down Expand Up @@ -523,20 +591,22 @@ shaka.cast.CastProxy.prototype.playerProxyGet_ = function(name) {
if (name == 'getSharedConfiguration') {
shaka.log.warning(
'Can\'t share configuration across a network. Returning copy.');
return this.sender_.get('player', 'getConfiguration');
return this.sender_ ?
this.sender_.get('player', 'getConfiguration') :
this.localPlayer_.getConfiguration();
}

if (name == 'getNetworkingEngine') {
// Always returns a local instance, in case you need to make a request.
// Issues a warning, in case you think you are making a remote request
// or affecting remote filters.
if (this.sender_.isCasting()) {
if (this.sender_ && this.sender_.isCasting()) {
shaka.log.warning('NOTE: getNetworkingEngine() is always local!');
}
return this.localPlayer_.getNetworkingEngine.bind(this.localPlayer_);
}

if (this.sender_.isCasting()) {
if (this.sender_ && this.sender_.isCasting()) {
// These methods are unavailable or otherwise stubbed during casting.
if (name == 'getManifest' || name == 'drmInfo') {
return function() {
Expand Down Expand Up @@ -564,7 +634,8 @@ shaka.cast.CastProxy.prototype.playerProxyGet_ = function(name) {

// If we are casting, but the first update has not come in yet, use local
// getters, but not local methods.
if (this.sender_.isCasting() && !this.sender_.hasRemoteProperties()) {
if (this.sender_ && this.sender_.isCasting() &&
!this.sender_.hasRemoteProperties()) {
if (shaka.cast.CastUtils.PlayerGetterMethods[name]) {
let value = /** @type {Object} */(this.localPlayer_)[name];
goog.asserts.assert(typeof value == 'function', 'only methods on Player');
Expand All @@ -573,7 +644,7 @@ shaka.cast.CastProxy.prototype.playerProxyGet_ = function(name) {
}

// Use local getters and methods if we are not casting.
if (!this.sender_.isCasting()) {
if (!this.sender_ || !this.sender_.isCasting()) {
let value = /** @type {Object} */(this.localPlayer_)[name];
goog.asserts.assert(typeof value == 'function', 'only methods on Player');
return value.bind(this.localPlayer_);
Expand All @@ -588,7 +659,7 @@ shaka.cast.CastProxy.prototype.playerProxyGet_ = function(name) {
* @private
*/
shaka.cast.CastProxy.prototype.playerProxyLocalEvent_ = function(event) {
if (this.sender_.isCasting()) {
if (this.sender_ && this.sender_.isCasting()) {
// Ignore any unexpected local events while casting.
return;
}
Expand All @@ -603,7 +674,7 @@ shaka.cast.CastProxy.prototype.playerProxyLocalEvent_ = function(event) {
* @private
*/
shaka.cast.CastProxy.prototype.onRemoteEvent_ = function(targetName, event) {
goog.asserts.assert(this.sender_.isCasting(),
goog.asserts.assert(this.sender_ && this.sender_.isCasting(),
'Should only receive remote events while casting');
if (!this.sender_.isCasting()) {
// Ignore any unexpected remote events.
Expand Down
6 changes: 6 additions & 0 deletions lib/util/error.js
Expand Up @@ -799,6 +799,12 @@ shaka.util.Error.Code = {
'CAST_RECEIVER_APP_UNAVAILABLE': 8006,


/**
* No receiver app id has been provided, making casting impossible.
*/
'CAST_RECEIVER_APP_ID_MISSING': 8007,


/**
* Offline storage is not supported on this browser; it is required for
* offline support.
Expand Down
2 changes: 2 additions & 0 deletions ui/controls.js
Expand Up @@ -359,6 +359,8 @@ shaka.ui.Controls.prototype.loadComplete = function() {
shaka.ui.Controls.prototype.configure = function(config) {
this.config_ = config;

this.castProxy_.changeReceiverId(config.castReceiverAppId);

if (this.controlsContainer_) {
// Deconstruct the old layout if applicable
shaka.util.Dom.removeAllChildren(this.controlsContainer_);
Expand Down

0 comments on commit 8c37740

Please sign in to comment.