From a6f98c6e8e9a75ab9e4c8d4358a6ef8225852287 Mon Sep 17 00:00:00 2001
From: Fabio Ritrovato <exsephiroth87@gmail.com>
Date: Sat, 25 Jul 2009 13:22:35 +0200
Subject: [PATCH] [GSoC] luasd: expand services discovery functionalities

---
 include/vlc_playlist.h            |    2 +
 include/vlc_services_discovery.h  |   24 +++++++
 src/libvlccore.sym                |    2 +
 src/playlist/services_discovery.c |  120 +++++++++++++++++++++++++++++++++++++
 4 files changed, 148 insertions(+), 0 deletions(-)

diff --git a/include/vlc_playlist.h b/include/vlc_playlist.h
index b98e13c..b99c21f 100644
--- a/include/vlc_playlist.h
+++ b/include/vlc_playlist.h
@@ -328,6 +328,8 @@ VLC_EXPORT( int, playlist_ServicesDiscoveryAdd, (playlist_t *, const char *));
 VLC_EXPORT( int, playlist_ServicesDiscoveryRemove, (playlist_t *, const char *));
 /** Check whether a given SD is loaded */
 VLC_EXPORT( bool, playlist_IsServicesDiscoveryLoaded, ( playlist_t *,const char *));
+/** Return a service discovery module by his playlist Id */
+VLC_EXPORT( services_discovery_t *, playlist_ServiceDiscoveryGetById, ( playlist_t *, int ) );
 
 
 
diff --git a/include/vlc_services_discovery.h b/include/vlc_services_discovery.h
index d647b61..bba8a49 100644
--- a/include/vlc_services_discovery.h
+++ b/include/vlc_services_discovery.h
@@ -40,6 +40,19 @@ extern "C" {
 #include <vlc_input.h>
 #include <vlc_events.h>
 
+typedef struct parameter_value_t
+{
+    char *psz_name;            /**< The name of the value */
+    char *psz_value;           /**< The actual name */
+} parameter_value_t;
+
+typedef struct parameter_t
+{
+    char   *psz_name;      /**< Name of the parameter */
+    int    i_values;        /**< Number of values in the parameter */
+    struct parameter_value_t **pp_values;     /**< Pointer to an array of values */
+} parameter_t;
+
 struct services_discovery_t
 {
     VLC_COMMON_MEMBERS
@@ -47,6 +60,15 @@ struct services_discovery_t
 
     vlc_event_manager_t event_manager;      /* Accessed through Setters for non class function */
 
+    int        i_parameters;         /**< Number of parameters */
+    parameter_t **pp_parameters; /**< Pointer to the first parameter */
+
+    int (*pf_item_put) ( services_discovery_t *, const char * );
+    int (*pf_item_get) ( services_discovery_t *, const char *, input_item_t * );
+    int (*pf_item_delete) ( services_discovery_t *, input_item_t * );
+
+    char *psz_name;
+
     services_discovery_sys_t *p_sys;
 };
 
@@ -86,6 +108,8 @@ VLC_EXPORT( vlc_event_manager_t *,  services_discovery_EventManager, ( services_
 VLC_EXPORT( void,                   services_discovery_AddItem, ( services_discovery_t * p_this, input_item_t * p_item, const char * psz_category ) );
 VLC_EXPORT( void,                   services_discovery_RemoveItem, ( services_discovery_t * p_this, input_item_t * p_item ) );
 
+VLC_EXPORT( int, services_discovery_AddParameterValue, (services_discovery_t *, const char *, const char *, const char *, ... ) LIBVLC_FORMAT( 4, 5 ) );
+
 /** @} */
 # ifdef __cplusplus
 }
diff --git a/src/libvlccore.sym b/src/libvlccore.sym
index 357f4ec..8c02f91 100644
--- a/src/libvlccore.sym
+++ b/src/libvlccore.sym
@@ -332,6 +332,7 @@ playlist_NodeRemoveItem
 playlist_PreparseEnqueue
 playlist_RecursiveNodeSort
 playlist_ServicesDiscoveryAdd
+playlist_ServiceDiscoveryGetById
 playlist_ServicesDiscoveryRemove
 playlist_Status
 playlist_TreeMove
@@ -343,6 +344,7 @@ sdp_AddAttribute
 sdp_AddMedia
 secstotimestr
 services_discovery_AddItem
+services_discovery_AddParameterValue
 services_discovery_EventManager
 services_discovery_GetLocalizedName
 services_discovery_RemoveItem
diff --git a/src/playlist/services_discovery.c b/src/playlist/services_discovery.c
index aaa4668..043afab 100644
--- a/src/playlist/services_discovery.c
+++ b/src/playlist/services_discovery.c
@@ -61,6 +61,10 @@ services_discovery_t *vlc_sd_Create( vlc_object_t *p_super )
     if( !p_sd )
         return NULL;
 
+    p_sd->pf_item_put = NULL;
+    p_sd->pf_item_get = NULL;
+    p_sd->pf_item_delete = NULL;
+
     vlc_event_manager_init( &p_sd->event_manager, p_sd, (vlc_object_t *)p_sd );
     vlc_event_manager_register_event_type( &p_sd->event_manager,
             vlc_ServicesDiscoveryItemAdded );
@@ -242,6 +246,8 @@ int playlist_ServicesDiscoveryAdd( playlist_t *p_playlist, const char *psz_modul
         return VLC_EGENERIC;
     }
 
+    p_sd->psz_name = strdup( psz_module );
+
     /* Free in playlist_ServicesDiscoveryRemove */
     struct playlist_services_discovery_support_t * p_sds;
     p_sds = malloc( sizeof(struct playlist_services_discovery_support_t) );
@@ -357,6 +363,23 @@ int playlist_ServicesDiscoveryRemove( playlist_t * p_playlist,
     }
     PL_UNLOCK;
 
+    for( int i = 0; i < p_sd->i_parameters; i++ )
+    {
+        parameter_t *p_parameter = p_sd->pp_parameters[i];
+        for( int j = 0; j < p_parameter->i_values; j++ )
+        {
+            parameter_value_t *p_value = p_parameter->pp_values[j];
+            free( p_value->psz_name );
+            free( p_value->psz_value );
+            free( p_value );
+        }
+        TAB_CLEAN( p_parameter->i_values, p_parameter->pp_values );
+        free( p_parameter->psz_name );
+        free( p_parameter );
+    }
+    TAB_CLEAN( p_sd->i_parameters, p_sd->pp_parameters );
+
+    free( p_sd->psz_name );
     vlc_sd_Destroy( p_sd );
     free( p_sds->psz_name );
     free( p_sds );
@@ -385,6 +408,25 @@ bool playlist_IsServicesDiscoveryLoaded( playlist_t * p_playlist,
     return found;
 }
 
+services_discovery_t * playlist_ServiceDiscoveryGetById( playlist_t *p_playlist,
+                                                       int i_id )
+{
+    int i;
+    PL_LOCK;
+
+    for( i = 0 ; i< pl_priv(p_playlist)->i_sds ; i ++ )
+    {
+        if( i_id == pl_priv(p_playlist)->pp_sds[i]->p_cat->i_id ||
+            i_id == pl_priv(p_playlist)->pp_sds[i]->p_one->i_id )
+        {
+            PL_UNLOCK;
+            return pl_priv(p_playlist)->pp_sds[i]->p_sd;
+        }
+    }
+    PL_UNLOCK;
+    return NULL;
+}
+
 void playlist_ServicesDiscoveryKillAll( playlist_t *p_playlist )
 {
     playlist_private_t *priv = pl_priv( p_playlist );
@@ -393,3 +435,81 @@ void playlist_ServicesDiscoveryKillAll( playlist_t *p_playlist )
         playlist_ServicesDiscoveryRemove( p_playlist,
                                           priv->pp_sds[0]->psz_name );
 }
+
+static int ServicesDiscoveryVaAddParameterValue( services_discovery_t *p_sd,
+                                                 const char *psz_parameter,
+                                                 const char *psz_name,
+                                                 const char *psz_format,
+                                                 va_list args )
+{
+    int i;
+    parameter_value_t *p_value = NULL;
+    parameter_t *p_parameter = NULL ;
+
+    for( i = 0 ; i < p_sd->i_parameters ; i ++ )
+    {
+        if( !strcmp( p_sd->pp_parameters[i]->psz_name, psz_parameter ) )
+        {
+            p_parameter = p_sd->pp_parameters[i];
+            break;
+        }
+    }
+    if( !p_parameter )
+    {
+        if( !(p_parameter = malloc( sizeof(*p_parameter) )) )
+            return VLC_ENOMEM;
+
+        p_parameter->psz_name = strdup( psz_parameter );
+        p_parameter->i_values = 0;
+        p_parameter->pp_values = 0;
+        INSERT_ELEM( p_sd->pp_parameters, p_sd->i_parameters, p_sd->i_parameters,
+                     p_parameter );
+    }
+
+    if( !psz_name )
+        return VLC_SUCCESS;
+
+    for( i = 0; i< p_parameter->i_values; i++ )
+    {
+        if( !strcmp( p_parameter->pp_values[i]->psz_name, psz_name ) )
+        {
+            p_value = p_parameter->pp_values[i];
+            break;
+        }
+    }
+
+    if( !p_value )
+    {
+        if( ( p_value = malloc( sizeof( *p_value ) ) ) == NULL )
+            return VLC_ENOMEM;
+
+        INSERT_ELEM( p_parameter->pp_values, p_parameter->i_values,
+                     p_parameter->i_values, p_value );
+        p_value->psz_name = strdup( psz_name );
+    }
+    else
+    {
+        free( p_value->psz_value );
+    }
+
+    if( vasprintf( &p_value->psz_value, psz_format, args ) == -1 )
+        p_value->psz_value = NULL;
+
+    return p_value->psz_value ? VLC_SUCCESS : VLC_ENOMEM;
+}
+
+int services_discovery_AddParameterValue( services_discovery_t *p_sd,
+                                          const char *psz_parameter,
+                                          const char *psz_name,
+                                          const char *psz_format, ... )
+{
+    va_list args;
+
+    va_start( args, psz_format );
+    const int i_ret = ServicesDiscoveryVaAddParameterValue( p_sd, psz_parameter,
+                                                            psz_name,
+                                                            psz_format, args );
+    va_end( args );
+
+    return i_ret;
+}
-- 
1.6.0.4

