[vlc-devel] [PATCH 2/3] microdns: handle renderer items
Steve Lhomme
robux4 at gmail.com
Wed Apr 20 10:15:57 CEST 2016
On Tue, Apr 19, 2016 at 5:45 PM, Thomas Guillem <thomas at gllm.fr> wrote:
> ---
> modules/services_discovery/microdns.c | 458 +++++++++++++++++++++++++---------
> 1 file changed, 341 insertions(+), 117 deletions(-)
>
> diff --git a/modules/services_discovery/microdns.c b/modules/services_discovery/microdns.c
> index e1f9159..1a01f03 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_discovery.h>
>
> #include <microdns/microdns.h>
>
> -static int Open( vlc_object_t * );
> -static void Close( vlc_object_t * );
> +static int OpenSD( vlc_object_t * );
> +static void CloseSD( vlc_object_t * );
> +static int OpenRD( vlc_object_t * );
> +static void CloseRD( vlc_object_t * );
>
> VLC_SD_PROBE_HELPER( "microdns", "mDNS Network Discovery", SD_CAT_LAN )
> -
> +VLC_RD_PROBE_HELPER( "microdns_renderer", "mDNS renderer Discovery" )
>
> #define CFG_PREFIX "sd-microdns-"
>
> @@ -55,26 +58,61 @@ vlc_module_begin()
> set_category( CAT_PLAYLIST )
> set_subcategory( SUBCAT_PLAYLIST_SD )
> set_capability( "services_discovery", 0 )
> - set_callbacks( Open, Close )
> + set_callbacks( OpenSD, CloseSD )
> add_shortcut( "mdns", "microdns" )
> VLC_SD_PROBE_SUBMODULE
> + add_submodule() \
> + set_description( N_( "mDNS Renderer Discovery" ) )
> + set_category( CAT_SOUT )
> + set_subcategory( SUBCAT_SOUT_RENDERER )
> + set_capability( "renderer_discovery", 0 )
> + set_callbacks( OpenRD, CloseRD )
> + add_shortcut( "mdns_renderer", "microdns_renderer" )
> + VLC_RD_PROBE_SUBMODULE
> vlc_module_end ()
>
> -struct services_discovery_sys_t
> +static const struct
> +{
> + const char *psz_protocol;
> + const char *psz_service_name;
> + bool b_renderer;
> + int i_renderer_flags;
> +} protocols[] = {
> + { "ftp", "_ftp._tcp.local", false, 0 },
> + { "smb", "_smb._tcp.local", false, 0 },
> + { "nfs", "_nfs._tcp.local", false, 0 },
> + { "sftp", "_sftp-ssh._tcp.local", false, 0 },
> + { "rtsp", "_rtsp._tcp.local", false, 0 },
> + { "chromecast", "_googlecast._tcp.local", true, VLC_RENDERER_CAN_AUDIO },
> +};
> +#define NB_PROTOCOLS (sizeof(protocols) / sizeof(*protocols))
> +
> +struct discovery_sys
> {
> vlc_thread_t thread;
> atomic_bool stop;
> struct mdns_ctx * p_microdns;
> - const char ** ppsz_service_names;
> + const char * ppsz_service_names[NB_PROTOCOLS];
> unsigned int i_nb_service_names;
> vlc_array_t items;
> };
>
> +struct services_discovery_sys_t
> +{
> + struct discovery_sys s;
> +};
> +
> +struct vlc_renderer_discovery_sys
> +{
> + struct discovery_sys s;
> +};
> +
> struct item
> {
> - char * psz_uri;
> - input_item_t * p_input_item;
> - mtime_t i_last_seen;
> + char * psz_uri;
> + input_item_t * p_input_item;
> + vlc_renderer_item * p_renderer_item;
> + mtime_t i_last_seen;
> };
>
> struct srv
> @@ -82,35 +120,22 @@ struct srv
> const char *psz_protocol;
> char * psz_device_name;
> uint16_t i_port;
> + int i_renderer_flags;
> };
>
> -static const struct
> -{
> - const char *psz_protocol;
> - const char *psz_service_name;
> - uint16_t i_default_port;
> -} 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 },
> -};
> -#define NB_PROTOCOLS (sizeof(protocols) / sizeof(*protocols))
> -
> static const char *const ppsz_options[] = {
> NULL
> };
>
> static void
> -print_error( services_discovery_t *p_sd, const char *psz_what, int i_status )
> +print_error( vlc_object_t *p_obj, const char *psz_what, int i_status )
> {
> char psz_err_str[128];
>
> if( mdns_strerror( i_status, psz_err_str, sizeof(psz_err_str) ) == 0)
> - msg_Err( p_sd, "mDNS %s error: %s", psz_what, psz_err_str);
> + msg_Err( p_obj, "mDNS %s error: %s", psz_what, psz_err_str);
> else
> - msg_Err( p_sd, "mDNS %s error: unknown: %d", psz_what, i_status);
> + msg_Err( p_obj, "mDNS %s error: unknown: %d", psz_what, i_status);
> }
>
>
> @@ -126,11 +151,9 @@ strrcmp(const char *s1, const char *s2)
> }
>
> static int
> -items_add_input( services_discovery_t *p_sd, char *psz_uri,
> - const char *psz_name )
> +items_add_input( struct discovery_sys *p_sys, services_discovery_t *p_sd,
> + char *psz_uri, const char *psz_name )
> {
> - services_discovery_sys_t *p_sys = p_sd->p_sys;
> -
> struct item *p_item = malloc( sizeof(struct item) );
> if( p_item == NULL )
> {
> @@ -149,6 +172,7 @@ items_add_input( services_discovery_t *p_sd, char *psz_uri,
>
> p_item->psz_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 );
> @@ -156,25 +180,59 @@ items_add_input( services_discovery_t *p_sd, char *psz_uri,
> return VLC_SUCCESS;
> }
>
> +static int
> +items_add_renderer( struct discovery_sys *p_sys, vlc_renderer_discovery *p_rd,
> + const char *psz_name, char *psz_uri,
> + const char *psz_icon_uri, int i_flags )
> +{
> + 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, NULL, psz_icon_uri, i_flags );
> + if( p_renderer_item == NULL )
> + {
> + free( psz_uri );
> + free( p_item );
> + return VLC_ENOMEM;
> + }
> +
> + p_item->psz_uri = psz_uri;
> + 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 );
> + vlc_rd_add_item( p_rd, p_renderer_item );
> +
> + return VLC_SUCCESS;
> +}
> +
> static void
> -items_release( services_discovery_t *p_sd, struct item *p_item, bool b_notify )
> +items_release( struct discovery_sys *p_sys, struct item *p_item )
> {
> - input_item_Release( p_item->p_input_item );
> - if( b_notify )
> - services_discovery_RemoveItem( p_sd, p_item->p_input_item );
> + (void) p_sys;
> + if( p_item->p_input_item != NULL )
> + {
> + input_item_Release( p_item->p_input_item );
> + }
> + else
> + {
> + assert( p_item->p_renderer_item != NULL );
> + vlc_renderer_item_release( p_item->p_renderer_item );
> + }
> +
> free( p_item->psz_uri );
> free( p_item );
> }
>
> static bool
> -items_exists( services_discovery_t *p_sd, const char *psz_uri )
> +items_exists( struct discovery_sys *p_sys, 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( strcmp( p_item->psz_uri, psz_uri ) == 0 )
> {
> p_item->i_last_seen = mdate();
> return true;
> @@ -184,9 +242,9 @@ items_exists( services_discovery_t *p_sd, const char *psz_uri )
> }
>
> static void
> -items_timeout( services_discovery_t *p_sd )
> +items_timeout( struct discovery_sys *p_sys, services_discovery_t *p_sd,
> + vlc_renderer_discovery *p_rd )
> {
> - services_discovery_sys_t *p_sys = p_sd->p_sys;
> mtime_t i_now = mdate();
>
> /* Remove items that are not seen since TIMEOUT */
> @@ -195,39 +253,37 @@ items_timeout( services_discovery_t *p_sd )
> struct item *p_item = vlc_array_item_at_index( &p_sys->items, i );
> if( i_now - p_item->i_last_seen > TIMEOUT )
> {
> - items_release( p_sd, p_item, true );
> + items_release( p_sys, p_item );
> + if( p_sd != NULL )
> + services_discovery_RemoveItem( p_sd, p_item->p_input_item );
> + else
> + {
> + assert( p_rd != NULL );
> + vlc_rd_remove_item( p_rd, p_item->p_renderer_item );
> + }
> vlc_array_remove( &p_sys->items, i-- );
> }
> }
> }
>
> static void
> -items_clear( services_discovery_t *p_sd )
> +items_clear( struct discovery_sys *p_sys )
> {
> - 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 );
> - items_release( p_sd, p_item, false );
> + items_release( p_sys, p_item );
> }
> vlc_array_clear( &p_sys->items );
> }
>
> -static void
> -new_entries_cb( void *p_this, int i_status,
> - const struct rr_entry *p_entries )
> +static int
> +parse_entries( const struct rr_entry *p_entries, bool b_renderer,
> + struct srv **pp_srvs, unsigned int *p_nb_srv,
> + const char **ppsz_ip )
> {
> - services_discovery_t *p_sd = p_this;
> -
> - if( i_status < 0 )
> - {
> - print_error( p_sd, "entry callback", i_status );
> - return;
> - }
> -
> /* Count the number of servers */
> - unsigned int i_nb_srv = 0, i_srv_idx = 0;
> + unsigned int i_nb_srv = 0;
> for( const struct rr_entry *p_entry = p_entries;
> p_entry != NULL; p_entry = p_entry->next )
> {
> @@ -235,34 +291,36 @@ new_entries_cb( void *p_this, int i_status,
> i_nb_srv++;
> }
> if( i_nb_srv == 0 )
> - return;
> + return VLC_EGENERIC;
>
> struct srv *p_srvs = calloc(i_nb_srv, sizeof(struct srv));
> if( p_srvs == NULL )
> - return;
> + return VLC_EGENERIC;
>
> /* There is one ip for several srvs, fetch them */
> const char *psz_ip = NULL;
> + i_nb_srv = 0;
> for( const struct rr_entry *p_entry = p_entries;
> p_entry != NULL; p_entry = p_entry->next )
> {
> if( p_entry->type == RR_SRV )
> {
> - struct srv *p_srv = &p_srvs[i_srv_idx];
> -
> for( unsigned i = 0; i < NB_PROTOCOLS; ++i )
> {
> - if( !strrcmp( p_entry->name, protocols[i].psz_service_name ) )
> + if( !strrcmp( p_entry->name, protocols[i].psz_service_name ) &&
> + protocols[i].b_renderer == b_renderer )
> {
> + struct srv *p_srv = &p_srvs[i_nb_srv];
> +
> p_srv->psz_device_name =
> strndup( p_entry->name, strlen( p_entry->name )
> - strlen( protocols[i].psz_service_name ) - 1);
> if( p_srv->psz_device_name == NULL )
> break;
> 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;
> - ++i_srv_idx;
> + p_srv->i_port = p_entry->data.SRV.port;
> + p_srv->i_renderer_flags = protocols[i].i_renderer_flags;
> + ++i_nb_srv;
> break;
> }
> }
> @@ -274,120 +332,247 @@ new_entries_cb( void *p_this, int i_status,
> psz_ip = p_entry->data.AAAA.addr_str;
> */
> }
> - if( psz_ip == NULL || i_srv_idx == 0 )
> + if( psz_ip == NULL || i_nb_srv == 0 )
> {
> free( p_srvs );
> + return VLC_EGENERIC;
> + }
> +
> + *pp_srvs = p_srvs;
> + *p_nb_srv = i_nb_srv;
> + *ppsz_ip = psz_ip;
> + return VLC_SUCCESS;
> +}
> +
> +static void
> +new_entries_sd_cb( void *p_this, int i_status, const struct rr_entry *p_entries )
> +{
> + services_discovery_t *p_sd = (services_discovery_t *)p_this;
> + struct discovery_sys *p_sys = &p_sd->p_sys->s;
> + if( i_status < 0 )
> + {
> + print_error( VLC_OBJECT( p_sd ), "entry callback", i_status );
> return;
> }
>
> + struct srv *p_srvs;
> + unsigned i_nb_srv;
> + const char *psz_ip;
> + if( parse_entries( p_entries, false, &p_srvs, &i_nb_srv,
> + &psz_ip ) != VLC_SUCCESS )
> + return;
> +
> /* send new input items (if they don't already exist) */
> - for( i_srv_idx = 0; i_srv_idx < i_nb_srv; ++i_srv_idx )
> + for( unsigned int i = 0; i < i_nb_srv; ++i )
> {
> - struct srv *p_srv = &p_srvs[i_srv_idx];
> - char psz_port[7]; /* ":65536\0" */
> - if( p_srv->i_port != 0 )
> - sprintf( psz_port, ":%u", p_srv->i_port );
> -
> + struct srv *p_srv = &p_srvs[i];
> 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( asprintf( &psz_uri, "%s://%s:%u", p_srv->psz_protocol, psz_ip,
> + p_srv->i_port ) < 0 )
> + break;
> +
> + if( items_exists( p_sys, psz_uri ) )
> {
> free( psz_uri );
> continue;
> }
> - items_add_input( p_sd, psz_uri, p_srv->psz_device_name );
> + items_add_input( p_sys, p_sd, psz_uri, p_srv->psz_device_name );
> }
>
> - for( i_srv_idx = 0; i_srv_idx < i_nb_srv; ++i_srv_idx )
> - free( p_srvs[i_srv_idx].psz_device_name );
> + for( unsigned int i = 0; i < i_nb_srv; ++i )
> + free( p_srvs[i].psz_device_name );
> free( p_srvs );
> }
>
> +
> static bool
> -stop_cb( void *p_this )
> +stop_sd_cb( void *p_this )
> {
> services_discovery_t *p_sd = ( services_discovery_t* )p_this;
> - services_discovery_sys_t *p_sys = p_sd->p_sys;
> + struct discovery_sys *p_sys = &p_sd->p_sys->s;
>
> if( atomic_load( &p_sys->stop ) )
> return true;
> else
> {
> - items_timeout( p_sd );
> + items_timeout( p_sys, p_sd, NULL );
> return false;
> }
> }
>
> static void *
> -Run( void *p_this )
> +RunSD( void *p_this )
> {
> services_discovery_t *p_sd = ( services_discovery_t* )p_this;
> - services_discovery_sys_t *p_sys = p_sd->p_sys;
> + struct discovery_sys *p_sys = &p_sd->p_sys->s;
>
> int i_status = mdns_listen( p_sys->p_microdns,
> p_sys->ppsz_service_names,
> p_sys->i_nb_service_names,
> RR_PTR, LISTEN_INTERVAL / INT64_C(1000000),
> - stop_cb, new_entries_cb, p_sd );
> + stop_sd_cb, new_entries_sd_cb, p_sd );
>
> if( i_status < 0 )
> - print_error( p_sd, "listen", i_status );
> + print_error( VLC_OBJECT( p_sd ), "listen", i_status );
>
> return NULL;
> }
>
> -static int
> -Open( vlc_object_t *p_obj )
> +static void
> +new_entries_rd_cb( void *p_this, int i_status, const struct rr_entry *p_entries )
> {
> - services_discovery_t *p_sd = (services_discovery_t *)p_obj;
> - services_discovery_sys_t *p_sys = NULL;
> - int i_ret = VLC_ENOMEM;
> + vlc_renderer_discovery *p_rd = (vlc_renderer_discovery *)p_this;
> + struct discovery_sys *p_sys = &p_rd->p_sys->s;
> + if( i_status < 0 )
> + {
> + print_error( VLC_OBJECT( p_rd ), "entry callback", i_status );
> + return;
> + }
>
> - p_sd->p_sys = p_sys = calloc( 1, sizeof(services_discovery_sys_t) );
> - if( !p_sys )
> - return VLC_ENOMEM;
> + struct srv *p_srvs;
> + unsigned i_nb_srv;
> + const char *psz_ip;
> + if( parse_entries( p_entries, true, &p_srvs, &i_nb_srv,
> + &psz_ip ) != VLC_SUCCESS )
> + return;
> +
> + const char *psz_model = NULL;
> + const char *psz_icon = NULL;
> + for( const struct rr_entry *p_entry = p_entries;
> + p_entry != NULL && (psz_model == NULL || psz_icon == NULL);
> + p_entry = p_entry->next )
> + {
> + if( p_entry->type == RR_TXT )
> + {
> + const struct rr_data_txt *p_txt = p_entry->data.TXT;
> + while( p_txt )
> + {
> + if( !p_txt->txt )
> + continue;
If txt is NULL you'll have an infinite loop
> + if( !strncmp("md=", p_txt->txt, 3) )
> + {
> + psz_model = p_txt->txt + 3;
> + break;
If you break here you will miss the ic= that may appear later.
> + }
> + else if( !strncmp("ic=", p_txt->txt, 3) )
> + {
> + psz_icon = p_txt->txt + 3;
> + break;
If you break here you will miss the md= that may appear later.
> + }
> + p_txt = p_txt->next;
> + }
> + }
> + }
> +
> + /* send new input items (if they don't already exist) */
> + for( unsigned int i = 0; i < i_nb_srv; ++i )
> + {
> + struct srv *p_srv = &p_srvs[i];
> + char *psz_uri, *psz_icon_uri = NULL;
> +
> + if( asprintf( &psz_uri, "%s://%s:%u", p_srv->psz_protocol, psz_ip,
> + p_srv->i_port ) == -1 )
> + break;
> +
> + if( items_exists( p_sys, psz_uri ) )
> + {
> + free( psz_uri );
> + continue;
> + }
> +
> + if( psz_icon != NULL
> + && asprintf( &psz_icon_uri, "http://%s:8008%s", psz_ip, psz_icon )
> + == -1 )
> + {
> + free( psz_uri );
> + break;
> + }
> +
> + 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_sys, p_rd, p_srv->psz_device_name, psz_uri,
> + psz_icon_uri, p_srv->i_renderer_flags );
> + free(psz_icon_uri);
> + }
> +
> + for( unsigned int i = 0; i < i_nb_srv; ++i )
> + free( p_srvs[i].psz_device_name );
> + free( p_srvs );
> +}
> +
> +static bool
> +stop_rd_cb( void *p_this )
> +{
> + vlc_renderer_discovery *p_rd = ( vlc_renderer_discovery* )p_this;
> + struct discovery_sys *p_sys = &p_rd->p_sys->s;
> +
> + if( atomic_load( &p_sys->stop ) )
> + return true;
> + else
> + {
> + items_timeout( p_sys, NULL, p_rd );
> + return false;
> + }
> +}
> +
> +static void *
> +RunRD( void *p_this )
> +{
> + vlc_renderer_discovery *p_rd = ( vlc_renderer_discovery* )p_this;
> + struct discovery_sys *p_sys = &p_rd->p_sys->s;
>
> + int i_status = mdns_listen( p_sys->p_microdns,
> + p_sys->ppsz_service_names,
> + p_sys->i_nb_service_names,
> + RR_PTR, LISTEN_INTERVAL / INT64_C(1000000),
> + stop_rd_cb, new_entries_rd_cb, p_rd );
> +
> + if( i_status < 0 )
> + print_error( VLC_OBJECT( p_rd ), "listen", i_status );
> +
> + return NULL;
> +}
> +
> +static int
> +OpenCommon( vlc_object_t *p_obj, struct discovery_sys *p_sys, bool b_renderer )
> +{
> + int i_ret = VLC_EGENERIC;
> atomic_init( &p_sys->stop, false );
> vlc_array_init( &p_sys->items );
> - config_ChainParse( p_sd, CFG_PREFIX, ppsz_options, p_sd->p_cfg );
>
> /* Listen to protocols that are handled by VLC */
> - const unsigned i_count = NB_PROTOCOLS;
> - p_sys->ppsz_service_names = calloc( i_count, sizeof(char*) );
> - if( !p_sys->ppsz_service_names )
> - goto error;
> -
> - for( unsigned int i = 0; i < i_count; ++i )
> + for( unsigned int i = 0; i < NB_PROTOCOLS; ++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 )
> p_sys->ppsz_service_names[p_sys->i_nb_service_names++] =
> protocols[i].psz_service_name;
> }
>
> - i_ret = VLC_EGENERIC;
> if( p_sys->i_nb_service_names == 0 )
> {
> - msg_Err( p_sd, "no services found" );
> + msg_Err( p_obj, "no services found" );
> goto error;
> }
> for( unsigned int i = 0; i < p_sys->i_nb_service_names; ++i )
> - msg_Dbg( p_sd, "mDNS: listening to %s", p_sys->ppsz_service_names[i] );
> + msg_Dbg( p_obj, "mDNS: listening to %s %s", p_sys->ppsz_service_names[i],
> + b_renderer ? "renderer" : "service" );
>
> int i_status;
> if( ( i_status = mdns_init( &p_sys->p_microdns, MDNS_ADDR_IPV4,
> MDNS_PORT ) ) < 0 )
> {
> - print_error( p_sd, "init", i_status );
> + print_error( p_obj, "init", i_status );
> goto error;
> }
>
> - if( vlc_clone( &p_sys->thread, Run, p_sd, VLC_THREAD_PRIORITY_LOW) )
> + if( vlc_clone( &p_sys->thread, b_renderer ? RunRD : RunSD, p_obj,
> + VLC_THREAD_PRIORITY_LOW) )
> {
> - msg_Err( p_sd, "Can't run the lookup thread" );
> + msg_Err( p_obj, "Can't run the lookup thread" );
> goto error;
> }
>
> @@ -395,23 +580,62 @@ Open( vlc_object_t *p_obj )
> error:
> if( p_sys->p_microdns != NULL )
> mdns_destroy( p_sys->p_microdns );
> - free( p_sys->ppsz_service_names );
> free( p_sys );
> return i_ret;
> }
>
> static void
> -Close( vlc_object_t *p_this )
> +CleanCommon( struct discovery_sys *p_sys )
> {
> - services_discovery_t *p_sd = (services_discovery_t *) p_this;
> - services_discovery_sys_t *p_sys = p_sd->p_sys;
> -
> atomic_store( &p_sys->stop, true );
> vlc_join( p_sys->thread, NULL );
>
> - items_clear( p_sd );
> + items_clear( p_sys );
> mdns_destroy( p_sys->p_microdns );
> +}
>
> - free( p_sys->ppsz_service_names );
> - free( p_sys );
> +static int
> +OpenSD( vlc_object_t *p_obj )
> +{
> + services_discovery_t *p_sd = (services_discovery_t *)p_obj;
> +
> + p_sd->p_sys = calloc( 1, sizeof(services_discovery_sys_t) );
> + if( !p_sd->p_sys )
> + return VLC_ENOMEM;
> +
> + config_ChainParse( p_sd, CFG_PREFIX, ppsz_options, p_sd->p_cfg );
> +
> + return OpenCommon( p_obj, &p_sd->p_sys->s, false );
> +}
> +
> +static void
> +CloseSD( vlc_object_t *p_this )
> +{
> + services_discovery_t *p_sd = (services_discovery_t *) p_this;
> +
> + CleanCommon( &p_sd->p_sys->s );
> + free( p_sd->p_sys );
> +}
> +
> +static int
> +OpenRD( vlc_object_t *p_obj )
> +{
> + vlc_renderer_discovery *p_rd = (vlc_renderer_discovery *)p_obj;
> +
> + p_rd->p_sys = calloc( 1, sizeof(vlc_renderer_discovery_sys) );
> + if( !p_rd->p_sys )
> + return VLC_ENOMEM;
> +
> + config_ChainParse( p_rd, CFG_PREFIX, ppsz_options, p_rd->p_cfg );
> +
> + return OpenCommon( p_obj, &p_rd->p_sys->s, true );
> +}
> +
> +static void
> +CloseRD( vlc_object_t *p_this )
> +{
> + vlc_renderer_discovery *p_rd = (vlc_renderer_discovery *) p_this;
> +
> + CleanCommon( &p_rd->p_sys->s );
> + free( p_rd->p_sys );
> }
> --
> 2.8.0.rc3
>
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel
More information about the vlc-devel
mailing list