1 /*****************************************************************************
2 * chromecast.cpp: Chromecast module for vlc
3 *****************************************************************************
4 * Copyright © 2014-2015 VideoLAN
6 * Authors: Adrien Maglo <magsoft@videolan.org>
7 * Jean-Baptiste Kempf <jb@videolan.org>
8 * Steve Lhomme <robux4@videolabs.io>
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU Lesser General Public License as published by
12 * the Free Software Foundation; either version 2.1 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this program; if not, write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
29 #ifndef VLC_CHROMECAST_H
30 #define VLC_CHROMECAST_H
32 #include <vlc_common.h>
33 #include <vlc_plugin.h>
35 #include <vlc_interrupt.h>
41 #ifndef PROTOBUF_INLINE_NOT_IN_HEADERS
42 # define PROTOBUF_INLINE_NOT_IN_HEADERS 0
44 #include "cast_channel.pb.h"
45 #include "chromecast_common.h"
47 #define PACKET_HEADER_LEN 4
49 // Media player Chromecast app id
50 static const std::string DEFAULT_CHOMECAST_RECEIVER
= "receiver-0";
51 /* see https://developers.google.com/cast/docs/reference/messages */
52 static const std::string NAMESPACE_MEDIA
= "urn:x-cast:com.google.cast.media";
53 static const std::string NAMESPACE_DEVICEAUTH
= "urn:x-cast:com.google.cast.tp.deviceauth";
54 static const std::string NAMESPACE_CONNECTION
= "urn:x-cast:com.google.cast.tp.connection";
55 static const std::string NAMESPACE_HEARTBEAT
= "urn:x-cast:com.google.cast.tp.heartbeat";
56 static const std::string NAMESPACE_RECEIVER
= "urn:x-cast:com.google.cast.receiver";
59 #define CHROMECAST_CONTROL_PORT 8009
60 #define HTTP_PORT 8010
62 #define PACKET_MAX_LEN 10 * 1024
64 // Media player Chromecast app id
65 #define APP_ID "CC1AD845" // Default media player aka DEFAULT_MEDIA_RECEIVER_APPLICATION_ID
69 // An authentication request has been sent
71 // We are sending a connection request
73 // We are connected to the chromecast but the receiver app is not running.
75 // We are launching the media receiver app
77 // The application is ready, but idle
79 // A media session is being initiated
85 // Something went wrong and the connection is dead.
89 class ChromecastCommunication
92 ChromecastCommunication( vlc_object_t
* module
, const char* targetIP
, unsigned int devicePort
);
93 ~ChromecastCommunication();
95 * @brief disconnect close the connection with the chromecast
101 void msgConnect( const std::string
& destinationId
);
103 void msgReceiverLaunchApp();
104 void msgReceiverGetStatus();
105 void msgReceiverClose(const std::string
& destinationId
);
107 void msgPlayerLoad( const std::string
& destinationId
, unsigned int i_port
, const std::string
& title
,
108 const std::string
& artwork
, const std::string
& mime
);
109 void msgPlayerPlay( const std::string
& destinationId
, const std::string
& mediaSessionId
);
110 void msgPlayerStop( const std::string
& destinationId
, const std::string
& mediaSessionId
);
111 void msgPlayerPause( const std::string
& destinationId
, const std::string
& mediaSessionId
);
112 void msgPlayerGetStatus( const std::string
& destinationId
);
113 void msgPlayerSeek( const std::string
& destinationId
, const std::string
& mediaSessionId
,
114 const std::string
& currentTime
);
115 void msgPlayerSetVolume( const std::string
& destinationId
, const std::string
& mediaSessionId
,
116 float volume
, bool mute
);
117 ssize_t
receive( uint8_t *p_data
, size_t i_size
, int i_timeout
, bool *pb_timeout
);
119 int sendMessage(const castchannel::CastMessage
&msg
);
121 void buildMessage(const std::string
& namespace_
,
122 const std::string
& payload
,
123 const std::string
& destinationId
= DEFAULT_CHOMECAST_RECEIVER
,
124 castchannel::CastMessage_PayloadType payloadType
= castchannel::CastMessage_PayloadType_STRING
);
125 void pushMediaPlayerMessage( const std::string
& destinationId
, const std::stringstream
& payload
);
126 std::string
GetMedia( unsigned int i_port
, const std::string
& title
,
127 const std::string
& artwork
, const std::string
& mime
);
130 vlc_object_t
* m_module
;
131 vlc_tls_creds_t
*m_creds
;
133 unsigned m_receiver_requestId
;
134 std::atomic_uint m_requestId
;
135 std::string m_serverIp
;
138 /*****************************************************************************
139 * intf_sys_t: description and status of interface
140 *****************************************************************************/
143 enum QueueableMessages
148 intf_sys_t(vlc_object_t
* const p_this
, int local_port
, std::string device_addr
, int device_port
, vlc_interrupt_t
*);
151 bool isFinishedPlaying();
153 void setHasInput(const std::string mime_type
= "");
155 void requestPlayerSeek(mtime_t pos
);
156 void requestPlayerStop();
159 bool handleMessages();
161 void waitAppStarted();
164 void processMessage(const castchannel::CastMessage
&msg
);
165 void queueMessage( QueueableMessages msg
);
167 void setPauseState(bool paused
);
169 void setTitle( const char *psz_title
);
171 void setArtwork( const char *psz_artwork
);
173 mtime_t
getPlaybackTimestamp() const;
175 double getPlaybackPosition() const;
177 void setInitialTime( mtime_t time
);
178 // Sets the current state and signal the associated wait cond.
179 // This must be called with the lock held
180 void setState( States state
);
183 void processAuthMessage( const castchannel::CastMessage
& msg
);
184 void processHeartBeatMessage( const castchannel::CastMessage
& msg
);
185 void processReceiverMessage( const castchannel::CastMessage
& msg
);
186 void processMediaMessage( const castchannel::CastMessage
& msg
);
187 void processConnectionMessage( const castchannel::CastMessage
& msg
);
190 static void* ChromecastThread(void* p_data
);
192 static void set_length(void*, mtime_t length
);
193 static mtime_t
get_time(void*);
194 static double get_position(void*);
195 static void set_initial_time( void*, mtime_t time
);
197 static void wait_app_started(void*);
199 static void request_seek(void*, mtime_t pos
);
200 static void wait_seek_done(void*);
202 static void set_pause_state(void*, bool paused
);
204 static void set_title(void*, const char *psz_title
);
205 static void set_artwork(void*, const char *psz_artwork
);
209 vlc_object_t
* const m_module
;
210 const int m_streaming_port
;
213 std::string m_appTransportId
;
214 std::string m_mediaSessionId
;
217 vlc_cond_t m_stateChangedCond
;
218 vlc_thread_t m_chromecastThread
;
220 ChromecastCommunication m_communication
;
221 std::queue
<QueueableMessages
> m_msgQueue
;
224 std::string m_artwork
;
227 vlc_interrupt_t
*m_ctl_thread_interrupt
;
229 /* local date when playback started/resumed, used by monotone clock */
230 mtime_t m_time_playback_started
;
231 /* local playback time of the input when playback started/resumed */
232 mtime_t m_ts_local_start
;
235 /* shared structure with the demux-filter */
236 chromecast_common m_common
;
239 uint8_t m_pingRetriesLeft
;
242 #endif /* VLC_CHROMECAST_H */