This developer guide describes how to add Google Cast support to your Chrome sender app using Cast SDK.
Terminology
The mobile device or laptop is the sender, which controls the playback; the Google Cast device is the receiver, which displays the content on the screen for playback.
The Chrome Sender API consists of two parts: the Framework API (cast.framework) and the Base API (chrome.cast) In general, you make calls on the simpler, higher-level Framework API, which are then processed by the lower-level Base API.
The sender framework refers to the Framework API, module and associated resources that provide a wrapper around lower-level functionality. The sender application or Google Cast Chrome application refers to a web (HTML/JavaScript) app running inside a Chrome browser on a sender device. A Web Receiver application refers to an HTML/JavaScript application running on Chromecast or a Google Cast device.
The sender framework uses an asynchronous callback design to inform the sender app of events and to transition between various states of the Cast app life cycle.
Load the library
For your app to implement the features of Google Cast, it needs to know the location of the Google Cast Chrome Sender API library, as shown. Add the loadCastFramework URL query parameter to load the Cast Sender Framework API as well. All pages of your app must refer to the library as follows:
<script src="https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1"></script>
Non-JavaScript player
Your sender application's properties and functions may be accessed or used with a non-JavaScript player such as Flash or Silverlight. These frameworks provide methods that hook into your JavaScript sender code and let you pass parameters and handle events in the Flash or Silverlight player.
For example, you can use the ActionScript method
Externalinterface.call(external-JavaScript-function, parameter-1,
parameter-2)
to hook into your media control methods, such as
initializeCastApi
. Likewise, use the ActionScript method
ExternalInterface.addCallback("EVENT", ActionScriptAction)
to
handle events like button clicks and progress bar updates.
See your framework's documentation for more information about hooking into your sender's JavaScript code.
Framework
The Chrome Sender API uses the cast.framework.* namespace. The namespace represents the following:
- Methods or functions that invoke operations on the API
- Event listeners for listener functions in the API
The framework consists of these main components:
- The
CastContext
is a singleton object that provides information about the current Cast state, and triggers events for Cast state and Cast session state changes. - The
CastSession
object manages the session -- it provides state information and triggers events, such as changes to device volume, mute state, and application metadata. - The Cast button element, which is a simple HTML custom element that extends the HTML button. If the provided Cast button is not sufficient, you can use the Cast state to implement a Cast button.
- The
RemotePlayerController
provides the data binding to simplify implementation of the remote player.
Review the Google Cast Chrome Sender API Reference for a complete description of the namespace.
Cast button
The Cast button component in your app is handled entirely by the framework. This includes visibility management, as well as click event handling.
<google-cast-launcher></google-cast-launcher>
Alternatively, you can create the button programmatically:
document.createElement("google-cast-launcher");
You can apply any additional styling, such as size or positioning, to the
element as necessary. Use the --connected-color
attribute to
choose the color for the connected Web Receiver state, and
--disconnected-color
for the disconnected state.
Example:
button.remove();
button.dispose();
It is safe to call dispose()
on all other browsers, but resources will be
disposed of automatically if Web Components
are available.
Initialization
After loading the framework API, the app will call the handler
window.__onGCastApiAvailable
. You should ensure that the app sets
this handler on the window
before loading the sender library.
Within this handler, you initialize the Cast interaction by calling the
CastContext.setOptions
method.
For example:
<script>
window['__onGCastApiAvailable'] = function(isAvailable) {
if (isAvailable) {
initializeCastApi();
}
};
</script>
Then, you initialize the API as follows:
initializeCastApi = function() {
cast.framework.CastContext.getInstance().setOptions({
receiverApplicationId: applicationId,
autoJoinPolicy: chrome.cast.AutoJoinPolicy.ORIGIN_SCOPED
});
};
First the app retrieves the singleton instance of the CastContext
object
provided by the framework. It then sets the Options
object using
your own applicationID
.
If you are using the Default Media Receiver, for which no registration is
required, you use a constant predefined by the Chrome Sender SDK, as shown
below, instead of the applicationID
:
cast.framework.CastContext.getInstance().setOptions({
receiverApplicationId:
chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID
});
Media control
Once the CastContext has been initialized, the app can retrieve the current Cast session at any time.
var castSession = cast.framework.CastContext.getInstance().getCurrentSession();
Now that you have a cast.framework.CastSession
object, the app can
load media to the connected Cast device by creating a MediaInfo
object for the currentMediaURL
and contentType
,
creating a LoadRequest
object from it, and then calling the
loadMedia
method of the CastSession
object.
var mediaInfo = new chrome.cast.media.MediaInfo(currentMediaURL, contentType);
var request = new chrome.cast.media.LoadRequest(mediaInfo);
castSession.loadMedia(request).then(
function() { console.log('Load succeed'); },
function(errorCode) { console.log('Error code: ' + errorCode); });
The loadMedia
method will return a Promise
that can be used to perform any necessary operations for a successful result.
If the Promise is rejected, the function argument will be a chrome.cast.ErrorCode
.
You can access player state variables in
cast.framework.RemotePlayer
. All interactions with the remote Cast
player, including media event callbacks and commands, are handled with the
cast.framework.RemotePlayerController
.
var player = new cast.framework.RemotePlayer();
var playerController = new cast.framework.RemotePlayerController(player);
The RemotePlayerController
gives the app full media control of
PLAY, PAUSE, STOP and SEEK for the loaded media.
- PLAY/PAUSE:
playerController.playOrPause();
- STOP:
playerController.stop();
- SEEK:
playerController.seek();
The RemotePlayer
and RemotePlayerController
can be
used with data binding frameworks, such as Polymer or Angular, to implement a
remote player.
Here is a code snippet for Angular:
<button id="playPauseButton" class="playerButton" ng-disabled="!player.canPause" ng-click="controller.playOrPause()"> {{player.isPaused ? 'Play' : 'Pause'}} </button> <script> var player = new cast.framework.RemotePlayer(); var controller = new cast.framework.RemotePlayerController(player); // Listen to any player update, and trigger angular data binding update.controller.addEventListener( cast.framework.RemotePlayerEventType.ANY_CHANGE, function(event) { if (!$scope.$$phase) $scope.$apply(); }); </script>
Media status
During media playback, various events occur which can be captured by setting
listeners for various cast.framework.RemotePlayerEventType
events
on the RemotePlayerController
object.
To get the media status information, use the MEDIA_INFO_CHANGED
event, which
triggers when playback changes and when the MediaSession.media
changes.
playerController.addEventListener(
cast.framework.RemotePlayerEventType.MEDIA_INFO_CHANGED, function() {
// Use the current session to get an up to date media status.
let session = cast.framework.CastContext.getInstance().getCurrentSession();
if (!session) {
return;
}
// Contains information about the playing media including currentTime.
let mediaStatus = session.getMediaSession();
if (!mediaStatus) {
return;
}
// mediaStatus also contains the mediaInfo containing metadata and other
// information about the in progress content.
let mediaInfo = mediaStatus.media;
});
When events such as pause, play, resume or seek occur, the app will need to act on them and synchronize between itself and the Web Receiver app on the Cast device. See Status updates for more information.
Disconnection
For disconnection, such as when the user clicks the "stop casting" button from
the Cast dialog, you must define an update listener for player state changes.
Add a listener for the RemotePlayerEventType.IS_CONNECTED_CHANGED
event type in your listener. In your listener check if RemotePlayer
is disconnected, and if so, update the local player state as necessary. For
example:
playerController.addEventListener(
cast.framework.RemotePlayerEventType.IS_CONNECTED_CHANGED, function() {
if (!player.isConnected) {
console.log('RemotePlayerController: Player disconnected');
// Update local player to disconnected state
}
});
If your app does not require the RemotePlayer
binding, you can add
a listener to the CastContext
itself to monitor session state.
var context = cast.framework.CastContext.getInstance();
context.addEventListener(
cast.framework.CastContextEventType.SESSION_STATE_CHANGED,
function(event) {
switch (event.sessionState) {
case cast.framework.SessionState.SESSION_STARTED:
case cast.framework.SessionState.SESSION_RESUMED:
break;
case cast.framework.SessionState.SESSION_ENDED:
console.log('CastContext: CastSession disconnected');
// Update locally as necessary
break;
}
})
While the user can directly control Cast termination via the framework Cast
button, the sender itself can stop casting using the current CastSession
object.
function stopCasting() {
var castSession = cast.framework.CastContext.getInstance().getCurrentSession();
// End the session and pass 'true' to indicate
// that Web Receiver application should be stopped.
castSession.endSession(true);
}