[vlc-devel] [PATCH 7/8] libvlc: add renderer_discoverer external API
Thomas Guillem
thomas at gllm.fr
Mon Sep 19 19:09:50 CEST 2016
---
include/vlc/libvlc_events.h | 14 ++
include/vlc/libvlc_renderer_discoverer.h | 230 ++++++++++++++++++++++++++
include/vlc/vlc.h | 1 +
lib/Makefile.am | 2 +
lib/libvlc.sym | 10 ++
lib/renderer_discoverer.c | 273 +++++++++++++++++++++++++++++++
modules/services_discovery/microdns.c | 6 +-
test/Makefile.am | 3 +
test/libvlc/renderer_discoverer.c | 126 ++++++++++++++
9 files changed, 661 insertions(+), 4 deletions(-)
create mode 100644 include/vlc/libvlc_renderer_discoverer.h
create mode 100644 lib/renderer_discoverer.c
create mode 100644 test/libvlc/renderer_discoverer.c
diff --git a/include/vlc/libvlc_events.h b/include/vlc/libvlc_events.h
index 462fe7f..b69c5ce 100644
--- a/include/vlc/libvlc_events.h
+++ b/include/vlc/libvlc_events.h
@@ -34,6 +34,8 @@
extern "C" {
# endif
+typedef struct libvlc_renderer_item_t libvlc_renderer_item_t;
+
/**
* \ingroup libvlc_event
* @{
@@ -111,6 +113,9 @@ enum libvlc_event_e {
*/
libvlc_MediaDiscovererEnded,
+ libvlc_RendererDiscovererItemAdded,
+ libvlc_RendererDiscovererItemDeleted,
+
libvlc_VlmMediaAdded=0x600,
libvlc_VlmMediaRemoved,
libvlc_VlmMediaChanged,
@@ -269,6 +274,15 @@ typedef struct libvlc_event_t
{
const char *device;
} media_player_audio_device;
+
+ struct
+ {
+ const libvlc_renderer_item_t *item;
+ } renderer_discoverer_item_added;
+ struct
+ {
+ const libvlc_renderer_item_t *item;
+ } renderer_discoverer_item_deleted;
} u; /**< Type-dependent event description */
} libvlc_event_t;
diff --git a/include/vlc/libvlc_renderer_discoverer.h b/include/vlc/libvlc_renderer_discoverer.h
new file mode 100644
index 0000000..5a8351f
--- /dev/null
+++ b/include/vlc/libvlc_renderer_discoverer.h
@@ -0,0 +1,230 @@
+/*****************************************************************************
+ * libvlc_renderer_discoverer.h: libvlc external API
+ *****************************************************************************
+ * Copyright © 2016 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifndef VLC_LIBVLC_RENDERER_DISCOVERER_H
+#define VLC_LIBVLC_RENDERER_DISCOVERER_H 1
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+/**
+ * @defgroup libvlc_renderer_discoverer LibVLC renderer discoverer
+ * @ingroup libvlc
+ * LibVLC renderer discoverer finds available renderers available on the local
+ * network
+ * @{
+ * @file
+ * LibVLC renderer discoverer external API
+ */
+
+typedef struct libvlc_renderer_discoverer_t libvlc_renderer_discoverer_t;
+
+/**
+ * Renderer discoverer description
+ *
+ * \see libvlc_renderer_discoverer_list_get()
+ */
+typedef struct libvlc_rd_description_t
+{
+ char *psz_name;
+ char *psz_longname;
+} libvlc_rd_description_t;
+
+/** The renderer can render audio */
+#define LIBVLC_RENDERER_CAN_AUDIO 0x0001
+/** The renderer can render video */
+#define LIBVLC_RENDERER_CAN_VIDEO 0x0002
+
+/**
+ * Renderer item
+ *
+ * This struct is passed by a @ref libvlc_event_t when a new renderer is added
+ * or deleted.
+ *
+ * An item is valid until the @ref libvlc_RendererDiscovererItemDeleted event
+ * is called with the same pointer.
+ *
+ * \see libvlc_renderer_discoverer_event_manager()
+ */
+typedef struct libvlc_renderer_item_t libvlc_renderer_item_t;
+
+/**
+ * Get the human readable name of a renderer item
+ *
+ * \version LibVLC 3.0.0 or later
+ *
+ * \return the name of the item (can't be NULL, must *not* be freed)
+ */
+LIBVLC_API const char *
+libvlc_renderer_item_name(const libvlc_renderer_item_t *p_item);
+
+/**
+ * Get the uri of a renderer item
+ *
+ * \version LibVLC 3.0.0 or later
+ *
+ * \return the uri of the item (can't be NULL, must *not* be freed)
+ */
+LIBVLC_API const char *
+libvlc_renderer_item_uri(const libvlc_renderer_item_t *p_item);
+
+/**
+ * Get the icon uri of a renderer item
+ *
+ * \version LibVLC 3.0.0 or later
+ *
+ * \return the uri of the item's icon (can be NULL, must *not* be freed)
+ */
+LIBVLC_API const char *
+libvlc_renderer_item_icon_uri(const libvlc_renderer_item_t *p_item);
+
+/**
+ * Get the flags of a renderer item
+ *
+ * \see LIBVLC_RENDERER_CAN_AUDIO
+ * \see LIBVLC_RENDERER_CAN_VIDEO
+ *
+ * \version LibVLC 3.0.0 or later
+ *
+ * \return bitwise flag: capabilities of the renderer, see
+ */
+LIBVLC_API int
+libvlc_renderer_item_flags(const libvlc_renderer_item_t *p_item);
+
+/**
+ * Create a renderer discoverer object by name
+ *
+ * After this object is created, you should attach to events in order to be
+ * notified of the discoverer events.
+ *
+ * You need to call libvlc_renderer_discoverer_start() in order to start the
+ * discovery.
+ *
+ * \see libvlc_renderer_discoverer_event_manager()
+ * \see libvlc_renderer_discoverer_start()
+ *
+ * \version LibVLC 3.0.0 or later
+ *
+ * \param p_inst libvlc instance
+ * \param psz_name service name; use libvlc_renderer_discoverer_list_get() to
+ * get a list of the discoverer names available in this libVLC instance
+ * \return media discover object or NULL in case of error
+ */
+LIBVLC_API libvlc_renderer_discoverer_t *
+libvlc_renderer_discoverer_new( libvlc_instance_t *p_inst,
+ const char *psz_name );
+
+/**
+ * Release a renderer discoverer object
+ *
+ * \version LibVLC 3.0.0 or later
+ *
+ * \param p_rd renderer discoverer object
+ */
+LIBVLC_API void
+libvlc_renderer_discoverer_release( libvlc_renderer_discoverer_t *p_rd );
+
+/**
+ * Start renderer discovery
+ *
+ * To stop it, call libvlc_renderer_discoverer_stop() or
+ * libvlc_renderer_discoverer_release() directly.
+ *
+ * \see libvlc_renderer_discoverer_stop()
+ *
+ * \version LibVLC 3.0.0 or later
+ *
+ * \param p_rd renderer discoverer object
+ * \return -1 in case of error, 0 otherwise
+ */
+LIBVLC_API int
+libvlc_renderer_discoverer_start( libvlc_renderer_discoverer_t *p_rd );
+
+/**
+ * Stop renderer discovery.
+ *
+ * \see libvlc_renderer_discoverer_start()
+ *
+ * \version LibVLC 3.0.0 or later
+ *
+ * \param p_rd renderer discoverer object
+ */
+LIBVLC_API void
+libvlc_renderer_discoverer_stop( libvlc_renderer_discoverer_t *p_rd );
+
+/**
+ * Get the event manager of the renderer discoverer
+ *
+ * The possible events to attach are @ref libvlc_RendererDiscovererItemAdded
+ * and @ref libvlc_RendererDiscovererItemDeleted.
+ *
+ * The @ref libvlc_renderer_item_t struct passed to event callbacks is owned by
+ * VLC, users should take care of copying this struct for their internal usage.
+ *
+ * \see libvlc_event_t.u.renderer_discoverer_item_added.item
+ * \see libvlc_event_t.u.renderer_discoverer_item_removed.item
+ *
+ * \version LibVLC 3.0.0 or later
+ *
+ * \return a valid event manager (can't fail)
+ */
+LIBVLC_API libvlc_event_manager_t *
+libvlc_renderer_discoverer_event_manager( libvlc_renderer_discoverer_t *p_rd );
+
+/**
+ * Get media discoverer services
+ *
+ * \see libvlc_renderer_list_release()
+ *
+ * \version LibVLC 3.0.0 and later
+ *
+ * \param p_inst libvlc instance
+ * \param ppp_services address to store an allocated array of renderer
+ * discoverer services (must be freed with libvlc_renderer_list_release() by
+ * the caller) [OUT]
+ *
+ * \return the number of media discoverer services or -1 on error
+ */
+LIBVLC_API ssize_t
+libvlc_renderer_discoverer_list_get( libvlc_instance_t *p_inst,
+ libvlc_rd_description_t ***ppp_services );
+
+/**
+ * Release an array of media discoverer services
+ *
+ * \see libvlc_renderer_discoverer_list_get()
+ *
+ * \version LibVLC 3.0.0 and later
+ *
+ * \param pp_services array to release
+ * \param i_count number of elements in the array
+ */
+LIBVLC_API void
+libvlc_renderer_discoverer_list_release( libvlc_rd_description_t **pp_services,
+ size_t i_count );
+
+/** @} */
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif
diff --git a/include/vlc/vlc.h b/include/vlc/vlc.h
index 1e2cf65..6d25cd5 100644
--- a/include/vlc/vlc.h
+++ b/include/vlc/vlc.h
@@ -38,6 +38,7 @@ extern "C" {
# endif
#include <vlc/libvlc.h>
+#include <vlc/libvlc_renderer_discoverer.h>
#include <vlc/libvlc_media.h>
#include <vlc/libvlc_media_player.h>
#include <vlc/libvlc_media_list.h>
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 7a6b7c1..1562ad3 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -20,6 +20,7 @@ pkginclude_HEADERS = \
../include/vlc/libvlc_media_list_player.h \
../include/vlc/libvlc_media_player.h \
../include/vlc/libvlc_vlm.h \
+ ../include/vlc/libvlc_renderer_discoverer.h \
../include/vlc/vlc.h
nodist_pkginclude_HEADERS = ../include/vlc/libvlc_version.h
@@ -37,6 +38,7 @@ libvlc_la_SOURCES = \
media_player_internal.h \
core.c \
dialog.c \
+ renderer_discoverer.c \
error.c \
log.c \
playlist.c \
diff --git a/lib/libvlc.sym b/lib/libvlc.sym
index 733a4dd..d37d100 100644
--- a/lib/libvlc.sym
+++ b/lib/libvlc.sym
@@ -218,6 +218,16 @@ libvlc_media_tracks_release
libvlc_new
libvlc_playlist_play
libvlc_release
+libvlc_renderer_item_name
+libvlc_renderer_item_uri
+libvlc_renderer_item_icon_uri
+libvlc_renderer_discoverer_event_manager
+libvlc_renderer_discoverer_list_get
+libvlc_renderer_discoverer_list_release
+libvlc_renderer_discoverer_new
+libvlc_renderer_discoverer_release
+libvlc_renderer_discoverer_start
+libvlc_renderer_discoverer_stop
libvlc_retain
libvlc_set_fullscreen
libvlc_set_log_verbosity
diff --git a/lib/renderer_discoverer.c b/lib/renderer_discoverer.c
new file mode 100644
index 0000000..c3664c6
--- /dev/null
+++ b/lib/renderer_discoverer.c
@@ -0,0 +1,273 @@
+/*****************************************************************************
+ * renderer_discoverer.c: libvlc renderer API
+ *****************************************************************************
+ * Copyright © 2016 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <assert.h>
+
+#include <vlc/libvlc.h>
+#include <vlc/libvlc_renderer_discoverer.h>
+
+#include <vlc_common.h>
+
+#include "libvlc_internal.h"
+#include "renderer_discoverer_internal.h"
+
+struct libvlc_renderer_discoverer_t
+{
+ vlc_renderer_discovery_t *p_rd;
+ libvlc_event_manager_t *p_event_manager;
+
+ int i_items;
+ vlc_renderer_item_t ** pp_items;
+};
+
+static_assert( VLC_RENDERER_CAN_AUDIO == LIBVLC_RENDERER_CAN_AUDIO &&
+ VLC_RENDERER_CAN_VIDEO == LIBVLC_RENDERER_CAN_VIDEO,
+ "core/libvlc renderer flags mismatch" );
+
+const vlc_renderer_item_t *
+libvlc_renderer_item_to_vlc( const libvlc_renderer_item_t *p_item )
+{
+ return (const vlc_renderer_item_t*) p_item;
+}
+
+static void
+renderer_discovery_item_added( const vlc_event_t *p_event, void *p_user_data )
+{
+ libvlc_renderer_discoverer_t *p_lrd = p_user_data;
+ vlc_renderer_item_t *p_item =
+ p_event->u.renderer_discovery_item_added.p_new_item;
+
+ vlc_renderer_item_hold( p_item );
+
+ TAB_APPEND( p_lrd->i_items, p_lrd->pp_items, p_item );
+
+ libvlc_event_t event = {
+ .type = libvlc_RendererDiscovererItemAdded,
+ .u.renderer_discoverer_item_added.item =
+ (libvlc_renderer_item_t*) p_item,
+ };
+ libvlc_event_send( p_lrd->p_event_manager, &event );
+}
+
+static void
+renderer_discovery_item_removed( const vlc_event_t *p_event, void *p_user_data )
+{
+ libvlc_renderer_discoverer_t *p_lrd = p_user_data;
+ vlc_renderer_item_t *p_item =
+ p_event->u.renderer_discovery_item_removed.p_item;
+
+ int i_idx;
+ TAB_FIND( p_lrd->i_items, p_lrd->pp_items, p_item, i_idx );
+ assert( i_idx != -1 );
+ TAB_ERASE( p_lrd->i_items, p_lrd->pp_items, i_idx );
+
+ libvlc_event_t event = {
+ .type = libvlc_RendererDiscovererItemDeleted,
+ .u.renderer_discoverer_item_deleted.item =
+ (libvlc_renderer_item_t*) p_item,
+ };
+ libvlc_event_send( p_lrd->p_event_manager, &event );
+
+ vlc_renderer_item_release( p_item );
+}
+
+const char *
+libvlc_renderer_item_name( const libvlc_renderer_item_t *p_item )
+{
+ return vlc_renderer_item_name( (vlc_renderer_item_t *) p_item );
+}
+
+const char *
+libvlc_renderer_item_uri( const libvlc_renderer_item_t *p_item )
+{
+ return vlc_renderer_item_uri( (vlc_renderer_item_t *) p_item );
+}
+
+const char *
+libvlc_renderer_item_icon_uri( const libvlc_renderer_item_t *p_item )
+{
+ return vlc_renderer_item_icon_uri( (vlc_renderer_item_t *) p_item );
+}
+
+libvlc_renderer_discoverer_t *
+libvlc_renderer_discoverer_new( libvlc_instance_t *p_inst,
+ const char *psz_name )
+{
+ libvlc_renderer_discoverer_t *p_lrd =
+ calloc( 1, sizeof(libvlc_renderer_discoverer_t) );
+
+ if( unlikely(p_lrd == NULL) )
+ return NULL;
+
+ p_lrd->p_rd = vlc_rd_new( VLC_OBJECT( p_inst->p_libvlc_int ), psz_name );
+ if( unlikely(p_lrd->p_rd == NULL) )
+ goto error;
+
+ TAB_INIT( p_lrd->i_items, p_lrd->pp_items );
+
+ p_lrd->p_event_manager = libvlc_event_manager_new( p_lrd );
+ if( unlikely(p_lrd->p_event_manager == NULL) )
+ goto error;
+
+ vlc_event_manager_t *p_rd_ev = vlc_rd_event_manager( p_lrd->p_rd );
+
+ if( vlc_event_attach( p_rd_ev, vlc_RendererDiscoveryItemAdded,
+ renderer_discovery_item_added, p_lrd )
+ != VLC_SUCCESS )
+ goto error;
+ if( vlc_event_attach( p_rd_ev, vlc_RendererDiscoveryItemRemoved,
+ renderer_discovery_item_removed, p_lrd )
+ != VLC_SUCCESS )
+ goto error;
+
+ return p_lrd;
+
+error:
+ libvlc_renderer_discoverer_release( p_lrd );
+ return NULL;
+}
+
+void
+libvlc_renderer_discoverer_release( libvlc_renderer_discoverer_t *p_lrd )
+{
+ if( p_lrd->p_rd != NULL )
+ vlc_rd_release( p_lrd->p_rd );
+
+ if( p_lrd->p_event_manager != NULL )
+ libvlc_event_manager_release( p_lrd->p_event_manager );
+
+ free( p_lrd );
+}
+
+int
+libvlc_renderer_discoverer_start( libvlc_renderer_discoverer_t *p_lrd )
+{
+ return vlc_rd_start( p_lrd->p_rd );
+}
+
+void
+libvlc_renderer_discoverer_stop( libvlc_renderer_discoverer_t *p_lrd )
+{
+ vlc_rd_stop( p_lrd->p_rd );
+
+ for( int i = 0; i < p_lrd->i_items; ++i )
+ vlc_renderer_item_release( p_lrd->pp_items[i] );
+ TAB_CLEAN( p_lrd->i_items, p_lrd->pp_items );
+}
+
+libvlc_event_manager_t *
+libvlc_renderer_discoverer_event_manager( libvlc_renderer_discoverer_t *p_lrd )
+{
+ return p_lrd->p_event_manager;
+}
+
+void
+libvlc_renderer_discoverer_list_release( libvlc_rd_description_t **pp_services,
+ size_t i_count )
+{
+ if( i_count > 0 )
+ {
+ for( size_t i = 0; i < i_count; ++i )
+ {
+ free( pp_services[i]->psz_name );
+ free( pp_services[i]->psz_longname );
+ }
+ free( *pp_services );
+ free( pp_services );
+ }
+}
+
+ssize_t
+libvlc_renderer_discoverer_list_get( libvlc_instance_t *p_inst,
+ libvlc_rd_description_t ***ppp_services )
+{
+ assert( p_inst != NULL && ppp_services != NULL );
+
+ /* Fetch all rd names, and longnames */
+ char **ppsz_names, **ppsz_longnames;
+ int i_ret = vlc_rd_get_names( p_inst->p_libvlc_int, &ppsz_names,
+ &ppsz_longnames );
+
+ if( i_ret != VLC_SUCCESS )
+ {
+ *ppp_services = NULL;
+ return -1;
+ }
+
+ /* Count the number of sd matching our category (i_cat/i_core_cat) */
+ size_t i_nb_services = 0;
+ char **ppsz_name = ppsz_names;
+ for( ; *ppsz_name != NULL; ppsz_name++ )
+ i_nb_services++;
+
+ libvlc_rd_description_t **pp_services = NULL,
+ *p_services = NULL;
+ if( i_nb_services > 0 )
+ {
+ /* Double alloc here, so that the caller iterates through pointers of
+ * struct instead of structs. This allows us to modify the struct
+ * without breaking the API. */
+
+ pp_services =
+ malloc( i_nb_services
+ * sizeof(libvlc_rd_description_t *) );
+ p_services =
+ malloc( i_nb_services
+ * sizeof(libvlc_rd_description_t) );
+ if( pp_services == NULL || p_services == NULL )
+ {
+ free( pp_services );
+ free( p_services );
+ pp_services = NULL;
+ p_services = NULL;
+ i_nb_services = -1;
+ /* Even if alloc fails, the next loop must be run in order to free
+ * names returned by vlc_sd_GetNames */
+ }
+ }
+
+ /* Fill output pp_services or free unused name, longname */
+ char **ppsz_longname = ppsz_longnames;
+ unsigned int i_service_idx = 0;
+ libvlc_rd_description_t *p_service = p_services;
+ for( ppsz_name = ppsz_names; *ppsz_name != NULL; ppsz_name++, ppsz_longname++ )
+ {
+ if( pp_services != NULL )
+ {
+ p_service->psz_name = *ppsz_name;
+ p_service->psz_longname = *ppsz_longname;
+ pp_services[i_service_idx++] = p_service++;
+ }
+ else
+ {
+ free( *ppsz_name );
+ free( *ppsz_longname );
+ }
+ }
+ free( ppsz_names );
+ free( ppsz_longnames );
+
+ *ppp_services = pp_services;
+ return i_nb_services;
+}
diff --git a/modules/services_discovery/microdns.c b/modules/services_discovery/microdns.c
index b82cb5c..289d321 100644
--- a/modules/services_discovery/microdns.c
+++ b/modules/services_discovery/microdns.c
@@ -249,6 +249,7 @@ static void
items_timeout( struct discovery_sys *p_sys, services_discovery_t *p_sd,
vlc_renderer_discovery_t *p_rd )
{
+ assert( p_rd != NULL || p_sd != NULL );
mtime_t i_now = mdate();
/* Remove items that are not seen since TIMEOUT */
@@ -257,14 +258,11 @@ items_timeout( struct discovery_sys *p_sys, 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_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 );
- }
+ items_release( p_sys, p_item );
vlc_array_remove( &p_sys->items, i-- );
}
}
diff --git a/test/Makefile.am b/test/Makefile.am
index 4e9b1f2..7731782 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -19,6 +19,7 @@ check_PROGRAMS = \
test_libvlc_media_list \
test_libvlc_media_player \
test_libvlc_media_discoverer \
+ test_libvlc_renderer_discoverer \
test_libvlc_slaves \
test_src_config_chain \
test_src_misc_variables \
@@ -85,6 +86,8 @@ test_libvlc_media_player_SOURCES = libvlc/media_player.c
test_libvlc_media_player_LDADD = $(LIBVLC)
test_libvlc_media_discoverer_SOURCES = libvlc/media_discoverer.c
test_libvlc_media_discoverer_LDADD = $(LIBVLC)
+test_libvlc_renderer_discoverer_SOURCES = libvlc/renderer_discoverer.c
+test_libvlc_renderer_discoverer_LDADD = $(LIBVLC)
test_libvlc_slaves_SOURCES = libvlc/slaves.c
test_libvlc_slaves_LDADD = $(LIBVLCCORE) $(LIBVLC)
test_libvlc_meta_SOURCES = libvlc/meta.c
diff --git a/test/libvlc/renderer_discoverer.c b/test/libvlc/renderer_discoverer.c
new file mode 100644
index 0000000..093b633
--- /dev/null
+++ b/test/libvlc/renderer_discoverer.c
@@ -0,0 +1,126 @@
+/*****************************************************************************
+ * renderer_discoverer.c - libvlc smoke test
+ *****************************************************************************
+ * Copyright © 2016 VLC authors, and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#include "test.h"
+
+#include <string.h>
+
+static void
+item_event(const libvlc_renderer_item_t *p_item, const char *psz_event)
+{
+ log("item %s: name: '%s', uri: '%s'\n", psz_event,
+ libvlc_renderer_item_name(p_item), libvlc_renderer_item_uri(p_item));
+}
+
+static void
+renderer_discoverer_item_added(const struct libvlc_event_t *p_ev, void *p_data)
+{
+ (void) p_data;
+ item_event(p_ev->u.renderer_discoverer_item_added.item, "added");
+}
+
+static void
+renderer_discoverer_item_deleted(const struct libvlc_event_t *p_ev, void *p_data)
+{
+ (void) p_data;
+ item_event(p_ev->u.renderer_discoverer_item_deleted.item, "deleted");
+}
+
+static void
+test_discoverer(libvlc_instance_t *p_vlc, const char *psz_name)
+{
+ log("creating and starting discoverer %s\n", psz_name);
+
+ libvlc_renderer_discoverer_t *p_rd =
+ libvlc_renderer_discoverer_new(p_vlc, psz_name);
+ assert(p_rd != NULL);
+
+ libvlc_event_manager_t *p_evm = libvlc_renderer_discoverer_event_manager(p_rd);
+ assert(p_evm);
+
+ int i_ret;
+ i_ret = libvlc_event_attach(p_evm, libvlc_RendererDiscovererItemAdded,
+ renderer_discoverer_item_added, NULL);
+ assert(i_ret == 0);
+ i_ret = libvlc_event_attach(p_evm, libvlc_RendererDiscovererItemDeleted,
+ renderer_discoverer_item_deleted, NULL);
+ assert(i_ret == 0);
+
+ if (libvlc_renderer_discoverer_start(p_rd) == -1)
+ {
+ log("warn: could not start md (not critical)\n");
+ }
+ else
+ {
+ log("Press any keys to stop\n");
+ getchar();
+ libvlc_renderer_discoverer_stop(p_rd);
+ }
+
+ libvlc_renderer_discoverer_release(p_rd);
+}
+
+int
+main(int i_argc, char *ppsz_argv[])
+{
+ test_init();
+
+ char *psz_test_name = i_argc > 1 ? ppsz_argv[1] : NULL;
+
+ libvlc_instance_t *p_vlc = libvlc_new(test_defaults_nargs,
+ test_defaults_args);
+ assert(p_vlc != NULL);
+
+ if (psz_test_name != NULL)
+ {
+ /* Test a specific service discovery from command line */
+ alarm(0);
+ test_discoverer(p_vlc, psz_test_name);
+ libvlc_release(p_vlc);
+ return 0;
+ }
+
+ log("== getting the list of renderer_discoverer ==\n");
+
+ libvlc_rd_description_t **pp_services;
+ ssize_t i_count =
+ libvlc_renderer_discoverer_list_get(p_vlc, &pp_services);
+ if (i_count <= 0)
+ {
+ log("warn: no discoverers (not critical)\n");
+ goto end;
+ }
+ assert(pp_services != NULL);
+
+ for (unsigned int i = 0; i < i_count; ++i)
+ {
+ libvlc_rd_description_t *p_service = pp_services[i];
+
+ log("= discoverer: name: '%s', longname: '%s' =\n",
+ p_service->psz_name, p_service->psz_longname);
+ }
+
+ libvlc_renderer_discoverer_list_release(pp_services, i_count);
+
+end:
+ libvlc_release(p_vlc);
+
+ return 0;
+}
--
2.9.3
More information about the vlc-devel
mailing list