[vlc-devel] [PATCH 1/9] core: Add a services advertisement API
Hugo Beauzée-Luyssen
hugo at beauzee.fr
Wed Sep 2 15:47:23 CEST 2020
Refs #18090
Co-authored-by: Roland Bewick <roland.bewick at gmail.com>
---
include/vlc_services_advertisement.h | 119 +++++++++++++++++
src/Makefile.am | 2 +
src/libvlc.c | 8 ++
src/libvlc.h | 2 +
src/libvlccore.sym | 11 ++
src/misc/services_advertisement.c | 192 +++++++++++++++++++++++++++
6 files changed, 334 insertions(+)
create mode 100644 include/vlc_services_advertisement.h
create mode 100644 src/misc/services_advertisement.c
diff --git a/include/vlc_services_advertisement.h b/include/vlc_services_advertisement.h
new file mode 100644
index 0000000000..cf713d017a
--- /dev/null
+++ b/include/vlc_services_advertisement.h
@@ -0,0 +1,119 @@
+/*****************************************************************************
+ * vlc_services_advertisement.h : Services Advertisement functions
+ *****************************************************************************
+ * Copyright (C) 1999-2019 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_SERVICES_ADVERTISEMENT_H_
+#define VLC_SERVICES_ADVERTISEMENT_H_
+
+#include <vlc_common.h>
+
+/**
+ * \file
+ * This file lists functions and structures for service advertisement (SA) in vlc
+ */
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+/**
+ * @{
+ */
+
+typedef struct services_advertisement_entry_t services_advertisement_entry_t;
+
+/**
+ * Main service advertisement structure to build a SA module
+ */
+typedef struct services_advertisement_t
+{
+ struct vlc_object_t obj;
+
+ module_t * p_module; /**< Loaded module */
+
+ char *psz_name; /**< Main name of the SA */
+ config_chain_t *p_cfg; /**< Configuration for the SA */
+
+ const char *description; /**< Human-readable name */
+
+ void *p_sys; /**< Custom private data */
+
+ int (*pf_announce)( struct services_advertisement_t*,
+ services_advertisement_entry_t* );
+ int (*pf_conceal)( struct services_advertisement_t*,
+ services_advertisement_entry_t* );
+} services_advertisement_t;
+
+/***********************************************************************
+ * Service Advertisement
+ ***********************************************************************/
+
+/**
+ * Stops and unloads services advertisement module if it was loaded.
+ *
+ * @param libvlc the LibVLC instance
+ */
+void vlc_sa_Destroy( libvlc_int_t *libvlc );
+
+/**
+ * @brief vlc_sa_Announce Announces a new service
+ * @param libvlc The LibVLC instance
+ * @param entry The entry to announce
+ * @return VLC_SUCCESS or an error code
+ */
+VLC_API int vlc_sa_Announce( libvlc_int_t *libvlc, services_advertisement_entry_t* entry );
+
+/**
+ * @brief vlc_sa_Conceal Conceals an announced service
+ * @param libvlc The LibVLC instance
+ * @param entry The entry to conceal
+ * @return VLC_SUCCESS or an error code
+ */
+VLC_API int vlc_sa_Conceal( libvlc_int_t *libvlc, services_advertisement_entry_t* entry );
+
+/**
+ * @brief vlc_sa_entry_New Creates a new service advertisement entry
+ * @param name The service name
+ * @param type The service type, eg. _http._tcp (without the .local suffix)
+ * @param port The port this service runs on
+ *
+ * @return A services_advertisement_entry_t on success or NULL in case of error
+ */
+VLC_API services_advertisement_entry_t*
+vlc_sa_entry_New( const char* name, const char* type, uint16_t port );
+
+VLC_API services_advertisement_entry_t*
+vlc_sa_entry_Hold( services_advertisement_entry_t *entry );
+VLC_API void vlc_sa_entry_Release( services_advertisement_entry_t *entry );
+
+VLC_API const char* vlc_sa_entry_Name( services_advertisement_entry_t *entry );
+VLC_API const char* vlc_sa_entry_Type( services_advertisement_entry_t *entry );
+VLC_API uint16_t vlc_sa_entry_Port( services_advertisement_entry_t *entry );
+
+VLC_API size_t vlc_sa_entry_Count_TXT( services_advertisement_entry_t* entry );
+VLC_API const char** vlc_sa_entry_Get_TXT( services_advertisement_entry_t* entry );
+VLC_API bool vlc_sa_entry_Add_TXT( services_advertisement_entry_t* entry,
+ const char* txt );
+
+/** @} */
+# ifdef __cplusplus
+}
+# endif
+
+#endif
diff --git a/src/Makefile.am b/src/Makefile.am
index 6dc46ab3d6..56ebc7a0fb 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -86,6 +86,7 @@ pluginsinclude_HEADERS = \
../include/vlc_queue.h \
../include/vlc_rand.h \
../include/vlc_services_discovery.h \
+ ../include/vlc_services_advertisement.h \
../include/vlc_fingerprinter.h \
../include/vlc_interrupt.h \
../include/vlc_renderer_discovery.h \
@@ -369,6 +370,7 @@ libvlccore_la_SOURCES = \
misc/interrupt.c \
misc/keystore.c \
misc/renderer_discovery.c \
+ misc/services_advertisement.c \
misc/threads.c \
misc/cpu.c \
misc/epg.c \
diff --git a/src/libvlc.c b/src/libvlc.c
index c1dcde276d..558b146561 100644
--- a/src/libvlc.c
+++ b/src/libvlc.c
@@ -63,6 +63,7 @@
#include <vlc_modules.h>
#include <vlc_media_library.h>
#include <vlc_thumbnailer.h>
+#include <vlc_services_advertisement.h>
#include "libvlc.h"
@@ -92,6 +93,7 @@ libvlc_int_t * libvlc_InternalCreate( void )
priv = libvlc_priv (p_libvlc);
vlc_mutex_init(&priv->lock);
priv->interfaces = NULL;
+ priv->services_advertisements = NULL;
priv->main_playlist = NULL;
priv->p_vlm = NULL;
priv->media_source_provider = NULL;
@@ -130,6 +132,7 @@ int libvlc_InternalInit( libvlc_int_t *p_libvlc, int i_argc,
const char *ppsz_argv[] )
{
libvlc_priv_t *priv = libvlc_priv (p_libvlc);
+ char * psz_services_advertisement = NULL;
char *psz_val;
int i_ret = VLC_EGENERIC;
@@ -282,6 +285,8 @@ int libvlc_InternalInit( libvlc_int_t *p_libvlc, int i_argc,
if( var_InheritBool( p_libvlc, "network-synchronisation") )
libvlc_InternalAddIntf( p_libvlc, "netsync,none" );
+ free( psz_services_advertisement );
+
#ifdef __APPLE__
var_Create( p_libvlc, "drawable-view-top", VLC_VAR_INTEGER );
var_Create( p_libvlc, "drawable-view-left", VLC_VAR_INTEGER );
@@ -347,6 +352,9 @@ void libvlc_InternalCleanup( libvlc_int_t *p_libvlc )
msg_Dbg( p_libvlc, "removing all interfaces" );
intf_DestroyAll( p_libvlc );
+ /* Ask the service announcement modules to stop and destroy them */
+ vlc_sa_Destroy( p_libvlc );
+
if ( priv->p_thumbnailer )
vlc_thumbnailer_Release( priv->p_thumbnailer );
diff --git a/src/libvlc.h b/src/libvlc.h
index d2d112aa56..fb3bd7a3ce 100644
--- a/src/libvlc.h
+++ b/src/libvlc.h
@@ -177,6 +177,7 @@ typedef struct vlc_actions_t vlc_actions_t;
typedef struct vlc_playlist vlc_playlist_t;
typedef struct vlc_media_source_provider_t vlc_media_source_provider_t;
typedef struct intf_thread_t intf_thread_t;
+typedef struct services_advertisement_t services_advertisement_t;
typedef struct libvlc_priv_t
{
@@ -194,6 +195,7 @@ typedef struct libvlc_priv_t
vlc_actions_t *actions; ///< Hotkeys handler
struct vlc_medialibrary_t *p_media_library; ///< Media library instance
struct vlc_thumbnailer_t *p_thumbnailer; ///< Lazily instantiated media thumbnailer
+ services_advertisement_t * services_advertisements; // Linked-list of SA modules
/* Exit callback */
vlc_exit_t exit;
diff --git a/src/libvlccore.sym b/src/libvlccore.sym
index 2b750873fc..b0aa359603 100644
--- a/src/libvlccore.sym
+++ b/src/libvlccore.sym
@@ -690,6 +690,17 @@ vlc_gl_Hold
vlc_gl_surface_Create
vlc_gl_surface_CheckSize
vlc_gl_surface_Destroy
+vlc_sa_Announce
+vlc_sa_Conceal
+vlc_sa_entry_New
+vlc_sa_entry_Hold
+vlc_sa_entry_Release
+vlc_sa_entry_Name
+vlc_sa_entry_Type
+vlc_sa_entry_Port
+vlc_sa_entry_Count_TXT
+vlc_sa_entry_Get_TXT
+vlc_sa_entry_Add_TXT
vlm_Control
vlm_Delete
vlm_ExecuteCommand
diff --git a/src/misc/services_advertisement.c b/src/misc/services_advertisement.c
new file mode 100644
index 0000000000..d42ea3578e
--- /dev/null
+++ b/src/misc/services_advertisement.c
@@ -0,0 +1,192 @@
+/*****************************************************************************
+ * services_advertisement.c : Manage services advertisement modules
+ *****************************************************************************
+ * Copyright (C) 2020 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_common.h>
+#include <vlc_services_advertisement.h>
+#include <vlc_modules.h>
+#include <vlc_atomic.h>
+#include <vlc_vector.h>
+#include "../libvlc.h"
+
+typedef struct VLC_VECTOR(char*) txt_vect;
+
+struct services_advertisement_entry_t
+{
+ vlc_atomic_rc_t refcount;
+ char* name;
+ char* type;
+ uint16_t port;
+ txt_vect txts;
+};
+
+static void vlc_sa_entry_Destroy( services_advertisement_entry_t* entry )
+{
+ for ( size_t i = 0; i < entry->txts.size; ++i )
+ free( entry->txts.data[i] );
+ vlc_vector_destroy( &entry->txts );
+ free( entry->name );
+ free( entry->type );
+ free( entry );
+}
+
+services_advertisement_entry_t* vlc_sa_entry_New( const char* name,
+ const char* type, uint16_t port )
+{
+ services_advertisement_entry_t* entry = malloc( sizeof( *entry ) );
+ if( !entry )
+ return NULL;
+ entry->name = strdup( name );
+ entry->type = strdup( type );
+ if( !entry->name || !entry->type )
+ {
+ vlc_sa_entry_Destroy( entry );
+ return NULL;
+ }
+ vlc_atomic_rc_init( &entry->refcount );
+ entry->port = port;
+ vlc_vector_init( &entry->txts );
+ return entry;
+}
+
+services_advertisement_entry_t*
+vlc_sa_entry_Hold( services_advertisement_entry_t *entry )
+{
+ vlc_atomic_rc_inc( &entry->refcount );
+ return entry;
+}
+
+void vlc_sa_entry_Release( services_advertisement_entry_t *entry )
+{
+ if ( vlc_atomic_rc_dec( &entry->refcount ) )
+ vlc_sa_entry_Destroy( entry );
+}
+
+const char* vlc_sa_entry_Name( services_advertisement_entry_t *entry )
+{
+ return entry->name;
+}
+
+const char* vlc_sa_entry_Type( services_advertisement_entry_t *entry )
+{
+ return entry->type;
+}
+
+uint16_t vlc_sa_entry_Port( services_advertisement_entry_t *entry )
+{
+ return entry->port;
+}
+
+VLC_API size_t vlc_sa_entry_Count_TXT( services_advertisement_entry_t* entry )
+{
+ return entry->txts.size;
+}
+
+VLC_API const char** vlc_sa_entry_Get_TXT( services_advertisement_entry_t* entry )
+{
+ return (const char**)entry->txts.data;
+}
+
+VLC_API bool vlc_sa_entry_Add_TXT( services_advertisement_entry_t* entry,
+ const char* txt )
+{
+ char* dup = strdup( txt );
+ if ( !dup )
+ return false;
+ if ( !vlc_vector_push( &entry->txts, dup ) )
+ {
+ free( dup );
+ return false;
+ }
+ return true;
+}
+
+static services_advertisement_t* vlc_sa_Get( libvlc_int_t *libvlc, const char *chain )
+{
+ assert( libvlc );
+ libvlc_priv_t *priv = libvlc_priv( libvlc );
+ vlc_mutex_lock( &priv->lock );
+ services_advertisement_t *sa = priv->services_advertisements;
+ if ( sa )
+ {
+ vlc_mutex_unlock( &priv->lock );
+ return sa;
+ }
+
+ sa = vlc_custom_create( libvlc, sizeof( *sa ), "services advertisement" );
+ if( unlikely( sa == NULL ) )
+ {
+ vlc_mutex_unlock( &priv->lock );
+ return NULL;
+ }
+
+ free( config_ChainCreate( &sa->psz_name, &sa->p_cfg, chain ) );
+
+ sa->description = NULL;
+ sa->p_module = module_need( sa, "services_advertisement",
+ sa->psz_name, true );
+ if ( sa->p_module == NULL )
+ {
+ msg_Err( sa, "no suitable services advertisement module" );
+ config_ChainDestroy( sa->p_cfg );
+ free( sa->psz_name );
+ vlc_object_delete( sa );
+ sa = NULL;
+ }
+ priv->services_advertisements = sa;
+ vlc_mutex_unlock( &priv->lock );
+
+ return sa;
+}
+
+void vlc_sa_Destroy( libvlc_int_t *libvlc )
+{
+ libvlc_priv_t *priv = libvlc_priv( libvlc );
+
+ services_advertisement_t *sa = priv->services_advertisements;
+ if( !sa )
+ return;
+
+ if( sa->p_module )
+ module_unneed( sa, sa->p_module );
+
+ config_ChainDestroy( sa->p_cfg );
+ free( sa->psz_name );
+ vlc_object_delete( sa );
+}
+
+int vlc_sa_Announce( libvlc_int_t *libvlc, services_advertisement_entry_t* entry )
+{
+ services_advertisement_t *sa = vlc_sa_Get( libvlc, "mdns" );
+ if( !sa )
+ return VLC_EGENERIC;
+ return sa->pf_announce( sa, entry );
+}
+
+int vlc_sa_Conceal( libvlc_int_t *libvlc, services_advertisement_entry_t* entry )
+{
+ services_advertisement_t *sa = vlc_sa_Get( libvlc, "mdns" );
+ if( !sa )
+ return VLC_EGENERIC;
+ return sa->pf_conceal( sa, entry );
+}
--
2.20.1
More information about the vlc-devel
mailing list