[vlc-devel] [PATCHv3 08/12] microdns: handle renderer items

Thomas Guillem thomas at gllm.fr
Tue Mar 29 15:06:39 CEST 2016


---
 modules/services_discovery/microdns.c | 175 +++++++++++++++++++++++++++++-----
 1 file changed, 150 insertions(+), 25 deletions(-)

diff --git a/modules/services_discovery/microdns.c b/modules/services_discovery/microdns.c
index 5a9a9eb..7ab5ea5 100644
--- a/modules/services_discovery/microdns.c
+++ b/modules/services_discovery/microdns.c
@@ -32,14 +32,17 @@
 #include <vlc_plugin.h>
 #include <vlc_modules.h>
 #include <vlc_services_discovery.h>
+#include <vlc_renderer.h>
 
 #include <microdns/microdns.h>
 
 static int Open( vlc_object_t * );
 static void Close( vlc_object_t * );
 
-VLC_SD_PROBE_HELPER( "microdns", "mDNS Network Discovery", SD_CAT_LAN )
+static int vlc_sd_probe_Open( vlc_object_t *p_obj );
 
+#define RENDERER_TEXT "Search for renderers"
+#define RENDERER_LONGTEXT "If true, this sd will only search for renderers"
 
 #define CFG_PREFIX "sd-microdns-"
 
@@ -57,6 +60,7 @@ vlc_module_begin()
     set_capability( "services_discovery", 0 )
     set_callbacks( Open, Close )
     add_shortcut( "mdns", "microdns" )
+    add_bool( CFG_PREFIX "renderer", false, RENDERER_TEXT, RENDERER_LONGTEXT, true )
     VLC_SD_PROBE_SUBMODULE
 vlc_module_end ()
 
@@ -72,9 +76,10 @@ struct services_discovery_sys_t
 
 struct item
 {
-    char *          psz_uri;
-    input_item_t *  p_input_item;
-    mtime_t         i_last_seen;
+    char *              psz_input_uri;
+    input_item_t *      p_input_item;
+    vlc_renderer_item * p_renderer_item;
+    mtime_t             i_last_seen;
 };
 
 struct srv
@@ -82,6 +87,8 @@ struct srv
     const char *psz_protocol;
     char *      psz_device_name;
     uint16_t    i_port;
+    bool        b_renderer;
+    int         i_renderer_flags;
 };
 
 static const struct
@@ -89,16 +96,32 @@ static const struct
     const char *psz_protocol;
     const char *psz_service_name;
     uint16_t    i_default_port;
+    bool        b_renderer;
+    int         i_renderer_flags;
 } protocols[] = {
-    { "ftp", "_ftp._tcp.local", 21 },
-    { "smb", "_smb._tcp.local", 445 },
-    { "nfs", "_nfs._tcp.local", 2049 },
-    { "sftp", "_sftp-ssh._tcp.local", 22 },
-    { "rtsp", "_rtsp._tcp.local", 554 },
+    { "ftp", "_ftp._tcp.local", 21, false, 0 },
+    { "smb", "_smb._tcp.local", 445, false, 0 },
+    { "nfs", "_nfs._tcp.local", 2049, false, 0 },
+    { "sftp", "_sftp-ssh._tcp.local", 22, false, 0 },
+    { "rtsp", "_rtsp._tcp.local", 554, false, 0 },
+    { "chromecast", "_googlecast._tcp.local", 8009, true, VLC_RENDERER_CAN_AUDIO },
 };
 #define NB_PROTOCOLS (sizeof(protocols) / sizeof(*protocols))
 
+static int vlc_sd_probe_Open( vlc_object_t *p_obj )
+{
+    vlc_probe_t *p_probe = (vlc_probe_t *)p_obj;
+    vlc_sd_probe_Add( p_probe, "microdns{longname=\"mDNS Network Discovery\","
+                      "no-renderer}",
+                      "mDNS Network Discovery", SD_CAT_LAN );
+    vlc_sd_probe_Add( p_probe, "microdns{longname=\"mDNS Network Discovery\","
+                      "renderer}",
+                      "mDNS Network Discovery", SD_CAT_RENDERER );
+    return VLC_PROBE_CONTINUE;
+}
+
 static const char *const ppsz_options[] = {
+    "renderer",
     NULL
 };
 
@@ -148,8 +171,9 @@ items_add_input( services_discovery_t *p_sd, char *psz_uri,
         return VLC_ENOMEM;
     }
 
-    p_item->psz_uri = psz_uri;
+    p_item->psz_input_uri = psz_uri;
     p_item->p_input_item = p_input_item;
+    p_item->p_renderer_item = NULL;
     p_item->i_last_seen = mdate();
     vlc_array_append( &p_sys->items, p_item );
     services_discovery_AddItem( p_sd, p_input_item, NULL );
@@ -157,25 +181,84 @@ items_add_input( services_discovery_t *p_sd, char *psz_uri,
     return VLC_SUCCESS;
 }
 
+static int
+items_add_renderer( services_discovery_t *p_sd, const char *psz_name,
+                    const char *psz_uri, int i_flags )
+{
+    services_discovery_sys_t *p_sys = p_sd->p_sys;
+
+    struct item *p_item = malloc( sizeof(struct item) );
+    if( p_item == NULL )
+        return VLC_ENOMEM;
+
+    vlc_renderer_item *p_renderer_item =
+        vlc_renderer_item_new( psz_name, psz_uri, i_flags );
+    if( p_renderer_item == NULL )
+    {
+        free( p_item );
+        return VLC_ENOMEM;
+    }
+
+    p_item->psz_input_uri = NULL;
+    p_item->p_input_item = NULL;
+    p_item->p_renderer_item = p_renderer_item;
+    p_item->i_last_seen = mdate();
+    vlc_array_append( &p_sys->items, p_item );
+    services_discovery_AddRenderer( p_sd, p_renderer_item );
+
+    return VLC_SUCCESS;
+}
+
 static void
 items_release( services_discovery_t *p_sd, struct item *p_item, bool b_notify )
 {
-    input_item_Release( p_item->p_input_item );
-    if( b_notify )
-        services_discovery_RemoveItem( p_sd, p_item->p_input_item );
-    free( p_item->psz_uri );
+    if( p_item->p_input_item != NULL )
+    {
+        input_item_Release( p_item->p_input_item );
+        if( b_notify )
+            services_discovery_RemoveItem( p_sd, p_item->p_input_item );
+    }
+    else
+    {
+        assert( p_item->p_renderer_item != NULL );
+        vlc_renderer_item_release( p_item->p_renderer_item );
+        if( b_notify )
+            services_discovery_RemoveRenderer( p_sd, p_item->p_renderer_item );
+    }
+
+    free( p_item->psz_input_uri );
     free( p_item );
 }
 
 static bool
-items_exists( services_discovery_t *p_sd, const char *psz_uri )
+items_input_exists( services_discovery_t *p_sd, const char *psz_uri )
+{
+    services_discovery_sys_t *p_sys = p_sd->p_sys;
+
+    for( int i = 0; i < vlc_array_count( &p_sys->items ); ++i )
+    {
+        struct item *p_item = vlc_array_item_at_index( &p_sys->items, i );
+        if( p_item->psz_input_uri != NULL
+         && strcmp( p_item->psz_input_uri, psz_uri ) == 0 )
+        {
+            p_item->i_last_seen = mdate();
+            return true;
+        }
+    }
+    return false;
+}
+
+static bool
+items_renderer_exists( services_discovery_t *p_sd, const char *psz_uri )
 {
     services_discovery_sys_t *p_sys = p_sd->p_sys;
 
     for( int i = 0; i < vlc_array_count( &p_sys->items ); ++i )
     {
         struct item *p_item = vlc_array_item_at_index( &p_sys->items, i );
-        if( strcmp( psz_uri, p_item->psz_uri ) == 0 )
+
+        if( p_item->p_renderer_item != NULL
+         && !strcmp( vlc_renderer_item_uri( p_item->p_renderer_item ), psz_uri ) )
         {
             p_item->i_last_seen = mdate();
             return true;
@@ -244,6 +327,7 @@ new_entries_cb( void *p_this, int i_status,
 
     /* There is one ip for several srvs, fetch them */
     const char *psz_ip = NULL;
+    const char *psz_model = NULL;
     for( const struct rr_entry *p_entry = p_entries;
          p_entry != NULL; p_entry = p_entry->next )
     {
@@ -263,11 +347,26 @@ new_entries_cb( void *p_this, int i_status,
                     p_srv->psz_protocol = protocols[i].psz_protocol;
                     if( protocols[i].i_default_port != p_entry->data.SRV.port )
                         p_srv->i_port = p_entry->data.SRV.port;
+                    p_srv->b_renderer = protocols[i].b_renderer;
+                    p_srv->i_renderer_flags = protocols[i].i_renderer_flags;
                     ++i_srv_idx;
                     break;
                 }
             }
         }
+        else if( p_entry->type == RR_TXT && psz_model == NULL )
+        {
+            const struct rr_data_txt *p_txt = p_entry->data.TXT;
+            while( p_txt )
+            {
+                if( p_txt->txt && !strncmp("md=", p_txt->txt, 3) )
+                {
+                    psz_model = p_txt->txt + 3;
+                    break;
+                }
+                p_txt = p_txt->next;
+            }
+        }
         else if( p_entry->type == RR_A && psz_ip == NULL )
             psz_ip = p_entry->data.A.addr_str;
         /* TODO support ipv6
@@ -289,17 +388,42 @@ new_entries_cb( void *p_this, int i_status,
         if( p_srv->i_port != 0 )
             sprintf( psz_port, ":%u", p_srv->i_port );
 
-        char *psz_uri;
-        if( asprintf( &psz_uri, "%s://%s%s", p_srv->psz_protocol, psz_ip,
-                      p_srv->i_port != 0 ? psz_port : "" ) < 0 )
-            continue;
+        if( !p_srv->b_renderer )
+        {
+            char *psz_uri;
+            if( asprintf( &psz_uri, "%s://%s%s", p_srv->psz_protocol, psz_ip,
+                          p_srv->i_port != 0 ? psz_port : "" ) < 0 )
+                continue;
 
-        if( items_exists( p_sd, psz_uri ) )
+            if( items_input_exists( p_sd, psz_uri ) )
+            {
+                free( psz_uri );
+                continue;
+            }
+            items_add_input( p_sd, psz_uri, p_srv->psz_device_name );
+        }
+        else
         {
+            char *psz_uri;
+            if( asprintf( &psz_uri, "%s://%s:%u", p_srv->psz_protocol, psz_ip,
+                          p_srv->i_port ) == -1 )
+                break;
+
+            if( items_renderer_exists( p_sd, psz_uri ) )
+            {
+                free( psz_uri );
+                continue;
+            }
+
+            if( strcmp( p_srv->psz_protocol, "chromecast" ) == 0
+             && ( psz_model == NULL
+               || strcasecmp( psz_model, "Chromecast Audio" ) != 0 ) )
+                p_srv->i_renderer_flags |= VLC_RENDERER_CAN_VIDEO;
+
+            items_add_renderer( p_sd, p_srv->psz_device_name, psz_uri,
+                                p_srv->i_renderer_flags );
             free( psz_uri );
-            continue;
         }
-        items_add_input( p_sd, psz_uri, p_srv->psz_device_name );
     }
 
     for( i_srv_idx = 0; i_srv_idx < i_nb_srv; ++i_srv_idx )
@@ -354,6 +478,7 @@ Open( vlc_object_t *p_obj )
     atomic_init( &p_sys->stop, false );
     vlc_array_init( &p_sys->items );
     config_ChainParse( p_sd, CFG_PREFIX, ppsz_options, p_sd->p_cfg );
+    bool b_renderer = var_GetBool( p_sd, CFG_PREFIX "renderer" );
 
     /* Listen to protocols that are handled by VLC */
     const unsigned i_count = NB_PROTOCOLS;
@@ -363,8 +488,8 @@ Open( vlc_object_t *p_obj )
 
     for( unsigned int i = 0; i < i_count; ++i )
     {
-        /* Listen to a protocol only if a module can handle it */
-        if( module_exists( protocols[i].psz_protocol ) )
+        if( protocols[i].b_renderer == b_renderer
+         && module_exists( protocols[i].psz_protocol ) )
             p_sys->ppsz_service_names[p_sys->i_nb_service_names++] =
                 protocols[i].psz_service_name;
     }
-- 
2.8.0.rc3



More information about the vlc-devel mailing list