[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