[vlc-devel] [PATCH 4/4] dlna: add PrepareForConnection action

Shaleen Jain shaleen at jain.sh
Fri Dec 7 13:42:14 CET 2018


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 | 88 ++++++++++++++++++++++++++++++--
 modules/stream_out/dlna/dlna.hpp |  9 ++++
 2 files changed, 94 insertions(+), 3 deletions(-)

diff --git a/modules/stream_out/dlna/dlna.cpp b/modules/stream_out/dlna/dlna.cpp
index 2e6cb0100e..0eab71d2e3 100644
--- a/modules/stream_out/dlna/dlna.cpp
+++ b/modules/stream_out/dlna/dlna.cpp
@@ -466,6 +466,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);
@@ -560,7 +562,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;
-    arg_list.push_back(std::make_pair("InstanceID", "0"));
+    arg_list.push_back(std::make_pair("InstanceID", AVTransportID.c_str()));
     arg_list.push_back(std::make_pair("Speed", speed));
 
     IXML_Document *p_response = SendAction("Play", AV_TRANSPORT_SERVICE_TYPE, arg_list);
@@ -575,7 +577,7 @@ int MediaRenderer::Play(const char *speed)
 int MediaRenderer::Stop()
 {
     std::list<std::pair<const char*, const char*>> arg_list;
-    arg_list.push_back(std::make_pair("InstanceID", "0"));
+    arg_list.push_back(std::make_pair("InstanceID", AVTransportID.c_str()));
 
     IXML_Document *p_response = SendAction("Stop", AV_TRANSPORT_SERVICE_TYPE, arg_list);
     if(!p_response)
@@ -660,6 +662,85 @@ 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;
+    arg_list.push_back(std::make_pair("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[] =
@@ -689,7 +770,7 @@ int MediaRenderer::SetAVTransportURI(const char* uri, const protocol_info_t prot
 
     msg_Dbg(parent, "didl: %s", meta_data);
     std::list<std::pair<const char*, const char*>> arg_list;
-    arg_list.push_back(std::make_pair("InstanceID", "0"));
+    arg_list.push_back(std::make_pair("InstanceID", AVTransportID.c_str()));
     arg_list.push_back(std::make_pair("CurrentURI", uri));
     arg_list.push_back(std::make_pair("CurrentURIMetaData", meta_data));
 
@@ -858,6 +939,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 5d22c17981..e579209df5 100644
--- a/modules/stream_out/dlna/dlna.hpp
+++ b/modules/stream_out/dlna/dlna.hpp
@@ -64,6 +64,9 @@ public:
         , base_url(base_url)
         , device_url(device_url)
         , handle(upnp->handle())
+        , ConnectionID("0")
+        , AVTransportID("0")
+        , RcsID("0")
     {
     }
 
@@ -72,6 +75,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);
@@ -79,6 +86,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.19.2


More information about the vlc-devel mailing list