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