[vlc-devel] [PATCH 07/33] chromecast: move processMessage() in the communication handler
Steve Lhomme
robux4 at videolabs.io
Wed Dec 23 12:58:26 CET 2015
---
modules/stream_out/chromecast/cast.cpp | 235 +++-------------------
modules/stream_out/chromecast/chromecast.h | 7 +
modules/stream_out/chromecast/chromecast_ctrl.cpp | 188 ++++++++++++++++-
3 files changed, 217 insertions(+), 213 deletions(-)
diff --git a/modules/stream_out/chromecast/cast.cpp b/modules/stream_out/chromecast/cast.cpp
index 9b1f0ca..cf4c966 100644
--- a/modules/stream_out/chromecast/cast.cpp
+++ b/modules/stream_out/chromecast/cast.cpp
@@ -45,19 +45,22 @@
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/io/coded_stream.h>
-#include "../../misc/webservices/json.h"
-
#define PACKET_MAX_LEN 10 * 1024
#define PACKET_HEADER_LEN 4
struct sout_stream_sys_t
{
sout_stream_sys_t(intf_sys_t *intf)
- : p_tls(NULL),
- i_status(CHROMECAST_DISCONNECTED), p_out(NULL)
- ,p_intf(intf)
+ : p_tls(NULL)
+ , p_out(NULL)
+ , p_intf(intf)
{
}
+
+ ~sout_stream_sys_t()
+ {
+ delete p_intf;
+ }
int i_sock_fd;
vlc_tls_creds_t *p_creds;
@@ -65,10 +68,6 @@ struct sout_stream_sys_t
vlc_thread_t chromecastThread;
- int i_status;
- vlc_mutex_t lock;
- vlc_cond_t loadCommandCond;
-
sout_stream_t *p_out;
intf_sys_t * const p_intf;
};
@@ -213,7 +212,7 @@ static int Open(vlc_object_t *p_this)
Clean(p_stream);
return VLC_EGENERIC;
}
- p_sys->i_status = CHROMECAST_TLS_CONNECTED;
+ p_sys->p_intf->i_status = CHROMECAST_TLS_CONNECTED;
char psz_localIP[NI_MAXNUMERICHOST];
if (net_GetSockAddress(p_sys->i_sock_fd, psz_localIP, NULL))
@@ -249,9 +248,6 @@ static int Open(vlc_object_t *p_this)
return VLC_EGENERIC;
}
- vlc_mutex_init(&p_sys->lock);
- vlc_cond_init(&p_sys->loadCommandCond);
-
// Start the Chromecast event thread.
if (vlc_clone(&p_sys->chromecastThread, chromecastThread, p_stream,
VLC_THREAD_PRIORITY_LOW))
@@ -268,20 +264,20 @@ static int Open(vlc_object_t *p_this)
// Lock the sout thread until we have sent the media loading command to the Chromecast.
int i_ret = 0;
const mtime_t deadline = mdate() + 6 * CLOCK_FREQ;
- vlc_mutex_lock(&p_sys->lock);
- while (p_sys->i_status != CHROMECAST_MEDIA_LOAD_SENT)
+ vlc_mutex_lock(&p_intf->lock);
+ while (p_sys->p_intf->i_status != CHROMECAST_MEDIA_LOAD_SENT)
{
- i_ret = vlc_cond_timedwait(&p_sys->loadCommandCond, &p_sys->lock, deadline);
+ i_ret = vlc_cond_timedwait(&p_sys->p_intf->loadCommandCond, &p_intf->lock, deadline);
if (i_ret == ETIMEDOUT)
{
msg_Err(p_stream, "Timeout reached before sending the media loading command");
- vlc_mutex_unlock(&p_sys->lock);
+ vlc_mutex_unlock(&p_intf->lock);
vlc_cancel(p_sys->chromecastThread);
Clean(p_stream);
return VLC_EGENERIC;
}
}
- vlc_mutex_unlock(&p_sys->lock);
+ vlc_mutex_unlock(&p_intf->lock);
/* Even uglier: sleep more to let to the Chromecast initiate the connection
* to the http server. */
@@ -309,7 +305,7 @@ static void Close(vlc_object_t *p_this)
vlc_cancel(p_sys->chromecastThread);
vlc_join(p_sys->chromecastThread, NULL);
- switch (p_sys->i_status)
+ switch (p_sys->p_intf->i_status)
{
case CHROMECAST_MEDIA_LOAD_SENT:
case CHROMECAST_APP_STARTED:
@@ -338,8 +334,6 @@ static void Clean(sout_stream_t *p_stream)
if (p_sys->p_out)
{
- vlc_mutex_destroy(&p_sys->lock);
- vlc_cond_destroy(&p_sys->loadCommandCond);
sout_StreamChainDelete(p_sys->p_out, p_sys->p_out);
}
@@ -393,7 +387,7 @@ static void disconnectChromecast(sout_stream_t *p_stream)
vlc_tls_SessionDelete(p_sys->p_tls);
vlc_tls_Delete(p_sys->p_creds);
p_sys->p_tls = NULL;
- p_sys->i_status = CHROMECAST_DISCONNECTED;
+ p_sys->p_intf->i_status = CHROMECAST_DISCONNECTED;
}
}
@@ -565,185 +559,6 @@ extern "C" int recvPacket(sout_stream_t *p_stream, bool &b_msgReceived,
}
-/**
- * @brief Process a message received from the Chromecast
- * @param p_stream the sout_stream_t structure
- * @param msg the CastMessage to process
- * @return 0 if the message has been successfuly processed else -1
- */
-static int processMessage(sout_stream_t *p_stream, const castchannel::CastMessage &msg)
-{
- int i_ret = 0;
- sout_stream_sys_t *p_sys = p_stream->p_sys;
- std::string namespace_ = msg.namespace_();
-
- if (namespace_ == NAMESPACE_DEVICEAUTH)
- {
- castchannel::DeviceAuthMessage authMessage;
- authMessage.ParseFromString(msg.payload_binary());
-
- if (authMessage.has_error())
- {
- msg_Err(p_stream, "Authentification error: %d", authMessage.error().error_type());
- i_ret = -1;
- }
- else if (!authMessage.has_response())
- {
- msg_Err(p_stream, "Authentification message has no response field");
- i_ret = -1;
- }
- else
- {
- vlc_mutex_locker locker(&p_sys->lock);
- p_sys->i_status = CHROMECAST_AUTHENTICATED;
- p_sys->p_intf->msgConnect(DEFAULT_CHOMECAST_RECEIVER);
- p_sys->p_intf->msgReceiverLaunchApp();
- }
- }
- else if (namespace_ == NAMESPACE_HEARTBEAT)
- {
- json_value *p_data = json_parse(msg.payload_utf8().c_str());
- std::string type((*p_data)["type"]);
-
- if (type == "PING")
- {
- msg_Dbg(p_stream, "PING received from the Chromecast");
- p_sys->p_intf->msgPong();
- }
- else if (type == "PONG")
- {
- msg_Dbg(p_stream, "PONG received from the Chromecast");
- }
- else
- {
- msg_Err(p_stream, "Heartbeat command not supported: %s", type.c_str());
- i_ret = -1;
- }
-
- json_value_free(p_data);
- }
- else if (namespace_ == NAMESPACE_RECEIVER)
- {
- json_value *p_data = json_parse(msg.payload_utf8().c_str());
- std::string type((*p_data)["type"]);
-
- if (type == "RECEIVER_STATUS")
- {
- json_value applications = (*p_data)["status"]["applications"];
- const json_value *p_app = NULL;
- for (unsigned i = 0; i < applications.u.array.length; ++i)
- {
- std::string appId(applications[i]["appId"]);
- if (appId == APP_ID)
- {
- p_app = &applications[i];
- vlc_mutex_lock(&p_sys->lock);
- if (p_sys->p_intf->appTransportId.empty())
- p_sys->p_intf->appTransportId = std::string(applications[i]["transportId"]);
- vlc_mutex_unlock(&p_sys->lock);
- break;
- }
- }
-
- vlc_mutex_lock(&p_sys->lock);
- if ( p_app )
- {
- if (!p_sys->p_intf->appTransportId.empty()
- && p_sys->i_status == CHROMECAST_AUTHENTICATED)
- {
- p_sys->i_status = CHROMECAST_APP_STARTED;
- p_sys->p_intf->msgConnect(p_sys->p_intf->appTransportId);
- p_sys->p_intf->msgPlayerLoad();
- p_sys->i_status = CHROMECAST_MEDIA_LOAD_SENT;
- vlc_cond_signal(&p_sys->loadCommandCond);
- }
- }
- else
- {
- switch(p_sys->i_status)
- {
- /* If the app is no longer present */
- case CHROMECAST_APP_STARTED:
- case CHROMECAST_MEDIA_LOAD_SENT:
- msg_Warn(p_stream, "app is no longer present. closing");
- p_sys->p_intf->msgReceiverClose(p_sys->p_intf->appTransportId);
- p_sys->i_status = CHROMECAST_CONNECTION_DEAD;
- // ft
- default:
- break;
- }
-
- }
- vlc_mutex_unlock(&p_sys->lock);
- }
- else
- {
- msg_Err(p_stream, "Receiver command not supported: %s",
- msg.payload_utf8().c_str());
- i_ret = -1;
- }
-
- json_value_free(p_data);
- }
- else if (namespace_ == NAMESPACE_MEDIA)
- {
- json_value *p_data = json_parse(msg.payload_utf8().c_str());
- std::string type((*p_data)["type"]);
-
- if (type == "MEDIA_STATUS")
- {
- json_value status = (*p_data)["status"];
- msg_Dbg(p_stream, "Player state: %s",
- status[0]["playerState"].operator const char *());
- }
- else if (type == "LOAD_FAILED")
- {
- msg_Err(p_stream, "Media load failed");
- p_sys->p_intf->msgReceiverClose(p_sys->p_intf->appTransportId);
- vlc_mutex_lock(&p_sys->lock);
- p_sys->i_status = CHROMECAST_CONNECTION_DEAD;
- vlc_mutex_unlock(&p_sys->lock);
- }
- else
- {
- msg_Err(p_stream, "Media command not supported: %s",
- msg.payload_utf8().c_str());
- i_ret = -1;
- }
-
- json_value_free(p_data);
- }
- else if (namespace_ == NAMESPACE_CONNECTION)
- {
- json_value *p_data = json_parse(msg.payload_utf8().c_str());
- std::string type((*p_data)["type"]);
- json_value_free(p_data);
-
- if (type == "CLOSE")
- {
- msg_Warn(p_stream, "received close message");
- vlc_mutex_lock(&p_sys->lock);
- p_sys->i_status = CHROMECAST_CONNECTION_DEAD;
- vlc_mutex_unlock(&p_sys->lock);
- }
- else
- {
- msg_Err(p_stream, "Connection command not supported: %s",
- type.c_str());
- i_ret = -1;
- }
- }
- else
- {
- msg_Err(p_stream, "Unknown namespace: %s", msg.namespace_().c_str());
- i_ret = -1;
- }
-
- return i_ret;
-}
-
-
-
/*****************************************************************************
* Chromecast thread
*****************************************************************************/
@@ -783,8 +598,8 @@ static void* chromecastThread(void* p_data)
#endif
{
msg_Err(p_stream, "The connection to the Chromecast died.");
- vlc_mutex_locker locker(&p_sys->lock);
- p_sys->i_status = CHROMECAST_CONNECTION_DEAD;
+ vlc_mutex_locker locker(&p_sys->p_intf->lock);
+ p_sys->p_intf->i_status = CHROMECAST_CONNECTION_DEAD;
break;
}
@@ -798,7 +613,7 @@ static void* chromecastThread(void* p_data)
{
castchannel::CastMessage msg;
msg.ParseFromArray(p_packet + PACKET_HEADER_LEN, i_payloadSize);
- processMessage(p_stream, msg);
+ p_sys->p_intf->processMessage(msg);
}
// Send the answer messages if there is any.
@@ -812,18 +627,18 @@ static void* chromecastThread(void* p_data)
#endif
{
msg_Err(p_stream, "The connection to the Chromecast died.");
- vlc_mutex_locker locker(&p_sys->lock);
- p_sys->i_status = CHROMECAST_CONNECTION_DEAD;
+ vlc_mutex_locker locker(&p_sys->p_intf->lock);
+ p_sys->p_intf->i_status = CHROMECAST_CONNECTION_DEAD;
}
}
- vlc_mutex_lock(&p_sys->lock);
- if ( p_sys->i_status == CHROMECAST_CONNECTION_DEAD )
+ vlc_mutex_lock(&p_sys->p_intf->lock);
+ if ( p_sys->p_intf->i_status == CHROMECAST_CONNECTION_DEAD )
{
- vlc_mutex_unlock(&p_sys->lock);
+ vlc_mutex_unlock(&p_sys->p_intf->lock);
break;
}
- vlc_mutex_unlock(&p_sys->lock);
+ vlc_mutex_unlock(&p_sys->p_intf->lock);
vlc_restorecancel(canc);
}
diff --git a/modules/stream_out/chromecast/chromecast.h b/modules/stream_out/chromecast/chromecast.h
index fa01fa5..9cdd1bb 100644
--- a/modules/stream_out/chromecast/chromecast.h
+++ b/modules/stream_out/chromecast/chromecast.h
@@ -66,6 +66,9 @@ struct intf_sys_t
std::string serverIP;
std::string appTransportId;
+ vlc_mutex_t lock;
+ vlc_cond_t loadCommandCond;
+
void msgAuth();
void msgReceiverClose(std::string destinationId);
void msgPing();
@@ -77,8 +80,12 @@ struct intf_sys_t
void msgPlayerLoad();
+ int i_status;
+
std::queue<castchannel::CastMessage> messagesToSend;
unsigned i_requestId;
+
+ int processMessage(const castchannel::CastMessage &msg);
};
#endif /* VLC_CHROMECAST_H */
diff --git a/modules/stream_out/chromecast/chromecast_ctrl.cpp b/modules/stream_out/chromecast/chromecast_ctrl.cpp
index 3e45cbb..e0da352 100644
--- a/modules/stream_out/chromecast/chromecast_ctrl.cpp
+++ b/modules/stream_out/chromecast/chromecast_ctrl.cpp
@@ -36,6 +36,8 @@
#include <sstream>
+#include "../../misc/webservices/json.h"
+
// Media player Chromecast app id
#define APP_ID "CC1AD845" // Default media player
@@ -52,7 +54,7 @@
*/
static castchannel::CastMessage buildMessage(std::string namespace_,
castchannel::CastMessage_PayloadType payloadType,
- std::string payload, std::string destinationId = "receiver-0")
+ std::string payload, std::string destinationId = DEFAULT_CHOMECAST_RECEIVER)
{
castchannel::CastMessage msg;
@@ -70,13 +72,193 @@ static castchannel::CastMessage buildMessage(std::string namespace_,
}
intf_sys_t::intf_sys_t(sout_stream_t * const p_this)
- :p_stream(p_this)
- ,i_requestId(0)
+ : p_stream(p_this)
+ , i_status(CHROMECAST_DISCONNECTED)
+ , i_requestId(0)
{
+ vlc_mutex_init(&lock);
+ vlc_cond_init(&loadCommandCond);
}
intf_sys_t::~intf_sys_t()
{
+ vlc_cond_destroy(&loadCommandCond);
+ vlc_mutex_destroy(&lock);
+}
+
+/**
+ * @brief Process a message received from the Chromecast
+ * @param msg the CastMessage to process
+ * @return 0 if the message has been successfuly processed else -1
+ */
+int intf_sys_t::processMessage(const castchannel::CastMessage &msg)
+{
+ int i_ret = 0;
+ std::string namespace_ = msg.namespace_();
+
+ if (namespace_ == NAMESPACE_DEVICEAUTH)
+ {
+ castchannel::DeviceAuthMessage authMessage;
+ authMessage.ParseFromString(msg.payload_binary());
+
+ if (authMessage.has_error())
+ {
+ msg_Err(p_stream, "Authentification error: %d", authMessage.error().error_type());
+ i_ret = -1;
+ }
+ else if (!authMessage.has_response())
+ {
+ msg_Err(p_stream, "Authentification message has no response field");
+ i_ret = -1;
+ }
+ else
+ {
+ vlc_mutex_locker locker(&lock);
+ i_status = CHROMECAST_AUTHENTICATED;
+ msgConnect(DEFAULT_CHOMECAST_RECEIVER);
+ msgReceiverLaunchApp();
+ }
+ }
+ else if (namespace_ == NAMESPACE_HEARTBEAT)
+ {
+ json_value *p_data = json_parse(msg.payload_utf8().c_str());
+ std::string type((*p_data)["type"]);
+
+ if (type == "PING")
+ {
+ msg_Dbg(p_stream, "PING received from the Chromecast");
+ msgPong();
+ }
+ else if (type == "PONG")
+ {
+ msg_Dbg(p_stream, "PONG received from the Chromecast");
+ }
+ else
+ {
+ msg_Err(p_stream, "Heartbeat command not supported: %s", type.c_str());
+ i_ret = -1;
+ }
+
+ json_value_free(p_data);
+ }
+ else if (namespace_ == NAMESPACE_RECEIVER)
+ {
+ json_value *p_data = json_parse(msg.payload_utf8().c_str());
+ std::string type((*p_data)["type"]);
+
+ if (type == "RECEIVER_STATUS")
+ {
+ json_value applications = (*p_data)["status"]["applications"];
+ const json_value *p_app = NULL;
+ for (unsigned i = 0; i < applications.u.array.length; ++i)
+ {
+ std::string appId(applications[i]["appId"]);
+ if (appId == APP_ID)
+ {
+ p_app = &applications[i];
+ vlc_mutex_lock(&lock);
+ if (appTransportId.empty())
+ appTransportId = std::string(applications[i]["transportId"]);
+ vlc_mutex_unlock(&lock);
+ break;
+ }
+ }
+
+ vlc_mutex_lock(&lock);
+ if ( p_app )
+ {
+ if (!appTransportId.empty()
+ && i_status == CHROMECAST_AUTHENTICATED)
+ {
+ i_status = CHROMECAST_APP_STARTED;
+ msgConnect(appTransportId);
+ msgPlayerLoad();
+ i_status = CHROMECAST_MEDIA_LOAD_SENT;
+ vlc_cond_signal(&loadCommandCond);
+ }
+ }
+ else
+ {
+ switch(i_status)
+ {
+ /* If the app is no longer present */
+ case CHROMECAST_APP_STARTED:
+ case CHROMECAST_MEDIA_LOAD_SENT:
+ msg_Warn(p_stream, "app is no longer present. closing");
+ msgReceiverClose(appTransportId);
+ i_status = CHROMECAST_CONNECTION_DEAD;
+ // ft
+ default:
+ break;
+ }
+
+ }
+ vlc_mutex_unlock(&lock);
+ }
+ else
+ {
+ msg_Err(p_stream, "Receiver command not supported: %s",
+ msg.payload_utf8().c_str());
+ i_ret = -1;
+ }
+
+ json_value_free(p_data);
+ }
+ else if (namespace_ == NAMESPACE_MEDIA)
+ {
+ json_value *p_data = json_parse(msg.payload_utf8().c_str());
+ std::string type((*p_data)["type"]);
+
+ if (type == "MEDIA_STATUS")
+ {
+ json_value status = (*p_data)["status"];
+ msg_Dbg(p_stream, "Player state: %s",
+ status[0]["playerState"].operator const char *());
+ }
+ else if (type == "LOAD_FAILED")
+ {
+ msg_Err(p_stream, "Media load failed");
+ msgReceiverClose(appTransportId);
+ vlc_mutex_lock(&lock);
+ i_status = CHROMECAST_CONNECTION_DEAD;
+ vlc_mutex_unlock(&lock);
+ }
+ else
+ {
+ msg_Err(p_stream, "Media command not supported: %s",
+ msg.payload_utf8().c_str());
+ i_ret = -1;
+ }
+
+ json_value_free(p_data);
+ }
+ else if (namespace_ == NAMESPACE_CONNECTION)
+ {
+ json_value *p_data = json_parse(msg.payload_utf8().c_str());
+ std::string type((*p_data)["type"]);
+ json_value_free(p_data);
+
+ if (type == "CLOSE")
+ {
+ msg_Warn(p_stream, "received close message");
+ vlc_mutex_lock(&lock);
+ i_status = CHROMECAST_CONNECTION_DEAD;
+ vlc_mutex_unlock(&lock);
+ }
+ else
+ {
+ msg_Err(p_stream, "Connection command not supported: %s",
+ type.c_str());
+ i_ret = -1;
+ }
+ }
+ else
+ {
+ msg_Err(p_stream, "Unknown namespace: %s", msg.namespace_().c_str());
+ i_ret = -1;
+ }
+
+ return i_ret;
}
/*****************************************************************************
--
2.6.3
More information about the vlc-devel
mailing list