]> git.sesse.net Git - vlc/blobdiff - src/misc/configuration.c
* ALL: improved hotkeys support.
[vlc] / src / misc / configuration.c
index a24da6a091493a65e7b288fff3f1edcc94eccf10..6be2cf5e89230fba0a47126fe53b8859f9e6ac06 100644 (file)
@@ -2,7 +2,7 @@
  * configuration.c management of the modules configuration
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: configuration.c,v 1.58 2003/06/27 13:38:54 sam Exp $
+ * $Id: configuration.c,v 1.66 2003/10/29 01:33:27 gbazin Exp $
  *
  * Authors: Gildas Bazin <gbazin@netcourrier.com>
  *
@@ -22,6 +22,7 @@
  *****************************************************************************/
 
 #include <vlc/vlc.h>
+#include "vlc_keys.h"
 
 #include <stdio.h>                                              /* sprintf() */
 #include <stdlib.h>                                      /* free(), strtol() */
 #   include <direct.h>
 #endif
 
+
+static int ConfigStringToKey( char * );
+static char *ConfigKeyToString( int );
+
+/*****************************************************************************
+ * config_GetType: get the type of a variable (bool, int, float, string)
+ *****************************************************************************
+ * This function is used to get the type of a variable from its name.
+ * Beware, this is quite slow.
+ *****************************************************************************/
+int __config_GetType( vlc_object_t *p_this, const char *psz_name )
+{
+    module_config_t *p_config;
+    int i_type;
+
+    p_config = config_FindConfig( p_this, psz_name );
+
+    /* sanity checks */
+    if( !p_config )
+    {
+        return 0;
+    }
+
+    switch( p_config->i_type )
+    {
+    case CONFIG_ITEM_BOOL:
+        i_type = VLC_VAR_BOOL;
+        break;
+
+    case CONFIG_ITEM_INTEGER:
+        i_type = VLC_VAR_INTEGER;
+        break;
+
+    case CONFIG_ITEM_FLOAT:
+        i_type = VLC_VAR_FLOAT;
+        break;
+
+    case CONFIG_ITEM_MODULE:
+    case CONFIG_ITEM_STRING:
+        i_type = VLC_VAR_STRING;
+        break;
+
+    case CONFIG_ITEM_FILE:
+        i_type = VLC_VAR_FILE;
+        break;
+
+    case CONFIG_ITEM_DIRECTORY:
+        i_type = VLC_VAR_DIRECTORY;
+        break;
+
+    default:
+        i_type = 0;
+        break;
+    }
+
+    return i_type;
+}
+
 /*****************************************************************************
  * config_GetInt: get the value of an int variable
  *****************************************************************************
@@ -76,6 +135,7 @@ int __config_GetInt( vlc_object_t *p_this, const char *psz_name )
         return -1;
     }
     if( (p_config->i_type!=CONFIG_ITEM_INTEGER) &&
+        (p_config->i_type!=CONFIG_ITEM_KEY) &&
         (p_config->i_type!=CONFIG_ITEM_BOOL) )
     {
         msg_Err( p_this, "option %s does not refer to an int", psz_name );
@@ -164,6 +224,7 @@ void __config_PutPsz( vlc_object_t *p_this,
                       const char *psz_name, const char *psz_value )
 {
     module_config_t *p_config;
+    vlc_value_t oldval, val;
 
     p_config = config_FindConfig( p_this, psz_name );
 
@@ -184,18 +245,24 @@ void __config_PutPsz( vlc_object_t *p_this,
 
     vlc_mutex_lock( p_config->p_lock );
 
-    /* free old string */
-    if( p_config->psz_value ) free( p_config->psz_value );
+    /* backup old value */
+    oldval.psz_string = p_config->psz_value;
 
     if( psz_value && *psz_value ) p_config->psz_value = strdup( psz_value );
     else p_config->psz_value = NULL;
 
+    val.psz_string = p_config->psz_value;
+
     vlc_mutex_unlock( p_config->p_lock );
 
     if( p_config->pf_callback )
     {
-        p_config->pf_callback( p_this );
+        p_config->pf_callback( p_this, psz_name, oldval, val,
+                               p_config->p_callback_data );
     }
+
+    /* free old string */
+    if( oldval.psz_string ) free( oldval.psz_string );
 }
 
 /*****************************************************************************
@@ -208,6 +275,7 @@ void __config_PutPsz( vlc_object_t *p_this,
 void __config_PutInt( vlc_object_t *p_this, const char *psz_name, int i_value )
 {
     module_config_t *p_config;
+    vlc_value_t oldval, val;
 
     p_config = config_FindConfig( p_this, psz_name );
 
@@ -218,12 +286,16 @@ void __config_PutInt( vlc_object_t *p_this, const char *psz_name, int i_value )
         return;
     }
     if( (p_config->i_type!=CONFIG_ITEM_INTEGER) &&
+        (p_config->i_type!=CONFIG_ITEM_KEY) &&
         (p_config->i_type!=CONFIG_ITEM_BOOL) )
     {
         msg_Err( p_this, "option %s does not refer to an int", psz_name );
         return;
     }
 
+    /* backup old value */
+    oldval.i_int = p_config->i_value;
+
     /* if i_min == i_max == 0, then do not use them */
     if ((p_config->i_min == 0) && (p_config->i_max == 0))
     {
@@ -242,9 +314,12 @@ void __config_PutInt( vlc_object_t *p_this, const char *psz_name, int i_value )
         p_config->i_value = i_value;
     }
 
+    val.i_int = p_config->i_value;
+
     if( p_config->pf_callback )
     {
-        p_config->pf_callback( p_this );
+        p_config->pf_callback( p_this, psz_name, oldval, val,
+                               p_config->p_callback_data );
     }
 }
 
@@ -258,6 +333,7 @@ void __config_PutFloat( vlc_object_t *p_this,
                         const char *psz_name, float f_value )
 {
     module_config_t *p_config;
+    vlc_value_t oldval, val;
 
     p_config = config_FindConfig( p_this, psz_name );
 
@@ -273,6 +349,9 @@ void __config_PutFloat( vlc_object_t *p_this,
         return;
     }
 
+    /* backup old value */
+    oldval.f_float = p_config->f_value;
+
     /* if f_min == f_max == 0, then do not use them */
     if ((p_config->f_min == 0) && (p_config->f_max == 0))
     {
@@ -291,9 +370,12 @@ void __config_PutFloat( vlc_object_t *p_this,
         p_config->f_value = f_value;
     }
 
+    val.f_float = p_config->f_value;
+
     if( p_config->pf_callback )
     {
-        p_config->pf_callback( p_this );
+        p_config->pf_callback( p_this, psz_name, oldval, val,
+                               p_config->p_callback_data );
     }
 }
 
@@ -558,23 +640,34 @@ int __config_LoadConfigFile( vlc_object_t *p_this, const char *psz_module_name )
     FILE *file;
     char line[1024];
     char *p_index, *psz_option_name, *psz_option_value;
-    char *psz_filename, *psz_homedir;
+    char *psz_filename, *psz_homedir, *psz_configfile;
     int i_index;
 
-    psz_homedir = p_this->p_vlc->psz_homedir;
-    if( !psz_homedir )
+    psz_configfile = p_this->p_vlc->psz_configfile;
+    if( !psz_configfile || !psz_configfile )
     {
-        msg_Err( p_this, "psz_homedir is null" );
-        return -1;
+        psz_homedir = p_this->p_vlc->psz_homedir;
+        if( !psz_homedir )
+        {
+            msg_Err( p_this, "psz_homedir is null" );
+            return -1;
+        }
+        psz_filename = (char *)malloc( sizeof("/" CONFIG_DIR "/" CONFIG_FILE) +
+                                       strlen(psz_homedir) );
+        if( psz_filename )
+            sprintf( psz_filename, "%s/" CONFIG_DIR "/" CONFIG_FILE,
+                     psz_homedir );
+    }
+    else
+    {
+        psz_filename = strdup( psz_configfile );
     }
-    psz_filename = (char *)malloc( strlen("/" CONFIG_DIR "/" CONFIG_FILE) +
-                                   strlen(psz_homedir) + 1 );
+
     if( !psz_filename )
     {
         msg_Err( p_this, "out of memory" );
         return -1;
     }
-    sprintf( psz_filename, "%s/" CONFIG_DIR "/" CONFIG_FILE, psz_homedir );
 
     msg_Dbg( p_this, "opening config file %s", psz_filename );
 
@@ -686,6 +779,11 @@ int __config_LoadConfigFile( vlc_object_t *p_this, const char *psz_module_name )
                                  p_item->psz_name, (double)p_item->f_value );
 #endif
                         break;
+                    case CONFIG_ITEM_KEY:
+                        if( !*psz_option_value )
+                            break;                    /* ignore empty option */
+                        p_item->i_value = ConfigStringToKey( psz_option_value );
+                        break;
 
                     default:
                         vlc_mutex_lock( p_item->p_lock );
@@ -751,60 +849,77 @@ int __config_SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name )
     int i_sizebuf = 0;
     char *p_bigbuffer, *p_index;
     vlc_bool_t b_backup;
-    char *psz_filename, *psz_homedir;
+    char *psz_filename, *psz_homedir, *psz_configfile;
     int i_index;
 
     /* Acquire config file lock */
     vlc_mutex_lock( &p_this->p_vlc->config_lock );
 
-    psz_homedir = p_this->p_vlc->psz_homedir;
-    if( !psz_homedir )
-    {
-        msg_Err( p_this, "psz_homedir is null" );
-        vlc_mutex_unlock( &p_this->p_vlc->config_lock );
-        return -1;
-    }
-    psz_filename = (char *)malloc( strlen("/" CONFIG_DIR "/" CONFIG_FILE) +
-                                   strlen(psz_homedir) + 1 );
-    if( !psz_filename )
+    psz_configfile = p_this->p_vlc->psz_configfile;
+    if( !psz_configfile || !psz_configfile )
     {
-        msg_Err( p_this, "out of memory" );
-        vlc_mutex_unlock( &p_this->p_vlc->config_lock );
-        return -1;
-    }
-    sprintf( psz_filename, "%s/" CONFIG_DIR, psz_homedir );
+        psz_homedir = p_this->p_vlc->psz_homedir;
+        if( !psz_homedir )
+        {
+            msg_Err( p_this, "psz_homedir is null" );
+            vlc_mutex_unlock( &p_this->p_vlc->config_lock );
+            return -1;
+        }
+        psz_filename = (char *)malloc( sizeof("/" CONFIG_DIR "/" CONFIG_FILE) +
+                                       strlen(psz_homedir) );
+
+        if( psz_filename )
+            sprintf( psz_filename, "%s/" CONFIG_DIR, psz_homedir );
+
+        if( !psz_filename )
+        {
+            msg_Err( p_this, "out of memory" );
+            vlc_mutex_unlock( &p_this->p_vlc->config_lock );
+            return -1;
+        }
 
 #if defined( UNDER_CE )
-    {
-        wchar_t psz_new[ MAX_PATH ];
-        MultiByteToWideChar( CP_ACP, 0, psz_filename, -1, psz_new, MAX_PATH );
-        if( CreateDirectory( psz_new, NULL ) )
         {
-            msg_Err( p_this, "could not create %s", psz_filename );
+            wchar_t psz_new[ MAX_PATH ];
+            MultiByteToWideChar( CP_ACP, 0, psz_filename, -1, psz_new,
+                                 MAX_PATH );
+            if( CreateDirectory( psz_new, NULL ) )
+            {
+                msg_Err( p_this, "could not create %s", psz_filename );
+            }
         }
-    }
 
 #elif defined( HAVE_ERRNO_H )
 #   if defined( WIN32 )
-    if( mkdir( psz_filename ) && errno != EEXIST )
+        if( mkdir( psz_filename ) && errno != EEXIST )
 #   else
-    if( mkdir( psz_filename, 0755 ) && errno != EEXIST )
+        if( mkdir( psz_filename, 0755 ) && errno != EEXIST )
 #   endif
-    {
-        msg_Err( p_this, "could not create %s (%s)",
-                         psz_filename, strerror(errno) );
-    }
+        {
+            msg_Err( p_this, "could not create %s (%s)",
+                             psz_filename, strerror(errno) );
+        }
 
 #else
-    if( mkdir( psz_filename ) )
-    {
-        msg_Err( p_this, "could not create %s", psz_filename );
-    }
+        if( mkdir( psz_filename ) )
+        {
+            msg_Err( p_this, "could not create %s", psz_filename );
+        }
 
 #endif
 
-    strcat( psz_filename, "/" CONFIG_FILE );
-
+        strcat( psz_filename, "/" CONFIG_FILE );
+    }
+    else
+    {
+        psz_filename = strdup( psz_configfile );
+        if( !psz_filename )
+        {
+            msg_Err( p_this, "out of memory" );
+            vlc_mutex_unlock( &p_this->p_vlc->config_lock );
+            return -1;
+        }
+    }
 
     msg_Dbg( p_this, "opening config file %s", psz_filename );
 
@@ -932,6 +1047,7 @@ int __config_SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name )
              p_item->i_type != CONFIG_HINT_END;
              p_item++ )
         {
+            char *psz_key;
             if( p_item->i_type & CONFIG_HINT )
                 /* ignore hints */
                 continue;
@@ -948,7 +1064,16 @@ int __config_SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name )
                     fprintf( file, "#" );
                 fprintf( file, "%s=%i\n", p_item->psz_name, p_item->i_value );
                 break;
-
+            case CONFIG_ITEM_KEY:
+                if( p_item->psz_text )
+                    fprintf( file, "# %s (%s)\n", p_item->psz_text,
+                             _("key") );
+                psz_key = ConfigKeyToString( p_item->i_value );
+                fprintf( file, "%s=%s\n", p_item->psz_name,
+                         psz_key ? psz_key : "" );
+                if ( psz_key ) free( psz_key );
+                break;
+                
             case CONFIG_ITEM_FLOAT:
                 if( p_item->psz_text )
                     fprintf( file, "# %s (%s)\n", p_item->psz_text,
@@ -1017,8 +1142,6 @@ int __config_LoadCmdLine( vlc_object_t *p_this, int *pi_argc, char *ppsz_argv[],
     p_this->p_vlc->i_argc    = *pi_argc;
     p_this->p_vlc->ppsz_argv = ppsz_argv;
 
-    p_this->p_vlc->p_channel = NULL;
-
 #ifdef SYS_DARWIN
     /* When vlc.app is run by double clicking in Mac OS X, the 2nd arg
      * is the PSN - process serial number (a unique PID-ish thingie)
@@ -1217,6 +1340,9 @@ int __config_LoadCmdLine( vlc_object_t *p_this, int *pi_argc, char *ppsz_argv[],
             case CONFIG_ITEM_FLOAT:
                 config_PutFloat( p_this, psz_name, (float)atof(optarg) );
                 break;
+            case CONFIG_ITEM_KEY:
+                config_PutInt( p_this, psz_name, ConfigStringToKey( optarg ) );
+                break;
             case CONFIG_ITEM_BOOL:
                 config_PutInt( p_this, psz_name, !flag );
                 break;
@@ -1294,7 +1420,6 @@ int __config_LoadCmdLine( vlc_object_t *p_this, int *pi_argc, char *ppsz_argv[],
 
             free( p_longopts );
             free( psz_shortopts );
-            if( b_ignore_errors ) free( ppsz_argv );
             return -1;
         }
     }
@@ -1385,3 +1510,65 @@ char *config_GetHomeDir( void )
 
     return p_homedir;
 }
+
+
+static int ConfigStringToKey( char *psz_key )
+{
+    int i_key = 0;
+    unsigned int i;
+    char *psz_parser = strchr( psz_key, '-' );
+    while( psz_parser && psz_parser != psz_key )
+    {
+        for( i = 0; i < sizeof(modifiers) / sizeof(key_descriptor_t); i++ )
+        {
+            if( !strncasecmp( modifiers[i].psz_key_string, psz_key,
+                              strlen( modifiers[i].psz_key_string ) ) )
+            {
+                i_key |= modifiers[i].i_key_code;
+            }
+        }
+        psz_key = psz_parser + 1;
+        psz_parser = strchr( psz_key, '-' );
+    }
+    for( i = 0; i < sizeof(keys) / sizeof( key_descriptor_t ); i++ )
+    {
+        if( !strcasecmp( keys[i].psz_key_string, psz_key ) )
+        {
+            i_key |= keys[i].i_key_code;
+            break;
+        }
+    }
+    return i_key;
+}
+
+static char *ConfigKeyToString( int i_key )
+{
+    char *psz_key = malloc( 100 );
+    char *p;
+    size_t index;
+
+    if ( !psz_key )
+    {
+        return NULL;
+    }
+    *psz_key = '\0';
+    p = psz_key;
+    for( index = 0; index < (sizeof(modifiers) / sizeof(key_descriptor_t));
+         index++ )
+    {
+        if( i_key & modifiers[index].i_key_code )
+        {
+            p += sprintf( p, "%s-", modifiers[index].psz_key_string );
+        }
+    }
+    for( index = 0; index < (sizeof(keys) / sizeof( key_descriptor_t));
+         index++)
+    {
+        if( (int)( i_key & ~KEY_MODIFIER ) == keys[index].i_key_code )
+        {
+            p += sprintf( p, "%s", keys[index].psz_key_string );
+            break;
+        }
+    }
+    return psz_key;
+}