From b120135edb4eefac060d4899f74df13902ef5ddf Mon Sep 17 00:00:00 2001
From: basos g<noxelia 4t gmail c0m>
Date: Thu, 20 Nov 2008 22:03:14 +0200
Subject: [PATCH] libvlc_config_update was added to libvlc API

It updates realtime configuration parameters for modules
( same used on argv, in the format of argv )  
Rev 1
---
 include/vlc/libvlc.h        |   17 +++++++
 include/vlc_configuration.h |    1 +
 src/config/core.c           |   45 +++++++++++++++++++
 src/control/core.c          |   99 +++++++++++++++++++++++++++++++++++++++++++
 src/libvlc.sym              |    1 +
 src/libvlccore.sym          |    1 +
 6 files changed, 164 insertions(+), 0 deletions(-)

diff --git a/include/vlc/libvlc.h b/include/vlc/libvlc.h
index 7f2f384..9cd492f 100644
--- a/include/vlc/libvlc.h
+++ b/include/vlc/libvlc.h
@@ -164,6 +164,23 @@ VLC_PUBLIC_API void libvlc_release( libvlc_instance_t * );
 VLC_PUBLIC_API void libvlc_retain( libvlc_instance_t * );
 
 /**
+ * Updates configuration parameters real time. psz_config has is the same as the
+ * argv parameter. All values should be passed as string (like argv) except for
+ * boolean that are optionally prefixed with --no and psz_value remains NULL.
+ * Also note that real-time takes effect in COMMAND variables (those that have
+ * a callback). Types supported are INTEGER, BOOLEAN, STRING, FLOAT
+ *
+ * \param p_instance the instance
+ * \param psz_config configuration name (e.g. blur-factor )
+ * \param psz_value configuration value as a string or NULL on boolean (e.g. 40 )
+ * \param b_lookVars this is a hack to also look for internal vars (not exported to
+ *		config) where psz_config is at the form "module-name". If you don't know what
+ *		this is set is to false
+ */
+VLC_PUBLIC_API void libvlc_config_update( libvlc_instance_t *, const char *psz_config,
+					 const char * psz_value, int b_lookVars, libvlc_exception_t *p_exception );
+
+/**
  * Try to start a user interface for the libvlc instance, and wait until the
  * user exits.
  *
diff --git a/include/vlc_configuration.h b/include/vlc_configuration.h
index 36d46cb..bb53485 100644
--- a/include/vlc_configuration.h
+++ b/include/vlc_configuration.h
@@ -214,6 +214,7 @@ VLC_EXPORT( int,    __config_SaveConfigFile, ( vlc_object_t *, const char * ) );
 VLC_EXPORT( int,    __config_SaveConfigFile, ( vlc_object_t *, const char * ) );
 #define config_ResetAll(a) __config_ResetAll(VLC_OBJECT(a))
+VLC_EXPORT( char *, config_FindModuleName,( vlc_object_t *p_this, const char *psz_name ) ) ;
 VLC_EXPORT( void,   __config_ResetAll, ( vlc_object_t * ) );
 
 VLC_EXPORT( module_config_t *, config_FindConfig,( vlc_object_t *, const char * ) LIBVLC_USED );
 
diff --git a/src/config/core.c b/src/config/core.c
index 3f6110e..749a693 100644
--- a/src/config/core.c
+++ b/src/config/core.c
@@ -447,6 +447,51 @@ module_config_t *config_FindConfig( vlc_object_t *p_this, const char *psz_name )
 }
 
 /*****************************************************************************
+ * config_FindModule: find the module object associated with an option.
+ *****************************************************************************
+ * FIXME: This function really needs to be optimized. The same as config_FindConfig
+ *****************************************************************************/
+char *config_FindModuleName( vlc_object_t *p_this, const char *psz_name )
+{
+    vlc_list_t *p_list;
+    int i_index;
+
+    if( !psz_name ) return NULL;
+
+    p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
+
+    for( i_index = 0; i_index < p_list->i_count; i_index++ )
+    {
+        module_config_t *p_item, *p_end;
+        module_t *p_parser = (module_t *)p_list->p_values[i_index].p_object;
+
+        if( !p_parser->i_config_items )
+            continue;
+
+        for( p_item = p_parser->p_config, p_end = p_item + p_parser->confsize;
+             p_item < p_end;
+             p_item++ )
+        {
+            if( p_item->i_type & CONFIG_HINT )
+                /* ignore hints */
+                continue;
+            if( !strcmp( psz_name, p_item->psz_name )
+             || ( p_item->psz_oldname
+              && !strcmp( psz_name, p_item->psz_oldname ) ) )
+            {
+                vlc_list_release( p_list );
+                char* psz_name = strdup( module_GetObjName( p_parser ) );
+                return psz_name;
+            }
+        }
+    }
+
+    vlc_list_release( p_list );
+
+    return NULL;
+}
+
+/*****************************************************************************
  * config_Free: frees a duplicated module's configuration data.
  *****************************************************************************
  * This function frees all the data duplicated by config_Duplicate.
diff --git a/src/control/core.c b/src/control/core.c
index a4a62f8..8edb018 100644
--- a/src/control/core.c
+++ b/src/control/core.c
@@ -30,6 +30,11 @@
 #include <limits.h>
 #include <assert.h>
 
+//#include <vlc_common.h>
+//#include "vlc_configuration.h"
+
+#include "config/configuration.h"
+
 static const char nomemstr[] = "Insufficient memory";
 
 /*************************************************************************
@@ -175,6 +180,97 @@ void libvlc_release( libvlc_instance_t *p_instance )
     }
 }
 
+void libvlc_config_update( libvlc_instance_t* p_instance, const char* psz_config,
+						const char* psz_value, int b_lookVars, libvlc_exception_t *p_e )
+{
+   if (!psz_config || !*psz_config)
+      RAISEVOID( "Config name cannot be empty empty")
+
+   /* parse boolean and strip prefix */
+   bool i_yes = 1 ;
+   if( (!strncmp( psz_config, "no-", 3 ) && (psz_config = psz_config + 3) ) ||
+      (!strncmp( psz_config, "no", 2 ) && (psz_config = psz_config + 2 ) ) ) {
+         i_yes = 0;
+    }
+
+   char tbuf[2] ;
+   snprintf( tbuf ,2 , "%d", i_yes ); ;
+
+   /* Find the corresponing module object that holds that config var */
+   char* psz_moduleName =
+             config_FindModuleName( (vlc_object_t*) p_instance->p_libvlc_int, psz_config );
+
+   if ( !psz_moduleName ) {
+      /* we didn't find it */
+
+      if (! b_lookVars )
+         RAISEVOID( "Config item %s does not belong to any module", psz_config );
+         /* If psz_config is not a config item and b_lookVars is true then we ASSUME
+            that it is an internal var name at the form "module-name" where module
+            is the internal module name. This is a hack to modify internal vars without
+            the need to export them at module config level. This could be usefull to modify
+            internal vars for callback purposes to assync trigger module "events" */
+       char* p_dashoff = strchr( psz_config, '-' );
+       if ( ! p_dashoff )
+          RAISEVOID( "Config item %s does not belong to any module and has not a valid object prefix", psz_config );
+       int i_dash = ( int ) (p_dashoff - psz_config) ;
+       psz_moduleName = malloc( i_dash + 1 ); // NULL + offset inc
+       strncpy( psz_moduleName, psz_config, i_dash );
+       psz_moduleName[ i_dash ] = '\0' ; // NULL terminate string
+       if (!psz_value) //assume boolean value
+          psz_value = (const char* ) &tbuf ;
+       msg_Dbg( (vlc_object_t*) p_instance->p_libvlc_int,
+             "config %s assumed to be bound to module %s (len=%d)", psz_config, psz_moduleName, i_dash );
+   }
+   else {
+      module_config_t * p_conf =
+           config_FindConfig( (vlc_object_t*) p_instance->p_libvlc_int, psz_config );
+
+      /* Check if the option is deprecated */
+      if( !p_conf ) {
+         if (! b_lookVars )
+            RAISEVOID( "Config item %s does not belong to any module!", psz_config );
+      }
+      else {
+         if( p_conf->b_removed ) {
+            RAISEVOID( "Option %s is not supported anymore.", psz_config );
+         }
+         if( p_conf->psz_oldname
+             && !strcmp( p_conf->psz_oldname, psz_config ) ) {
+               msg_Warn( (vlc_object_t*) p_instance->p_libvlc_int, "Option %s is obsolete. Use %s instead.",
+                    psz_config, p_conf->psz_name );
+         }
+      }
+
+       /* Check boolean specific */
+       int i_type  =
+            config_GetType((vlc_object_t*) p_instance->p_libvlc_int, psz_config )  ;
+       //int i_type = p_conf->i_type & CONFIG_ITEM ;
+       if( i_type != VLC_VAR_BOOL && psz_value == NULL )
+       {
+          free( psz_moduleName ) ;
+          RAISEVOID( "missing value for option %s", psz_config );
+       }
+       if ( i_type == VLC_VAR_BOOL ) {
+          psz_value = (const char* )  &tbuf ;
+       }
+       msg_Dbg( (vlc_object_t*) p_instance->p_libvlc_int,
+              "config %s bound to module %s", psz_config, psz_moduleName );
+   }
+
+   char* psz_err ;
+   int i_ret = var_Command( (vlc_object_t*) p_instance->p_libvlc_int, psz_moduleName, psz_config,
+         psz_value, &psz_err ) ;
+
+   if ( i_ret != VLC_SUCCESS ) {
+      libvlc_exception_raise( p_e, psz_err );
+   }
+   else
+      msg_Dbg( (vlc_object_t*) p_instance->p_libvlc_int, psz_err ) ;
+   free( psz_err ) ;
+   free( psz_moduleName );
+}
+
 void libvlc_add_intf( libvlc_instance_t *p_i, const char *name,
                       libvlc_exception_t *p_e )
 {
@@ -210,3 +308,4 @@ const char * libvlc_get_changeset(void)
 {
     return VLC_Changeset();
 }
+
diff --git a/src/libvlc.sym b/src/libvlc.sym
index ce03edd..dba24ad 100644
--- a/src/libvlc.sym
+++ b/src/libvlc.sym
@@ -28,6 +28,7 @@ libvlc_get_input_thread
 libvlc_get_log_verbosity
 libvlc_get_version
 libvlc_get_vlc_id
+libvlc_config_update
 libvlc_log_clear
 libvlc_log_close
 libvlc_log_count
diff --git a/src/libvlccore.sym b/src/libvlccore.sym
index 05acc07..73d70fb 100644
--- a/src/libvlccore.sym
+++ b/src/libvlccore.sym
@@ -52,6 +52,7 @@ config_ChainDestroy
 __config_ChainParse
 __config_ExistIntf
 config_FindConfig
+config_FindModuleName
 config_GetCacheDir
 config_GetConfDir
 config_GetDataDir
-- 
1.5.6.5

