Sunday, 22 June 2014

Using Google Chromecast from Delphi desktop application

I have done a small example of a desktop application, starting the YouTube app on the Chromecast device and playing a video on your TV. Using some Indy components and a couple of the new REST components that came with XE6. Not bothering with the API's from Google.


This example does not really have any real life usage - since installing Google cast in your Chrome browser or using the YouTube app on your phone would make more sense. So unless you for some reason don't use Chrome as a browser or do not have an iOS or Android phone, this example is not that useful - but it shows the concept.

And I think that the Chromecast is a nice $30 device, that like "almost" anything else can be accessed from Delphi :-D (Update: I might end up using Mozilla's cast device, if the rumors are true - see update at the end of post).

A little while back, I bought a Google Chromecast dongle - a nice inexpensive casting device for your TV, it has built-in support for Netflix, YouTube and various others.

Google does provide an API for iOS, Android and there is an extension for the Chrome browser.

I wanted to access the Chromecast from my desktop application, so a simple description of the protocol, would be more helpful, than digging into some API and converting this to my needs.

It seems that the Chromecast uses a form of DIAL protocol - using UDP to discover and TCP/REST to communicate.

A word of warning: this is a prof of concept - not ready for production or deployment - you need to do some work yourself to make it fit your needs. I have tried to use as little code as possible - leaving out all exception handling :-).

Start with a new Desktop application - could also be a mobile application, but since the mobile YouTube app already has support for Chromecast - it would make little sense :-).

Place a TIdUDPClient, a TIdHTTP, a TLabeledEdit, a TButton, a RESTClient and a RESTRequest component on the form - which all should end up looking a bit like this:


Part 1 - Chromecast discovery.

On the IdUDPClient we set the property BoundIP to the IP address of the PC you will run the application from. In a real application you would of cause get the IP by code - but making that both OS independent and handling multiple IP/Adapters - would add more that 2 lines of code :-). Also set the BroadcastEnabled and the Active properties to true.

On the onClick event of the button, add the following code to broadcast for dial-multiscreen devices:

  // DIAL Service Discovery
  IdUDPClient1.Send('239.255.255.250', 1900, 'M-SEARCH * HTTP/1.1' + #13#10 +
     'HOST: 239.255.255.250:1900' + #13#10 +
     'MAN: "ssdp:discover"'+ #13#10 +
     'MX: 3'+ #13#10 +
     'ST: urn:dial-multiscreen-org:service:dial:1'+ #13#10 +
  //   'ST: ssdp:all'+ #13#10 +
     #13#10);
  IdUDPClient1.ReceiveTimeout := 1000;
  r := IdUDPClient1.ReceiveString(ip, p);
  desc := '';
  if p<>0 then
  begin
    res := TStringList.Create;
    res.Text := r;
    for r in res do
    begin
      if Pos('LOCATION: ', r)=1 then
      begin
        desc := Copy(r, 11 , 9999);
        Break;
      end;
    end;
    res.Free;
  end;
  IdHTTP1.Get(desc);
  servURL := IdHTTP1.Response.RawHeaders.Values['Application-URL'];
  servURL := copy(servURL,1,Length(servURL)-1);  // DIAL REST Service URL

As you can see I only care for the first device that I get on my list of devices that response - but you can play around and see what other devices you can find using the SSDP protocol, using the commented ST: ssdp:all - and throw the response to a TMemo. The DIAL protocol used is explained in more detail here.

Part 2 - Start YouTube app and start video.

Now have the service URL, which is the address the Chromecast device responds to. We add the name of the app - here YouTube to the service URL to get the application URL. If the YouTube app responds, we post a REST request, adding the parameter of the unique id of the video - parsing the the YouTube URL in the TLabeledEdit to only get the unique id.

  // DIAL REST Service
  appURL := servURL+'/YouTube';
  IdHTTP1.Get(appURL);
  if (IdHTTP1.ResponseCode=200) then
  begin
    RESTRequest1.Resource := appURL;
    RESTRequest1.AddParameter('v', Copy(LabeledEdit1.Text, Pos('?v=', LabeledEdit1.Text)+3, 9999));
    RESTRequest1.Method := rmPOST;
    RESTRequest1.Execute;
  end;

Now you can sit back and enjoy the video on your big screen TV :-)

If you do want to dig deeper into the Chromecast - by making your own receiver and sender app - you have to look into the APIs and also get a cast appid from Google.

It would be nice if someone spend the time wrapping the API - for us Delphi/C++ users, or did an example of an mobile app and a receiver app :-)

Update.

It seems like Mozilla has been working on a similar casting device, that might not be that restricted as Google wants to make the Chromecast: http://gigaom.com/2014/06/20/this-firefox-os-powered-streaming-stick-is-mozillas-answer-to-chromecast-exclusive-video/

Links:

The source code: FoilcastClient.
DIAL homepage: http://www.dial-multiscreen.org/
UPnP related: http://upnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v1.1.pdf
Google Cast developer page: https://developers.google.com/cast/

5 comments:

  1. A good example of the use of this script. I'll have to try it to write something like that. The author of Respect!

    ReplyDelete

  2. Regards. I developed a panel to call passwords care . Can generate html and loads it on google chrome where shooting for chromecast with the help of the extension installed on the browser. How could shoot page html5 directly to the chromecast so that attendants could shoot from your window ? Thank you

    ReplyDelete
  3. I guess I am not the only one having all the enjoyment here! Keep up the good work. Thank you for reading.airplay vs chromecast

    ReplyDelete