Skip to content

Commit

Permalink
Add support for casting from the cast button built into Chrome.
Browse files Browse the repository at this point in the history
Closes #261

Change-Id: I1eb8d673d202d913444746f5adc079fede2f605a
  • Loading branch information
ismena committed Sep 1, 2016
1 parent 20ff6e8 commit 359d2c7
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 42 deletions.
87 changes: 50 additions & 37 deletions lib/cast/cast_proxy.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ shaka.cast.CastProxy = function(video, player, receiverAppId) {
receiverAppId,
this.onCastStatusChanged_.bind(this),
this.onRemoteEvent_.bind(this),
this.onResumeLocal_.bind(this));
this.onResumeLocal_.bind(this),
this.getInitState_.bind(this));

this.init_();
};
Expand Down Expand Up @@ -174,42 +175,7 @@ shaka.cast.CastProxy.prototype.receiverName = function() {
* @export
*/
shaka.cast.CastProxy.prototype.cast = function() {
var initState = {
'video': {},
'player': {},
'playerAfterLoad': {},
'manifest': this.localPlayer_.getManifestUri(),
'startTime': null
};

// Pause local playback before capturing state.
this.localVideo_.pause();

shaka.cast.CastUtils.VideoInitStateAttributes.forEach(function(name) {
initState['video'][name] = this.localVideo_[name];
}.bind(this));

// If the video is still playing, set the startTime.
// Has no effect if nothing is loaded.
if (!this.localVideo_.ended) {
initState['startTime'] = this.localVideo_.currentTime;
}

shaka.cast.CastUtils.PlayerInitState.forEach(function(pair) {
var getter = pair[0];
var setter = pair[1];
var value = /** @type {Object} */(this.localPlayer_)[getter]();

initState['player'][setter] = value;
}.bind(this));

shaka.cast.CastUtils.PlayerInitAfterLoadState.forEach(function(pair) {
var getter = pair[0];
var setter = pair[1];
var value = /** @type {Object} */(this.localPlayer_)[getter]();

initState['playerAfterLoad'][setter] = value;
}.bind(this));
var initState = this.getInitState_();

// TODO: transfer manually-selected tracks?
// TODO: transfer side-loaded text tracks?
Expand Down Expand Up @@ -291,6 +257,53 @@ shaka.cast.CastProxy.prototype.init_ = function() {
};


/**
* @return {shaka.cast.CastUtils.InitStateType} initState Video and player state
* to be sent to the receiver.
* @private
*/
shaka.cast.CastProxy.prototype.getInitState_ = function() {
var initState = {
'video': {},
'player': {},
'playerAfterLoad': {},
'manifest': this.localPlayer_.getManifestUri(),
'startTime': null
};

// Pause local playback before capturing state.
this.localVideo_.pause();

shaka.cast.CastUtils.VideoInitStateAttributes.forEach(function(name) {
initState['video'][name] = this.localVideo_[name];
}.bind(this));

// If the video is still playing, set the startTime.
// Has no effect if nothing is loaded.
if (!this.localVideo_.ended) {
initState['startTime'] = this.localVideo_.currentTime;
}

shaka.cast.CastUtils.PlayerInitState.forEach(function(pair) {
var getter = pair[0];
var setter = pair[1];
var value = /** @type {Object} */(this.localPlayer_)[getter]();

initState['player'][setter] = value;
}.bind(this));

shaka.cast.CastUtils.PlayerInitAfterLoadState.forEach(function(pair) {
var getter = pair[0];
var setter = pair[1];
var value = /** @type {Object} */(this.localPlayer_)[getter]();

initState['playerAfterLoad'][setter] = value;
}.bind(this));

return initState;
};


/**
* Dispatch an event to notify the app that the status has changed.
* @private
Expand Down
17 changes: 13 additions & 4 deletions lib/cast/cast_sender.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,13 @@ goog.require('shaka.util.PublicPromise');
* invoked with target name and event when a remote event is received.
* @param {function()} onResumeLocal A callback invoked when the local player
* should resume playback. Called before cached remote state is wiped.
* @param {function()} onInitStateRequired A callback to get local player's.
* state. Invoked when casting is initiated from Chrome's cast button.
* @implements {shaka.util.IDestroyable}
*/
shaka.cast.CastSender =
function(receiverAppId, onStatusChanged, onRemoteEvent, onResumeLocal) {
function(receiverAppId, onStatusChanged, onRemoteEvent, onResumeLocal,
onInitStateRequired) {
/** @private {string} */
this.receiverAppId_ = receiverAppId;

Expand All @@ -53,6 +56,9 @@ shaka.cast.CastSender =
/** @private {?function()} */
this.onResumeLocal_ = onResumeLocal;

/** @private {?function()} */
this.onInitStateRequired_ = onInitStateRequired;

/** @private {boolean} */
this.apiReady_ = false;

Expand Down Expand Up @@ -407,10 +413,13 @@ shaka.cast.CastSender.prototype.remoteAsyncCall_ =
* @private
*/
shaka.cast.CastSender.prototype.onExistingSessionJoined_ = function(session) {
// TODO: improve support for connecting from Chrome UI (during local playback)
// TODO: improve support for joining existing non-idle sessions on startup
shaka.log.debug('CastSender: onExistingSessionJoined');
this.onSessionCreated_(session);

var initState = this.onInitStateRequired_();

this.castPromise_ = new shaka.util.PublicPromise();

this.onSessionInitiated_(initState, session);
};


Expand Down
10 changes: 9 additions & 1 deletion test/cast/cast_sender_unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ describe('CastSender', function() {
var onStatusChanged;
var onRemoteEvent;
var onResumeLocal;
var onInitStateRequired;

var mockCastApi;
var mockSession;
Expand All @@ -50,6 +51,8 @@ describe('CastSender', function() {
onStatusChanged = jasmine.createSpy('onStatusChanged');
onRemoteEvent = jasmine.createSpy('onRemoteEvent');
onResumeLocal = jasmine.createSpy('onResumeLocal');
onInitStateRequired = jasmine.createSpy('onInitStateRequired')
.and.returnValue(fakeInitState);

mockCastApi = createMockCastApi();
// We're using quotes to access window.chrome because the compiler
Expand All @@ -59,7 +62,7 @@ describe('CastSender', function() {
mockSession = null;

sender = new CastSender(fakeAppId, onStatusChanged, onRemoteEvent,
onResumeLocal);
onResumeLocal, onInitStateRequired);
});

afterEach(function(done) {
Expand Down Expand Up @@ -224,6 +227,11 @@ describe('CastSender', function() {
shaka.test.Util.delay(0.1).then(function() {
expect(onStatusChanged).toHaveBeenCalled();
expect(sender.isCasting()).toBe(true);
expect(onInitStateRequired).toHaveBeenCalled();
expect(mockSession.messages).toContain(jasmine.objectContaining({
type: 'init',
initState: fakeInitState
}));
}).catch(fail).then(done);
});

Expand Down

0 comments on commit 359d2c7

Please sign in to comment.