configuration.c
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:55k
源码类别:

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * configuration.c management of the modules configuration
  3.  *****************************************************************************
  4.  * Copyright (C) 2001-2004 VideoLAN
  5.  * $Id: configuration.c 8950 2004-10-07 22:05:34Z hartman $
  6.  *
  7.  * Authors: Gildas Bazin <gbazin@videolan.org>
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2 of the License, or
  12.  * (at your option) any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  22.  *****************************************************************************/
  23. #include <vlc/vlc.h>
  24. #include "vlc_keys.h"
  25. #include <stdio.h>                                              /* sprintf() */
  26. #include <stdlib.h>                                      /* free(), strtol() */
  27. #include <string.h>                                              /* strdup() */
  28. #include <errno.h>                                                  /* errno */
  29. #ifdef HAVE_UNISTD_H
  30. #    include <unistd.h>                                          /* getuid() */
  31. #endif
  32. #ifdef HAVE_GETOPT_LONG
  33. #   ifdef HAVE_GETOPT_H
  34. #       include <getopt.h>                                       /* getopt() */
  35. #   endif
  36. #else
  37. #   include "../extras/getopt.h"
  38. #endif
  39. #if defined(HAVE_GETPWUID)
  40. #   include <pwd.h>                                            /* getpwuid() */
  41. #endif
  42. #if defined( HAVE_SYS_STAT_H )
  43. #   include <sys/stat.h>
  44. #endif
  45. #if defined( HAVE_SYS_TYPES_H )
  46. #   include <sys/types.h>
  47. #endif
  48. #if defined( WIN32 )
  49. #   if !defined( UNDER_CE )
  50. #       include <direct.h>
  51. #   endif
  52. #include <tchar.h>
  53. #endif
  54. static int ConfigStringToKey( char * );
  55. static char *ConfigKeyToString( int );
  56. /*****************************************************************************
  57.  * config_GetType: get the type of a variable (bool, int, float, string)
  58.  *****************************************************************************
  59.  * This function is used to get the type of a variable from its name.
  60.  * Beware, this is quite slow.
  61.  *****************************************************************************/
  62. int __config_GetType( vlc_object_t *p_this, const char *psz_name )
  63. {
  64.     module_config_t *p_config;
  65.     int i_type;
  66.     p_config = config_FindConfig( p_this, psz_name );
  67.     /* sanity checks */
  68.     if( !p_config )
  69.     {
  70.         return 0;
  71.     }
  72.     switch( p_config->i_type )
  73.     {
  74.     case CONFIG_ITEM_BOOL:
  75.         i_type = VLC_VAR_BOOL;
  76.         break;
  77.     case CONFIG_ITEM_INTEGER:
  78.         i_type = VLC_VAR_INTEGER;
  79.         break;
  80.     case CONFIG_ITEM_FLOAT:
  81.         i_type = VLC_VAR_FLOAT;
  82.         break;
  83.     case CONFIG_ITEM_MODULE:
  84.         i_type = VLC_VAR_MODULE;
  85.         break;
  86.     case CONFIG_ITEM_STRING:
  87.         i_type = VLC_VAR_STRING;
  88.         break;
  89.     case CONFIG_ITEM_FILE:
  90.         i_type = VLC_VAR_FILE;
  91.         break;
  92.     case CONFIG_ITEM_DIRECTORY:
  93.         i_type = VLC_VAR_DIRECTORY;
  94.         break;
  95.     default:
  96.         i_type = 0;
  97.         break;
  98.     }
  99.     return i_type;
  100. }
  101. /*****************************************************************************
  102.  * config_GetInt: get the value of an int variable
  103.  *****************************************************************************
  104.  * This function is used to get the value of variables which are internally
  105.  * represented by an integer (CONFIG_ITEM_INTEGER and
  106.  * CONFIG_ITEM_BOOL).
  107.  *****************************************************************************/
  108. int __config_GetInt( vlc_object_t *p_this, const char *psz_name )
  109. {
  110.     module_config_t *p_config;
  111.     p_config = config_FindConfig( p_this, psz_name );
  112.     /* sanity checks */
  113.     if( !p_config )
  114.     {
  115.         msg_Err( p_this, "option %s does not exist", psz_name );
  116.         return -1;
  117.     }
  118.     if( (p_config->i_type!=CONFIG_ITEM_INTEGER) &&
  119.         (p_config->i_type!=CONFIG_ITEM_KEY) &&
  120.         (p_config->i_type!=CONFIG_ITEM_BOOL) )
  121.     {
  122.         msg_Err( p_this, "option %s does not refer to an int", psz_name );
  123.         return -1;
  124.     }
  125.     return p_config->i_value;
  126. }
  127. /*****************************************************************************
  128.  * config_GetFloat: get the value of a float variable
  129.  *****************************************************************************
  130.  * This function is used to get the value of variables which are internally
  131.  * represented by a float (CONFIG_ITEM_FLOAT).
  132.  *****************************************************************************/
  133. float __config_GetFloat( vlc_object_t *p_this, const char *psz_name )
  134. {
  135.     module_config_t *p_config;
  136.     p_config = config_FindConfig( p_this, psz_name );
  137.     /* sanity checks */
  138.     if( !p_config )
  139.     {
  140.         msg_Err( p_this, "option %s does not exist", psz_name );
  141.         return -1;
  142.     }
  143.     if( p_config->i_type != CONFIG_ITEM_FLOAT )
  144.     {
  145.         msg_Err( p_this, "option %s does not refer to a float", psz_name );
  146.         return -1;
  147.     }
  148.     return p_config->f_value;
  149. }
  150. /*****************************************************************************
  151.  * config_GetPsz: get the string value of a string variable
  152.  *****************************************************************************
  153.  * This function is used to get the value of variables which are internally
  154.  * represented by a string (CONFIG_ITEM_STRING, CONFIG_ITEM_FILE,
  155.  * CONFIG_ITEM_DIRECTORY, and CONFIG_ITEM_MODULE).
  156.  *
  157.  * Important note: remember to free() the returned char* because it's a
  158.  *   duplicate of the actual value. It isn't safe to return a pointer to the
  159.  *   actual value as it can be modified at any time.
  160.  *****************************************************************************/
  161. char * __config_GetPsz( vlc_object_t *p_this, const char *psz_name )
  162. {
  163.     module_config_t *p_config;
  164.     char *psz_value = NULL;
  165.     p_config = config_FindConfig( p_this, psz_name );
  166.     /* sanity checks */
  167.     if( !p_config )
  168.     {
  169.         msg_Err( p_this, "option %s does not exist", psz_name );
  170.         return NULL;
  171.     }
  172.     if( (p_config->i_type!=CONFIG_ITEM_STRING) &&
  173.         (p_config->i_type!=CONFIG_ITEM_FILE) &&
  174.         (p_config->i_type!=CONFIG_ITEM_DIRECTORY) &&
  175.         (p_config->i_type!=CONFIG_ITEM_MODULE) )
  176.     {
  177.         msg_Err( p_this, "option %s does not refer to a string", psz_name );
  178.         return NULL;
  179.     }
  180.     /* return a copy of the string */
  181.     vlc_mutex_lock( p_config->p_lock );
  182.     if( p_config->psz_value ) psz_value = strdup( p_config->psz_value );
  183.     vlc_mutex_unlock( p_config->p_lock );
  184.     return psz_value;
  185. }
  186. /*****************************************************************************
  187.  * config_PutPsz: set the string value of a string variable
  188.  *****************************************************************************
  189.  * This function is used to set the value of variables which are internally
  190.  * represented by a string (CONFIG_ITEM_STRING, CONFIG_ITEM_FILE,
  191.  * CONFIG_ITEM_DIRECTORY, and CONFIG_ITEM_MODULE).
  192.  *****************************************************************************/
  193. void __config_PutPsz( vlc_object_t *p_this,
  194.                       const char *psz_name, const char *psz_value )
  195. {
  196.     module_config_t *p_config;
  197.     vlc_value_t oldval, val;
  198.     p_config = config_FindConfig( p_this, psz_name );
  199.     /* sanity checks */
  200.     if( !p_config )
  201.     {
  202.         msg_Warn( p_this, "option %s does not exist", psz_name );
  203.         return;
  204.     }
  205.     if( (p_config->i_type!=CONFIG_ITEM_STRING) &&
  206.         (p_config->i_type!=CONFIG_ITEM_FILE) &&
  207.         (p_config->i_type!=CONFIG_ITEM_DIRECTORY) &&
  208.         (p_config->i_type!=CONFIG_ITEM_MODULE) )
  209.     {
  210.         msg_Err( p_this, "option %s does not refer to a string", psz_name );
  211.         return;
  212.     }
  213.     vlc_mutex_lock( p_config->p_lock );
  214.     /* backup old value */
  215.     oldval.psz_string = p_config->psz_value;
  216.     if( psz_value && *psz_value ) p_config->psz_value = strdup( psz_value );
  217.     else p_config->psz_value = NULL;
  218.     val.psz_string = p_config->psz_value;
  219.     vlc_mutex_unlock( p_config->p_lock );
  220.     if( p_config->pf_callback )
  221.     {
  222.         p_config->pf_callback( p_this, psz_name, oldval, val,
  223.                                p_config->p_callback_data );
  224.     }
  225.     /* free old string */
  226.     if( oldval.psz_string ) free( oldval.psz_string );
  227. }
  228. /*****************************************************************************
  229.  * config_PutInt: set the integer value of an int variable
  230.  *****************************************************************************
  231.  * This function is used to set the value of variables which are internally
  232.  * represented by an integer (CONFIG_ITEM_INTEGER and
  233.  * CONFIG_ITEM_BOOL).
  234.  *****************************************************************************/
  235. void __config_PutInt( vlc_object_t *p_this, const char *psz_name, int i_value )
  236. {
  237.     module_config_t *p_config;
  238.     vlc_value_t oldval, val;
  239.     p_config = config_FindConfig( p_this, psz_name );
  240.     /* sanity checks */
  241.     if( !p_config )
  242.     {
  243.         msg_Warn( p_this, "option %s does not exist", psz_name );
  244.         return;
  245.     }
  246.     if( (p_config->i_type!=CONFIG_ITEM_INTEGER) &&
  247.         (p_config->i_type!=CONFIG_ITEM_KEY) &&
  248.         (p_config->i_type!=CONFIG_ITEM_BOOL) )
  249.     {
  250.         msg_Err( p_this, "option %s does not refer to an int", psz_name );
  251.         return;
  252.     }
  253.     /* backup old value */
  254.     oldval.i_int = p_config->i_value;
  255.     /* if i_min == i_max == 0, then do not use them */
  256.     if ((p_config->i_min == 0) && (p_config->i_max == 0))
  257.     {
  258.         p_config->i_value = i_value;
  259.     }
  260.     else if (i_value < p_config->i_min)
  261.     {
  262.         p_config->i_value = p_config->i_min;
  263.     }
  264.     else if (i_value > p_config->i_max)
  265.     {
  266.         p_config->i_value = p_config->i_max;
  267.     }
  268.     else
  269.     {
  270.         p_config->i_value = i_value;
  271.     }
  272.     val.i_int = p_config->i_value;
  273.     if( p_config->pf_callback )
  274.     {
  275.         p_config->pf_callback( p_this, psz_name, oldval, val,
  276.                                p_config->p_callback_data );
  277.     }
  278. }
  279. /*****************************************************************************
  280.  * config_PutFloat: set the value of a float variable
  281.  *****************************************************************************
  282.  * This function is used to set the value of variables which are internally
  283.  * represented by a float (CONFIG_ITEM_FLOAT).
  284.  *****************************************************************************/
  285. void __config_PutFloat( vlc_object_t *p_this,
  286.                         const char *psz_name, float f_value )
  287. {
  288.     module_config_t *p_config;
  289.     vlc_value_t oldval, val;
  290.     p_config = config_FindConfig( p_this, psz_name );
  291.     /* sanity checks */
  292.     if( !p_config )
  293.     {
  294.         msg_Warn( p_this, "option %s does not exist", psz_name );
  295.         return;
  296.     }
  297.     if( p_config->i_type != CONFIG_ITEM_FLOAT )
  298.     {
  299.         msg_Err( p_this, "option %s does not refer to a float", psz_name );
  300.         return;
  301.     }
  302.     /* backup old value */
  303.     oldval.f_float = p_config->f_value;
  304.     /* if f_min == f_max == 0, then do not use them */
  305.     if ((p_config->f_min == 0) && (p_config->f_max == 0))
  306.     {
  307.         p_config->f_value = f_value;
  308.     }
  309.     else if (f_value < p_config->f_min)
  310.     {
  311.         p_config->f_value = p_config->f_min;
  312.     }
  313.     else if (f_value > p_config->f_max)
  314.     {
  315.         p_config->f_value = p_config->f_max;
  316.     }
  317.     else
  318.     {
  319.         p_config->f_value = f_value;
  320.     }
  321.     val.f_float = p_config->f_value;
  322.     if( p_config->pf_callback )
  323.     {
  324.         p_config->pf_callback( p_this, psz_name, oldval, val,
  325.                                p_config->p_callback_data );
  326.     }
  327. }
  328. /*****************************************************************************
  329.  * config_FindConfig: find the config structure associated with an option.
  330.  *****************************************************************************
  331.  * FIXME: This function really needs to be optimized.
  332.  * FIXME: And now even more.
  333.  *****************************************************************************/
  334. module_config_t *config_FindConfig( vlc_object_t *p_this, const char *psz_name )
  335. {
  336.     vlc_list_t *p_list;
  337.     module_t *p_parser;
  338.     module_config_t *p_item;
  339.     int i_index;
  340.     if( !psz_name ) return NULL;
  341.     p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
  342.     for( i_index = 0; i_index < p_list->i_count; i_index++ )
  343.     {
  344.         p_parser = (module_t *)p_list->p_values[i_index].p_object ;
  345.         if( !p_parser->i_config_items )
  346.             continue;
  347.         for( p_item = p_parser->p_config;
  348.              p_item->i_type != CONFIG_HINT_END;
  349.              p_item++ )
  350.         {
  351.             if( p_item->i_type & CONFIG_HINT )
  352.                 /* ignore hints */
  353.                 continue;
  354.             if( !strcmp( psz_name, p_item->psz_name ) )
  355.             {
  356.                 vlc_list_release( p_list );
  357.                 return p_item;
  358.             }
  359.         }
  360.     }
  361.     vlc_list_release( p_list );
  362.     return NULL;
  363. }
  364. /*****************************************************************************
  365.  * config_FindModule: find a specific module structure.
  366.  *****************************************************************************/
  367. module_t *config_FindModule( vlc_object_t *p_this, const char *psz_name )
  368. {
  369.     vlc_list_t *p_list;
  370.     module_t *p_module, *p_result = NULL;
  371.     int i_index;
  372.     if( !psz_name ) return NULL;
  373.     p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
  374.     for( i_index = 0; i_index < p_list->i_count; i_index++ )
  375.     {
  376.         p_module = (module_t *)p_list->p_values[i_index].p_object;
  377.         if( !strcmp( p_module->psz_object_name, psz_name ) )
  378.         {
  379.              p_result = p_module;
  380.              break;
  381.         }
  382.     }
  383.     vlc_list_release( p_list );
  384.     return p_result;
  385. }
  386. /*****************************************************************************
  387.  * config_Duplicate: creates a duplicate of a module's configuration data.
  388.  *****************************************************************************
  389.  * Unfortunatly we cannot work directly with the module's config data as
  390.  * this module might be unloaded from memory at any time (remember HideModule).
  391.  * This is why we need to create an exact copy of the config data.
  392.  *****************************************************************************/
  393. void config_Duplicate( module_t *p_module, module_config_t *p_orig )
  394. {
  395.     int i, j, i_lines = 1;
  396.     module_config_t *p_item;
  397.     /* Calculate the structure length */
  398.     p_module->i_config_items = 0;
  399.     p_module->i_bool_items = 0;
  400.     for( p_item = p_orig; p_item->i_type != CONFIG_HINT_END; p_item++ )
  401.     {
  402.         i_lines++;
  403.         if( p_item->i_type & CONFIG_ITEM )
  404.         {
  405.             p_module->i_config_items++;
  406.         }
  407.         if( p_item->i_type == CONFIG_ITEM_BOOL )
  408.         {
  409.             p_module->i_bool_items++;
  410.         }
  411.     }
  412.     /* Allocate memory */
  413.     p_module->p_config = (module_config_t *)malloc( sizeof(module_config_t)
  414.                                                      * i_lines );
  415.     if( p_module->p_config == NULL )
  416.     {
  417.         msg_Err( p_module, "config error: can't duplicate p_config" );
  418.         return;
  419.     }
  420.     /* Do the duplication job */
  421.     for( i = 0; i < i_lines ; i++ )
  422.     {
  423.         p_module->p_config[i] = p_orig[i];
  424.         p_module->p_config[i].i_value_orig = p_orig[i].i_value;
  425.         p_module->p_config[i].f_value_orig = p_orig[i].f_value;
  426.         p_module->p_config[i].psz_type = p_orig[i].psz_type ?
  427.                                    strdup( p_orig[i].psz_type ) : NULL;
  428.         p_module->p_config[i].psz_name = p_orig[i].psz_name ?
  429.                                    strdup( p_orig[i].psz_name ) : NULL;
  430.         p_module->p_config[i].psz_text = p_orig[i].psz_text ?
  431.                                    strdup( _(p_orig[i].psz_text) ) : NULL;
  432.         p_module->p_config[i].psz_longtext = p_orig[i].psz_longtext ?
  433.                                    strdup( _(p_orig[i].psz_longtext) ) : NULL;
  434.         p_module->p_config[i].psz_value = p_orig[i].psz_value ?
  435.                                    strdup( p_orig[i].psz_value ) : NULL;
  436.         p_module->p_config[i].psz_value_orig = p_orig[i].psz_value ?
  437.                                    strdup( p_orig[i].psz_value ) : NULL;
  438.         p_module->p_config[i].p_lock = &p_module->object_lock;
  439.         /* duplicate the string list */
  440.         if( p_orig[i].i_list )
  441.         {
  442.             if( p_orig[i].ppsz_list )
  443.             {
  444.                 p_module->p_config[i].ppsz_list =
  445.                     malloc( (p_orig[i].i_list + 1) * sizeof(char *) );
  446.                 if( p_module->p_config[i].ppsz_list )
  447.                 {
  448.                     for( j = 0; j < p_orig[i].i_list; j++ )
  449.                         p_module->p_config[i].ppsz_list[j] = p_orig[i].ppsz_list[j] ?
  450.                             strdup( p_orig[i].ppsz_list[j] ) : NULL ;
  451.                     p_module->p_config[i].ppsz_list[j] = NULL;
  452.                 }
  453.             }
  454.             if( p_orig[i].ppsz_list_text )
  455.             {
  456.                 p_module->p_config[i].ppsz_list_text =
  457.                     malloc( (p_orig[i].i_list + 1) * sizeof(char *) );
  458.                 if( p_module->p_config[i].ppsz_list_text )
  459.                 {
  460.                     for( j = 0; j < p_orig[i].i_list; j++ )
  461.                         p_module->p_config[i].ppsz_list_text[j] = _(p_orig[i].ppsz_list_text[j]) ?
  462.                             strdup( _(p_orig[i].ppsz_list_text[j] ) ) : NULL ;
  463.                     p_module->p_config[i].ppsz_list_text[j] = NULL;
  464.                 }
  465.             }
  466.             if( p_orig[i].pi_list )
  467.             {
  468.                 p_module->p_config[i].pi_list =
  469.                     malloc( (p_orig[i].i_list + 1) * sizeof(int) );
  470.                 if( p_module->p_config[i].pi_list )
  471.                 {
  472.                     for( j = 0; j < p_orig[i].i_list; j++ )
  473.                         p_module->p_config[i].pi_list[j] =
  474.                             p_orig[i].pi_list[j];
  475.                 }
  476.             }
  477.         }
  478.         /* duplicate the actions list */
  479.         if( p_orig[i].i_action )
  480.         {
  481.             int j;
  482.             p_module->p_config[i].ppf_action =
  483.                 malloc( p_orig[i].i_action * sizeof(void *) );
  484.             p_module->p_config[i].ppsz_action_text =
  485.                 malloc( p_orig[i].i_action * sizeof(char *) );
  486.             for( j = 0; j < p_orig[i].i_action; j++ )
  487.             {
  488.                 p_module->p_config[i].ppf_action[j] =
  489.                     p_orig[i].ppf_action[j];
  490.                 p_module->p_config[i].ppsz_action_text[j] =
  491.                     p_orig[i].ppsz_action_text[j] ?
  492.                     strdup( p_orig[i].ppsz_action_text[j] ) : NULL;
  493.             }
  494.         }
  495.         p_module->p_config[i].pf_callback = p_orig[i].pf_callback;
  496.     }
  497. }
  498. /*****************************************************************************
  499.  * config_Free: frees a duplicated module's configuration data.
  500.  *****************************************************************************
  501.  * This function frees all the data duplicated by config_Duplicate.
  502.  *****************************************************************************/
  503. void config_Free( module_t *p_module )
  504. {
  505.     module_config_t *p_item = p_module->p_config;
  506.     int i;
  507.     if( p_item == NULL )
  508.     {
  509.         return;
  510.     }
  511.     for( ; p_item->i_type != CONFIG_HINT_END ; p_item++ )
  512.     {
  513.         if( p_item->psz_type )
  514.             free( p_item->psz_type );
  515.         if( p_item->psz_name )
  516.             free( p_item->psz_name );
  517.         if( p_item->psz_text )
  518.             free( p_item->psz_text );
  519.         if( p_item->psz_longtext )
  520.             free( p_item->psz_longtext );
  521.         if( p_item->psz_value )
  522.             free( p_item->psz_value );
  523.         if( p_item->psz_value_orig )
  524.             free( p_item->psz_value_orig );
  525.         if( p_item->i_list )
  526.         {
  527.             for( i = 0; i < p_item->i_list; i++ )
  528.             {
  529.                 if( p_item->ppsz_list && p_item->ppsz_list[i] )
  530.                     free( p_item->ppsz_list[i] );
  531.                 if( p_item->ppsz_list_text && p_item->ppsz_list_text[i] )
  532.                     free( p_item->ppsz_list_text[i] );
  533.             }
  534.             if( p_item->ppsz_list ) free( p_item->ppsz_list );
  535.             if( p_item->ppsz_list_text ) free( p_item->ppsz_list_text );
  536.             if( p_item->pi_list ) free( p_item->pi_list );
  537.         }
  538.         if( p_item->i_action )
  539.         {
  540.             for( i = 0; i < p_item->i_action; i++ )
  541.             {
  542.                 if( p_item->ppsz_action_text[i] )
  543.                     free( p_item->ppsz_action_text[i] );
  544.             }
  545.             if( p_item->ppf_action ) free( p_item->ppf_action );
  546.             if( p_item->ppsz_action_text ) free( p_item->ppsz_action_text );
  547.         }
  548.     }
  549.     free( p_module->p_config );
  550.     p_module->p_config = NULL;
  551. }
  552. /*****************************************************************************
  553.  * config_SetCallbacks: sets callback functions in the duplicate p_config.
  554.  *****************************************************************************
  555.  * Unfortunatly we cannot work directly with the module's config data as
  556.  * this module might be unloaded from memory at any time (remember HideModule).
  557.  * This is why we need to duplicate callbacks each time we reload the module.
  558.  *****************************************************************************/
  559. void config_SetCallbacks( module_config_t *p_new, module_config_t *p_orig )
  560. {
  561.     while( p_new->i_type != CONFIG_HINT_END )
  562.     {
  563.         p_new->pf_callback = p_orig->pf_callback;
  564.         p_new++;
  565.         p_orig++;
  566.     }
  567. }
  568. /*****************************************************************************
  569.  * config_UnsetCallbacks: unsets callback functions in the duplicate p_config.
  570.  *****************************************************************************
  571.  * We simply undo what we did in config_SetCallbacks.
  572.  *****************************************************************************/
  573. void config_UnsetCallbacks( module_config_t *p_new )
  574. {
  575.     while( p_new->i_type != CONFIG_HINT_END )
  576.     {
  577.         p_new->pf_callback = NULL;
  578.         p_new++;
  579.     }
  580. }
  581. /*****************************************************************************
  582.  * config_ResetAll: reset the configuration data for all the modules.
  583.  *****************************************************************************/
  584. void __config_ResetAll( vlc_object_t *p_this )
  585. {
  586.     int i_index, i;
  587.     vlc_list_t *p_list;
  588.     module_t *p_module;
  589.     /* Acquire config file lock */
  590.     vlc_mutex_lock( &p_this->p_vlc->config_lock );
  591.     p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
  592.     for( i_index = 0; i_index < p_list->i_count; i_index++ )
  593.     {
  594.         p_module = (module_t *)p_list->p_values[i_index].p_object ;
  595.         if( p_module->b_submodule ) continue;
  596.         for( i = 0; p_module->p_config[i].i_type != CONFIG_HINT_END; i++ )
  597.         {
  598.             p_module->p_config[i].i_value = p_module->p_config[i].i_value_orig;
  599.             p_module->p_config[i].f_value = p_module->p_config[i].f_value_orig;
  600.             if( p_module->p_config[i].psz_value )
  601.                 free( p_module->p_config[i].psz_value );
  602.             p_module->p_config[i].psz_value =
  603.                 p_module->p_config[i].psz_value_orig ?
  604.                 strdup( p_module->p_config[i].psz_value_orig ) : NULL;
  605.         }
  606.     }
  607.     vlc_list_release( p_list );
  608.     vlc_mutex_unlock( &p_this->p_vlc->config_lock );
  609. }
  610. /*****************************************************************************
  611.  * config_LoadConfigFile: loads the configuration file.
  612.  *****************************************************************************
  613.  * This function is called to load the config options stored in the config
  614.  * file.
  615.  *****************************************************************************/
  616. int __config_LoadConfigFile( vlc_object_t *p_this, const char *psz_module_name )
  617. {
  618.     vlc_list_t *p_list;
  619.     module_t *p_parser;
  620.     module_config_t *p_item;
  621.     FILE *file;
  622.     char line[1024];
  623.     char *p_index, *psz_option_name, *psz_option_value;
  624.     char *psz_filename, *psz_homedir, *psz_configfile;
  625.     int i_index;
  626.     psz_configfile = p_this->p_vlc->psz_configfile;
  627.     if( !psz_configfile || !psz_configfile )
  628.     {
  629.         psz_homedir = p_this->p_vlc->psz_homedir;
  630.         if( !psz_homedir )
  631.         {
  632.             msg_Err( p_this, "psz_homedir is null" );
  633.             return -1;
  634.         }
  635.         psz_filename = (char *)malloc( sizeof("/" CONFIG_DIR "/" CONFIG_FILE) +
  636.                                        strlen(psz_homedir) );
  637.         if( psz_filename )
  638.             sprintf( psz_filename, "%s/" CONFIG_DIR "/" CONFIG_FILE,
  639.                      psz_homedir );
  640.     }
  641.     else
  642.     {
  643.         psz_filename = strdup( psz_configfile );
  644.     }
  645.     if( !psz_filename )
  646.     {
  647.         msg_Err( p_this, "out of memory" );
  648.         return -1;
  649.     }
  650.     msg_Dbg( p_this, "opening config file %s", psz_filename );
  651.     /* Acquire config file lock */
  652.     vlc_mutex_lock( &p_this->p_vlc->config_lock );
  653.     file = fopen( psz_filename, "rt" );
  654.     if( !file )
  655.     {
  656.         msg_Warn( p_this, "config file %s does not exist yet", psz_filename );
  657.         free( psz_filename );
  658.         vlc_mutex_unlock( &p_this->p_vlc->config_lock );
  659.         return -1;
  660.     }
  661.     /* Look for the selected module, if NULL then save everything */
  662.     p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
  663.     for( i_index = 0; i_index < p_list->i_count; i_index++ )
  664.     {
  665.         p_parser = (module_t *)p_list->p_values[i_index].p_object ;
  666.         if( psz_module_name
  667.              && strcmp( psz_module_name, p_parser->psz_object_name ) )
  668.         {
  669.             continue;
  670.         }
  671.         /* The config file is organized in sections, one per module. Look for
  672.          * the interesting section ( a section is of the form [foo] ) */
  673.         fseek( file, 0L, SEEK_SET );
  674.         while( fgets( line, 1024, file ) )
  675.         {
  676.             if( (line[0] == '[')
  677.                && (p_index = strchr(line,']'))
  678.                && (p_index - &line[1]
  679.                     == (int)strlen(p_parser->psz_object_name))
  680.                && !memcmp( &line[1], p_parser->psz_object_name,
  681.                            strlen(p_parser->psz_object_name) ) )
  682.             {
  683. #if 0
  684.                 msg_Dbg( p_this, "loading config for module "%s"",
  685.                                  p_parser->psz_object_name );
  686. #endif
  687.                 break;
  688.             }
  689.         }
  690.         /* either we found the section or we're at the EOF */
  691.         /* Now try to load the options in this section */
  692.         while( fgets( line, 1024, file ) )
  693.         {
  694.             if( line[0] == '[' ) break; /* end of section */
  695.             /* ignore comments or empty lines */
  696.             if( (line[0] == '#') || (line[0] == 'n') || (line[0] == (char)0) )
  697.                 continue;
  698.             /* get rid of line feed */
  699.             if( line[strlen(line)-1] == 'n' )
  700.                 line[strlen(line)-1] = (char)0;
  701.             /* look for option name */
  702.             psz_option_name = line;
  703.             psz_option_value = NULL;
  704.             p_index = strchr( line, '=' );
  705.             if( !p_index ) break; /* this ain't an option!!! */
  706.             *p_index = (char)0;
  707.             psz_option_value = p_index + 1;
  708.             if( !p_parser->i_config_items )
  709.             {
  710.                 continue;
  711.             }
  712.             /* try to match this option with one of the module's options */
  713.             for( p_item = p_parser->p_config;
  714.                  p_item->i_type != CONFIG_HINT_END;
  715.                  p_item++ )
  716.             {
  717.                 if( p_item->i_type & CONFIG_HINT )
  718.                     /* ignore hints */
  719.                     continue;
  720.                 if( !strcmp( p_item->psz_name, psz_option_name ) )
  721.                 {
  722.                     /* We found it */
  723.                     switch( p_item->i_type )
  724.                     {
  725.                     case CONFIG_ITEM_BOOL:
  726.                     case CONFIG_ITEM_INTEGER:
  727.                         if( !*psz_option_value )
  728.                             break;                    /* ignore empty option */
  729.                         p_item->i_value = strtol( psz_option_value, 0, 0 );
  730. #if 0
  731.                         msg_Dbg( p_this, "option "%s", value %i",
  732.                                  p_item->psz_name, p_item->i_value );
  733. #endif
  734.                         break;
  735.                     case CONFIG_ITEM_FLOAT:
  736.                         if( !*psz_option_value )
  737.                             break;                    /* ignore empty option */
  738.                         p_item->f_value = (float)atof( psz_option_value);
  739. #if O
  740.                         msg_Dbg( p_this, "option "%s", value %f",
  741.                                  p_item->psz_name, (double)p_item->f_value );
  742. #endif
  743.                         break;
  744.                     case CONFIG_ITEM_KEY:
  745.                         if( !*psz_option_value )
  746.                             break;                    /* ignore empty option */
  747.                         p_item->i_value = ConfigStringToKey( psz_option_value );
  748.                         break;
  749.                     default:
  750.                         vlc_mutex_lock( p_item->p_lock );
  751.                         /* free old string */
  752.                         if( p_item->psz_value )
  753.                             free( p_item->psz_value );
  754.                         p_item->psz_value = *psz_option_value ?
  755.                             strdup( psz_option_value ) : NULL;
  756.                         vlc_mutex_unlock( p_item->p_lock );
  757. #if 0
  758.                         msg_Dbg( p_this, "option "%s", value "%s"",
  759.                                  p_item->psz_name,
  760.                                  p_item->psz_value ? p_item->psz_value : "" );
  761. #endif
  762.                         break;
  763.                     }
  764.                 }
  765.             }
  766.         }
  767.     }
  768.     vlc_list_release( p_list );
  769.     fclose( file );
  770.     free( psz_filename );
  771.     vlc_mutex_unlock( &p_this->p_vlc->config_lock );
  772.     return 0;
  773. }
  774. /*****************************************************************************
  775.  * config_CreateDir: Create configuration directory if it doesn't exist.
  776.  *****************************************************************************/
  777. int config_CreateDir( vlc_object_t *p_this, char *psz_dirname )
  778. {
  779.     if( !psz_dirname && !*psz_dirname ) return -1;
  780. #if defined( UNDER_CE )
  781.     {
  782.         wchar_t psz_new[ MAX_PATH ];
  783.         char psz_mod[MAX_PATH];
  784.         int i = 0;
  785.         /* Convert '/' into '' */
  786.         while( *psz_dirname )
  787.         {
  788.             if( *psz_dirname == '/' ) psz_mod[i] = '\';
  789.             else psz_mod[i] = *psz_dirname;
  790.             psz_dirname++;
  791.             i++;
  792.         }
  793.         psz_mod[i] = 0;
  794.         MultiByteToWideChar( CP_ACP, 0, psz_mod, -1, psz_new, MAX_PATH );
  795.         if( CreateDirectory( psz_new, NULL ) )
  796.         {
  797.             msg_Err( p_this, "could not create %s", psz_mod );
  798.         }
  799.     }
  800. #else
  801. #   if defined( WIN32 )
  802.     if( mkdir( psz_dirname ) && errno != EEXIST )
  803. #   else
  804.     if( mkdir( psz_dirname, 0755 ) && errno != EEXIST )
  805. #   endif
  806.     {
  807.         msg_Err( p_this, "could not create %s (%s)",
  808.                  psz_dirname, strerror(errno) );
  809.     }
  810. #endif
  811.     return 0;
  812. }
  813. /*****************************************************************************
  814.  * config_SaveConfigFile: Save a module's config options.
  815.  *****************************************************************************
  816.  * This will save the specified module's config options to the config file.
  817.  * If psz_module_name is NULL then we save all the modules config options.
  818.  * It's no use to save the config options that kept their default values, so
  819.  * we'll try to be a bit clever here.
  820.  *
  821.  * When we save we mustn't delete the config options of the modules that
  822.  * haven't been loaded. So we cannot just create a new config file with the
  823.  * config structures we've got in memory.
  824.  * I don't really know how to deal with this nicely, so I will use a completly
  825.  * dumb method ;-)
  826.  * I will load the config file in memory, but skipping all the sections of the
  827.  * modules we want to save. Then I will create a brand new file, dump the file
  828.  * loaded in memory and then append the sections of the modules we want to
  829.  * save.
  830.  * Really stupid no ?
  831.  *****************************************************************************/
  832. int __config_SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name )
  833. {
  834.     module_t *p_parser;
  835.     vlc_list_t *p_list;
  836.     module_config_t *p_item;
  837.     FILE *file;
  838.     char p_line[1024], *p_index2;
  839.     int i_sizebuf = 0;
  840.     char *p_bigbuffer, *p_index;
  841.     vlc_bool_t b_backup;
  842.     char *psz_filename, *psz_homedir, *psz_configfile;
  843.     int i_index;
  844.     /* Acquire config file lock */
  845.     vlc_mutex_lock( &p_this->p_vlc->config_lock );
  846.     psz_configfile = p_this->p_vlc->psz_configfile;
  847.     if( !psz_configfile || !psz_configfile )
  848.     {
  849.         psz_homedir = p_this->p_vlc->psz_homedir;
  850.         if( !psz_homedir )
  851.         {
  852.             msg_Err( p_this, "psz_homedir is null" );
  853.             vlc_mutex_unlock( &p_this->p_vlc->config_lock );
  854.             return -1;
  855.         }
  856.         psz_filename = (char *)malloc( sizeof("/" CONFIG_DIR "/" CONFIG_FILE) +
  857.                                        strlen(psz_homedir) );
  858.         if( psz_filename )
  859.             sprintf( psz_filename, "%s/" CONFIG_DIR, psz_homedir );
  860.         if( !psz_filename )
  861.         {
  862.             msg_Err( p_this, "out of memory" );
  863.             vlc_mutex_unlock( &p_this->p_vlc->config_lock );
  864.             return -1;
  865.         }
  866.         config_CreateDir( p_this, psz_filename );
  867.         strcat( psz_filename, "/" CONFIG_FILE );
  868.     }
  869.     else
  870.     {
  871.         psz_filename = strdup( psz_configfile );
  872.         if( !psz_filename )
  873.         {
  874.             msg_Err( p_this, "out of memory" );
  875.             vlc_mutex_unlock( &p_this->p_vlc->config_lock );
  876.             return -1;
  877.         }
  878.     }
  879.     msg_Dbg( p_this, "opening config file %s", psz_filename );
  880.     file = fopen( psz_filename, "rt" );
  881.     if( !file )
  882.     {
  883.         msg_Warn( p_this, "config file %s does not exist yet", psz_filename );
  884.     }
  885.     else
  886.     {
  887.         /* look for file size */
  888.         fseek( file, 0L, SEEK_END );
  889.         i_sizebuf = ftell( file );
  890.         fseek( file, 0L, SEEK_SET );
  891.     }
  892.     p_bigbuffer = p_index = malloc( i_sizebuf+1 );
  893.     if( !p_bigbuffer )
  894.     {
  895.         msg_Err( p_this, "out of memory" );
  896.         if( file ) fclose( file );
  897.         free( psz_filename );
  898.         vlc_mutex_unlock( &p_this->p_vlc->config_lock );
  899.         return -1;
  900.     }
  901.     p_bigbuffer[0] = 0;
  902.     /* List all available modules */
  903.     p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
  904.     /* backup file into memory, we only need to backup the sections we won't
  905.      * save later on */
  906.     b_backup = 0;
  907.     while( file && fgets( p_line, 1024, file ) )
  908.     {
  909.         if( (p_line[0] == '[') && (p_index2 = strchr(p_line,']')))
  910.         {
  911.             /* we found a section, check if we need to do a backup */
  912.             for( i_index = 0; i_index < p_list->i_count; i_index++ )
  913.             {
  914.                 p_parser = (module_t *)p_list->p_values[i_index].p_object ;
  915.                 if( ((p_index2 - &p_line[1])
  916.                        == (int)strlen(p_parser->psz_object_name) )
  917.                     && !memcmp( &p_line[1], p_parser->psz_object_name,
  918.                                 strlen(p_parser->psz_object_name) ) )
  919.                 {
  920.                     if( !psz_module_name )
  921.                         break;
  922.                     else if( !strcmp( psz_module_name,
  923.                                       p_parser->psz_object_name ) )
  924.                         break;
  925.                 }
  926.             }
  927.             if( i_index == p_list->i_count )
  928.             {
  929.                 /* we don't have this section in our list so we need to back
  930.                  * it up */
  931.                 *p_index2 = 0;
  932.                 msg_Dbg( p_this, "backing up config for unknown module "%s"",
  933.                                  &p_line[1] );
  934.                 *p_index2 = ']';
  935.                 b_backup = 1;
  936.             }
  937.             else
  938.             {
  939.                 b_backup = 0;
  940.             }
  941.         }
  942.         /* save line if requested and line is valid (doesn't begin with a
  943.          * space, tab, or eol) */
  944.         if( b_backup && (p_line[0] != 'n') && (p_line[0] != ' ')
  945.             && (p_line[0] != 't') )
  946.         {
  947.             strcpy( p_index, p_line );
  948.             p_index += strlen( p_line );
  949.         }
  950.     }
  951.     if( file ) fclose( file );
  952.     /*
  953.      * Save module config in file
  954.      */
  955.     file = fopen( psz_filename, "wt" );
  956.     if( !file )
  957.     {
  958.         msg_Warn( p_this, "could not open config file %s for writing",
  959.                           psz_filename );
  960.         free( psz_filename );
  961.         vlc_list_release( p_list );
  962.         vlc_mutex_unlock( &p_this->p_vlc->config_lock );
  963.         return -1;
  964.     }
  965.     fprintf( file, "###n###  " COPYRIGHT_MESSAGE "n###nn" );
  966.     /* Look for the selected module, if NULL then save everything */
  967.     for( i_index = 0; i_index < p_list->i_count; i_index++ )
  968.     {
  969.         p_parser = (module_t *)p_list->p_values[i_index].p_object ;
  970.         if( psz_module_name && strcmp( psz_module_name,
  971.                                        p_parser->psz_object_name ) )
  972.             continue;
  973.         if( !p_parser->i_config_items )
  974.             continue;
  975.         msg_Dbg( p_this, "saving config for module "%s"",
  976.                          p_parser->psz_object_name );
  977.         fprintf( file, "[%s]", p_parser->psz_object_name );
  978.         if( p_parser->psz_longname )
  979.             fprintf( file, " # %snn", p_parser->psz_longname );
  980.         else
  981.             fprintf( file, "nn" );
  982.         for( p_item = p_parser->p_config;
  983.              p_item->i_type != CONFIG_HINT_END;
  984.              p_item++ )
  985.         {
  986.             char *psz_key;
  987.             if( p_item->i_type & CONFIG_HINT )
  988.                 /* ignore hints */
  989.                 continue;
  990.             switch( p_item->i_type )
  991.             {
  992.             case CONFIG_ITEM_BOOL:
  993.             case CONFIG_ITEM_INTEGER:
  994.                 if( p_item->psz_text )
  995.                     fprintf( file, "# %s (%s)n", p_item->psz_text,
  996.                              (p_item->i_type == CONFIG_ITEM_BOOL) ?
  997.                              _("boolean") : _("integer") );
  998.                 if( p_item->i_value == p_item->i_value_orig )
  999.                     fprintf( file, "#" );
  1000.                 fprintf( file, "%s=%in", p_item->psz_name, p_item->i_value );
  1001.                 break;
  1002.             case CONFIG_ITEM_KEY:
  1003.                 if( p_item->psz_text )
  1004.                     fprintf( file, "# %s (%s)n", p_item->psz_text,
  1005.                              _("key") );
  1006.                 if( p_item->i_value == p_item->i_value_orig )
  1007.                     fprintf( file, "#" );
  1008.                 psz_key = ConfigKeyToString( p_item->i_value );
  1009.                 fprintf( file, "%s=%sn", p_item->psz_name,
  1010.                          psz_key ? psz_key : "" );
  1011.                 if ( psz_key ) free( psz_key );
  1012.                 break;
  1013.             case CONFIG_ITEM_FLOAT:
  1014.                 if( p_item->psz_text )
  1015.                     fprintf( file, "# %s (%s)n", p_item->psz_text,
  1016.                              _("float") );
  1017.                 if( p_item->f_value == p_item->f_value_orig )
  1018.                     fprintf( file, "#" );
  1019.                 fprintf( file, "%s=%fn", p_item->psz_name,
  1020.                          (double)p_item->f_value );
  1021.                 break;
  1022.             default:
  1023.                 if( p_item->psz_text )
  1024.                     fprintf( file, "# %s (%s)n", p_item->psz_text,
  1025.                              _("string") );
  1026.                 if( (!p_item->psz_value && !p_item->psz_value_orig) ||
  1027.                     (p_item->psz_value && p_item->psz_value_orig &&
  1028.                      !strcmp( p_item->psz_value, p_item->psz_value_orig )) )
  1029.                     fprintf( file, "#" );
  1030.                 fprintf( file, "%s=%sn", p_item->psz_name,
  1031.                          p_item->psz_value ? p_item->psz_value : "" );
  1032.             }
  1033.         }
  1034.         fprintf( file, "n" );
  1035.     }
  1036.     vlc_list_release( p_list );
  1037.     /*
  1038.      * Restore old settings from the config in file
  1039.      */
  1040.     fputs( p_bigbuffer, file );
  1041.     free( p_bigbuffer );
  1042.     fclose( file );
  1043.     free( psz_filename );
  1044.     vlc_mutex_unlock( &p_this->p_vlc->config_lock );
  1045.     return 0;
  1046. }
  1047. /*****************************************************************************
  1048.  * config_LoadCmdLine: parse command line
  1049.  *****************************************************************************
  1050.  * Parse command line for configuration options.
  1051.  * Now that the module_bank has been initialized, we can dynamically
  1052.  * generate the longopts structure used by getops. We have to do it this way
  1053.  * because we don't know (and don't want to know) in advance the configuration
  1054.  * options used (ie. exported) by each module.
  1055.  *****************************************************************************/
  1056. int __config_LoadCmdLine( vlc_object_t *p_this, int *pi_argc, char *ppsz_argv[],
  1057.                           vlc_bool_t b_ignore_errors )
  1058. {
  1059.     int i_cmd, i_index, i_opts, i_shortopts, flag, i_verbose = 0;
  1060.     module_t *p_parser;
  1061.     vlc_list_t *p_list;
  1062.     module_config_t *p_item;
  1063.     struct option *p_longopts;
  1064.     int i_modules_index;
  1065.     /* Short options */
  1066.     module_config_t *pp_shortopts[256];
  1067.     char *psz_shortopts;
  1068.     /* Set default configuration and copy arguments */
  1069.     p_this->p_vlc->i_argc    = *pi_argc;
  1070.     p_this->p_vlc->ppsz_argv = ppsz_argv;
  1071. #ifdef SYS_DARWIN
  1072.     /* When vlc.app is run by double clicking in Mac OS X, the 2nd arg
  1073.      * is the PSN - process serial number (a unique PID-ish thingie)
  1074.      * still ok for real Darwin & when run from command line */
  1075.     if ( (*pi_argc > 1) && (strncmp( ppsz_argv[ 1 ] , "-psn" , 4 ) == 0) )
  1076.                                         /* for example -psn_0_9306113 */
  1077.     {
  1078.         /* GDMF!... I can't do this or else the MacOSX window server will
  1079.          * not pick up the PSN and not register the app and we crash...
  1080.          * hence the following kludge otherwise we'll get confused w/ argv[1]
  1081.          * being an input file name */
  1082. #if 0
  1083.         ppsz_argv[ 1 ] = NULL;
  1084. #endif
  1085.         *pi_argc = *pi_argc - 1;
  1086.         pi_argc--;
  1087.         return 0;
  1088.     }
  1089. #endif
  1090.     /* List all modules */
  1091.     p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
  1092.     /*
  1093.      * Generate the longopts and shortopts structures used by getopt_long
  1094.      */
  1095.     i_opts = 0;
  1096.     for( i_modules_index = 0; i_modules_index < p_list->i_count;
  1097.          i_modules_index++ )
  1098.     {
  1099.         p_parser = (module_t *)p_list->p_values[i_modules_index].p_object ;
  1100.         /* count the number of exported configuration options (to allocate
  1101.          * longopts). We also need to allocate space for too options when
  1102.          * dealing with boolean to allow for --foo and --no-foo */
  1103.         i_opts += p_parser->i_config_items
  1104.                      + 2 * p_parser->i_bool_items;
  1105.     }
  1106.     p_longopts = malloc( sizeof(struct option) * (i_opts + 1) );
  1107.     if( p_longopts == NULL )
  1108.     {
  1109.         msg_Err( p_this, "out of memory" );
  1110.         vlc_list_release( p_list );
  1111.         return -1;
  1112.     }
  1113.     psz_shortopts = malloc( sizeof( char ) * (2 * i_opts + 1) );
  1114.     if( psz_shortopts == NULL )
  1115.     {
  1116.         msg_Err( p_this, "out of memory" );
  1117.         free( p_longopts );
  1118.         vlc_list_release( p_list );
  1119.         return -1;
  1120.     }
  1121.     /* If we are requested to ignore errors, then we must work on a copy
  1122.      * of the ppsz_argv array, otherwise getopt_long will reorder it for
  1123.      * us, ignoring the arity of the options */
  1124.     if( b_ignore_errors )
  1125.     {
  1126.         ppsz_argv = (char**)malloc( *pi_argc * sizeof(char *) );
  1127.         if( ppsz_argv == NULL )
  1128.         {
  1129.             msg_Err( p_this, "out of memory" );
  1130.             free( psz_shortopts );
  1131.             free( p_longopts );
  1132.             vlc_list_release( p_list );
  1133.             return -1;
  1134.         }
  1135.         memcpy( ppsz_argv, p_this->p_vlc->ppsz_argv,
  1136.                 *pi_argc * sizeof(char *) );
  1137.     }
  1138.     i_shortopts = 0;
  1139.     for( i_index = 0; i_index < 256; i_index++ )
  1140.     {
  1141.         pp_shortopts[i_index] = NULL;
  1142.     }
  1143.     /* Fill the p_longopts and psz_shortopts structures */
  1144.     i_index = 0;
  1145.     for( i_modules_index = 0; i_modules_index < p_list->i_count;
  1146.          i_modules_index++ )
  1147.     {
  1148.         p_parser = (module_t *)p_list->p_values[i_modules_index].p_object ;
  1149.         if( !p_parser->i_config_items )
  1150.             continue;
  1151.         for( p_item = p_parser->p_config;
  1152.              p_item->i_type != CONFIG_HINT_END;
  1153.              p_item++ )
  1154.         {
  1155.             /* Ignore hints */
  1156.             if( p_item->i_type & CONFIG_HINT )
  1157.                 continue;
  1158.             /* Add item to long options */
  1159.             p_longopts[i_index].name = strdup( p_item->psz_name );
  1160.             if( p_longopts[i_index].name == NULL ) continue;
  1161.             p_longopts[i_index].has_arg =
  1162.                 (p_item->i_type == CONFIG_ITEM_BOOL)?
  1163.                                                no_argument : required_argument;
  1164.             p_longopts[i_index].flag = &flag;
  1165.             p_longopts[i_index].val = 0;
  1166.             i_index++;
  1167.             /* When dealing with bools we also need to add the --no-foo
  1168.              * option */
  1169.             if( p_item->i_type == CONFIG_ITEM_BOOL )
  1170.             {
  1171.                 char *psz_name = malloc( strlen(p_item->psz_name) + 3 );
  1172.                 if( psz_name == NULL ) continue;
  1173.                 strcpy( psz_name, "no" );
  1174.                 strcat( psz_name, p_item->psz_name );
  1175.                 p_longopts[i_index].name = psz_name;
  1176.                 p_longopts[i_index].has_arg = no_argument;
  1177.                 p_longopts[i_index].flag = &flag;
  1178.                 p_longopts[i_index].val = 1;
  1179.                 i_index++;
  1180.                 psz_name = malloc( strlen(p_item->psz_name) + 4 );
  1181.                 if( psz_name == NULL ) continue;
  1182.                 strcpy( psz_name, "no-" );
  1183.                 strcat( psz_name, p_item->psz_name );
  1184.                 p_longopts[i_index].name = psz_name;
  1185.                 p_longopts[i_index].has_arg = no_argument;
  1186.                 p_longopts[i_index].flag = &flag;
  1187.                 p_longopts[i_index].val = 1;
  1188.                 i_index++;
  1189.             }
  1190.             /* If item also has a short option, add it */
  1191.             if( p_item->i_short )
  1192.             {
  1193.                 pp_shortopts[(int)p_item->i_short] = p_item;
  1194.                 psz_shortopts[i_shortopts] = p_item->i_short;
  1195.                 i_shortopts++;
  1196.                 if( p_item->i_type != CONFIG_ITEM_BOOL )
  1197.                 {
  1198.                     psz_shortopts[i_shortopts] = ':';
  1199.                     i_shortopts++;
  1200.                     if( p_item->i_short == 'v' )
  1201.                     {
  1202.                         psz_shortopts[i_shortopts] = ':';
  1203.                         i_shortopts++;
  1204.                     }
  1205.                 }
  1206.             }
  1207.         }
  1208.     }
  1209.     /* We don't need the module list anymore */
  1210.     vlc_list_release( p_list );
  1211.     /* Close the longopts and shortopts structures */
  1212.     memset( &p_longopts[i_index], 0, sizeof(struct option) );
  1213.     psz_shortopts[i_shortopts] = '';
  1214.     /*
  1215.      * Parse the command line options
  1216.      */
  1217.     opterr = 0;
  1218.     optind = 1;
  1219.     while( ( i_cmd = getopt_long( *pi_argc, ppsz_argv, psz_shortopts,
  1220.                                   p_longopts, &i_index ) ) != EOF )
  1221.     {
  1222.         /* A long option has been recognized */
  1223.         if( i_cmd == 0 )
  1224.         {
  1225.             module_config_t *p_conf;
  1226.             char *psz_name = (char *)p_longopts[i_index].name;
  1227.             /* Check if we deal with a --nofoo or --no-foo long option */
  1228.             if( flag ) psz_name += psz_name[2] == '-' ? 3 : 2;
  1229.             /* Store the configuration option */
  1230.             p_conf = config_FindConfig( p_this, psz_name );
  1231.             if( p_conf ) switch( p_conf->i_type )
  1232.             {
  1233.             case CONFIG_ITEM_STRING:
  1234.             case CONFIG_ITEM_FILE:
  1235.             case CONFIG_ITEM_DIRECTORY:
  1236.             case CONFIG_ITEM_MODULE:
  1237.                 config_PutPsz( p_this, psz_name, optarg );
  1238.                 break;
  1239.             case CONFIG_ITEM_INTEGER:
  1240.                 config_PutInt( p_this, psz_name, strtol(optarg, 0, 0));
  1241.                 break;
  1242.             case CONFIG_ITEM_FLOAT:
  1243.                 config_PutFloat( p_this, psz_name, (float)atof(optarg) );
  1244.                 break;
  1245.             case CONFIG_ITEM_KEY:
  1246.                 config_PutInt( p_this, psz_name, ConfigStringToKey( optarg ) );
  1247.                 break;
  1248.             case CONFIG_ITEM_BOOL:
  1249.                 config_PutInt( p_this, psz_name, !flag );
  1250.                 break;
  1251.             }
  1252.             continue;
  1253.         }
  1254.         /* A short option has been recognized */
  1255.         if( pp_shortopts[i_cmd] != NULL )
  1256.         {
  1257.             switch( pp_shortopts[i_cmd]->i_type )
  1258.             {
  1259.             case CONFIG_ITEM_STRING:
  1260.             case CONFIG_ITEM_FILE:
  1261.             case CONFIG_ITEM_DIRECTORY:
  1262.             case CONFIG_ITEM_MODULE:
  1263.                 config_PutPsz( p_this, pp_shortopts[i_cmd]->psz_name, optarg );
  1264.                 break;
  1265.             case CONFIG_ITEM_INTEGER:
  1266.                 if( i_cmd == 'v' )
  1267.                 {
  1268.                     if( optarg )
  1269.                     {
  1270.                         if( *optarg == 'v' ) /* eg. -vvv */
  1271.                         {
  1272.                             i_verbose++;
  1273.                             while( *optarg == 'v' )
  1274.                             {
  1275.                                 i_verbose++;
  1276.                                 optarg++;
  1277.                             }
  1278.                         }
  1279.                         else
  1280.                         {
  1281.                             i_verbose += atoi( optarg ); /* eg. -v2 */
  1282.                         }
  1283.                     }
  1284.                     else
  1285.                     {
  1286.                         i_verbose++; /* -v */
  1287.                     }
  1288.                     config_PutInt( p_this, pp_shortopts[i_cmd]->psz_name,
  1289.                                            i_verbose );
  1290.                 }
  1291.                 else
  1292.                 {
  1293.                     config_PutInt( p_this, pp_shortopts[i_cmd]->psz_name,
  1294.                                            strtol(optarg, 0, 0) );
  1295.                 }
  1296.                 break;
  1297.             case CONFIG_ITEM_BOOL:
  1298.                 config_PutInt( p_this, pp_shortopts[i_cmd]->psz_name, 1 );
  1299.                 break;
  1300.             }
  1301.             continue;
  1302.         }
  1303.         /* Internal error: unknown option */
  1304.         if( !b_ignore_errors )
  1305.         {
  1306.             fprintf( stderr, "%s: unknown option ",
  1307.                              p_this->p_vlc->psz_object_name );
  1308.             if( optopt )
  1309.             {
  1310.                 fprintf( stderr, "`-%c'n", optopt );
  1311.             }
  1312.             else
  1313.             {
  1314.                 fprintf( stderr, "`%s'n", ppsz_argv[optind-1] );
  1315.             }
  1316.             fprintf( stderr, "Try `%s --help' for more information.n",
  1317.                              p_this->p_vlc->psz_object_name );
  1318.             free( p_longopts );
  1319.             free( psz_shortopts );
  1320.             return -1;
  1321.         }
  1322.     }
  1323.     /* Free allocated resources */
  1324.     for( i_index = 0; p_longopts[i_index].name; i_index++ )
  1325.         free( (char *)p_longopts[i_index].name );
  1326.     free( p_longopts );
  1327.     free( psz_shortopts );
  1328.     if( b_ignore_errors ) free( ppsz_argv );
  1329.     return 0;
  1330. }
  1331. /*****************************************************************************
  1332.  * config_GetHomeDir: find the user's home directory.
  1333.  *****************************************************************************
  1334.  * This function will try by different ways to find the user's home path.
  1335.  * Note that this function is not reentrant, it should be called only once
  1336.  * at the beginning of main where the result will be stored for later use.
  1337.  *****************************************************************************/
  1338. char *config_GetHomeDir( void )
  1339. {
  1340.     char *p_tmp, *p_homedir = NULL;
  1341. #if defined(HAVE_GETPWUID)
  1342.     struct passwd *p_pw = NULL;
  1343. #endif
  1344. #if defined(WIN32) && !defined(UNDER_CE)
  1345.     typedef HRESULT (WINAPI *SHGETFOLDERPATH)( HWND, int, HANDLE, DWORD,
  1346.                                                LPSTR );
  1347. #ifndef CSIDL_FLAG_CREATE
  1348. #   define CSIDL_FLAG_CREATE 0x8000
  1349. #endif
  1350. #ifndef CSIDL_APPDATA
  1351. #   define CSIDL_APPDATA 0x1A
  1352. #endif
  1353. #ifndef SHGFP_TYPE_CURRENT
  1354. #   define SHGFP_TYPE_CURRENT 0
  1355. #endif
  1356.     HINSTANCE shfolder_dll;
  1357.     SHGETFOLDERPATH SHGetFolderPath ;
  1358.     /* load the shfolder dll to retrieve SHGetFolderPath */
  1359.     if( ( shfolder_dll = LoadLibrary( _T("SHFolder.dll") ) ) != NULL )
  1360.     {
  1361.         SHGetFolderPath = (void *)GetProcAddress( shfolder_dll,
  1362.                                                   _T("SHGetFolderPathA") );
  1363.         if ( SHGetFolderPath != NULL )
  1364.         {
  1365.             p_homedir = (char *)malloc( MAX_PATH );
  1366.             if( !p_homedir ) return NULL;
  1367.             /* get the "Application Data" folder for the current user */
  1368.             if( S_OK == SHGetFolderPath( NULL,
  1369.                                          CSIDL_APPDATA | CSIDL_FLAG_CREATE,
  1370.                                          NULL, SHGFP_TYPE_CURRENT,
  1371.                                          p_homedir ) )
  1372.             {
  1373.                 FreeLibrary( shfolder_dll );
  1374.                 return p_homedir;
  1375.             }
  1376.             free( p_homedir );
  1377.             p_homedir = NULL;
  1378.         }
  1379.         FreeLibrary( shfolder_dll );
  1380.     }
  1381. #elif defined(UNDER_CE)
  1382.     wchar_t p_whomedir[MAX_PATH];
  1383.     /* get the "Application Data" folder for the current user */
  1384.     if( SHGetSpecialFolderPath( NULL, p_whomedir, CSIDL_APPDATA, 1 ) )
  1385.     {
  1386.         p_homedir = (char *)malloc( MAX_PATH );
  1387.         if( !p_homedir ) return NULL;
  1388.         sprintf( p_homedir, "%ls", p_whomedir );
  1389.         return p_homedir;
  1390.     }
  1391. #endif
  1392. #if defined(HAVE_GETPWUID)
  1393.     if( ( p_pw = getpwuid( getuid() ) ) == NULL )
  1394. #endif
  1395.     {
  1396.         if( ( p_tmp = getenv( "HOME" ) ) == NULL )
  1397.         {
  1398.             if( ( p_tmp = getenv( "TMP" ) ) == NULL )
  1399.             {
  1400.                 p_tmp = "/tmp";
  1401.             }
  1402.         }
  1403.         p_homedir = strdup( p_tmp );
  1404.     }
  1405. #if defined(HAVE_GETPWUID)
  1406.     else
  1407.     {
  1408.         p_homedir = strdup( p_pw->pw_dir );
  1409.     }
  1410. #endif
  1411.     return p_homedir;
  1412. }
  1413. static int ConfigStringToKey( char *psz_key )
  1414. {
  1415.     int i_key = 0;
  1416.     unsigned int i;
  1417.     char *psz_parser = strchr( psz_key, '-' );
  1418.     while( psz_parser && psz_parser != psz_key )
  1419.     {
  1420.         for( i = 0; i < sizeof(vlc_modifiers) / sizeof(key_descriptor_t); i++ )
  1421.         {
  1422.             if( !strncasecmp( vlc_modifiers[i].psz_key_string, psz_key,
  1423.                               strlen( vlc_modifiers[i].psz_key_string ) ) )
  1424.             {
  1425.                 i_key |= vlc_modifiers[i].i_key_code;
  1426.             }
  1427.         }
  1428.         psz_key = psz_parser + 1;
  1429.         psz_parser = strchr( psz_key, '-' );
  1430.     }
  1431.     for( i = 0; i < sizeof(vlc_keys) / sizeof( key_descriptor_t ); i++ )
  1432.     {
  1433.         if( !strcasecmp( vlc_keys[i].psz_key_string, psz_key ) )
  1434.         {
  1435.             i_key |= vlc_keys[i].i_key_code;
  1436.             break;
  1437.         }
  1438.     }
  1439.     return i_key;
  1440. }
  1441. static char *ConfigKeyToString( int i_key )
  1442. {
  1443.     char *psz_key = malloc( 100 );
  1444.     char *p;
  1445.     size_t index;
  1446.     if ( !psz_key )
  1447.     {
  1448.         return NULL;
  1449.     }
  1450.     *psz_key = '';
  1451.     p = psz_key;
  1452.     for( index = 0; index < (sizeof(vlc_modifiers) / sizeof(key_descriptor_t));
  1453.          index++ )
  1454.     {
  1455.         if( i_key & vlc_modifiers[index].i_key_code )
  1456.         {
  1457.             p += sprintf( p, "%s-", vlc_modifiers[index].psz_key_string );
  1458.         }
  1459.     }
  1460.     for( index = 0; index < (sizeof(vlc_keys) / sizeof( key_descriptor_t));
  1461.          index++)
  1462.     {
  1463.         if( (int)( i_key & ~KEY_MODIFIER ) == vlc_keys[index].i_key_code )
  1464.         {
  1465.             p += sprintf( p, "%s", vlc_keys[index].psz_key_string );
  1466.             break;
  1467.         }
  1468.     }
  1469.     return psz_key;
  1470. }