Integrate Cast v3 into your Chrome app

This developer guide describes how to add Google Cast support to your Chrome sender app using Google Cast SDK v3.

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 TV.

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 Chrome 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 Cast Sender Framework 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:

  1. 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.
  2. The CastSession object manages the session -- it provides state information and triggers events, such as changes to device volume, mute state, and application metadata.
  3. 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.
  4. 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. The button element tag requires the is='google-cast-button' attribute for it to be recognized by the framework.

<button is="google-cast-button"></button>

Alternatively, you can create the button programmatically:

document.createElement('button', 'google-cast-button')

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 receiver state, and --disconnected-color for the disconnected state.

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. This includes changes to the media info.

playerController.addEventListener(
  cast.framework.RemotePlayerEventType.MEDIA_INFO_CHANGED, function() {
    var newMediaInfo = player.mediaInfo;
  });

When events such as pause, play, resume or seek occur, the app will need to act on them and synchronize between itself and the 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 receiver application should be stopped.
  castSession.endSession(true);
}

Next Step

To add more Cast v3 features to your Chrome sender app, visit Add Advanced Cast v3 Features to your Chrome App.