[vlc-devel] [PATCH 4/4] dlna: add PrepareForConnection action
Shaleen Jain
shaleen at jain.sh
Wed Jan 9 16:10:40 CET 2019
This adds support for casting to Media Renderers that
implement the optional CM::PrepareForConnection action
and require Control Points to call this action before
being able to play any content.
---
modules/stream_out/dlna/dlna.cpp | 89 ++++++++++++++++++++++++++++++--
modules/stream_out/dlna/dlna.hpp | 9 ++++
2 files changed, 95 insertions(+), 3 deletions(-)
diff --git a/modules/stream_out/dlna/dlna.cpp b/modules/stream_out/dlna/dlna.cpp
index f9f7a61c29..54a09dc03b 100644
--- a/modules/stream_out/dlna/dlna.cpp
+++ b/modules/stream_out/dlna/dlna.cpp
@@ -471,6 +471,8 @@ int sout_stream_sys_t::UpdateOutput( sout_stream_t *p_stream )
if ( !startSoutChain( p_stream, new_streams, ssout.str() ) )
return VLC_EGENERIC;
+ renderer->PrepareForConnection(dlna_write_protocol_info(*stream_protocol));
+
msg_Dbg(p_stream, "AVTransportURI: %s", uri);
renderer->Stop();
renderer->SetAVTransportURI(uri, *stream_protocol);
@@ -565,7 +567,7 @@ IXML_Document *MediaRenderer::SendAction(const char* action_name,const char *ser
int MediaRenderer::Play(const char *speed)
{
std::list<std::pair<const char*, const char*>> arg_list = {
- {"InstanceID", "0"},
+ {"InstanceID", AVTransportID.c_str()},
{"Speed", speed},
};
@@ -581,7 +583,7 @@ int MediaRenderer::Play(const char *speed)
int MediaRenderer::Stop()
{
std::list<std::pair<const char*, const char*>> arg_list = {
- {"InstanceID", "0"},
+ {"InstanceID", AVTransportID.c_str()},
};
IXML_Document *p_response = SendAction("Stop", AV_TRANSPORT_SERVICE_TYPE, arg_list);
@@ -667,6 +669,86 @@ std::vector<protocol_info_t> MediaRenderer::GetProtocolInfo()
return supported_protocols;
}
+int MediaRenderer::PrepareForConnection(std::string protocol_str)
+{
+ std::list<std::pair<const char*, const char*>> arg_list;
+ arg_list.push_back(std::make_pair("PeerConnectionID", "-1"));
+ arg_list.push_back(std::make_pair("PeerConnectionManager", ""));
+ arg_list.push_back(std::make_pair("Direction", "Input"));
+ arg_list.push_back(std::make_pair("RemoteProtocolInfo", protocol_str.c_str()));
+
+ IXML_Document *response = SendAction("PrepareForConnection",
+ CONNECTION_MANAGER_SERVICE_TYPE, arg_list);
+ if(!response)
+ {
+ return VLC_EGENERIC;
+ }
+
+ msg_Dbg(parent, "PrepareForConnection response: %s",
+ ixmlPrintDocument(response));
+ if (IXML_NodeList *node_list =
+ ixmlDocument_getElementsByTagName(response , "ConnectionID"))
+ {
+ if (IXML_Node* node = ixmlNodeList_item(node_list, 0))
+ {
+ IXML_Node* p_text_node = ixmlNode_getFirstChild(node);
+ if (p_text_node)
+ {
+ ConnectionID.assign(ixmlNode_getNodeValue(p_text_node));
+ }
+ }
+ ixmlNodeList_free(node_list);
+ }
+
+ if (IXML_NodeList *node_list =
+ ixmlDocument_getElementsByTagName(response , "AVTransportID"))
+ {
+ if (IXML_Node* node = ixmlNodeList_item(node_list, 0))
+ {
+ IXML_Node* p_text_node = ixmlNode_getFirstChild(node);
+ if (p_text_node)
+ {
+ AVTransportID.assign(ixmlNode_getNodeValue(p_text_node));
+ }
+ }
+ ixmlNodeList_free(node_list);
+ }
+
+ if (IXML_NodeList *node_list =
+ ixmlDocument_getElementsByTagName(response , "RcsID"))
+ {
+ if (IXML_Node* node = ixmlNodeList_item(node_list, 0))
+ {
+ IXML_Node* p_text_node = ixmlNode_getFirstChild(node);
+ if (p_text_node)
+ {
+ RcsID.assign(ixmlNode_getNodeValue(p_text_node));
+ }
+ }
+ ixmlNodeList_free(node_list);
+ }
+
+ ixmlDocument_free(response);
+ return VLC_SUCCESS;
+}
+
+int MediaRenderer::ConnectionComplete()
+{
+ std::list<std::pair<const char*, const char*>> arg_list = {
+ {"ConnectionID", ConnectionID.c_str()},
+ };
+
+ IXML_Document *p_response = SendAction("ConnectionComplete",
+ CONNECTION_MANAGER_SERVICE_TYPE, arg_list);
+ if(!p_response)
+ {
+ return VLC_EGENERIC;
+ }
+
+ ixmlDocument_free(p_response);
+ return VLC_SUCCESS;
+}
+
int MediaRenderer::SetAVTransportURI(const char* uri, const protocol_info_t& proto)
{
static const char didl[] =
@@ -696,7 +778,7 @@ int MediaRenderer::SetAVTransportURI(const char* uri, const protocol_info_t& pro
msg_Dbg(parent, "didl: %s", meta_data);
std::list<std::pair<const char*, const char*>> arg_list = {
- {"InstanceID", "0"},
+ {"InstanceID", AVTransportID.c_str()},
{"CurrentURI", uri},
{"CurrentURIMetaData", meta_data},
};
@@ -865,6 +947,7 @@ void CloseSout( vlc_object_t *p_this)
sout_stream_t *p_stream = reinterpret_cast<sout_stream_t*>( p_this );
sout_stream_sys_t *p_sys = static_cast<sout_stream_sys_t *>( p_stream->p_sys );
+ p_sys->renderer->ConnectionComplete();
p_sys->p_upnp->release();
delete p_sys;
}
diff --git a/modules/stream_out/dlna/dlna.hpp b/modules/stream_out/dlna/dlna.hpp
index d4a18ebd52..d2b2cb8f8d 100644
--- a/modules/stream_out/dlna/dlna.hpp
+++ b/modules/stream_out/dlna/dlna.hpp
@@ -77,6 +77,9 @@ public:
, base_url(base_url)
, device_url(device_url)
, handle(upnp->handle())
+ , ConnectionID("0")
+ , AVTransportID("0")
+ , RcsID("0")
{
}
@@ -85,6 +88,10 @@ public:
std::string device_url;
UpnpClient_Handle handle;
+ std::string ConnectionID;
+ std::string AVTransportID;
+ std::string RcsID;
+
char *getServiceURL(const char* type, const char* service);
IXML_Document *SendAction(const char* action_name, const char *service_type,
std::list<std::pair<const char*, const char*>> arguments);
@@ -92,6 +99,8 @@ public:
int Play(const char *speed);
int Stop();
std::vector<protocol_info_t> GetProtocolInfo();
+ int PrepareForConnection(std::string protocol_str);
+ int ConnectionComplete();
int SetAVTransportURI(const char* uri, const protocol_info_t& proto);
};
--
2.20.1
More information about the vlc-devel
mailing list