Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

configuration.c

00001 /*****************************************************************************
00002  * configuration.c management of the modules configuration
00003  *****************************************************************************
00004  * Copyright (C) 2001-2004 the VideoLAN team
00005  * $Id: configuration.c 12428 2005-08-29 16:34:32Z massiot $
00006  *
00007  * Authors: Gildas Bazin <[email protected]>
00008  *
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00022  *****************************************************************************/
00023 
00024 #include <vlc/vlc.h>
00025 #include "vlc_keys.h"
00026 
00027 #include <stdio.h>                                              /* sprintf() */
00028 #include <stdlib.h>                                      /* free(), strtol() */
00029 #include <string.h>                                              /* strdup() */
00030 #include <errno.h>                                                  /* errno */
00031 
00032 #ifdef HAVE_UNISTD_H
00033 #    include <unistd.h>                                          /* getuid() */
00034 #endif
00035 
00036 #ifdef HAVE_GETOPT_LONG
00037 #   ifdef HAVE_GETOPT_H
00038 #       include <getopt.h>                                       /* getopt() */
00039 #   endif
00040 #else
00041 #   include "../extras/getopt.h"
00042 #endif
00043 
00044 #if defined(HAVE_GETPWUID)
00045 #   include <pwd.h>                                            /* getpwuid() */
00046 #endif
00047 
00048 #if defined( HAVE_SYS_STAT_H )
00049 #   include <sys/stat.h>
00050 #endif
00051 #if defined( HAVE_SYS_TYPES_H )
00052 #   include <sys/types.h>
00053 #endif
00054 #if defined( WIN32 )
00055 #   if !defined( UNDER_CE )
00056 #       include <direct.h>
00057 #   endif
00058 #include <tchar.h>
00059 #endif
00060 
00061 
00062 static int ConfigStringToKey( char * );
00063 static char *ConfigKeyToString( int );
00064 
00065 /*****************************************************************************
00066  * config_GetType: get the type of a variable (bool, int, float, string)
00067  *****************************************************************************
00068  * This function is used to get the type of a variable from its name.
00069  * Beware, this is quite slow.
00070  *****************************************************************************/
00071 int __config_GetType( vlc_object_t *p_this, const char *psz_name )
00072 {
00073     module_config_t *p_config;
00074     int i_type;
00075 
00076     p_config = config_FindConfig( p_this, psz_name );
00077 
00078     /* sanity checks */
00079     if( !p_config )
00080     {
00081         return 0;
00082     }
00083 
00084     switch( p_config->i_type )
00085     {
00086     case CONFIG_ITEM_BOOL:
00087         i_type = VLC_VAR_BOOL;
00088         break;
00089 
00090     case CONFIG_ITEM_INTEGER:
00091         i_type = VLC_VAR_INTEGER;
00092         break;
00093 
00094     case CONFIG_ITEM_FLOAT:
00095         i_type = VLC_VAR_FLOAT;
00096         break;
00097 
00098     case CONFIG_ITEM_MODULE:
00099     case CONFIG_ITEM_MODULE_CAT:
00100     case CONFIG_ITEM_MODULE_LIST:
00101     case CONFIG_ITEM_MODULE_LIST_CAT:
00102         i_type = VLC_VAR_MODULE;
00103         break;
00104 
00105     case CONFIG_ITEM_STRING:
00106         i_type = VLC_VAR_STRING;
00107         break;
00108 
00109     case CONFIG_ITEM_FILE:
00110         i_type = VLC_VAR_FILE;
00111         break;
00112 
00113     case CONFIG_ITEM_DIRECTORY:
00114         i_type = VLC_VAR_DIRECTORY;
00115         break;
00116 
00117     default:
00118         i_type = 0;
00119         break;
00120     }
00121 
00122     return i_type;
00123 }
00124 
00125 /*****************************************************************************
00126  * config_GetInt: get the value of an int variable
00127  *****************************************************************************
00128  * This function is used to get the value of variables which are internally
00129  * represented by an integer (CONFIG_ITEM_INTEGER and
00130  * CONFIG_ITEM_BOOL).
00131  *****************************************************************************/
00132 int __config_GetInt( vlc_object_t *p_this, const char *psz_name )
00133 {
00134     module_config_t *p_config;
00135 
00136     p_config = config_FindConfig( p_this, psz_name );
00137 
00138     /* sanity checks */
00139     if( !p_config )
00140     {
00141         msg_Err( p_this, "option %s does not exist", psz_name );
00142         return -1;
00143     }
00144     if( (p_config->i_type!=CONFIG_ITEM_INTEGER) &&
00145         (p_config->i_type!=CONFIG_ITEM_KEY) &&
00146         (p_config->i_type!=CONFIG_ITEM_BOOL) )
00147     {
00148         msg_Err( p_this, "option %s does not refer to an int", psz_name );
00149         return -1;
00150     }
00151 
00152     return p_config->i_value;
00153 }
00154 
00155 /*****************************************************************************
00156  * config_GetFloat: get the value of a float variable
00157  *****************************************************************************
00158  * This function is used to get the value of variables which are internally
00159  * represented by a float (CONFIG_ITEM_FLOAT).
00160  *****************************************************************************/
00161 float __config_GetFloat( vlc_object_t *p_this, const char *psz_name )
00162 {
00163     module_config_t *p_config;
00164 
00165     p_config = config_FindConfig( p_this, psz_name );
00166 
00167     /* sanity checks */
00168     if( !p_config )
00169     {
00170         msg_Err( p_this, "option %s does not exist", psz_name );
00171         return -1;
00172     }
00173     if( p_config->i_type != CONFIG_ITEM_FLOAT )
00174     {
00175         msg_Err( p_this, "option %s does not refer to a float", psz_name );
00176         return -1;
00177     }
00178 
00179     return p_config->f_value;
00180 }
00181 
00182 /*****************************************************************************
00183  * config_GetPsz: get the string value of a string variable
00184  *****************************************************************************
00185  * This function is used to get the value of variables which are internally
00186  * represented by a string (CONFIG_ITEM_STRING, CONFIG_ITEM_FILE,
00187  * CONFIG_ITEM_DIRECTORY, and CONFIG_ITEM_MODULE).
00188  *
00189  * Important note: remember to free() the returned char* because it's a
00190  *   duplicate of the actual value. It isn't safe to return a pointer to the
00191  *   actual value as it can be modified at any time.
00192  *****************************************************************************/
00193 char * __config_GetPsz( vlc_object_t *p_this, const char *psz_name )
00194 {
00195     module_config_t *p_config;
00196     char *psz_value = NULL;
00197 
00198     p_config = config_FindConfig( p_this, psz_name );
00199 
00200     /* sanity checks */
00201     if( !p_config )
00202     {
00203         msg_Err( p_this, "option %s does not exist", psz_name );
00204         return NULL;
00205     }
00206     if( (p_config->i_type!=CONFIG_ITEM_STRING) &&
00207         (p_config->i_type!=CONFIG_ITEM_FILE) &&
00208         (p_config->i_type!=CONFIG_ITEM_DIRECTORY) &&
00209         (p_config->i_type!=CONFIG_ITEM_MODULE_LIST) &&
00210         (p_config->i_type!=CONFIG_ITEM_MODULE_LIST_CAT) &&
00211         (p_config->i_type!=CONFIG_ITEM_MODULE_CAT) &&
00212         (p_config->i_type!=CONFIG_ITEM_MODULE) )
00213     {
00214         msg_Err( p_this, "option %s does not refer to a string", psz_name );
00215         return NULL;
00216     }
00217 
00218 
00219     /* return a copy of the string */
00220     vlc_mutex_lock( p_config->p_lock );
00221     if( p_config->psz_value ) psz_value = strdup( p_config->psz_value );
00222     vlc_mutex_unlock( p_config->p_lock );
00223 
00224     return psz_value;
00225 }
00226 
00227 /*****************************************************************************
00228  * config_PutPsz: set the string value of a string variable
00229  *****************************************************************************
00230  * This function is used to set the value of variables which are internally
00231  * represented by a string (CONFIG_ITEM_STRING, CONFIG_ITEM_FILE,
00232  * CONFIG_ITEM_DIRECTORY, and CONFIG_ITEM_MODULE).
00233  *****************************************************************************/
00234 void __config_PutPsz( vlc_object_t *p_this,
00235                       const char *psz_name, const char *psz_value )
00236 {
00237     module_config_t *p_config;
00238     vlc_value_t oldval, val;
00239 
00240     p_config = config_FindConfig( p_this, psz_name );
00241 
00242 
00243     /* sanity checks */
00244     if( !p_config )
00245     {
00246         msg_Warn( p_this, "option %s does not exist", psz_name );
00247         return;
00248     }
00249     if( (p_config->i_type!=CONFIG_ITEM_STRING) &&
00250         (p_config->i_type!=CONFIG_ITEM_FILE) &&
00251         (p_config->i_type!=CONFIG_ITEM_DIRECTORY) &&
00252         (p_config->i_type!=CONFIG_ITEM_MODULE_LIST) &&
00253         (p_config->i_type!=CONFIG_ITEM_MODULE_CAT) &&
00254         (p_config->i_type!=CONFIG_ITEM_MODULE_LIST_CAT) &&
00255         (p_config->i_type!=CONFIG_ITEM_MODULE) )
00256     {
00257         msg_Err( p_this, "option %s does not refer to a string", psz_name );
00258         return;
00259     }
00260 
00261     vlc_mutex_lock( p_config->p_lock );
00262 
00263     /* backup old value */
00264     oldval.psz_string = p_config->psz_value;
00265 
00266     if( psz_value && *psz_value ) p_config->psz_value = strdup( psz_value );
00267     else p_config->psz_value = NULL;
00268 
00269     p_config->b_dirty = VLC_TRUE;
00270 
00271     val.psz_string = p_config->psz_value;
00272 
00273     vlc_mutex_unlock( p_config->p_lock );
00274 
00275     if( p_config->pf_callback )
00276     {
00277         p_config->pf_callback( p_this, psz_name, oldval, val,
00278                                p_config->p_callback_data );
00279     }
00280 
00281     /* free old string */
00282     if( oldval.psz_string ) free( oldval.psz_string );
00283 }
00284 
00285 /*****************************************************************************
00286  * config_PutInt: set the integer value of an int variable
00287  *****************************************************************************
00288  * This function is used to set the value of variables which are internally
00289  * represented by an integer (CONFIG_ITEM_INTEGER and
00290  * CONFIG_ITEM_BOOL).
00291  *****************************************************************************/
00292 void __config_PutInt( vlc_object_t *p_this, const char *psz_name, int i_value )
00293 {
00294     module_config_t *p_config;
00295     vlc_value_t oldval, val;
00296 
00297     p_config = config_FindConfig( p_this, psz_name );
00298 
00299     /* sanity checks */
00300     if( !p_config )
00301     {
00302         msg_Warn( p_this, "option %s does not exist", psz_name );
00303         return;
00304     }
00305     if( (p_config->i_type!=CONFIG_ITEM_INTEGER) &&
00306         (p_config->i_type!=CONFIG_ITEM_KEY) &&
00307         (p_config->i_type!=CONFIG_ITEM_BOOL) )
00308     {
00309         msg_Err( p_this, "option %s does not refer to an int", psz_name );
00310         return;
00311     }
00312 
00313     /* backup old value */
00314     oldval.i_int = p_config->i_value;
00315 
00316     /* if i_min == i_max == 0, then do not use them */
00317     if ((p_config->i_min == 0) && (p_config->i_max == 0))
00318     {
00319         p_config->i_value = i_value;
00320     }
00321     else if (i_value < p_config->i_min)
00322     {
00323         p_config->i_value = p_config->i_min;
00324     }
00325     else if (i_value > p_config->i_max)
00326     {
00327         p_config->i_value = p_config->i_max;
00328     }
00329     else
00330     {
00331         p_config->i_value = i_value;
00332     }
00333 
00334     p_config->b_dirty = VLC_TRUE;
00335 
00336     val.i_int = p_config->i_value;
00337 
00338     if( p_config->pf_callback )
00339     {
00340         p_config->pf_callback( p_this, psz_name, oldval, val,
00341                                p_config->p_callback_data );
00342     }
00343 }
00344 
00345 /*****************************************************************************
00346  * config_PutFloat: set the value of a float variable
00347  *****************************************************************************
00348  * This function is used to set the value of variables which are internally
00349  * represented by a float (CONFIG_ITEM_FLOAT).
00350  *****************************************************************************/
00351 void __config_PutFloat( vlc_object_t *p_this,
00352                         const char *psz_name, float f_value )
00353 {
00354     module_config_t *p_config;
00355     vlc_value_t oldval, val;
00356 
00357     p_config = config_FindConfig( p_this, psz_name );
00358 
00359     /* sanity checks */
00360     if( !p_config )
00361     {
00362         msg_Warn( p_this, "option %s does not exist", psz_name );
00363         return;
00364     }
00365     if( p_config->i_type != CONFIG_ITEM_FLOAT )
00366     {
00367         msg_Err( p_this, "option %s does not refer to a float", psz_name );
00368         return;
00369     }
00370 
00371     /* backup old value */
00372     oldval.f_float = p_config->f_value;
00373 
00374     /* if f_min == f_max == 0, then do not use them */
00375     if ((p_config->f_min == 0) && (p_config->f_max == 0))
00376     {
00377         p_config->f_value = f_value;
00378     }
00379     else if (f_value < p_config->f_min)
00380     {
00381         p_config->f_value = p_config->f_min;
00382     }
00383     else if (f_value > p_config->f_max)
00384     {
00385         p_config->f_value = p_config->f_max;
00386     }
00387     else
00388     {
00389         p_config->f_value = f_value;
00390     }
00391 
00392     p_config->b_dirty = VLC_TRUE;
00393 
00394     val.f_float = p_config->f_value;
00395 
00396     if( p_config->pf_callback )
00397     {
00398         p_config->pf_callback( p_this, psz_name, oldval, val,
00399                                p_config->p_callback_data );
00400     }
00401 }
00402 
00403 /*****************************************************************************
00404  * config_FindConfig: find the config structure associated with an option.
00405  *****************************************************************************
00406  * FIXME: This function really needs to be optimized.
00407  * FIXME: And now even more.
00408  *****************************************************************************/
00409 module_config_t *config_FindConfig( vlc_object_t *p_this, const char *psz_name )
00410 {
00411     vlc_list_t *p_list;
00412     module_t *p_parser;
00413     module_config_t *p_item;
00414     int i_index;
00415 
00416     if( !psz_name ) return NULL;
00417 
00418     p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
00419 
00420     for( i_index = 0; i_index < p_list->i_count; i_index++ )
00421     {
00422         p_parser = (module_t *)p_list->p_values[i_index].p_object ;
00423 
00424         if( !p_parser->i_config_items )
00425             continue;
00426 
00427         for( p_item = p_parser->p_config;
00428              p_item->i_type != CONFIG_HINT_END;
00429              p_item++ )
00430         {
00431             if( p_item->i_type & CONFIG_HINT )
00432                 /* ignore hints */
00433                 continue;
00434             if( !strcmp( psz_name, p_item->psz_name ) )
00435             {
00436                 vlc_list_release( p_list );
00437                 return p_item;
00438             }
00439         }
00440     }
00441 
00442     vlc_list_release( p_list );
00443 
00444     return NULL;
00445 }
00446 
00447 /*****************************************************************************
00448  * config_FindModule: find a specific module structure.
00449  *****************************************************************************/
00450 module_t *config_FindModule( vlc_object_t *p_this, const char *psz_name )
00451 {
00452     vlc_list_t *p_list;
00453     module_t *p_module, *p_result = NULL;
00454     int i_index;
00455 
00456     if( !psz_name ) return NULL;
00457 
00458     p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
00459 
00460     for( i_index = 0; i_index < p_list->i_count; i_index++ )
00461     {
00462         p_module = (module_t *)p_list->p_values[i_index].p_object;
00463         if( !strcmp( p_module->psz_object_name, psz_name ) )
00464         {
00465              p_result = p_module;
00466              break;
00467         }
00468     }
00469 
00470     vlc_list_release( p_list );
00471 
00472     return p_result;
00473 }
00474 
00475 /*****************************************************************************
00476  * config_Duplicate: creates a duplicate of a module's configuration data.
00477  *****************************************************************************
00478  * Unfortunatly we cannot work directly with the module's config data as
00479  * this module might be unloaded from memory at any time (remember HideModule).
00480  * This is why we need to create an exact copy of the config data.
00481  *****************************************************************************/
00482 void config_Duplicate( module_t *p_module, module_config_t *p_orig )
00483 {
00484     int i, j, i_lines = 1;
00485     module_config_t *p_item;
00486 
00487     /* Calculate the structure length */
00488     p_module->i_config_items = 0;
00489     p_module->i_bool_items = 0;
00490 
00491     for( p_item = p_orig; p_item->i_type != CONFIG_HINT_END; p_item++ )
00492     {
00493         i_lines++;
00494 
00495         if( p_item->i_type & CONFIG_ITEM )
00496         {
00497             p_module->i_config_items++;
00498         }
00499 
00500         if( p_item->i_type == CONFIG_ITEM_BOOL )
00501         {
00502             p_module->i_bool_items++;
00503         }
00504     }
00505 
00506     /* Allocate memory */
00507     p_module->p_config = (module_config_t *)malloc( sizeof(module_config_t)
00508                                                      * i_lines );
00509     if( p_module->p_config == NULL )
00510     {
00511         msg_Err( p_module, "config error: can't duplicate p_config" );
00512         return;
00513     }
00514 
00515     /* Do the duplication job */
00516     for( i = 0; i < i_lines ; i++ )
00517     {
00518         p_module->p_config[i] = p_orig[i];
00519 
00520         p_module->p_config[i].i_value_orig = p_orig[i].i_value;
00521         p_module->p_config[i].f_value_orig = p_orig[i].f_value;
00522         p_module->p_config[i].i_value_saved = p_orig[i].i_value;
00523         p_module->p_config[i].f_value_saved = p_orig[i].f_value;
00524         p_module->p_config[i].psz_value_saved = 0;
00525 
00526         p_module->p_config[i].psz_type = p_orig[i].psz_type ?
00527                                    strdup( p_orig[i].psz_type ) : NULL;
00528         p_module->p_config[i].psz_name = p_orig[i].psz_name ?
00529                                    strdup( p_orig[i].psz_name ) : NULL;
00530         p_module->p_config[i].psz_current = p_orig[i].psz_current?
00531                                    strdup( p_orig[i].psz_current ) : NULL;
00532         p_module->p_config[i].psz_text = p_orig[i].psz_text ?
00533                                    strdup( _(p_orig[i].psz_text) ) : NULL;
00534         p_module->p_config[i].psz_longtext = p_orig[i].psz_longtext ?
00535                                    strdup( _(p_orig[i].psz_longtext) ) : NULL;
00536         p_module->p_config[i].psz_value = p_orig[i].psz_value ?
00537                                    strdup( p_orig[i].psz_value ) : NULL;
00538         p_module->p_config[i].psz_value_orig = p_orig[i].psz_value ?
00539                                    strdup( p_orig[i].psz_value ) : NULL;
00540 
00541         p_module->p_config[i].p_lock = &p_module->object_lock;
00542 
00543         /* duplicate the string list */
00544         if( p_orig[i].i_list )
00545         {
00546             if( p_orig[i].ppsz_list )
00547             {
00548                 p_module->p_config[i].ppsz_list =
00549                     malloc( (p_orig[i].i_list + 1) * sizeof(char *) );
00550                 if( p_module->p_config[i].ppsz_list )
00551                 {
00552                     for( j = 0; j < p_orig[i].i_list; j++ )
00553                         p_module->p_config[i].ppsz_list[j] = p_orig[i].ppsz_list[j] ?
00554                             strdup( p_orig[i].ppsz_list[j] ) : NULL ;
00555                     p_module->p_config[i].ppsz_list[j] = NULL;
00556                 }
00557             }
00558             if( p_orig[i].ppsz_list_text )
00559             {
00560                 p_module->p_config[i].ppsz_list_text =
00561                     malloc( (p_orig[i].i_list + 1) * sizeof(char *) );
00562                 if( p_module->p_config[i].ppsz_list_text )
00563                 {
00564                     for( j = 0; j < p_orig[i].i_list; j++ )
00565                         p_module->p_config[i].ppsz_list_text[j] = _(p_orig[i].ppsz_list_text[j]) ?
00566                             strdup( _(p_orig[i].ppsz_list_text[j] ) ) : NULL ;
00567                     p_module->p_config[i].ppsz_list_text[j] = NULL;
00568                 }
00569             }
00570             if( p_orig[i].pi_list )
00571             {
00572                 p_module->p_config[i].pi_list =
00573                     malloc( (p_orig[i].i_list + 1) * sizeof(int) );
00574                 if( p_module->p_config[i].pi_list )
00575                 {
00576                     for( j = 0; j < p_orig[i].i_list; j++ )
00577                         p_module->p_config[i].pi_list[j] =
00578                             p_orig[i].pi_list[j];
00579                 }
00580             }
00581         }
00582 
00583         /* duplicate the actions list */
00584         if( p_orig[i].i_action )
00585         {
00586             int j;
00587 
00588             p_module->p_config[i].ppf_action =
00589                 malloc( p_orig[i].i_action * sizeof(void *) );
00590             p_module->p_config[i].ppsz_action_text =
00591                 malloc( p_orig[i].i_action * sizeof(char *) );
00592 
00593             for( j = 0; j < p_orig[i].i_action; j++ )
00594             {
00595                 p_module->p_config[i].ppf_action[j] =
00596                     p_orig[i].ppf_action[j];
00597                 p_module->p_config[i].ppsz_action_text[j] =
00598                     p_orig[i].ppsz_action_text[j] ?
00599                     strdup( p_orig[i].ppsz_action_text[j] ) : NULL;
00600             }
00601         }
00602 
00603         p_module->p_config[i].pf_callback = p_orig[i].pf_callback;
00604     }
00605 }
00606 
00607 /*****************************************************************************
00608  * config_Free: frees a duplicated module's configuration data.
00609  *****************************************************************************
00610  * This function frees all the data duplicated by config_Duplicate.
00611  *****************************************************************************/
00612 void config_Free( module_t *p_module )
00613 {
00614     module_config_t *p_item = p_module->p_config;
00615     int i;
00616 
00617     if( p_item == NULL )
00618     {
00619         return;
00620     }
00621 
00622     for( ; p_item->i_type != CONFIG_HINT_END ; p_item++ )
00623     {
00624         if( p_item->psz_type )
00625             free( p_item->psz_type );
00626 
00627         if( p_item->psz_name )
00628             free( p_item->psz_name );
00629 
00630         if( p_item->psz_current )
00631             free( p_item->psz_current );
00632 
00633         if( p_item->psz_text )
00634             free( p_item->psz_text );
00635 
00636         if( p_item->psz_longtext )
00637             free( p_item->psz_longtext );
00638 
00639         if( p_item->psz_value )
00640             free( p_item->psz_value );
00641 
00642         if( p_item->psz_value_orig )
00643             free( p_item->psz_value_orig );
00644 
00645         if( p_item->psz_value_saved )
00646             free( p_item->psz_value_saved );
00647 
00648         if( p_item->i_list )
00649         {
00650             for( i = 0; i < p_item->i_list; i++ )
00651             {
00652                 if( p_item->ppsz_list && p_item->ppsz_list[i] )
00653                     free( p_item->ppsz_list[i] );
00654                 if( p_item->ppsz_list_text && p_item->ppsz_list_text[i] )
00655                     free( p_item->ppsz_list_text[i] );
00656             }
00657             if( p_item->ppsz_list ) free( p_item->ppsz_list );
00658             if( p_item->ppsz_list_text ) free( p_item->ppsz_list_text );
00659             if( p_item->pi_list ) free( p_item->pi_list );
00660         }
00661 
00662         if( p_item->i_action )
00663         {
00664             for( i = 0; i < p_item->i_action; i++ )
00665             {
00666                 if( p_item->ppsz_action_text[i] )
00667                     free( p_item->ppsz_action_text[i] );
00668             }
00669             if( p_item->ppf_action ) free( p_item->ppf_action );
00670             if( p_item->ppsz_action_text ) free( p_item->ppsz_action_text );
00671         }
00672     }
00673 
00674     free( p_module->p_config );
00675     p_module->p_config = NULL;
00676 }
00677 
00678 /*****************************************************************************
00679  * config_SetCallbacks: sets callback functions in the duplicate p_config.
00680  *****************************************************************************
00681  * Unfortunatly we cannot work directly with the module's config data as
00682  * this module might be unloaded from memory at any time (remember HideModule).
00683  * This is why we need to duplicate callbacks each time we reload the module.
00684  *****************************************************************************/
00685 void config_SetCallbacks( module_config_t *p_new, module_config_t *p_orig )
00686 {
00687     while( p_new->i_type != CONFIG_HINT_END )
00688     {
00689         p_new->pf_callback = p_orig->pf_callback;
00690         p_new++;
00691         p_orig++;
00692     }
00693 }
00694 
00695 /*****************************************************************************
00696  * config_UnsetCallbacks: unsets callback functions in the duplicate p_config.
00697  *****************************************************************************
00698  * We simply undo what we did in config_SetCallbacks.
00699  *****************************************************************************/
00700 void config_UnsetCallbacks( module_config_t *p_new )
00701 {
00702     while( p_new->i_type != CONFIG_HINT_END )
00703     {
00704         p_new->pf_callback = NULL;
00705         p_new++;
00706     }
00707 }
00708 
00709 /*****************************************************************************
00710  * config_ResetAll: reset the configuration data for all the modules.
00711  *****************************************************************************/
00712 void __config_ResetAll( vlc_object_t *p_this )
00713 {
00714     int i_index, i;
00715     vlc_list_t *p_list;
00716     module_t *p_module;
00717 
00718     /* Acquire config file lock */
00719     vlc_mutex_lock( &p_this->p_vlc->config_lock );
00720 
00721     p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
00722 
00723     for( i_index = 0; i_index < p_list->i_count; i_index++ )
00724     {
00725         p_module = (module_t *)p_list->p_values[i_index].p_object ;
00726         if( p_module->b_submodule ) continue;
00727 
00728         for( i = 0; p_module->p_config[i].i_type != CONFIG_HINT_END; i++ )
00729         {
00730             p_module->p_config[i].i_value = p_module->p_config[i].i_value_orig;
00731             p_module->p_config[i].f_value = p_module->p_config[i].f_value_orig;
00732             if( p_module->p_config[i].psz_value )
00733                 free( p_module->p_config[i].psz_value );
00734             p_module->p_config[i].psz_value =
00735                 p_module->p_config[i].psz_value_orig ?
00736                 strdup( p_module->p_config[i].psz_value_orig ) : NULL;
00737         }
00738     }
00739 
00740     vlc_list_release( p_list );
00741     vlc_mutex_unlock( &p_this->p_vlc->config_lock );
00742 }
00743 
00744 /*****************************************************************************
00745  * config_LoadConfigFile: loads the configuration file.
00746  *****************************************************************************
00747  * This function is called to load the config options stored in the config
00748  * file.
00749  *****************************************************************************/
00750 int __config_LoadConfigFile( vlc_object_t *p_this, const char *psz_module_name )
00751 {
00752     vlc_list_t *p_list;
00753     module_t *p_parser;
00754     module_config_t *p_item;
00755     FILE *file;
00756     char line[1024];
00757     char *p_index, *psz_option_name, *psz_option_value;
00758     char *psz_filename, *psz_homedir, *psz_configfile;
00759     int i_index;
00760 
00761     psz_configfile = p_this->p_vlc->psz_configfile;
00762     if( !psz_configfile || !psz_configfile )
00763     {
00764         psz_homedir = p_this->p_vlc->psz_homedir;
00765         if( !psz_homedir )
00766         {
00767             msg_Err( p_this, "psz_homedir is null" );
00768             return -1;
00769         }
00770         psz_filename = (char *)malloc( sizeof("/" CONFIG_DIR "/" CONFIG_FILE) +
00771                                        strlen(psz_homedir) );
00772         if( psz_filename )
00773             sprintf( psz_filename, "%s/" CONFIG_DIR "/" CONFIG_FILE,
00774                      psz_homedir );
00775     }
00776     else
00777     {
00778         psz_filename = strdup( psz_configfile );
00779     }
00780 
00781     if( !psz_filename )
00782     {
00783         msg_Err( p_this, "out of memory" );
00784         return -1;
00785     }
00786 
00787     msg_Dbg( p_this, "opening config file %s", psz_filename );
00788 
00789     /* Acquire config file lock */
00790     vlc_mutex_lock( &p_this->p_vlc->config_lock );
00791 
00792     file = fopen( psz_filename, "rt" );
00793     if( !file )
00794     {
00795         msg_Warn( p_this, "config file %s does not exist yet", psz_filename );
00796         free( psz_filename );
00797         vlc_mutex_unlock( &p_this->p_vlc->config_lock );
00798         return -1;
00799     }
00800 
00801     /* Look for the selected module, if NULL then save everything */
00802     p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
00803 
00804     for( i_index = 0; i_index < p_list->i_count; i_index++ )
00805     {
00806         p_parser = (module_t *)p_list->p_values[i_index].p_object ;
00807 
00808         if( psz_module_name
00809              && strcmp( psz_module_name, p_parser->psz_object_name ) )
00810         {
00811             continue;
00812         }
00813 
00814         /* The config file is organized in sections, one per module. Look for
00815          * the interesting section ( a section is of the form [foo] ) */
00816         fseek( file, 0L, SEEK_SET );
00817         while( fgets( line, 1024, file ) )
00818         {
00819             if( (line[0] == '[')
00820                && (p_index = strchr(line,']'))
00821                && (p_index - &line[1]
00822                     == (int)strlen(p_parser->psz_object_name))
00823                && !memcmp( &line[1], p_parser->psz_object_name,
00824                            strlen(p_parser->psz_object_name) ) )
00825             {
00826 #if 0
00827                 msg_Dbg( p_this, "loading config for module \"%s\"",
00828                                  p_parser->psz_object_name );
00829 #endif
00830 
00831                 break;
00832             }
00833         }
00834         /* either we found the section or we're at the EOF */
00835 
00836         /* Now try to load the options in this section */
00837         while( fgets( line, 1024, file ) )
00838         {
00839             if( line[0] == '[' ) break; /* end of section */
00840 
00841             /* ignore comments or empty lines */
00842             if( (line[0] == '#') || (line[0] == '\n') || (line[0] == (char)0) )
00843                 continue;
00844 
00845             /* get rid of line feed */
00846             if( line[strlen(line)-1] == '\n' )
00847                 line[strlen(line)-1] = (char)0;
00848 
00849             /* look for option name */
00850             psz_option_name = line;
00851             psz_option_value = NULL;
00852             p_index = strchr( line, '=' );
00853             if( !p_index ) break; /* this ain't an option!!! */
00854 
00855             *p_index = (char)0;
00856             psz_option_value = p_index + 1;
00857 
00858             if( !p_parser->i_config_items )
00859             {
00860                 continue;
00861             }
00862 
00863             /* try to match this option with one of the module's options */
00864             for( p_item = p_parser->p_config;
00865                  p_item->i_type != CONFIG_HINT_END;
00866                  p_item++ )
00867             {
00868                 if( p_item->i_type & CONFIG_HINT )
00869                     /* ignore hints */
00870                     continue;
00871 
00872                 if( !strcmp( p_item->psz_name, psz_option_name ) )
00873                 {
00874                     /* We found it */
00875                     switch( p_item->i_type )
00876                     {
00877                     case CONFIG_ITEM_BOOL:
00878                     case CONFIG_ITEM_INTEGER:
00879                         if( !*psz_option_value )
00880                             break;                    /* ignore empty option */
00881                         p_item->i_value = strtol( psz_option_value, 0, 0 );
00882                         p_item->i_value_saved = p_item->i_value;
00883 #if 0
00884                         msg_Dbg( p_this, "option \"%s\", value %i",
00885                                  p_item->psz_name, p_item->i_value );
00886 #endif
00887                         break;
00888 
00889                     case CONFIG_ITEM_FLOAT:
00890                         if( !*psz_option_value )
00891                             break;                    /* ignore empty option */
00892                         p_item->f_value = (float)atof( psz_option_value);
00893                         p_item->f_value_saved = p_item->f_value;
00894 #if 0
00895                         msg_Dbg( p_this, "option \"%s\", value %f",
00896                                  p_item->psz_name, (double)p_item->f_value );
00897 #endif
00898                         break;
00899                     case CONFIG_ITEM_KEY:
00900                         if( !*psz_option_value )
00901                             break;                    /* ignore empty option */
00902                         p_item->i_value = ConfigStringToKey(psz_option_value);
00903                         p_item->i_value_saved = p_item->i_value;
00904                         break;
00905 
00906                     default:
00907                         vlc_mutex_lock( p_item->p_lock );
00908 
00909                         /* free old string */
00910                         if( p_item->psz_value )
00911                             free( p_item->psz_value );
00912 
00913                         p_item->psz_value = *psz_option_value ?
00914                             strdup( psz_option_value ) : NULL;
00915 
00916                         if( p_item->psz_value_saved )
00917                             free( p_item->psz_value_saved );
00918                         p_item->psz_value_saved = 0;
00919                         if( !p_item->psz_value || !p_item->psz_value_orig ||
00920                             (p_item->psz_value && p_item->psz_value_orig &&
00921                              strcmp(p_item->psz_value,p_item->psz_value_orig)))
00922                             p_item->psz_value_saved = p_item->psz_value ?
00923                                 strdup( p_item->psz_value ) : 0;
00924 
00925                         vlc_mutex_unlock( p_item->p_lock );
00926 
00927 #if 0
00928                         msg_Dbg( p_this, "option \"%s\", value \"%s\"",
00929                                  p_item->psz_name,
00930                                  p_item->psz_value ? p_item->psz_value : "" );
00931 #endif
00932                         break;
00933                     }
00934                 }
00935             }
00936         }
00937 
00938     }
00939 
00940     vlc_list_release( p_list );
00941 
00942     fclose( file );
00943     free( psz_filename );
00944 
00945     vlc_mutex_unlock( &p_this->p_vlc->config_lock );
00946 
00947     return 0;
00948 }
00949 
00950 /*****************************************************************************
00951  * config_CreateDir: Create configuration directory if it doesn't exist.
00952  *****************************************************************************/
00953 int config_CreateDir( vlc_object_t *p_this, char *psz_dirname )
00954 {
00955     if( !psz_dirname && !*psz_dirname ) return -1;
00956 
00957 #if defined( UNDER_CE )
00958     {
00959         wchar_t psz_new[ MAX_PATH ];
00960         char psz_mod[MAX_PATH];
00961         int i = 0;
00962 
00963         /* Convert '/' into '\' */
00964         while( *psz_dirname )
00965         {
00966             if( *psz_dirname == '/' ) psz_mod[i] = '\\';
00967             else psz_mod[i] = *psz_dirname;
00968             psz_dirname++;
00969             i++;
00970         }
00971         psz_mod[i] = 0;
00972 
00973         MultiByteToWideChar( CP_ACP, 0, psz_mod, -1, psz_new, MAX_PATH );
00974         if( CreateDirectory( psz_new, NULL ) )
00975         {
00976             msg_Err( p_this, "could not create %s", psz_mod );
00977         }
00978     }
00979 
00980 #else
00981 #   if defined( WIN32 )
00982     if( mkdir( psz_dirname ) && errno != EEXIST )
00983 #   else
00984     if( mkdir( psz_dirname, 0755 ) && errno != EEXIST )
00985 #   endif
00986     {
00987         msg_Err( p_this, "could not create %s (%s)",
00988                  psz_dirname, strerror(errno) );
00989     }
00990 
00991 #endif
00992 
00993     return 0;
00994 }
00995 
00996 /*****************************************************************************
00997  * config_SaveConfigFile: Save a module's config options.
00998  *****************************************************************************
00999  * This will save the specified module's config options to the config file.
01000  * If psz_module_name is NULL then we save all the modules config options.
01001  * It's no use to save the config options that kept their default values, so
01002  * we'll try to be a bit clever here.
01003  *
01004  * When we save we mustn't delete the config options of the modules that
01005  * haven't been loaded. So we cannot just create a new config file with the
01006  * config structures we've got in memory.
01007  * I don't really know how to deal with this nicely, so I will use a completly
01008  * dumb method ;-)
01009  * I will load the config file in memory, but skipping all the sections of the
01010  * modules we want to save. Then I will create a brand new file, dump the file
01011  * loaded in memory and then append the sections of the modules we want to
01012  * save.
01013  * Really stupid no ?
01014  *****************************************************************************/
01015 static int SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name,
01016                            vlc_bool_t b_autosave )
01017 {
01018     module_t *p_parser;
01019     vlc_list_t *p_list;
01020     module_config_t *p_item;
01021     FILE *file;
01022     char p_line[1024], *p_index2;
01023     int i_sizebuf = 0;
01024     char *p_bigbuffer, *p_index;
01025     vlc_bool_t b_backup;
01026     char *psz_filename, *psz_homedir, *psz_configfile;
01027     int i_index;
01028 
01029     /* Acquire config file lock */
01030     vlc_mutex_lock( &p_this->p_vlc->config_lock );
01031 
01032     psz_configfile = p_this->p_vlc->psz_configfile;
01033     if( !psz_configfile || !psz_configfile )
01034     {
01035         psz_homedir = p_this->p_vlc->psz_homedir;
01036         if( !psz_homedir )
01037         {
01038             msg_Err( p_this, "psz_homedir is null" );
01039             vlc_mutex_unlock( &p_this->p_vlc->config_lock );
01040             return -1;
01041         }
01042         psz_filename = (char *)malloc( sizeof("/" CONFIG_DIR "/" CONFIG_FILE) +
01043                                        strlen(psz_homedir) );
01044 
01045         if( psz_filename )
01046             sprintf( psz_filename, "%s/" CONFIG_DIR, psz_homedir );
01047 
01048         if( !psz_filename )
01049         {
01050             msg_Err( p_this, "out of memory" );
01051             vlc_mutex_unlock( &p_this->p_vlc->config_lock );
01052             return -1;
01053         }
01054 
01055         config_CreateDir( p_this, psz_filename );
01056 
01057         strcat( psz_filename, "/" CONFIG_FILE );
01058     }
01059     else
01060     {
01061         psz_filename = strdup( psz_configfile );
01062         if( !psz_filename )
01063         {
01064             msg_Err( p_this, "out of memory" );
01065             vlc_mutex_unlock( &p_this->p_vlc->config_lock );
01066             return -1;
01067         }
01068     }
01069 
01070     msg_Dbg( p_this, "opening config file %s", psz_filename );
01071 
01072     file = fopen( psz_filename, "rt" );
01073     if( !file )
01074     {
01075         msg_Warn( p_this, "config file %s does not exist yet", psz_filename );
01076     }
01077     else
01078     {
01079         /* look for file size */
01080         fseek( file, 0L, SEEK_END );
01081         i_sizebuf = ftell( file );
01082         fseek( file, 0L, SEEK_SET );
01083     }
01084 
01085     p_bigbuffer = p_index = malloc( i_sizebuf+1 );
01086     if( !p_bigbuffer )
01087     {
01088         msg_Err( p_this, "out of memory" );
01089         if( file ) fclose( file );
01090         free( psz_filename );
01091         vlc_mutex_unlock( &p_this->p_vlc->config_lock );
01092         return -1;
01093     }
01094     p_bigbuffer[0] = 0;
01095 
01096     /* List all available modules */
01097     p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
01098 
01099     /* backup file into memory, we only need to backup the sections we won't
01100      * save later on */
01101     b_backup = 0;
01102     while( file && fgets( p_line, 1024, file ) )
01103     {
01104         if( (p_line[0] == '[') && (p_index2 = strchr(p_line,']')))
01105         {
01106 
01107             /* we found a section, check if we need to do a backup */
01108             for( i_index = 0; i_index < p_list->i_count; i_index++ )
01109             {
01110                 p_parser = (module_t *)p_list->p_values[i_index].p_object ;
01111 
01112                 if( ((p_index2 - &p_line[1])
01113                        == (int)strlen(p_parser->psz_object_name) )
01114                     && !memcmp( &p_line[1], p_parser->psz_object_name,
01115                                 strlen(p_parser->psz_object_name) ) )
01116                 {
01117                     if( !psz_module_name )
01118                         break;
01119                     else if( !strcmp( psz_module_name,
01120                                       p_parser->psz_object_name ) )
01121                         break;
01122                 }
01123             }
01124 
01125             if( i_index == p_list->i_count )
01126             {
01127                 /* we don't have this section in our list so we need to back
01128                  * it up */
01129                 *p_index2 = 0;
01130 #if 0
01131                 msg_Dbg( p_this, "backing up config for unknown module \"%s\"",
01132                                  &p_line[1] );
01133 #endif
01134                 *p_index2 = ']';
01135 
01136                 b_backup = 1;
01137             }
01138             else
01139             {
01140                 b_backup = 0;
01141             }
01142         }
01143 
01144         /* save line if requested and line is valid (doesn't begin with a
01145          * space, tab, or eol) */
01146         if( b_backup && (p_line[0] != '\n') && (p_line[0] != ' ')
01147             && (p_line[0] != '\t') )
01148         {
01149             strcpy( p_index, p_line );
01150             p_index += strlen( p_line );
01151         }
01152     }
01153     if( file ) fclose( file );
01154 
01155 
01156     /*
01157      * Save module config in file
01158      */
01159 
01160     file = fopen( psz_filename, "wt" );
01161     if( !file )
01162     {
01163         msg_Warn( p_this, "could not open config file %s for writing",
01164                           psz_filename );
01165         free( psz_filename );
01166         vlc_list_release( p_list );
01167         vlc_mutex_unlock( &p_this->p_vlc->config_lock );
01168         return -1;
01169     }
01170 
01171     fprintf( file, "###\n###  " COPYRIGHT_MESSAGE "\n###\n\n" );
01172 
01173     /* Look for the selected module, if NULL then save everything */
01174     for( i_index = 0; i_index < p_list->i_count; i_index++ )
01175     {
01176         p_parser = (module_t *)p_list->p_values[i_index].p_object ;
01177 
01178         if( psz_module_name && strcmp( psz_module_name,
01179                                        p_parser->psz_object_name ) )
01180             continue;
01181 
01182         if( !p_parser->i_config_items )
01183             continue;
01184 
01185         if( psz_module_name )
01186             msg_Dbg( p_this, "saving config for module \"%s\"",
01187                      p_parser->psz_object_name );
01188 
01189         fprintf( file, "[%s]", p_parser->psz_object_name );
01190         if( p_parser->psz_longname )
01191             fprintf( file, " # %s\n\n", p_parser->psz_longname );
01192         else
01193             fprintf( file, "\n\n" );
01194 
01195         for( p_item = p_parser->p_config;
01196              p_item->i_type != CONFIG_HINT_END;
01197              p_item++ )
01198         {
01199             char  *psz_key;
01200             int   i_value = p_item->i_value;
01201             float f_value = p_item->f_value;
01202             char  *psz_value = p_item->psz_value;
01203 
01204             if( p_item->i_type & CONFIG_HINT )
01205                 /* ignore hints */
01206                 continue;
01207             /* Ignore deprecated options */
01208             if( p_item->psz_current )
01209                 continue;
01210             if( b_autosave && !p_item->b_autosave )
01211             {
01212                 i_value = p_item->i_value_saved;
01213                 f_value = p_item->f_value_saved;
01214                 psz_value = p_item->psz_value_saved;
01215                 if( !psz_value ) psz_value = p_item->psz_value_orig;
01216             }
01217             else
01218             {
01219                 p_item->b_dirty = VLC_FALSE;
01220             }
01221 
01222             switch( p_item->i_type )
01223             {
01224             case CONFIG_ITEM_BOOL:
01225             case CONFIG_ITEM_INTEGER:
01226                 if( p_item->psz_text )
01227                     fprintf( file, "# %s (%s)\n", p_item->psz_text,
01228                              (p_item->i_type == CONFIG_ITEM_BOOL) ?
01229                              _("boolean") : _("integer") );
01230                 if( i_value == p_item->i_value_orig )
01231                     fprintf( file, "#" );
01232                 fprintf( file, "%s=%i\n", p_item->psz_name, i_value );
01233 
01234                 p_item->i_value_saved = i_value;
01235                 break;
01236 
01237             case CONFIG_ITEM_KEY:
01238                 if( p_item->psz_text )
01239                     fprintf( file, "# %s (%s)\n", p_item->psz_text,
01240                              _("key") );
01241                 if( i_value == p_item->i_value_orig )
01242                     fprintf( file, "#" );
01243                 psz_key = ConfigKeyToString( i_value );
01244                 fprintf( file, "%s=%s\n", p_item->psz_name,
01245                          psz_key ? psz_key : "" );
01246                 if ( psz_key ) free( psz_key );
01247 
01248                 p_item->i_value_saved = i_value;
01249                 break;
01250 
01251             case CONFIG_ITEM_FLOAT:
01252                 if( p_item->psz_text )
01253                     fprintf( file, "# %s (%s)\n", p_item->psz_text,
01254                              _("float") );
01255                 if( f_value == p_item->f_value_orig )
01256                     fprintf( file, "#" );
01257                 fprintf( file, "%s=%f\n", p_item->psz_name, (double)f_value );
01258 
01259                 p_item->f_value_saved = f_value;
01260                 break;
01261 
01262             default:
01263                 if( p_item->psz_text )
01264                     fprintf( file, "# %s (%s)\n", p_item->psz_text,
01265                              _("string") );
01266                 if( (!psz_value && !p_item->psz_value_orig) ||
01267                     (psz_value && p_item->psz_value_orig &&
01268                      !strcmp( psz_value, p_item->psz_value_orig )) )
01269                     fprintf( file, "#" );
01270                 fprintf( file, "%s=%s\n", p_item->psz_name,
01271                          psz_value ? psz_value : "" );
01272 
01273                 if( b_autosave && !p_item->b_autosave ) break;
01274 
01275                 if( p_item->psz_value_saved ) free( p_item->psz_value_saved );
01276                 p_item->psz_value_saved = 0;
01277                 if( (psz_value && p_item->psz_value_orig &&
01278                      strcmp( psz_value, p_item->psz_value_orig )) ||
01279                     !psz_value || !p_item->psz_value_orig)
01280                     p_item->psz_value_saved = psz_value ? strdup(psz_value):0;
01281             }
01282         }
01283 
01284         fprintf( file, "\n" );
01285     }
01286 
01287     vlc_list_release( p_list );
01288 
01289     /*
01290      * Restore old settings from the config in file
01291      */
01292     fputs( p_bigbuffer, file );
01293     free( p_bigbuffer );
01294 
01295     fclose( file );
01296     free( psz_filename );
01297     vlc_mutex_unlock( &p_this->p_vlc->config_lock );
01298 
01299     return 0;
01300 }
01301 
01302 int config_AutoSaveConfigFile( vlc_object_t *p_this )
01303 {
01304     vlc_list_t *p_list;
01305     module_t *p_parser;
01306     module_config_t *p_item;
01307     int i_index, i_count;
01308 
01309     /* Check if there's anything to save */
01310     vlc_mutex_lock( &p_this->p_vlc->config_lock );
01311     p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
01312     i_count = p_list->i_count;
01313     for( i_index = 0; i_index < i_count; i_index++ )
01314     {
01315         p_parser = (module_t *)p_list->p_values[i_index].p_object ;
01316 
01317         if( !p_parser->i_config_items ) continue;
01318 
01319         for( p_item = p_parser->p_config;
01320              p_item->i_type != CONFIG_HINT_END;
01321              p_item++ )
01322         {
01323             if( p_item->b_autosave && p_item->b_dirty ) break;
01324         }
01325         if( p_item->i_type != CONFIG_HINT_END ) break;
01326     }
01327     vlc_list_release( p_list );
01328     vlc_mutex_unlock( &p_this->p_vlc->config_lock );
01329 
01330     if( i_index == i_count ) return VLC_SUCCESS;
01331     return SaveConfigFile( p_this, 0, VLC_TRUE );
01332 }
01333 
01334 int __config_SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name )
01335 {
01336     return SaveConfigFile( p_this, psz_module_name, VLC_FALSE );
01337 }
01338 
01339 /*****************************************************************************
01340  * config_LoadCmdLine: parse command line
01341  *****************************************************************************
01342  * Parse command line for configuration options.
01343  * Now that the module_bank has been initialized, we can dynamically
01344  * generate the longopts structure used by getops. We have to do it this way
01345  * because we don't know (and don't want to know) in advance the configuration
01346  * options used (ie. exported) by each module.
01347  *****************************************************************************/
01348 int __config_LoadCmdLine( vlc_object_t *p_this, int *pi_argc, char *ppsz_argv[],
01349                           vlc_bool_t b_ignore_errors )
01350 {
01351     int i_cmd, i_index, i_opts, i_shortopts, flag, i_verbose = 0;
01352     module_t *p_parser;
01353     vlc_list_t *p_list;
01354     module_config_t *p_item;
01355     struct option *p_longopts;
01356     int i_modules_index;
01357 
01358     /* Short options */
01359     module_config_t *pp_shortopts[256];
01360     char *psz_shortopts;
01361 
01362     /* Set default configuration and copy arguments */
01363     p_this->p_vlc->i_argc    = *pi_argc;
01364     p_this->p_vlc->ppsz_argv = ppsz_argv;
01365 
01366 #ifdef SYS_DARWIN
01367     /* When vlc.app is run by double clicking in Mac OS X, the 2nd arg
01368      * is the PSN - process serial number (a unique PID-ish thingie)
01369      * still ok for real Darwin & when run from command line */
01370     if ( (*pi_argc > 1) && (strncmp( ppsz_argv[ 1 ] , "-psn" , 4 ) == 0) )
01371                                         /* for example -psn_0_9306113 */
01372     {
01373         /* GDMF!... I can't do this or else the MacOSX window server will
01374          * not pick up the PSN and not register the app and we crash...
01375          * hence the following kludge otherwise we'll get confused w/ argv[1]
01376          * being an input file name */
01377 #if 0
01378         ppsz_argv[ 1 ] = NULL;
01379 #endif
01380         *pi_argc = *pi_argc - 1;
01381         pi_argc--;
01382         return 0;
01383     }
01384 #endif
01385 
01386     /* List all modules */
01387     p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
01388 
01389     /*
01390      * Generate the longopts and shortopts structures used by getopt_long
01391      */
01392 
01393     i_opts = 0;
01394     for( i_modules_index = 0; i_modules_index < p_list->i_count;
01395          i_modules_index++ )
01396     {
01397         p_parser = (module_t *)p_list->p_values[i_modules_index].p_object ;
01398 
01399         /* count the number of exported configuration options (to allocate
01400          * longopts). We also need to allocate space for too options when
01401          * dealing with boolean to allow for --foo and --no-foo */
01402         i_opts += p_parser->i_config_items
01403                      + 2 * p_parser->i_bool_items;
01404     }
01405 
01406     p_longopts = malloc( sizeof(struct option) * (i_opts + 1) );
01407     if( p_longopts == NULL )
01408     {
01409         msg_Err( p_this, "out of memory" );
01410         vlc_list_release( p_list );
01411         return -1;
01412     }
01413 
01414     psz_shortopts = malloc( sizeof( char ) * (2 * i_opts + 1) );
01415     if( psz_shortopts == NULL )
01416     {
01417         msg_Err( p_this, "out of memory" );
01418         free( p_longopts );
01419         vlc_list_release( p_list );
01420         return -1;
01421     }
01422 
01423     /* If we are requested to ignore errors, then we must work on a copy
01424      * of the ppsz_argv array, otherwise getopt_long will reorder it for
01425      * us, ignoring the arity of the options */
01426     if( b_ignore_errors )
01427     {
01428         ppsz_argv = (char**)malloc( *pi_argc * sizeof(char *) );
01429         if( ppsz_argv == NULL )
01430         {
01431             msg_Err( p_this, "out of memory" );
01432             free( psz_shortopts );
01433             free( p_longopts );
01434             vlc_list_release( p_list );
01435             return -1;
01436         }
01437         memcpy( ppsz_argv, p_this->p_vlc->ppsz_argv,
01438                 *pi_argc * sizeof(char *) );
01439     }
01440 
01441     i_shortopts = 0;
01442     for( i_index = 0; i_index < 256; i_index++ )
01443     {
01444         pp_shortopts[i_index] = NULL;
01445     }
01446 
01447     /* Fill the p_longopts and psz_shortopts structures */
01448     i_index = 0;
01449     for( i_modules_index = 0; i_modules_index < p_list->i_count;
01450          i_modules_index++ )
01451     {
01452         p_parser = (module_t *)p_list->p_values[i_modules_index].p_object ;
01453 
01454         if( !p_parser->i_config_items )
01455             continue;
01456 
01457         for( p_item = p_parser->p_config;
01458              p_item->i_type != CONFIG_HINT_END;
01459              p_item++ )
01460         {
01461             /* Ignore hints */
01462             if( p_item->i_type & CONFIG_HINT )
01463                 continue;
01464 
01465             /* Add item to long options */
01466             p_longopts[i_index].name = strdup( p_item->psz_name );
01467             if( p_longopts[i_index].name == NULL ) continue;
01468             p_longopts[i_index].has_arg =
01469                 (p_item->i_type == CONFIG_ITEM_BOOL)?
01470                                                no_argument : required_argument;
01471             p_longopts[i_index].flag = &flag;
01472             p_longopts[i_index].val = 0;
01473             i_index++;
01474 
01475             /* When dealing with bools we also need to add the --no-foo
01476              * option */
01477             if( p_item->i_type == CONFIG_ITEM_BOOL )
01478             {
01479                 char *psz_name = malloc( strlen(p_item->psz_name) + 3 );
01480                 if( psz_name == NULL ) continue;
01481                 strcpy( psz_name, "no" );
01482                 strcat( psz_name, p_item->psz_name );
01483 
01484                 p_longopts[i_index].name = psz_name;
01485                 p_longopts[i_index].has_arg = no_argument;
01486                 p_longopts[i_index].flag = &flag;
01487                 p_longopts[i_index].val = 1;
01488                 i_index++;
01489 
01490                 psz_name = malloc( strlen(p_item->psz_name) + 4 );
01491                 if( psz_name == NULL ) continue;
01492                 strcpy( psz_name, "no-" );
01493                 strcat( psz_name, p_item->psz_name );
01494 
01495                 p_longopts[i_index].name = psz_name;
01496                 p_longopts[i_index].has_arg = no_argument;
01497                 p_longopts[i_index].flag = &flag;
01498                 p_longopts[i_index].val = 1;
01499                 i_index++;
01500             }
01501 
01502             /* If item also has a short option, add it */
01503             if( p_item->i_short )
01504             {
01505                 pp_shortopts[(int)p_item->i_short] = p_item;
01506                 psz_shortopts[i_shortopts] = p_item->i_short;
01507                 i_shortopts++;
01508                 if( p_item->i_type != CONFIG_ITEM_BOOL )
01509                 {
01510                     psz_shortopts[i_shortopts] = ':';
01511                     i_shortopts++;
01512 
01513                     if( p_item->i_short == 'v' )
01514                     {
01515                         psz_shortopts[i_shortopts] = ':';
01516                         i_shortopts++;
01517                     }
01518                 }
01519             }
01520         }
01521     }
01522 
01523     /* We don't need the module list anymore */
01524     vlc_list_release( p_list );
01525 
01526     /* Close the longopts and shortopts structures */
01527     memset( &p_longopts[i_index], 0, sizeof(struct option) );
01528     psz_shortopts[i_shortopts] = '\0';
01529 
01530     /*
01531      * Parse the command line options
01532      */
01533     opterr = 0;
01534     optind = 1;
01535     while( ( i_cmd = getopt_long( *pi_argc, ppsz_argv, psz_shortopts,
01536                                   p_longopts, &i_index ) ) != EOF )
01537     {
01538         /* A long option has been recognized */
01539         if( i_cmd == 0 )
01540         {
01541             module_config_t *p_conf;
01542             char *psz_name = (char *)p_longopts[i_index].name;
01543 
01544             /* Check if we deal with a --nofoo or --no-foo long option */
01545             if( flag ) psz_name += psz_name[2] == '-' ? 3 : 2;
01546 
01547             /* Store the configuration option */
01548             p_conf = config_FindConfig( p_this, psz_name );
01549             if( p_conf )
01550             {
01551                 /* Check if the option is deprecated */
01552                 if( p_conf->psz_current )
01553                 {
01554                     if( !strcmp(p_conf->psz_current,"SUPPRESSED") )
01555                     {
01556                        if( !b_ignore_errors ) 
01557                         {
01558                             fprintf(stderr,
01559                                     "Warning: option --%s is no longer used.\n",
01560                                     p_conf->psz_name);
01561                         }
01562                        continue;
01563                     }
01564                     if( !b_ignore_errors )
01565                     {
01566                         if( p_conf->b_strict )
01567                         {
01568                             fprintf( stderr,
01569                                      "Error: option --%s is deprecated. "
01570                                      "Use --%s instead.\n",
01571                                      p_conf->psz_name, p_conf->psz_current);
01572                             /*free */
01573                             for( i_index = 0; p_longopts[i_index].name; i_index++ )
01574                                 free( (char *)p_longopts[i_index].name );
01575 
01576                             free( p_longopts );
01577                             free( psz_shortopts );
01578                             return -1;
01579                         }
01580                         fprintf(stderr,
01581                                 "Warning: option --%s is deprecated. "
01582                                 "You should use --%s instead.\n",
01583                                 p_conf->psz_name, p_conf->psz_current);
01584                     }
01585                     psz_name=p_conf->psz_current;
01586                     p_conf = config_FindConfig( p_this, psz_name );
01587                 }
01588 
01589             switch( p_conf->i_type )
01590             {
01591                 case CONFIG_ITEM_STRING:
01592                 case CONFIG_ITEM_FILE:
01593                 case CONFIG_ITEM_DIRECTORY:
01594                 case CONFIG_ITEM_MODULE:
01595                 case CONFIG_ITEM_MODULE_LIST:
01596                 case CONFIG_ITEM_MODULE_LIST_CAT:
01597                 case CONFIG_ITEM_MODULE_CAT:
01598                     config_PutPsz( p_this, psz_name, optarg );
01599                     break;
01600                 case CONFIG_ITEM_INTEGER:
01601                     config_PutInt( p_this, psz_name, strtol(optarg, 0, 0));
01602                     break;
01603                 case CONFIG_ITEM_FLOAT:
01604                     config_PutFloat( p_this, psz_name, (float)atof(optarg) );
01605                     break;
01606                 case CONFIG_ITEM_KEY:
01607                     config_PutInt( p_this, psz_name, ConfigStringToKey( optarg ) );
01608                     break;
01609                 case CONFIG_ITEM_BOOL:
01610                     config_PutInt( p_this, psz_name, !flag );
01611                     break;
01612             }
01613 
01614             continue;
01615         }
01616     }
01617     /* A short option has been recognized */
01618     if( pp_shortopts[i_cmd] != NULL )
01619     {
01620         switch( pp_shortopts[i_cmd]->i_type )
01621         {
01622             case CONFIG_ITEM_STRING:
01623             case CONFIG_ITEM_FILE:
01624             case CONFIG_ITEM_DIRECTORY:
01625             case CONFIG_ITEM_MODULE:
01626             case CONFIG_ITEM_MODULE_CAT:
01627             case CONFIG_ITEM_MODULE_LIST:
01628             case CONFIG_ITEM_MODULE_LIST_CAT:
01629                 config_PutPsz( p_this, pp_shortopts[i_cmd]->psz_name, optarg );
01630                 break;
01631             case CONFIG_ITEM_INTEGER:
01632                 if( i_cmd == 'v' )
01633                 {
01634                     if( optarg )
01635                     {
01636                         if( *optarg == 'v' ) /* eg. -vvv */
01637                         {
01638                             i_verbose++;
01639                             while( *optarg == 'v' )
01640                             {
01641                                 i_verbose++;
01642                                 optarg++;
01643                             }
01644                         }
01645                         else
01646                         {
01647                             i_verbose += atoi( optarg ); /* eg. -v2 */
01648                         }
01649                     }
01650                     else
01651                     {
01652                         i_verbose++; /* -v */
01653                     }
01654                     config_PutInt( p_this, pp_shortopts[i_cmd]->psz_name,
01655                                            i_verbose );
01656                 }
01657                 else
01658                 {
01659                     config_PutInt( p_this, pp_shortopts[i_cmd]->psz_name,
01660                                            strtol(optarg, 0, 0) );
01661                 }
01662                 break;
01663             case CONFIG_ITEM_BOOL:
01664                 config_PutInt( p_this, pp_shortopts[i_cmd]->psz_name, 1 );
01665                 break;
01666             }
01667 
01668             continue;
01669         }
01670 
01671         /* Internal error: unknown option */
01672         if( !b_ignore_errors )
01673         {
01674             fprintf( stderr, "%s: unknown option"
01675                      " or missing mandatory argument ",
01676                      p_this->p_vlc->psz_object_name );
01677             if( optopt )
01678             {
01679                 fprintf( stderr, "`-%c'\n", optopt );
01680             }
01681             else
01682             {
01683                 fprintf( stderr, "`%s'\n", ppsz_argv[optind-1] );
01684             }
01685             fprintf( stderr, "Try `%s --help' for more information.\n",
01686                              p_this->p_vlc->psz_object_name );
01687 
01688             for( i_index = 0; p_longopts[i_index].name; i_index++ )
01689                 free( (char *)p_longopts[i_index].name );
01690             free( p_longopts );
01691             free( psz_shortopts );
01692             return -1;
01693         }
01694     }
01695 
01696     /* Free allocated resources */
01697     for( i_index = 0; p_longopts[i_index].name; i_index++ )
01698         free( (char *)p_longopts[i_index].name );
01699     free( p_longopts );
01700     free( psz_shortopts );
01701     if( b_ignore_errors ) free( ppsz_argv );
01702 
01703     return 0;
01704 }
01705 
01706 /*****************************************************************************
01707  * config_GetHomeDir, config_GetUserDir: find the user's home directory.
01708  *****************************************************************************
01709  * This function will try by different ways to find the user's home path.
01710  * Note that this function is not reentrant, it should be called only once
01711  * at the beginning of main where the result will be stored for later use.
01712  *****************************************************************************/
01713 static char *GetDir( vlc_bool_t b_appdata )
01714 {
01715     char *p_tmp, *p_homedir = NULL;
01716 
01717 #if defined(HAVE_GETPWUID)
01718     struct passwd *p_pw = NULL;
01719 #endif
01720 
01721 #if defined(WIN32) && !defined(UNDER_CE)
01722     typedef HRESULT (WINAPI *SHGETFOLDERPATH)( HWND, int, HANDLE, DWORD,
01723                                                LPSTR );
01724 #ifndef CSIDL_FLAG_CREATE
01725 #   define CSIDL_FLAG_CREATE 0x8000
01726 #endif
01727 #ifndef CSIDL_APPDATA
01728 #   define CSIDL_APPDATA 0x1A
01729 #endif
01730 #ifndef CSIDL_PROFILE
01731 #   define CSIDL_PROFILE 0x28
01732 #endif
01733 #ifndef SHGFP_TYPE_CURRENT
01734 #   define SHGFP_TYPE_CURRENT 0
01735 #endif
01736 
01737     HINSTANCE shfolder_dll;
01738     SHGETFOLDERPATH SHGetFolderPath ;
01739 
01740     /* load the shfolder dll to retrieve SHGetFolderPath */
01741     if( ( shfolder_dll = LoadLibrary( _T("SHFolder.dll") ) ) != NULL )
01742     {
01743         SHGetFolderPath = (void *)GetProcAddress( shfolder_dll,
01744                                                   _T("SHGetFolderPathA") );
01745         if ( SHGetFolderPath != NULL )
01746         {
01747             p_homedir = (char *)malloc( MAX_PATH );
01748             if( !p_homedir ) return NULL;
01749 
01750             /* get the "Application Data" folder for the current user */
01751             if( S_OK == SHGetFolderPath( NULL,
01752                                          (b_appdata ? CSIDL_APPDATA :
01753                                            CSIDL_PROFILE) | CSIDL_FLAG_CREATE,
01754                                          NULL, SHGFP_TYPE_CURRENT,
01755                                          p_homedir ) )
01756             {
01757                 FreeLibrary( shfolder_dll );
01758                 return p_homedir;
01759             }
01760             free( p_homedir );
01761             p_homedir = NULL;
01762         }
01763         FreeLibrary( shfolder_dll );
01764     }
01765 
01766 #elif defined(UNDER_CE)
01767 
01768 #ifndef CSIDL_APPDATA
01769 #   define CSIDL_APPDATA 0x1A
01770 #endif
01771 
01772     wchar_t p_whomedir[MAX_PATH];
01773 
01774     /* get the "Application Data" folder for the current user */
01775     if( SHGetSpecialFolderPath( NULL, p_whomedir, CSIDL_APPDATA, 1 ) )
01776     {
01777         p_homedir = (char *)malloc( MAX_PATH );
01778         if( !p_homedir ) return NULL;
01779 
01780         sprintf( p_homedir, "%ls", p_whomedir );
01781         return p_homedir;
01782     }
01783 #endif
01784 
01785 #if defined(HAVE_GETPWUID)
01786     if( ( p_pw = getpwuid( getuid() ) ) == NULL )
01787 #endif
01788     {
01789         if( ( p_tmp = getenv( "HOME" ) ) == NULL )
01790         {
01791             if( ( p_tmp = getenv( "TMP" ) ) == NULL )
01792             {
01793                 p_tmp = "/tmp";
01794             }
01795         }
01796 
01797         p_homedir = strdup( p_tmp );
01798     }
01799 #if defined(HAVE_GETPWUID)
01800     else
01801     {
01802         p_homedir = strdup( p_pw->pw_dir );
01803     }
01804 #endif
01805 
01806     return p_homedir;
01807 }
01808 
01809 char *config_GetHomeDir( void )
01810 {
01811     return GetDir( VLC_TRUE );
01812 }
01813 
01814 char *config_GetUserDir( void )
01815 {
01816     return GetDir( VLC_FALSE );
01817 }
01818 
01819 
01820 static int ConfigStringToKey( char *psz_key )
01821 {
01822     int i_key = 0;
01823     unsigned int i;
01824     char *psz_parser = strchr( psz_key, '-' );
01825     while( psz_parser && psz_parser != psz_key )
01826     {
01827         for( i = 0; i < sizeof(vlc_modifiers) / sizeof(key_descriptor_t); i++ )
01828         {
01829             if( !strncasecmp( vlc_modifiers[i].psz_key_string, psz_key,
01830                               strlen( vlc_modifiers[i].psz_key_string ) ) )
01831             {
01832                 i_key |= vlc_modifiers[i].i_key_code;
01833             }
01834         }
01835         psz_key = psz_parser + 1;
01836         psz_parser = strchr( psz_key, '-' );
01837     }
01838     for( i = 0; i < sizeof(vlc_keys) / sizeof( key_descriptor_t ); i++ )
01839     {
01840         if( !strcasecmp( vlc_keys[i].psz_key_string, psz_key ) )
01841         {
01842             i_key |= vlc_keys[i].i_key_code;
01843             break;
01844         }
01845     }
01846     return i_key;
01847 }
01848 
01849 static char *ConfigKeyToString( int i_key )
01850 {
01851     char *psz_key = malloc( 100 );
01852     char *p;
01853     size_t index;
01854 
01855     if ( !psz_key )
01856     {
01857         return NULL;
01858     }
01859     *psz_key = '\0';
01860     p = psz_key;
01861     for( index = 0; index < (sizeof(vlc_modifiers) / sizeof(key_descriptor_t));
01862          index++ )
01863     {
01864         if( i_key & vlc_modifiers[index].i_key_code )
01865         {
01866             p += sprintf( p, "%s-", vlc_modifiers[index].psz_key_string );
01867         }
01868     }
01869     for( index = 0; index < (sizeof(vlc_keys) / sizeof( key_descriptor_t));
01870          index++)
01871     {
01872         if( (int)( i_key & ~KEY_MODIFIER ) == vlc_keys[index].i_key_code )
01873         {
01874             p += sprintf( p, "%s", vlc_keys[index].psz_key_string );
01875             break;
01876         }
01877     }
01878     return psz_key;
01879 }

Generated on Tue Dec 20 10:15:00 2005 for vlc-0.8.4a by  doxygen 1.4.2