[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