Chromecast Hello World – Part 2, Receiver App

This is the second part of the Hello World app we started earlier.

In this part we are going to create a receiver app for Chromecast.

Overview

Receiver application is notting but a web application that gets loaded on the Chrome browser that is in the Cast device. Only one caveat, In order to load the web application we need to whitelist the application. We do not give it a absolute URL but a App_ID that google provides when you whitelist your domain (it will make more sense later in the post below).
This web application is launched on the cast device when a sender app, sends the message to do so. At this time there is a websocket connection between the sender and receiver which is managed by the Cast API. This API exposes ability to transmit commands between sender and receiver. We can do the standard play, pause etc. In addition we can send any free form of message as we choose. This is how authentication is done on the receiver app as well. (Passing Auth token from sender app to receiver app, that is how it would play content on netflix app).

Lets gets started.

Receiver App

Receiver app will be much simpler and we would want to keep it that way because cast has limited resources. You would not want to perform heavy computation on receiver app.
To create a receiver app, you begin with importing the following script on your receiver html page.

<script src="https://www.gstatic.com/cast/js/receiver/1.0/cast_receiver.js"></script>

With that we now can initialize our receiver application.
To do this, we start by creating Receiver object. This receiver object lets us perform media actions on the media content in the page.
Receives notification when media play is complete and sends it to the sender application. (There are some guidelines provided by Google on how we should manage this, but for this demo we are going to simply play an mp3)
Lets add the script below:

      <script type="text/javascript">

	var receiver = new cast.receiver.Receiver(
	    'YOUR_APP_ID', [cast.receiver.RemoteMedia.NAMESPACE], "", 5);
	var remoteMedia = new cast.receiver.RemoteMedia();
	remoteMedia.addChannelFactory(
	    receiver.createChannelFactory(cast.receiver.RemoteMedia.NAMESPACE));

	receiver.start();

	window.addEventListener('load', function() {
	  var elem = document.getElementById('music-player');
	  remoteMedia.setMediaElement(elem);
	});

	</script>

Here, we create a Receiver object with the App_ID provided google, this would be the App_ID that sender application would have sent to cast. We then setup the media element that will be managed by Cast. (In this case there is a audio element that has an id of ‘music-player’).

Here is the full HTML of the receiver application:

<html>
   <script src="https://www.gstatic.com/cast/js/receiver/1.0/cast_receiver.js"></script>
   <script type="text/javascript">

	var receiver = new cast.receiver.Receiver(
	    'YOUR_APP_ID', [cast.receiver.RemoteMedia.NAMESPACE], "", 5);
	var remoteMedia = new cast.receiver.RemoteMedia();
	remoteMedia.addChannelFactory(
	    receiver.createChannelFactory(cast.receiver.RemoteMedia.NAMESPACE));

	receiver.start();

	window.addEventListener('load', function() {
	  var elem = document.getElementById('music-player');
	  remoteMedia.setMediaElement(elem);
	});

   </script>

   <body>
      <img src="logo.png"/>
      <audio autoplay id="music-player">
         <source src="test.mp3" type="audio/mpeg">
      </audio>
   </body>
</html>

Screen Shot 2013-09-15 at 1.21.00 PM

Thats it!, we have the receiver application that. This page is simple when loaded will play the test.mp3 music on the receiver. Remember the media controls we did on the sender, like pause, stop. That will mange this audio here. You can try my sender app from github. Load the “music-player.html”

Full code could be found on github. https://github.com/manijshrestha/chromecast

Chromecast Hello World

Since the launch of google chromecast, I had been thinking about writing a quick app. Here is my attempt to build a simple chromecast app.
This will be multipart post as chromecast app needs different pieces to work together.

Chromecast Overview
Chromecast app consist of 2 part. One is the “Sender” App and another is the “Receiver”. Below image describes how it all fits together:
https://developers.google.com/cast/images/Diagram.jpg
Sender app can be a web app or a native ios or an android app.

Only thing sender does is to message the chromecast device to play a content. It can pass various parameters.

Behind the scene, your device and cast device in the network is using a managed websocket connection.

Today I am going to start with a simple web app as a sender app that will play youtube content on your cast device.
Google Chromecast web app can be a simple html page where “Chrome cast plugin” in Chrome browser will inject cast specific stuff to it.

Before we begin there are few things we need to take care of.

We must be running Chrome version 28 or higher.

Download the chomecast extension from chrome web store.

Enable developer option

We would need to enable developer option for your cast extension.
Here is how: Open “chrome://extensions” on your browser address bar.
Look for “Google Cast” extension, click on “options”, You should see page like below:

Screen Shot 2013-09-14 at 2.05.52 PM

Click on the cast icon 4 times. You should see following developer options appear (Google Loves Easter Egg… 🙂 )

Screen Shot 2013-09-14 at 2.08.44 PM

While you are at it, put “localhost” in the box, so the chromecast extension will inject in the required javascript on your page. You can add more domain as you would like but remember you need to get google’s blessing and get it whitelisted first.

White listing your receiver

In order build application and run on your chromecast for development, you will need to “whitelist” your device. Detailed instruction could be found here:
It takes few hours to a day to get it approved. You can get 2 URL whitelisted as well, usually one for test and one for production.

Sender

Sender Part of the application is responsible to detect available cast devices in the network. Sender app then is able to launch the given application on the Receiver cast device.

This tutorial we will be building a simple Sender app, that will open youtube on your cast device. Lets get started.
To test this, I had apache server running on my machine where I could host my app to send these messages to cast device. (Remember we had to put localhost on the extension?, without that it would not have initialized the cast api)

So Lets get it started.

First thing we need to do is to tell cast that it is able to “cast” content, to do this we need to put data-cast-api-enabled=”true” attribute on the html tag.

<html data-cast-api-enabled="true">
<head>
	<title>Chromecast Sender</title>
.. .. ..

I am going to be using very simple page and jquery to put it all together rather than using other js framework to demonstrate this.

Lets import the jQuery in our page

<script src="http://code.jquery.com/jquery-2.0.3.min.js"></script>

Now, let the fun begin, start a new script tag and lets initialize the cast.

   var cast_api, cv_activity;
   var receiverList = {};

   // Wait for API to post a message to us
   window.addEventListener("message", function(event) {
     if (event.source == window && event.data && event.data.source == "CastApi" && event.data.event == "Hello") {
	    initializeApi();
     }
   });

Here we what we did, we created some global variables to keep track of things. We added a event listener, this is because, the chomecast extension basically triggers this event. We verify it by running those checks 🙂 CastApi sends “Hello” event telling our page that cast extension is present. When this happens, we start by calling our initializeApi function.

Lets write that function,

   initializeApi = function() {
      cast_api = new cast.Api();
      cast_api.addReceiverListener("YouTube", onReceiverList);
      };

We are creating an instance of cast.Api telling it that we will be calling “YouTube” receiver app. The second parameter is the function name that will be called by cast api with list of receiver that is available.

Lets take care of that now.

   onReceiverList = function(list) {
   if (list.length > 0 ) {
      $("#receivers").empty();
      $.each(list, function(index, receiver){
         receiverList[receiver.id] = receiver;
         $device = $("<input type='radio' name='device-to-play' data-receiver-id=" +receiver.id+">"+receiver.name+"</li>");
         $("#receivers").append($device);
       });
    } else {
      $("#receivers").html("Opps No Cast device was found in the network.");
    }
   };

“list” consist of all the receiver that is available currently. We need to keep track of this so that we can send message to particular receiver later.

So, at this point we now have a sender application that is aware of cast devices that we can send message to.

Lets, send a message now.

Sending a message

We send a message to a receiver cast device via javascript. The device will then start the activity (“Activity”, if you have done some android stuff, you will feel right at home)
For this demo, lets assume that we are going to start a youtube video, we pass on the video id to be played.

	doLaunch = function(receiver, videoId) {
					var request = new cast.LaunchRequest("YouTube", receiver);
					request.parameters = "v="+videoId;
					request.description = new cast.LaunchDescription();
					request.description.text = "Playing Via Sender App";
					cast_api.launch(request, onLaunch);
				}

Here we are telling the cast device that we want to start “YouTube” app. (This could be other app id as well, we will talk about it in receiver section).
“receiver”, is one of the receiver we got from the list above.
we then call the “launch” function with a callback function name, in this case we call it “onLaunch”. This function will be called by the api once it gets a response from the receiver.

Here is onLaunch:

onLaunch = function(activity) {
					if (activity.status == "running") {
						cv_activity = activity;
						$("#status").html("On Air");
					} else {
						$("#status").html("Idle");
					}
				}

When we get the activity response we can check its status to know whats going on. If it is “running” we know that it is now running the activity. On the UI, we are putting “On Air” message “Idle” otherwise. (Currently you could get one of the three status: ‘running’, ‘stopped’, or ‘error’)

Thats it with the code above you are now able to fire up an activity on cast device.
Lets cover one more thing. If you need to send other message such as “pause” or “stop”, we would need to pass on activity id and call back function that needs to be called.
I am going to show how to stop the running media below:

   doStop = function() {
                         cast_api.stopActivity(cv_activity.activityId, onStop);
                       }

   onStop = function(mediaResult) {
					$("#status").html(mediaResult.status);
				}

Here we are calling “stopActivity” along with activityId of the running activity and a function to call, in this case it is “onStop”. Here we are simply putting the status string on the page.

You can see my sender.html code in following gist

Here is the github repo if you want to look at full code.
https://github.com/manijshrestha/chromecast/blob/master/sender/sender.html

Here is a view of finished product.
Screen Shot 2013-09-14 at 3.25.11 PM