[vlc-commits] chromecast: Rework the state machine
Hugo Beauzée-Luyssen
git at videolan.org
Tue Feb 21 14:00:57 CET 2017
vlc | branch: master | Hugo Beauzée-Luyssen <hugo at beauzee.fr> | Mon Feb 20 13:27:07 2017 +0100| [8310c195849c922f46b736e472d2498f91a4aa7a] | committer: Hugo Beauzée-Luyssen
chromecast: Rework the state machine
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=8310c195849c922f46b736e472d2498f91a4aa7a
---
modules/stream_out/chromecast/chromecast.h | 53 ++-
modules/stream_out/chromecast/chromecast_ctrl.cpp | 418 ++++++++++++----------
2 files changed, 248 insertions(+), 223 deletions(-)
diff --git a/modules/stream_out/chromecast/chromecast.h b/modules/stream_out/chromecast/chromecast.h
index 4ff504c..ac4bc2c 100644
--- a/modules/stream_out/chromecast/chromecast.h
+++ b/modules/stream_out/chromecast/chromecast.h
@@ -64,28 +64,26 @@ static const std::string NAMESPACE_RECEIVER = "urn:x-cast:com.google.cas
// Media player Chromecast app id
#define APP_ID "CC1AD845" // Default media player aka DEFAULT_MEDIA_RECEIVER_APPLICATION_ID
-// Status
-enum connection_status
+enum States
{
- CHROMECAST_DISCONNECTED,
- CHROMECAST_TLS_CONNECTED,
- CHROMECAST_AUTHENTICATED,
- CHROMECAST_APP_STARTED,
- CHROMECAST_CONNECTION_DEAD,
-};
-
-enum command_status {
- NO_CMD_PENDING,
- CMD_LOAD_SENT,
- CMD_PLAYBACK_SENT,
- CMD_SEEK_SENT,
-};
-
-enum receiver_state {
- RECEIVER_IDLE,
- RECEIVER_PLAYING,
- RECEIVER_BUFFERING,
- RECEIVER_PAUSED,
+ // An authentication request has been sent
+ Authenticating,
+ // We are sending a connection request
+ Connecting,
+ // We are connected to the chromecast but the receiver app is not running.
+ Connected,
+ // We are launching the media receiver app
+ Launching,
+ // The application is ready, but idle
+ Ready,
+ // A media session is being initiated
+ Loading,
+ Buffering,
+ Playing,
+ Paused,
+ Seeking,
+ // Something went wrong and the connection is dead.
+ Dead,
};
class ChromecastCommunication
@@ -158,8 +156,6 @@ struct intf_sys_t
private:
bool handleMessages();
- void setConnectionStatus(connection_status status);
-
void waitAppStarted();
void waitSeekDone();
@@ -173,11 +169,12 @@ private:
void setArtwork( const char *psz_artwork );
- void setPlayerStatus(enum command_status status);
-
mtime_t getPlaybackTimestamp() const;
double getPlaybackPosition() const;
+ // Sets the current state and signal the associated wait cond.
+ // This must be called with the lock held
+ void setState( States state );
void mainLoop();
void processAuthMessage( const castchannel::CastMessage& msg );
@@ -211,15 +208,13 @@ private:
std::string m_appTransportId;
std::string m_mediaSessionId;
- receiver_state m_receiverState;
vlc_mutex_t m_lock;
- vlc_cond_t m_loadCommandCond;
+ vlc_cond_t m_stateChangedCond;
vlc_thread_t m_chromecastThread;
ChromecastCommunication m_communication;
- connection_status m_conn_status;
- command_status m_cmd_status;
+ States m_state;
std::atomic_bool m_requested_stop;
std::atomic_bool m_requested_seek;
diff --git a/modules/stream_out/chromecast/chromecast_ctrl.cpp b/modules/stream_out/chromecast/chromecast_ctrl.cpp
index 084355d..9ff2731 100644
--- a/modules/stream_out/chromecast/chromecast_ctrl.cpp
+++ b/modules/stream_out/chromecast/chromecast_ctrl.cpp
@@ -6,6 +6,7 @@
* Authors: Adrien Maglo <magsoft at videolan.org>
* Jean-Baptiste Kempf <jb at videolan.org>
* Steve Lhomme <robux4 at videolabs.io>
+ * Hugo Beauzée-Luyssen <hugo at beauzee.fr>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
@@ -43,18 +44,46 @@
static const mtime_t SEEK_FORWARD_OFFSET = 1000000;
+static const char* StateToStr( States s )
+{
+ switch (s )
+ {
+ case Authenticating:
+ return "Authenticating";
+ case Connecting:
+ return "Connecting";
+ case Connected:
+ return "Connected";
+ case Launching:
+ return "Lauching";
+ case Ready:
+ return "Ready";
+ case Loading:
+ return "Loading";
+ case Buffering:
+ return "Buffering";
+ case Playing:
+ return "Playing";
+ case Paused:
+ return "Paused";
+ case Seeking:
+ return "Seeking";
+ case Dead:
+ return "Dead";
+ }
+ vlc_assert_unreachable();
+}
+
/*****************************************************************************
* intf_sys_t: class definition
*****************************************************************************/
intf_sys_t::intf_sys_t(vlc_object_t * const p_this, int port, std::string device_addr, int device_port, vlc_interrupt_t *p_interrupt)
: m_module(p_this)
, m_streaming_port(port)
- , m_receiverState(RECEIVER_IDLE)
, m_communication( p_this, device_addr.c_str(), device_port )
+ , m_state( Authenticating )
, m_requested_stop(false)
, m_requested_seek(false)
- , m_conn_status(CHROMECAST_DISCONNECTED)
- , m_cmd_status(NO_CMD_PENDING)
, m_has_input(false)
, m_ctl_thread_interrupt(p_interrupt)
, m_time_playback_started( VLC_TS_INVALID )
@@ -64,7 +93,7 @@ intf_sys_t::intf_sys_t(vlc_object_t * const p_this, int port, std::string device
, m_seek_request_time( VLC_TS_INVALID )
{
vlc_mutex_init(&m_lock);
- vlc_cond_init(&m_loadCommandCond);
+ vlc_cond_init( &m_stateChangedCond );
vlc_cond_init(&m_seekCommandCond);
m_common.p_opaque = this;
@@ -96,18 +125,22 @@ intf_sys_t::~intf_sys_t()
var_Destroy( m_module->obj.parent->obj.parent, CC_SHARED_VAR_NAME );
- switch ( m_conn_status )
+ switch ( m_state )
{
- case CHROMECAST_APP_STARTED:
+ case Ready:
+ case Loading:
+ case Buffering:
+ case Playing:
+ case Paused:
+ case Seeking:
// Generate the close messages.
- m_communication.msgReceiverClose(m_appTransportId);
+ m_communication.msgReceiverClose( m_appTransportId );
// ft
- case CHROMECAST_TLS_CONNECTED:
- case CHROMECAST_AUTHENTICATED:
+ case Connecting:
+ case Connected:
+ case Launching:
m_communication.msgReceiverClose(DEFAULT_CHOMECAST_RECEIVER);
// ft
- case CHROMECAST_DISCONNECTED:
- case CHROMECAST_CONNECTION_DEAD:
default:
break;
}
@@ -123,7 +156,7 @@ intf_sys_t::~intf_sys_t()
vlc_cond_signal(&m_seekCommandCond);
vlc_cond_destroy(&m_seekCommandCond);
- vlc_cond_destroy(&m_loadCommandCond);
+ vlc_cond_destroy(&m_stateChangedCond);
vlc_mutex_destroy(&m_lock);
}
@@ -138,26 +171,20 @@ void intf_sys_t::setHasInput( bool b_has_input, const std::string mime_type )
if( this->m_has_input )
{
mutex_cleanup_push(&m_lock);
- while (m_conn_status != CHROMECAST_APP_STARTED && m_conn_status != CHROMECAST_CONNECTION_DEAD)
- {
- msg_Dbg( m_module, "setHasInput waiting for Chromecast connection, current %d", m_conn_status);
- vlc_cond_wait(&m_loadCommandCond, &m_lock);
- }
+ waitAppStarted();
vlc_cleanup_pop();
- if (m_conn_status == CHROMECAST_CONNECTION_DEAD)
+ if ( m_state == Dead )
{
msg_Warn( m_module, "no Chromecast hook possible");
return;
}
-
- if ( m_receiverState == RECEIVER_IDLE )
- {
- // we cannot start a new load when the last one is still processing
- m_ts_local_start = VLC_TS_0;
- m_communication.msgPlayerLoad( m_appTransportId, m_streaming_port, m_title, m_artwork, mime_type );
- setPlayerStatus(CMD_LOAD_SENT);
- }
+ // We should now be in the ready state, and therefor have a valid transportId
+ assert( m_state == Ready && m_appTransportId.empty() == false );
+ // we cannot start a new load when the last one is still processing
+ m_ts_local_start = VLC_TS_0;
+ m_communication.msgPlayerLoad( m_appTransportId, m_streaming_port, m_title, m_artwork, mime_type );
+ setState( Loading );
}
}
@@ -206,10 +233,7 @@ void intf_sys_t::mainLoop()
{
vlc_interrupt_set( m_ctl_thread_interrupt );
- vlc_mutex_lock(&m_lock);
- setConnectionStatus(CHROMECAST_TLS_CONNECTED);
- vlc_mutex_unlock(&m_lock);
-
+ // State was already initialized as Authenticating
m_communication.msgAuth();
while ( !vlc_killed() && handleMessages() )
@@ -236,7 +260,7 @@ void intf_sys_t::processAuthMessage( const castchannel::CastMessage& msg )
else
{
vlc_mutex_locker locker(&m_lock);
- setConnectionStatus(CHROMECAST_AUTHENTICATED);
+ setState( Connecting );
m_communication.msgConnect(DEFAULT_CHOMECAST_RECEIVER);
m_communication.msgReceiverGetStatus();
}
@@ -274,55 +298,68 @@ void intf_sys_t::processReceiverMessage( const castchannel::CastMessage& msg )
json_value applications = (*p_data)["status"]["applications"];
const json_value *p_app = NULL;
- vlc_mutex_locker locker(&m_lock);
for (unsigned i = 0; i < applications.u.array.length; ++i)
{
- std::string appId(applications[i]["appId"]);
- if (appId == APP_ID)
+ if ( strcmp( applications[i]["appId"], APP_ID ) == 0 )
{
- const char *pz_transportId = applications[i]["transportId"];
- if (pz_transportId != NULL)
+ if ( (const char*)applications[i]["transportId"] != NULL)
{
- m_appTransportId = std::string(pz_transportId);
p_app = &applications[i];
+ break;
}
- break;
}
}
- if ( p_app )
+ vlc_mutex_locker locker(&m_lock);
+
+ switch ( m_state )
{
- if (!m_appTransportId.empty()
- && m_conn_status == CHROMECAST_AUTHENTICATED)
+ case Connecting:
+ // We were connecting & fetching the current status.
+ // The media receiver app is running, we are ready to proceed
+ if ( p_app != NULL )
{
+ msg_Dbg( m_module, "Media receiver application was already running" );
+ m_appTransportId = (const char*)(*p_app)["transportId"];
+ setState( Ready );
m_communication.msgConnect( m_appTransportId );
- setPlayerStatus(NO_CMD_PENDING);
- setConnectionStatus(CHROMECAST_APP_STARTED);
}
- }
- else
- {
- switch( m_conn_status )
+ else
{
- /* If the app is no longer present */
- case CHROMECAST_APP_STARTED:
- msg_Warn( m_module, "app is no longer present. closing");
- m_communication.msgReceiverClose(m_appTransportId);
- setConnectionStatus(CHROMECAST_CONNECTION_DEAD);
- break;
-
- case CHROMECAST_AUTHENTICATED:
- msg_Dbg( m_module, "Chromecast was running no app, launch media_app");
+ setState( Connected );
+ }
+ break;
+ case Launching:
+ // We already asked for the media receiver application to start
+ if ( p_app != NULL )
+ {
+ msg_Dbg( m_module, "Media receiver application has been started." );
+ setState( Ready );
+ m_appTransportId = (const char*)(*p_app)["transportId"];
+ m_communication.msgConnect( m_appTransportId );
+ }
+ break;
+ case Loading:
+ case Playing:
+ case Paused:
+ case Seeking:
+ case Ready:
+ if ( p_app == NULL )
+ {
+ msg_Warn( m_module, "Media receiver application got closed." );
+ setState( Connected );
m_appTransportId = "";
- m_mediaSessionId = ""; // this session is not valid anymore
- m_receiverState = RECEIVER_IDLE;
- m_communication.msgReceiverLaunchApp();
- break;
-
- default:
- break;
+ m_mediaSessionId = "";
}
-
+ break;
+ case Connected:
+ // We might receive a RECEIVER_STATUS while being connected, when pinging/asking the status
+ if ( p_app == NULL )
+ break;
+ // else: fall through and warn
+ default:
+ msg_Warn( m_module, "Unexpected RECEIVER_STATUS with state %d", m_state );
+ break;
}
}
else if (type == "LAUNCH_ERROR")
@@ -330,6 +367,8 @@ void intf_sys_t::processReceiverMessage( const castchannel::CastMessage& msg )
json_value reason = (*p_data)["reason"];
msg_Err( m_module, "Failed to start the MediaPlayer: %s",
(const char *)reason);
+ vlc_mutex_locker locker(&m_lock);
+ setState( Dead );
}
else
{
@@ -352,25 +391,20 @@ void intf_sys_t::processMediaMessage( const castchannel::CastMessage& msg )
status[0]["playerState"].operator const char *(),
(int)(json_int_t) status[0]["mediaSessionId"]);
- vlc_mutex_locker locker(&m_lock);
- receiver_state oldPlayerState = m_receiverState;
- std::string newPlayerState = status[0]["playerState"].operator const char *();
- std::string idleReason = status[0]["idleReason"].operator const char *();
+ std::string newPlayerState = (const char*)status[0]["playerState"];
+ std::string idleReason = (const char*)status[0]["idleReason"];
+
+ vlc_mutex_locker locker( &m_lock );
if (newPlayerState == "IDLE")
- m_receiverState = RECEIVER_IDLE;
- else if (newPlayerState == "PLAYING")
- m_receiverState = RECEIVER_PLAYING;
- else if (newPlayerState == "BUFFERING")
- m_receiverState = RECEIVER_BUFFERING;
- else if (newPlayerState == "PAUSED")
- m_receiverState = RECEIVER_PAUSED;
- else if (!newPlayerState.empty())
- msg_Warn( m_module, "Unknown Chromecast state %s", newPlayerState.c_str());
-
- if (m_receiverState == RECEIVER_IDLE)
{
- m_mediaSessionId = ""; // this session is not valid anymore
+ if ( m_state != Ready )
+ {
+ // The playback stopped
+ m_mediaSessionId = "";
+ m_time_playback_started = VLC_TS_INVALID;
+ setState( Ready );
+ }
}
else
{
@@ -385,79 +419,74 @@ void intf_sys_t::processMediaMessage( const castchannel::CastMessage& msg )
msg_Warn( m_module, "different mediaSessionId detected %s was %s", session_id, this->m_mediaSessionId.c_str());
m_mediaSessionId = session_id;
}
- }
- if (m_receiverState != oldPlayerState)
- {
-#ifndef NDEBUG
- msg_Dbg( m_module, "change Chromecast player state from %d to %d", oldPlayerState, m_receiverState );
-#endif
- switch( m_receiverState )
+ if (newPlayerState == "PLAYING")
{
- case RECEIVER_BUFFERING:
- if ( double(status[0]["currentTime"]) == 0.0 )
+ msg_Dbg( m_module, "Playback started with an offset of %" PRId64 " now:%" PRId64 " i_ts_local_start:%" PRId64,
+ m_chromecast_start_time, m_time_playback_started, m_ts_local_start);
+ if ( m_state != Playing )
{
- m_receiverState = oldPlayerState;
- msg_Dbg( m_module, "Invalid buffering time, keep previous state %d", oldPlayerState);
+ /* TODO reset demux PCR ? */
+ if (unlikely(m_chromecast_start_time == VLC_TS_INVALID)) {
+ msg_Warn( m_module, "start playing without buffering" );
+ m_chromecast_start_time = (1 + mtime_t( double( status[0]["currentTime"] ) ) ) * 1000000L;
+ }
+ m_time_playback_started = mdate();
+ if ( m_state == Seeking )
+ vlc_cond_signal( &m_seekCommandCond );
+ setState( Playing );
}
- else
+ }
+ else if (newPlayerState == "BUFFERING")
+ {
+ if ( m_state != Buffering )
{
- m_chromecast_start_time = (1 + mtime_t( double( status[0]["currentTime"] ) ) ) * 1000000L;
- msg_Dbg( m_module, "Playback pending with an offset of %" PRId64, m_chromecast_start_time);
+ if ( double(status[0]["currentTime"]) == 0.0 )
+ {
+ msg_Dbg( m_module, "Invalid buffering time, keep current state");
+ }
+ else
+ {
+ m_chromecast_start_time = (1 + mtime_t( double( status[0]["currentTime"] ) ) ) * 1000000L;
+ msg_Dbg( m_module, "Playback pending with an offset of %" PRId64, m_chromecast_start_time);
+ if ( m_state == Seeking )
+ vlc_cond_signal( &m_seekCommandCond );
+ m_time_playback_started = VLC_TS_INVALID;
+ setState( Buffering );
+ }
}
- m_time_playback_started = VLC_TS_INVALID;
- break;
-
- case RECEIVER_PLAYING:
- /* TODO reset demux PCR ? */
- if (unlikely(m_chromecast_start_time == VLC_TS_INVALID)) {
- msg_Warn( m_module, "start playing without buffering" );
+ }
+ else if (newPlayerState == "PAUSED")
+ {
+ if ( m_state != Paused )
+ {
m_chromecast_start_time = (1 + mtime_t( double( status[0]["currentTime"] ) ) ) * 1000000L;
+ #ifndef NDEBUG
+ msg_Dbg( m_module, "Playback paused with an offset of %" PRId64 " date_play_start:%" PRId64, m_chromecast_start_time, m_time_playback_started);
+ #endif
+
+ if ( m_time_playback_started != VLC_TS_INVALID && m_state == Playing )
+ {
+ /* this is a pause generated remotely, adjust the playback time */
+ m_ts_local_start += mdate() - m_time_playback_started;
+ #ifndef NDEBUG
+ msg_Dbg( m_module, "updated i_ts_local_start:%" PRId64, m_ts_local_start);
+ #endif
+ }
+ m_time_playback_started = VLC_TS_INVALID;
+ setState( Paused );
}
- setPlayerStatus(CMD_PLAYBACK_SENT);
- m_time_playback_started = mdate();
-#ifndef NDEBUG
- msg_Dbg( m_module, "Playback started with an offset of %" PRId64 " now:%" PRId64 " i_ts_local_start:%" PRId64, m_chromecast_start_time, m_time_playback_started, m_ts_local_start);
-#endif
- break;
-
- case RECEIVER_PAUSED:
- m_chromecast_start_time = (1 + mtime_t( double( status[0]["currentTime"] ) ) ) * 1000000L;
-#ifndef NDEBUG
- msg_Dbg( m_module, "Playback paused with an offset of %" PRId64 " date_play_start:%" PRId64, m_chromecast_start_time, m_time_playback_started);
-#endif
-
- if ( m_time_playback_started != VLC_TS_INVALID && oldPlayerState == RECEIVER_PLAYING )
+ }
+ else if ( newPlayerState == "LOADING" )
+ {
+ if ( m_state != Loading )
{
- /* this is a pause generated remotely, adjust the playback time */
- m_ts_local_start += mdate() - m_time_playback_started;
-#ifndef NDEBUG
- msg_Dbg( m_module, "updated i_ts_local_start:%" PRId64, m_ts_local_start);
-#endif
+ msg_Dbg( m_module, "Chromecast is loading the stream" );
+ setState( Loading );
}
- m_time_playback_started = VLC_TS_INVALID;
- break;
-
- case RECEIVER_IDLE:
- if ( m_has_input )
- setPlayerStatus(NO_CMD_PENDING);
- m_time_playback_started = VLC_TS_INVALID;
- break;
}
- }
-
- if (m_receiverState == RECEIVER_BUFFERING && m_seek_request_time != VLC_TS_INVALID)
- {
- msg_Dbg( m_module, "Chromecast seeking possibly done");
- vlc_cond_signal( &m_seekCommandCond );
- }
-
- if ( (m_cmd_status != CMD_LOAD_SENT || idleReason == "CANCELLED") && m_receiverState == RECEIVER_IDLE && m_has_input )
- {
- msg_Dbg( m_module, "the device missed the LOAD command");
- m_ts_local_start = VLC_TS_0;
- m_communication.msgPlayerLoad( m_appTransportId, m_streaming_port, m_title, m_artwork, m_mime );
- setPlayerStatus(CMD_LOAD_SENT);
+ else if (!newPlayerState.empty())
+ msg_Warn( m_module, "Unknown Chromecast MEDIA_STATUS state %s", newPlayerState.c_str());
}
}
else if (type == "LOAD_FAILED")
@@ -465,7 +494,7 @@ void intf_sys_t::processMediaMessage( const castchannel::CastMessage& msg )
msg_Err( m_module, "Media load failed");
vlc_mutex_locker locker(&m_lock);
/* close the app to restart it */
- if ( m_conn_status == CHROMECAST_APP_STARTED )
+ if ( m_state == Launching )
m_communication.msgReceiverClose(m_appTransportId);
else
m_communication.msgReceiverGetStatus();
@@ -476,7 +505,7 @@ void intf_sys_t::processMediaMessage( const castchannel::CastMessage& msg )
}
else if (type == "INVALID_REQUEST")
{
- msg_Dbg( m_module, "We sent an invalid request reason:%s", (*p_data)["reason"].operator const char *());
+ msg_Dbg( m_module, "We sent an invalid request reason:%s", (const char*)(*p_data)["reason"] );
}
else
{
@@ -493,12 +522,15 @@ void intf_sys_t::processConnectionMessage( const castchannel::CastMessage& msg )
std::string type((*p_data)["type"]);
json_value_free(p_data);
- if (type == "CLOSE")
+ if ( type == "CLOSE" )
{
- msg_Warn( m_module, "received close message");
+ // Close message indicates an application is being closed, not the connection.
+ // From this point on, we need to relaunch the media receiver app
setHasInput( false );
vlc_mutex_locker locker(&m_lock);
- setConnectionStatus(CHROMECAST_CONNECTION_DEAD);
+ m_appTransportId = "";
+ m_mediaSessionId = "";
+ setState( Connected );
// make sure we unblock the demuxer
m_seek_request_time = VLC_TS_INVALID;
vlc_cond_signal(&m_seekCommandCond);
@@ -536,8 +568,7 @@ bool intf_sys_t::handleMessages()
msg_Err( m_module, "snprintf() truncated string for mediaSessionId" );
current_time[sizeof(current_time) - 1] = '\0';
}
- vlc_mutex_locker locker(&m_lock);
- setPlayerStatus(CMD_SEEK_SENT);
+ // No need to change the state to "Seeking" it was already done upon requesting
/* send a fake time to seek to, to make sure the device flushes its buffers */
m_communication.msgPlayerSeek( m_appTransportId, m_mediaSessionId, current_time );
}
@@ -555,7 +586,8 @@ bool intf_sys_t::handleMessages()
{
msg_Err( m_module, "The connection to the Chromecast died (receiving).");
vlc_mutex_locker locker(&m_lock);
- setConnectionStatus(CHROMECAST_CONNECTION_DEAD);
+ setState( Dead );
+ return false;
}
if (b_pingTimeout)
@@ -570,9 +602,7 @@ bool intf_sys_t::handleMessages()
msg.ParseFromArray(p_packet + PACKET_HEADER_LEN, i_payloadSize);
processMessage(msg);
}
-
- vlc_mutex_locker locker(&m_lock);
- return m_conn_status != CHROMECAST_CONNECTION_DEAD;
+ return true;
}
void intf_sys_t::notifySendRequest()
@@ -593,38 +623,45 @@ void intf_sys_t::requestPlayerSeek(mtime_t pos)
if ( pos != VLC_TS_INVALID )
m_ts_local_start = pos;
m_requested_seek = true;
+ setState( Seeking );
notifySendRequest();
}
void intf_sys_t::setPauseState(bool paused)
{
msg_Dbg( m_module, "%s state for %s", paused ? "paused" : "playing", m_title.c_str() );
+ vlc_mutex_locker locker( &m_lock );
if ( !paused )
{
- if ( !m_mediaSessionId.empty() && m_receiverState != RECEIVER_IDLE )
+ if ( !m_mediaSessionId.empty() )
{
m_communication.msgPlayerPlay( m_appTransportId, m_mediaSessionId );
- setPlayerStatus(CMD_PLAYBACK_SENT);
}
}
else
{
- if ( !m_mediaSessionId.empty() && m_receiverState != RECEIVER_IDLE )
+ if ( !m_mediaSessionId.empty() && m_state != Paused )
{
m_communication.msgPlayerPause( m_appTransportId, m_mediaSessionId );
- setPlayerStatus(CMD_PLAYBACK_SENT);
}
}
}
void intf_sys_t::waitAppStarted()
{
- vlc_mutex_locker locker(&m_lock);
- mutex_cleanup_push(&m_lock);
- while ( m_conn_status != CHROMECAST_APP_STARTED &&
- m_conn_status != CHROMECAST_CONNECTION_DEAD )
- vlc_cond_wait(&m_loadCommandCond, &m_lock);
- vlc_cleanup_pop();
+ while ( m_state != Ready && m_state != Dead )
+ {
+ if ( m_state == Connected )
+ {
+ msg_Dbg( m_module, "Starting the media receiver application" );
+ // Don't use setState as we don't want to signal the condition in this case.
+ m_state = Launching;
+ m_communication.msgReceiverLaunchApp();
+ }
+ msg_Dbg( m_module, "Waiting for Chromecast media receiver app to be ready" );
+ vlc_cond_wait(&m_stateChangedCond, &m_lock);
+ }
+ msg_Dbg( m_module, "Done waiting for application. transportId: %s", m_appTransportId.c_str() );
}
void intf_sys_t::waitSeekDone()
@@ -633,8 +670,7 @@ void intf_sys_t::waitSeekDone()
if ( m_seek_request_time != VLC_TS_INVALID )
{
mutex_cleanup_push(&m_lock);
- while ( m_chromecast_start_time < m_seek_request_time &&
- m_conn_status == CHROMECAST_APP_STARTED )
+ while ( m_state == Seeking )
{
#ifndef NDEBUG
msg_Dbg( m_module, "waiting for Chromecast seek" );
@@ -649,23 +685,10 @@ void intf_sys_t::waitSeekDone()
}
}
-void intf_sys_t::setConnectionStatus(connection_status status)
-{
- if (m_conn_status != status)
- {
-#ifndef NDEBUG
- msg_Dbg(m_module, "change Chromecast connection status from %d to %d", m_conn_status, status);
-#endif
- m_conn_status = status;
- vlc_cond_broadcast(&m_loadCommandCond);
- vlc_cond_signal(&m_seekCommandCond);
- }
-}
-
bool intf_sys_t::isFinishedPlaying()
{
vlc_mutex_locker locker(&m_lock);
- return m_conn_status == CHROMECAST_CONNECTION_DEAD || (m_receiverState == RECEIVER_BUFFERING && m_cmd_status != CMD_SEEK_SENT);
+ return m_state == Ready;
}
void intf_sys_t::setTitle(const char* psz_title)
@@ -684,31 +707,23 @@ void intf_sys_t::setArtwork(const char* psz_artwork)
m_artwork = "";
}
-void intf_sys_t::setPlayerStatus(command_status status)
-{
- if (m_cmd_status != status)
- {
- msg_Dbg(m_module, "change Chromecast command status from %d to %d", m_cmd_status, status);
- m_cmd_status = status;
- }
-}
-
mtime_t intf_sys_t::getPlaybackTimestamp() const
{
- switch( m_receiverState )
+ switch( m_state )
{
- case RECEIVER_PLAYING:
+ case Playing:
return ( mdate() - m_time_playback_started ) + m_ts_local_start;
-
- case RECEIVER_IDLE:
+ case Ready:
msg_Dbg(m_module, "receiver idle using buffering time %" PRId64, m_ts_local_start);
break;
- case RECEIVER_BUFFERING:
+ case Buffering:
msg_Dbg(m_module, "receiver buffering using buffering time %" PRId64, m_ts_local_start);
break;
- case RECEIVER_PAUSED:
+ case Paused:
msg_Dbg(m_module, "receiver paused using buffering time %" PRId64, m_ts_local_start);
break;
+ default:
+ break;
}
return m_ts_local_start;
}
@@ -720,6 +735,18 @@ double intf_sys_t::getPlaybackPosition() const
return 0.0;
}
+void intf_sys_t::setState( States state )
+{
+ if ( m_state != state )
+ {
+#ifndef NDEBUG
+ msg_Dbg( m_module, "Switching from state %s to %s", StateToStr( m_state ), StateToStr( state ) );
+#endif
+ m_state = state;
+ vlc_cond_signal( &m_stateChangedCond );
+ }
+}
+
mtime_t intf_sys_t::get_time(void *pt)
{
intf_sys_t *p_this = reinterpret_cast<intf_sys_t*>(pt);
@@ -743,7 +770,10 @@ void intf_sys_t::set_length(void *pt, mtime_t length)
void intf_sys_t::wait_app_started(void *pt)
{
intf_sys_t *p_this = reinterpret_cast<intf_sys_t*>(pt);
+ vlc_mutex_locker locker( &p_this->m_lock);
+ mutex_cleanup_push( &p_this->m_lock );
p_this->waitAppStarted();
+ vlc_cleanup_pop();
}
void intf_sys_t::request_seek(void *pt, mtime_t pos)
More information about the vlc-commits
mailing list