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>
36 #include <vlc_httpd.h>
42 #ifndef PROTOBUF_INLINE_NOT_IN_HEADERS
43 # define PROTOBUF_INLINE_NOT_IN_HEADERS 0
45 #include "cast_channel.pb.h"
46 #include "chromecast_common.h"
48 #define PACKET_HEADER_LEN 4
50 // Media player Chromecast app id
51 static const std::string DEFAULT_CHOMECAST_RECEIVER
= "receiver-0";
52 /* see https://developers.google.com/cast/docs/reference/messages */
53 static const std::string NAMESPACE_MEDIA
= "urn:x-cast:com.google.cast.media";
54 static const std::string NAMESPACE_DEVICEAUTH
= "urn:x-cast:com.google.cast.tp.deviceauth";
55 static const std::string NAMESPACE_CONNECTION
= "urn:x-cast:com.google.cast.tp.connection";
56 static const std::string NAMESPACE_HEARTBEAT
= "urn:x-cast:com.google.cast.tp.heartbeat";
57 static const std::string NAMESPACE_RECEIVER
= "urn:x-cast:com.google.cast.receiver";
60 #define CHROMECAST_CONTROL_PORT 8009
61 #define HTTP_PORT 8010
63 #define PACKET_MAX_LEN 10 * 1024
65 //#define CHROMECAST_VERBOSE
67 // Media player Chromecast app id
68 #define APP_ID "CC1AD845" // Default media player aka DEFAULT_MEDIA_RECEIVER_APPLICATION_ID
72 // An authentication request has been sent
74 // We are sending a connection request
76 // We are connected to the chromecast but the receiver app is not running.
78 // We are launching the media receiver app
80 // The application is ready, but idle
82 // The chromecast rejected the media
84 // A media session is being initiated
91 // Something went wrong and the connection is dead.
93 // Another playback started on the same cast device
97 class ChromecastCommunication
100 ChromecastCommunication( vlc_object_t
* module
, const char* targetIP
, unsigned int devicePort
);
101 ~ChromecastCommunication();
103 * @brief disconnect close the connection with the chromecast
107 static const unsigned kInvalidId
= 0;
109 /* All msg*() methods return kInvalidId on error, 1 or the receiver/player
110 * request ID on success */
114 unsigned msgConnect( const std::string
& destinationId
);
116 unsigned msgReceiverLaunchApp();
117 unsigned msgReceiverGetStatus();
118 unsigned msgReceiverClose(const std::string
& destinationId
);
120 unsigned msgPlayerLoad( const std::string
& destinationId
, unsigned int i_port
,
121 const std::string
& mime
, const vlc_meta_t
*p_meta
);
122 unsigned msgPlayerPlay( const std::string
& destinationId
, int64_t mediaSessionId
);
123 unsigned msgPlayerStop( const std::string
& destinationId
, int64_t mediaSessionId
);
124 unsigned msgPlayerPause( const std::string
& destinationId
, int64_t mediaSessionId
);
125 unsigned msgPlayerGetStatus( const std::string
& destinationId
);
126 unsigned msgPlayerSeek( const std::string
& destinationId
, int64_t mediaSessionId
,
127 const std::string
& currentTime
);
128 unsigned msgPlayerSetVolume( const std::string
& destinationId
, int64_t mediaSessionId
,
129 float volume
, bool mute
);
130 ssize_t
receive( uint8_t *p_data
, size_t i_size
, int i_timeout
, bool *pb_timeout
);
132 const std::string
getServerIp()
137 int sendMessage(const castchannel::CastMessage
&msg
);
139 int buildMessage(const std::string
& namespace_
,
140 const std::string
& payload
,
141 const std::string
& destinationId
= DEFAULT_CHOMECAST_RECEIVER
,
142 castchannel::CastMessage_PayloadType payloadType
= castchannel::CastMessage_PayloadType_STRING
);
143 int pushMediaPlayerMessage( const std::string
& destinationId
, const std::stringstream
& payload
);
144 std::string
GetMedia( unsigned int i_port
, const std::string
& mime
,
145 const vlc_meta_t
*p_meta
);
146 unsigned getNextReceiverRequestId();
147 unsigned getNextRequestId();
150 vlc_object_t
* m_module
;
151 vlc_tls_creds_t
*m_creds
;
153 unsigned m_receiver_requestId
;
154 unsigned m_requestId
;
155 std::string m_serverIp
;
158 /*****************************************************************************
159 * intf_sys_t: description and status of interface
160 *****************************************************************************/
163 enum QueueableMessages
167 intf_sys_t(vlc_object_t
* const p_this
, int local_port
, std::string device_addr
,
168 int device_port
, httpd_host_t
*);
171 void setRetryOnFail(bool);
172 void setHasInput(const std::string mime_type
= "");
174 void setOnInputEventCb(on_input_event_itf on_input_event
, void *on_input_event_data
);
175 void setDemuxEnabled(bool enabled
, on_paused_changed_itf on_paused_changed
,
176 void *on_paused_changed_data
);
177 void requestPlayerStop();
178 States
state() const;
180 void setPacing(bool do_pace
);
182 void sendInputEvent(enum cc_input_event event
, union cc_input_arg arg
);
183 vlc_tick_t
getPauseDelay();
185 int httpd_file_fill( uint8_t *psz_request
, uint8_t **pp_data
, int *pi_data
);
186 void interrupt_wake_up();
189 bool handleMessages();
191 bool processMessage(const castchannel::CastMessage
&msg
);
192 void queueMessage( QueueableMessages msg
);
194 void setPauseState(bool paused
, vlc_tick_t delay
);
195 bool isFinishedPlaying();
196 bool isStateError() const;
197 bool isStatePlaying() const;
198 bool isStateReady() const;
202 void setMeta( vlc_meta_t
*p_meta
);
204 vlc_tick_t
getPlaybackTimestamp();
206 double getPlaybackPosition() const;
208 void setInitialTime( vlc_tick_t time
);
209 // Sets the current state and signal the associated wait cond.
210 // This must be called with the lock held
211 void setState( States state
);
214 void processAuthMessage( const castchannel::CastMessage
& msg
);
215 void processHeartBeatMessage( const castchannel::CastMessage
& msg
);
216 bool processReceiverMessage( const castchannel::CastMessage
& msg
);
217 void processMediaMessage( const castchannel::CastMessage
& msg
);
218 void processConnectionMessage( const castchannel::CastMessage
& msg
);
221 static void* ChromecastThread(void* p_data
);
223 static vlc_tick_t
get_time(void*);
225 static int pace(void*);
226 static void send_input_event(void *, enum cc_input_event event
, union cc_input_arg arg
);
227 static void set_demux_enabled(void *, bool, on_paused_changed_itf
, void *);
229 static void set_pause_state(void*, bool paused
, vlc_tick_t delay
);
231 static void set_meta(void*, vlc_meta_t
*p_meta
);
233 void prepareHttpArtwork();
235 static vlc_tick_t
timeCCToVLC(double);
236 static std::string
timeVLCToCC(vlc_tick_t
);
239 vlc_object_t
* const m_module
;
240 const int m_streaming_port
;
241 const int m_device_port
;
243 std::string m_device_addr
;
245 std::string m_appTransportId
;
246 unsigned m_last_request_id
;
247 int64_t m_mediaSessionId
;
249 mutable vlc_mutex_t m_lock
;
250 vlc_cond_t m_stateChangedCond
;
251 vlc_cond_t m_pace_cond
;
252 vlc_thread_t m_chromecastThread
;
254 on_input_event_itf m_on_input_event
;
255 void *m_on_input_event_data
;
257 on_paused_changed_itf m_on_paused_changed
;
258 void *m_on_paused_changed_data
;
260 ChromecastCommunication
*m_communication
;
261 std::queue
<QueueableMessages
> m_msgQueue
;
263 bool m_retry_on_fail
;
275 vlc_interrupt_t
*m_ctl_thread_interrupt
;
277 httpd_host_t
*m_httpd_host
;
278 httpd_file_t
*m_httpd_file
;
279 std::string m_art_http_ip
;
283 vlc_tick_t m_cc_time_last_request_date
;
284 vlc_tick_t m_cc_time_date
;
285 vlc_tick_t m_cc_time
;
286 vlc_tick_t m_pause_delay
;
288 /* shared structure with the demux-filter */
289 chromecast_common m_common
;
292 uint8_t m_pingRetriesLeft
;
295 #endif /* VLC_CHROMECAST_H */