From f4cebf8976153097408ed90090ded32fb4fa3817 Mon Sep 17 00:00:00 2001
From: Fabio Ritrovato <exsephiroth87@gmail.com>
Date: Wed, 22 Jul 2009 00:09:48 +0200
Subject: [PATCH] [GSoC] luasd: upgrade services discovery and modules for new functionalities

---
 include/vlc_common.h              |    2 +
 include/vlc_events.h              |   19 +++++-
 include/vlc_playlist.h            |    2 +
 include/vlc_plugin.h              |    5 ++
 include/vlc_services_discovery.h  |   24 +++++++
 src/libvlccore.sym                |    2 +
 src/misc/events.c                 |    5 +-
 src/modules/cache.c               |   14 ++++
 src/modules/entry.c               |    6 ++
 src/playlist/services_discovery.c |  127 +++++++++++++++++++++++++++++++++++++
 10 files changed, 203 insertions(+), 3 deletions(-)

diff --git a/include/vlc_common.h b/include/vlc_common.h
index 88b938b..b998432 100644
--- a/include/vlc_common.h
+++ b/include/vlc_common.h
@@ -165,6 +165,8 @@ typedef struct playlist_view_t playlist_view_t;
 typedef struct playlist_export_t playlist_export_t;
 typedef struct services_discovery_t services_discovery_t;
 typedef struct services_discovery_sys_t services_discovery_sys_t;
+typedef struct parameter_value_t parameter_value_t;
+typedef struct parameter_t parameter_t;
 typedef struct playlist_add_t playlist_add_t;
 
 /* Modules */
diff --git a/include/vlc_events.h b/include/vlc_events.h
index cba7fb9..2bf1397 100644
--- a/include/vlc_events.h
+++ b/include/vlc_events.h
@@ -129,7 +129,10 @@ typedef enum vlc_event_type_t {
     vlc_ServicesDiscoveryItemAdded,
     vlc_ServicesDiscoveryItemRemoved,
     vlc_ServicesDiscoveryStarted,
-    vlc_ServicesDiscoveryEnded
+    vlc_ServicesDiscoveryEnded,
+    vlc_ServicesDiscoveryItemPut,
+    vlc_ServicesDiscoveryItemGet,
+    vlc_ServicesDiscoveryItemDelete
 } vlc_event_type_t;
 
 /* Event definition */
@@ -197,7 +200,19 @@ typedef struct vlc_event_t
         {
             void * unused;
         } services_discovery_ended;
-
+        struct vlc_services_discovery_item_put
+        {
+            char *psz_string;
+        } services_discovery_item_put;
+        struct vlc_services_discovery_item_get
+        {
+            input_item_t *p_item;
+            char *psz_string;
+        } services_discovery_item_get;
+        struct vlc_services_discovery_item_delete
+        {
+            input_item_t *p_item;
+        } services_discovery_item_delete;
     } u;
 } vlc_event_t;
 
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_plugin.h b/include/vlc_plugin.h
index c95acfe..2d43019 100644
--- a/include/vlc_plugin.h
+++ b/include/vlc_plugin.h
@@ -52,6 +52,7 @@ enum vlc_module_properties
     VLC_MODULE_SHORTNAME,
     VLC_MODULE_DESCRIPTION,
     VLC_MODULE_HELP,
+    VLC_MODULE_NO_CACHE,
     /* Insert new VLC_MODULE_* here */
 
     /* DO NOT EVER REMOVE, INSERT OR REPLACE ANY ITEM! It would break the ABI!
@@ -235,6 +236,10 @@ enum vlc_module_properties
     if (vlc_module_set (p_submodule, VLC_MODULE_NO_UNLOAD)) \
         goto error;
 
+#define set_not_cacheable( ) \
+    if (vlc_module_set (p_submodule, VLC_MODULE_NO_CACHE)) \
+        goto error;
+
 #define set_text_domain( dom ) domain = (dom);
 
 /*****************************************************************************
diff --git a/include/vlc_services_discovery.h b/include/vlc_services_discovery.h
index d647b61..94af1f6 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>
 
+struct parameter_value_t
+{
+    char *psz_name;            /**< The name of the value */
+    char *psz_value;           /**< The actual name */
+};
+
+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 */
+};
+
 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 */
+
+    bool b_can_put;         /**< Set true if the sd has the ItemPut function */
+    bool b_can_get;         /**< Set true if the sd has the ItemGet function */
+    bool b_can_delete;   /**< Set true if the sd has the ItemDelete function */
+
+    vlc_mutex_t lock;
+
     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/misc/events.c b/src/misc/events.c
index 9d7602a..a65f168 100644
--- a/src/misc/events.c
+++ b/src/misc/events.c
@@ -86,7 +86,10 @@ static const char ppsz_event_type_to_name[][40] =
     [vlc_ServicesDiscoveryItemAdded]    = "vlc_ServicesDiscoveryItemAdded",
     [vlc_ServicesDiscoveryItemRemoved]  = "vlc_ServicesDiscoveryItemRemoved",
     [vlc_ServicesDiscoveryStarted]      = "vlc_ServicesDiscoveryStarted",
-    [vlc_ServicesDiscoveryEnded]        = "vlc_ServicesDiscoveryEnded"
+    [vlc_ServicesDiscoveryEnded]        = "vlc_ServicesDiscoveryEnded",
+    [vlc_ServicesDiscoveryPut]          = "vlc_ServicesDiscoveryPut",
+    [vlc_ServicesDiscoveryGet]          = "vlc_ServicesDiscoveryGet",
+    [vlc_ServicesDiscoveryDelete]       = "vlc_ServicesDiscoveryDelete",
 };
 #endif
 
diff --git a/src/modules/cache.c b/src/modules/cache.c
index 89d1a99..e13effd 100644
--- a/src/modules/cache.c
+++ b/src/modules/cache.c
@@ -300,6 +300,7 @@ void CacheLoad( vlc_object_t *p_this, module_bank_t *p_bank, bool b_delete )
         LOAD_IMMEDIATE( pp_cache[i]->p_module->b_unloadable );
         LOAD_IMMEDIATE( pp_cache[i]->p_module->b_reentrant );
         LOAD_IMMEDIATE( pp_cache[i]->p_module->b_submodule );
+        LOAD_IMMEDIATE( pp_cache[i]->p_module->b_cacheable );
 
         /* Config stuff */
         if( CacheLoadConfig( pp_cache[i]->p_module, file ) != VLC_SUCCESS )
@@ -326,6 +327,7 @@ void CacheLoad( vlc_object_t *p_this, module_bank_t *p_bank, bool b_delete )
             LOAD_IMMEDIATE( p_module->i_cpu );
             LOAD_IMMEDIATE( p_module->b_unloadable );
             LOAD_IMMEDIATE( p_module->b_reentrant );
+            LOAD_IMMEDIATE( p_module->b_cacheable );
         }
     }
 
@@ -548,9 +550,17 @@ void CacheSave( vlc_object_t *p_this, module_bank_t *p_bank )
     i_cache = p_bank->i_cache;
     pp_cache = p_bank->pp_cache;
 
+    int i_uncacheable = 0;
+    for( int i = 0; i < i_cache; i++ )
+        if( !pp_cache[i]->p_module->b_cacheable )
+            i_uncacheable++;
+    i_cache -= i_uncacheable;
+
     if (fwrite( &i_cache, sizeof (i_cache), 1, file) != 1)
         goto error;
 
+    i_cache += i_uncacheable;
+
 #define SAVE_IMMEDIATE( a ) \
     if (fwrite (&a, sizeof(a), 1, file) != 1) \
         goto error
@@ -566,6 +576,8 @@ void CacheSave( vlc_object_t *p_this, module_bank_t *p_bank )
     {
         uint32_t i_submodule;
 
+        if( !pp_cache[i]->p_module->b_cacheable ) continue;
+
         /* Save common info */
         SAVE_STRING( pp_cache[i]->psz_file );
         SAVE_IMMEDIATE( pp_cache[i]->i_time );
@@ -589,6 +601,7 @@ void CacheSave( vlc_object_t *p_this, module_bank_t *p_bank )
         SAVE_IMMEDIATE( pp_cache[i]->p_module->b_unloadable );
         SAVE_IMMEDIATE( pp_cache[i]->p_module->b_reentrant );
         SAVE_IMMEDIATE( pp_cache[i]->p_module->b_submodule );
+        SAVE_IMMEDIATE( pp_cache[i]->p_module->b_cacheable );
 
         /* Config stuff */
         if (CacheSaveConfig (pp_cache[i]->p_module, file))
@@ -648,6 +661,7 @@ static int CacheSaveSubmodule( FILE *file, module_t *p_module )
     SAVE_IMMEDIATE( p_module->i_cpu );
     SAVE_IMMEDIATE( p_module->b_unloadable );
     SAVE_IMMEDIATE( p_module->b_reentrant );
+    SAVE_IMMEDIATE( p_module->b_cacheable );
     return 0;
 
 error:
diff --git a/src/modules/entry.c b/src/modules/entry.c
index 647bf9d..0464f30 100644
--- a/src/modules/entry.c
+++ b/src/modules/entry.c
@@ -82,6 +82,7 @@ module_t *vlc_module_create (vlc_object_t *obj)
     module->b_unloadable = true;
     module->b_reentrant = true;
     module->b_submodule = false;
+    module->b_cacheable = true;
     module->pf_activate = NULL;
     module->pf_deactivate = NULL;
     module->p_config = NULL;
@@ -132,6 +133,7 @@ module_t *vlc_submodule_create (module_t *module)
     submodule->i_score = module->i_score;
     submodule->i_cpu = module->i_cpu;
     submodule->b_submodule = true;
+    submodule->b_cacheable = module->b_cacheable;
     return submodule;
 }
 
@@ -228,6 +230,10 @@ int vlc_plugin_set (module_t *module, module_config_t *item, int propid, ...)
             module->b_unloadable = false;
             break;
 
+        case VLC_MODULE_NO_CACHE:
+            module->b_cacheable = false;
+            break;
+
         case VLC_MODULE_NAME:
         {
             const char *value = va_arg (ap, const char *);
diff --git a/src/playlist/services_discovery.c b/src/playlist/services_discovery.c
index aaa4668..8d42dd8 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->b_can_put = false;
+    p_sd->b_can_get = false;
+    p_sd->b_can_delete = false;
+
     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 );
@@ -73,6 +77,8 @@ services_discovery_t *vlc_sd_Create( vlc_object_t *p_super )
 
     vlc_object_attach( p_sd, p_super );
 
+    vlc_mutex_init( &p_sd->lock );
+
     return p_sd;
 }
 
@@ -357,6 +363,24 @@ 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 );
+
+    vlc_mutex_destroy( &p_sd->lock );
+
     vlc_sd_Destroy( p_sd );
     free( p_sds->psz_name );
     free( p_sds );
@@ -385,6 +409,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 +436,87 @@ 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 ;
+
+    vlc_assert_locked( &p_sd->lock );
+
+    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;
+
+    vlc_mutex_lock( &p_sd->lock );
+
+    va_start( args, psz_format );
+    const int i_ret = ServicesDiscoveryVaAddParameterValue( p_sd, psz_parameter,
+                                                            psz_name,
+                                                            psz_format, args );
+    va_end( args );
+
+    vlc_mutex_unlock( &p_sd->lock );
+
+    return i_ret;
+}
-- 
1.6.0.4

