kakone / GoogleCast

Implementation of the Google Cast protocol (.NET Standard 2.0 library)
GNU General Public License v3.0
141 stars 22 forks source link

Add GetStatusAsync and StopAsync to ReceiverChannel #7

Closed Marcus-L closed 6 years ago

Marcus-L commented 6 years ago

Connecting to a session that a different sender created is now possible by calling StopAsync() on the ReceiverChannel which then under the covers calls GetStatusAsync() (GET_STATUS command) on the receiver channel and then uses the session from the retrieved status to call STOP on the receiver to stop the playing media.

Something like this:

var sender = new Sender();
var receiver = new Receiver()
{
    IPEndPoint = ... // the IP of the receiver playing media from a different sender
}
await sender.ConnectAsync(receiver);
var channel = sender.GetChannel<IReceiverChannel>();
await channel.StopAsync();

Note that there now are StopAsync() methods on both the ReceiverChannel and MediaChannel objects (with different uses). I did not try to implement PauseAsync() on ReceiverChannel, although it might be possible.

Marcus-L commented 6 years ago

This addresses issue #6 which I'd created earlier, can close that out with this PR if it looks good to you.

kakone commented 6 years ago

I'm not agree with this. It seems to work because it cancels the playing, but in fact, it doesn't work (try to do the same thing with a Pause method, it won't work). There are several problems : The StopAsync method shouldn't be on the ReceiverChannel class but in MediaChannel class. In fact, to control again the video in another program, you should have the MediaSessionId and you can't obtain it by sending the GET_STATUS message. In the MediaSessionMessage.cs, the MediaSessionId property can't be nullable. The SessionId property in StopMessage.cs is useless.

I will thinking about this problematic, but I think it's not possible to control the video in another program without passing the MediaSessionId.

Marcus-L commented 6 years ago

In the case where your client did not start the media session, you do not have the MediaSessionId. However, Chromecast still exposes the ability to stop the media from being played on the receiver by other connected clients. This is why STOP can be called using the urn:x-cast:com.google.cast.receiver namespace (in addition to the urn:x-cast:com.google.cast.media namespace).

For example, if you start playing a media using the API, you will notice in Chrome that if you go to the "cast" menu, you still have the ability to view Chromecast devices on your network, see what media is playing, and stop the media. You can do this even though you do not have access to the MediaSessionId, you only have access to the SessionId.

screenshot_091717_110045_pm

You are correct that other than STOP, you cannot control the media being played. I thought I remembered pause being available, but maybe not. However, it is important to have the ability to stop the media from other clients, since you may start the media playing from one API call, and want to stop it from another API call without having access to the MediaSessionId.

You linked to documentation here: https://github.com/thibauts/node-castv2/blob/master/README.md, this document also references calling the STOP command using the urn:x-cast:com.google.cast.receiver namespace with only the SessionId (not the MediaSessionId).

I have tested this and it works, you can stop media calling the STOP command on the receiver channel using the SessionId.

kakone commented 6 years ago

OK, thanks, I understood now, we can stop the current application (that's why we must pass a SessionId to the StopMessage). I added a StopAsync method on the Receiver channel, it should work now.