configuration.c 43.9 KB
Newer Older
gbazin's avatar
 
gbazin committed
1
2
3
4
/*****************************************************************************
 * configuration.c management of the modules configuration
 *****************************************************************************
 * Copyright (C) 2001 VideoLAN
5
 * $Id: configuration.c,v 1.55 2003/05/09 00:58:25 titer Exp $
gbazin's avatar
 
gbazin committed
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 *
 * Authors: Gildas Bazin <gbazin@netcourrier.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
 *****************************************************************************/
Sam Hocevar's avatar
   
Sam Hocevar committed
23

24
#include <vlc/vlc.h>
gbazin's avatar
   
gbazin committed
25

gbazin's avatar
 
gbazin committed
26
#include <stdio.h>                                              /* sprintf() */
gbazin's avatar
   
gbazin committed
27
#include <stdlib.h>                                      /* free(), strtol() */
gbazin's avatar
 
gbazin committed
28
#include <string.h>                                              /* strdup() */
29
30
31
#ifdef HAVE_ERRNO_H
#   include <errno.h>                                               /* errno */
#endif
gbazin's avatar
 
gbazin committed
32

gbazin's avatar
   
gbazin committed
33
34
35
#ifdef HAVE_UNISTD_H
#    include <unistd.h>                                          /* getuid() */
#endif
gbazin's avatar
 
gbazin committed
36

gbazin's avatar
   
gbazin committed
37
38
39
40
41
#ifdef HAVE_GETOPT_LONG
#   ifdef HAVE_GETOPT_H
#       include <getopt.h>                                       /* getopt() */
#   endif
#else
42
#   include "../extras/getopt.h"
gbazin's avatar
   
gbazin committed
43
44
45
#endif

#if defined(HAVE_GETPWUID)
46
#   include <pwd.h>                                            /* getpwuid() */
gbazin's avatar
   
gbazin committed
47
48
#endif

49
50
51
52
53
54
#if defined( HAVE_SYS_STAT_H )
#   include <sys/stat.h>
#endif
#if defined( HAVE_SYS_TYPES_H )
#   include <sys/types.h>
#endif
55
56
57
#if defined( WIN32 ) && !defined( UNDER_CE )
#   include <direct.h>
#endif
gbazin's avatar
   
gbazin committed
58

gbazin's avatar
 
gbazin committed
59
/*****************************************************************************
60
 * config_GetInt: get the value of an int variable
gbazin's avatar
 
gbazin committed
61
62
 *****************************************************************************
 * This function is used to get the value of variables which are internally
gbazin's avatar
   
gbazin committed
63
64
 * represented by an integer (CONFIG_ITEM_INTEGER and
 * CONFIG_ITEM_BOOL).
gbazin's avatar
 
gbazin committed
65
 *****************************************************************************/
66
int __config_GetInt( vlc_object_t *p_this, const char *psz_name )
gbazin's avatar
 
gbazin committed
67
68
69
{
    module_config_t *p_config;

70
    p_config = config_FindConfig( p_this, psz_name );
gbazin's avatar
 
gbazin committed
71
72
73
74

    /* sanity checks */
    if( !p_config )
    {
75
        msg_Err( p_this, "option %s does not exist", psz_name );
gbazin's avatar
 
gbazin committed
76
77
        return -1;
    }
gbazin's avatar
   
gbazin committed
78
79
    if( (p_config->i_type!=CONFIG_ITEM_INTEGER) &&
        (p_config->i_type!=CONFIG_ITEM_BOOL) )
gbazin's avatar
 
gbazin committed
80
    {
81
        msg_Err( p_this, "option %s does not refer to an int", psz_name );
gbazin's avatar
 
gbazin committed
82
83
84
85
86
87
        return -1;
    }

    return p_config->i_value;
}

gbazin's avatar
   
gbazin committed
88
/*****************************************************************************
89
 * config_GetFloat: get the value of a float variable
gbazin's avatar
   
gbazin committed
90
91
 *****************************************************************************
 * This function is used to get the value of variables which are internally
gbazin's avatar
   
gbazin committed
92
 * represented by a float (CONFIG_ITEM_FLOAT).
gbazin's avatar
   
gbazin committed
93
 *****************************************************************************/
94
float __config_GetFloat( vlc_object_t *p_this, const char *psz_name )
gbazin's avatar
   
gbazin committed
95
96
97
{
    module_config_t *p_config;

98
    p_config = config_FindConfig( p_this, psz_name );
gbazin's avatar
   
gbazin committed
99
100
101
102

    /* sanity checks */
    if( !p_config )
    {
103
        msg_Err( p_this, "option %s does not exist", psz_name );
gbazin's avatar
   
gbazin committed
104
105
        return -1;
    }
gbazin's avatar
   
gbazin committed
106
    if( p_config->i_type != CONFIG_ITEM_FLOAT )
gbazin's avatar
   
gbazin committed
107
    {
108
        msg_Err( p_this, "option %s does not refer to a float", psz_name );
gbazin's avatar
   
gbazin committed
109
110
111
112
113
114
        return -1;
    }

    return p_config->f_value;
}

gbazin's avatar
 
gbazin committed
115
/*****************************************************************************
116
 * config_GetPsz: get the string value of a string variable
gbazin's avatar
 
gbazin committed
117
118
 *****************************************************************************
 * This function is used to get the value of variables which are internally
gbazin's avatar
   
gbazin committed
119
 * represented by a string (CONFIG_ITEM_STRING, CONFIG_ITEM_FILE,
gbazin's avatar
   
gbazin committed
120
 * CONFIG_ITEM_DIRECTORY, and CONFIG_ITEM_MODULE).
gbazin's avatar
 
gbazin committed
121
 *
gbazin's avatar
   
gbazin committed
122
123
124
 * Important note: remember to free() the returned char* because it's a
 *   duplicate of the actual value. It isn't safe to return a pointer to the
 *   actual value as it can be modified at any time.
gbazin's avatar
 
gbazin committed
125
 *****************************************************************************/
126
char * __config_GetPsz( vlc_object_t *p_this, const char *psz_name )
gbazin's avatar
 
gbazin committed
127
128
129
130
{
    module_config_t *p_config;
    char *psz_value = NULL;

131
    p_config = config_FindConfig( p_this, psz_name );
gbazin's avatar
 
gbazin committed
132
133
134
135

    /* sanity checks */
    if( !p_config )
    {
136
        msg_Err( p_this, "option %s does not exist", psz_name );
gbazin's avatar
 
gbazin committed
137
138
        return NULL;
    }
gbazin's avatar
   
gbazin committed
139
140
    if( (p_config->i_type!=CONFIG_ITEM_STRING) &&
        (p_config->i_type!=CONFIG_ITEM_FILE) &&
gbazin's avatar
   
gbazin committed
141
        (p_config->i_type!=CONFIG_ITEM_DIRECTORY) &&
gbazin's avatar
   
gbazin committed
142
        (p_config->i_type!=CONFIG_ITEM_MODULE) )
gbazin's avatar
 
gbazin committed
143
    {
144
        msg_Err( p_this, "option %s does not refer to a string", psz_name );
gbazin's avatar
 
gbazin committed
145
146
147
148
        return NULL;
    }

    /* return a copy of the string */
gbazin's avatar
   
gbazin committed
149
    vlc_mutex_lock( p_config->p_lock );
gbazin's avatar
 
gbazin committed
150
    if( p_config->psz_value ) psz_value = strdup( p_config->psz_value );
gbazin's avatar
   
gbazin committed
151
    vlc_mutex_unlock( p_config->p_lock );
gbazin's avatar
 
gbazin committed
152
153
154
155
156

    return psz_value;
}

/*****************************************************************************
157
 * config_PutPsz: set the string value of a string variable
gbazin's avatar
 
gbazin committed
158
159
 *****************************************************************************
 * This function is used to set the value of variables which are internally
gbazin's avatar
   
gbazin committed
160
 * represented by a string (CONFIG_ITEM_STRING, CONFIG_ITEM_FILE,
gbazin's avatar
   
gbazin committed
161
 * CONFIG_ITEM_DIRECTORY, and CONFIG_ITEM_MODULE).
gbazin's avatar
 
gbazin committed
162
 *****************************************************************************/
163
void __config_PutPsz( vlc_object_t *p_this,
164
                      const char *psz_name, const char *psz_value )
gbazin's avatar
 
gbazin committed
165
166
167
{
    module_config_t *p_config;

168
    p_config = config_FindConfig( p_this, psz_name );
gbazin's avatar
 
gbazin committed
169
170
171
172

    /* sanity checks */
    if( !p_config )
    {
173
        msg_Warn( p_this, "option %s does not exist", psz_name );
gbazin's avatar
 
gbazin committed
174
175
        return;
    }
gbazin's avatar
   
gbazin committed
176
177
    if( (p_config->i_type!=CONFIG_ITEM_STRING) &&
        (p_config->i_type!=CONFIG_ITEM_FILE) &&
gbazin's avatar
   
gbazin committed
178
        (p_config->i_type!=CONFIG_ITEM_DIRECTORY) &&
gbazin's avatar
   
gbazin committed
179
        (p_config->i_type!=CONFIG_ITEM_MODULE) )
gbazin's avatar
 
gbazin committed
180
    {
181
        msg_Err( p_this, "option %s does not refer to a string", psz_name );
gbazin's avatar
 
gbazin committed
182
183
184
        return;
    }

gbazin's avatar
   
gbazin committed
185
186
187
188
189
    vlc_mutex_lock( p_config->p_lock );

    /* free old string */
    if( p_config->psz_value ) free( p_config->psz_value );

190
    if( psz_value && *psz_value ) p_config->psz_value = strdup( psz_value );
gbazin's avatar
 
gbazin committed
191
192
    else p_config->psz_value = NULL;

gbazin's avatar
   
gbazin committed
193
    vlc_mutex_unlock( p_config->p_lock );
gbazin's avatar
 
gbazin committed
194

195
    if( p_config->pf_callback )
196
    {
197
        p_config->pf_callback( p_this );
198
    }
gbazin's avatar
 
gbazin committed
199
200
201
}

/*****************************************************************************
202
 * config_PutInt: set the integer value of an int variable
gbazin's avatar
 
gbazin committed
203
204
 *****************************************************************************
 * This function is used to set the value of variables which are internally
gbazin's avatar
   
gbazin committed
205
206
 * represented by an integer (CONFIG_ITEM_INTEGER and
 * CONFIG_ITEM_BOOL).
gbazin's avatar
 
gbazin committed
207
 *****************************************************************************/
208
void __config_PutInt( vlc_object_t *p_this, const char *psz_name, int i_value )
gbazin's avatar
 
gbazin committed
209
210
211
{
    module_config_t *p_config;

212
    p_config = config_FindConfig( p_this, psz_name );
gbazin's avatar
 
gbazin committed
213
214
215
216

    /* sanity checks */
    if( !p_config )
    {
217
        msg_Warn( p_this, "option %s does not exist", psz_name );
gbazin's avatar
 
gbazin committed
218
219
        return;
    }
gbazin's avatar
   
gbazin committed
220
221
    if( (p_config->i_type!=CONFIG_ITEM_INTEGER) &&
        (p_config->i_type!=CONFIG_ITEM_BOOL) )
gbazin's avatar
 
gbazin committed
222
    {
223
        msg_Err( p_this, "option %s does not refer to an int", psz_name );
gbazin's avatar
 
gbazin committed
224
225
226
        return;
    }

227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
    /* if i_min == i_max == 0, then do not use them */
    if ((p_config->i_min == 0) && (p_config->i_max == 0))
    {
        p_config->i_value = i_value;
    }
    else if (i_value < p_config->i_min)
    {
        p_config->i_value = p_config->i_min;
    }
    else if (i_value > p_config->i_max)
    {
        p_config->i_value = p_config->i_max;
    }
    else
    {
        p_config->i_value = i_value;
    }
244

245
    if( p_config->pf_callback )
246
    {
247
        p_config->pf_callback( p_this );
248
    }
gbazin's avatar
 
gbazin committed
249
250
}

gbazin's avatar
   
gbazin committed
251
/*****************************************************************************
252
 * config_PutFloat: set the value of a float variable
gbazin's avatar
   
gbazin committed
253
254
 *****************************************************************************
 * This function is used to set the value of variables which are internally
gbazin's avatar
   
gbazin committed
255
 * represented by a float (CONFIG_ITEM_FLOAT).
gbazin's avatar
   
gbazin committed
256
 *****************************************************************************/
257
258
void __config_PutFloat( vlc_object_t *p_this,
                        const char *psz_name, float f_value )
gbazin's avatar
   
gbazin committed
259
260
261
{
    module_config_t *p_config;

262
    p_config = config_FindConfig( p_this, psz_name );
gbazin's avatar
   
gbazin committed
263
264
265
266

    /* sanity checks */
    if( !p_config )
    {
267
        msg_Warn( p_this, "option %s does not exist", psz_name );
gbazin's avatar
   
gbazin committed
268
269
        return;
    }
gbazin's avatar
   
gbazin committed
270
    if( p_config->i_type != CONFIG_ITEM_FLOAT )
gbazin's avatar
   
gbazin committed
271
    {
272
        msg_Err( p_this, "option %s does not refer to a float", psz_name );
gbazin's avatar
   
gbazin committed
273
274
275
        return;
    }

276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
    /* if f_min == f_max == 0, then do not use them */
    if ((p_config->f_min == 0) && (p_config->f_max == 0))
    {
        p_config->f_value = f_value;
    }
    else if (f_value < p_config->f_min)
    {
        p_config->f_value = p_config->f_min;
    }
    else if (f_value > p_config->f_max)
    {
        p_config->f_value = p_config->f_max;
    }
    else
    {
        p_config->f_value = f_value;
    }
293

294
    if( p_config->pf_callback )
295
    {
296
        p_config->pf_callback( p_this );
297
    }
gbazin's avatar
   
gbazin committed
298
299
}

gbazin's avatar
 
gbazin committed
300
301
302
303
/*****************************************************************************
 * config_FindConfig: find the config structure associated with an option.
 *****************************************************************************
 * FIXME: This function really needs to be optimized.
304
 * FIXME: And now even more.
gbazin's avatar
 
gbazin committed
305
 *****************************************************************************/
306
module_config_t *config_FindConfig( vlc_object_t *p_this, const char *psz_name )
gbazin's avatar
 
gbazin committed
307
{
308
    vlc_list_t *p_list;
gbazin's avatar
   
gbazin committed
309
    module_t *p_parser;
Sam Hocevar's avatar
   
Sam Hocevar committed
310
    module_config_t *p_item;
gbazin's avatar
   
gbazin committed
311
    int i_index;
gbazin's avatar
 
gbazin committed
312
313
314

    if( !psz_name ) return NULL;

315
    p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
316

317
    for( i_index = 0; i_index < p_list->i_count; i_index++ )
gbazin's avatar
 
gbazin committed
318
    {
319
        p_parser = (module_t *)p_list->p_values[i_index].p_object ;
gbazin's avatar
   
gbazin committed
320
321

        if( !p_parser->i_config_items )
322
323
            continue;

gbazin's avatar
   
gbazin committed
324
        for( p_item = p_parser->p_config;
gbazin's avatar
   
gbazin committed
325
             p_item->i_type != CONFIG_HINT_END;
Sam Hocevar's avatar
   
Sam Hocevar committed
326
             p_item++ )
gbazin's avatar
 
gbazin committed
327
        {
gbazin's avatar
   
gbazin committed
328
            if( p_item->i_type & CONFIG_HINT )
gbazin's avatar
   
gbazin committed
329
                /* ignore hints */
gbazin's avatar
 
gbazin committed
330
                continue;
Sam Hocevar's avatar
   
Sam Hocevar committed
331
            if( !strcmp( psz_name, p_item->psz_name ) )
332
            {
333
                vlc_list_release( p_list );
Sam Hocevar's avatar
   
Sam Hocevar committed
334
                return p_item;
335
            }
gbazin's avatar
 
gbazin committed
336
337
338
        }
    }

339
    vlc_list_release( p_list );
340

gbazin's avatar
 
gbazin committed
341
342
343
344
345
346
347
348
349
350
    return NULL;
}

/*****************************************************************************
 * config_Duplicate: creates a duplicate of a module's configuration data.
 *****************************************************************************
 * Unfortunatly we cannot work directly with the module's config data as
 * this module might be unloaded from memory at any time (remember HideModule).
 * This is why we need to create an exact copy of the config data.
 *****************************************************************************/
351
void config_Duplicate( module_t *p_module, module_config_t *p_orig )
gbazin's avatar
 
gbazin committed
352
{
gbazin's avatar
   
gbazin committed
353
    int i, j, i_lines = 1;
354
    module_config_t *p_item;
gbazin's avatar
 
gbazin committed
355

Sam Hocevar's avatar
   
Sam Hocevar committed
356
    /* Calculate the structure length */
357
358
359
    p_module->i_config_items = 0;
    p_module->i_bool_items = 0;

gbazin's avatar
   
gbazin committed
360
    for( p_item = p_orig; p_item->i_type != CONFIG_HINT_END; p_item++ )
361
362
363
    {
        i_lines++;

gbazin's avatar
   
gbazin committed
364
        if( p_item->i_type & CONFIG_ITEM )
365
366
367
368
        {
            p_module->i_config_items++;
        }

gbazin's avatar
   
gbazin committed
369
        if( p_item->i_type == CONFIG_ITEM_BOOL )
370
371
372
373
        {
            p_module->i_bool_items++;
        }
    }
Sam Hocevar's avatar
   
Sam Hocevar committed
374
375

    /* Allocate memory */
376
377
378
    p_module->p_config = (module_config_t *)malloc( sizeof(module_config_t)
                                                     * i_lines );
    if( p_module->p_config == NULL )
gbazin's avatar
 
gbazin committed
379
    {
380
381
        msg_Err( p_module, "config error: can't duplicate p_config" );
        return;
gbazin's avatar
 
gbazin committed
382
383
    }

Sam Hocevar's avatar
   
Sam Hocevar committed
384
385
    /* Do the duplication job */
    for( i = 0; i < i_lines ; i++ )
gbazin's avatar
 
gbazin committed
386
    {
387
388
389
        p_module->p_config[i].i_type = p_orig[i].i_type;
        p_module->p_config[i].i_short = p_orig[i].i_short;
        p_module->p_config[i].i_value = p_orig[i].i_value;
390
391
        p_module->p_config[i].i_min = p_orig[i].i_min;
        p_module->p_config[i].i_max = p_orig[i].i_max;
392
        p_module->p_config[i].f_value = p_orig[i].f_value;
393
394
        p_module->p_config[i].f_min = p_orig[i].f_min;
        p_module->p_config[i].f_max = p_orig[i].f_max;
395
        p_module->p_config[i].b_dirty = p_orig[i].b_dirty;
396
        p_module->p_config[i].b_advanced = p_orig[i].b_advanced;
Sam Hocevar's avatar
   
Sam Hocevar committed
397

398
        p_module->p_config[i].psz_type = p_orig[i].psz_type ?
gbazin's avatar
   
gbazin committed
399
                                   strdup( p_orig[i].psz_type ) : NULL;
400
        p_module->p_config[i].psz_name = p_orig[i].psz_name ?
gbazin's avatar
   
gbazin committed
401
                                   strdup( p_orig[i].psz_name ) : NULL;
402
        p_module->p_config[i].psz_text = p_orig[i].psz_text ?
Sam Hocevar's avatar
   
Sam Hocevar committed
403
                                   strdup( _(p_orig[i].psz_text) ) : NULL;
404
        p_module->p_config[i].psz_longtext = p_orig[i].psz_longtext ?
Sam Hocevar's avatar
   
Sam Hocevar committed
405
                                   strdup( _(p_orig[i].psz_longtext) ) : NULL;
406
        p_module->p_config[i].psz_value = p_orig[i].psz_value ?
gbazin's avatar
   
gbazin committed
407
                                   strdup( p_orig[i].psz_value ) : NULL;
gbazin's avatar
 
gbazin committed
408

Sam Hocevar's avatar
Sam Hocevar committed
409
        p_module->p_config[i].p_lock = &p_module->object_lock;
410

gbazin's avatar
   
gbazin committed
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
        /* duplicate the string list */
        p_module->p_config[i].ppsz_list = NULL;
        if( p_orig[i].ppsz_list )
        {
            for( j = 0; p_orig[i].ppsz_list[j]; j++ );
            p_module->p_config[i].ppsz_list = malloc( (j+1) *sizeof(char *) );
            if( p_module->p_config[i].ppsz_list )
            {
                for( j = 0; p_orig[i].ppsz_list[j]; j++ )
                    p_module->p_config[i].ppsz_list[j] =
                        strdup( p_orig[i].ppsz_list[j] );
            }
            p_module->p_config[i].ppsz_list[j] = NULL;
        }

426
        p_module->p_config[i].pf_callback = p_orig[i].pf_callback;
gbazin's avatar
 
gbazin committed
427
    }
428
429
430
431
432
433
434
435
436
437
}

/*****************************************************************************
 * config_Free: frees a duplicated module's configuration data.
 *****************************************************************************
 * This function frees all the data duplicated by config_Duplicate.
 *****************************************************************************/
void config_Free( module_t *p_module )
{
    module_config_t *p_item = p_module->p_config;
gbazin's avatar
   
gbazin committed
438
    int i;
439

440
441
442
443
444
    if( p_item == NULL )
    {
        return;
    }

gbazin's avatar
   
gbazin committed
445
    for( ; p_item->i_type != CONFIG_HINT_END ; p_item++ )
446
    {
447
448
449
        if( p_item->psz_type )
            free( p_item->psz_type );

450
451
        if( p_item->psz_name )
            free( p_item->psz_name );
gbazin's avatar
 
gbazin committed
452

453
454
455
456
457
458
459
460
        if( p_item->psz_text )
            free( p_item->psz_text );

        if( p_item->psz_longtext )
            free( p_item->psz_longtext );

        if( p_item->psz_value )
            free( p_item->psz_value );
gbazin's avatar
   
gbazin committed
461
462

        if( p_item->ppsz_list )
gbazin's avatar
   
gbazin committed
463
464
465
466
467
        {
            for( i = 0; p_item->ppsz_list[i]; i++ )
                free(p_item->ppsz_list[i]);
            free( p_item->ppsz_list );
        }
468
469
470
471
    }

    free( p_module->p_config );
    p_module->p_config = NULL;
gbazin's avatar
 
gbazin committed
472
}
gbazin's avatar
   
gbazin committed
473

474
475
476
477
478
479
480
481
482
/*****************************************************************************
 * config_SetCallbacks: sets callback functions in the duplicate p_config.
 *****************************************************************************
 * Unfortunatly we cannot work directly with the module's config data as
 * this module might be unloaded from memory at any time (remember HideModule).
 * This is why we need to duplicate callbacks each time we reload the module.
 *****************************************************************************/
void config_SetCallbacks( module_config_t *p_new, module_config_t *p_orig )
{
gbazin's avatar
   
gbazin committed
483
    while( p_new->i_type != CONFIG_HINT_END )
484
    {
485
        p_new->pf_callback = p_orig->pf_callback;
486
487
488
489
490
491
492
493
494
495
496
497
        p_new++;
        p_orig++;
    }
}

/*****************************************************************************
 * config_UnsetCallbacks: unsets callback functions in the duplicate p_config.
 *****************************************************************************
 * We simply undo what we did in config_SetCallbacks.
 *****************************************************************************/
void config_UnsetCallbacks( module_config_t *p_new )
{
gbazin's avatar
   
gbazin committed
498
    while( p_new->i_type != CONFIG_HINT_END )
499
    {
500
        p_new->pf_callback = NULL;
501
502
503
504
        p_new++;
    }
}

gbazin's avatar
   
gbazin committed
505
506
507
508
509
510
/*****************************************************************************
 * config_LoadConfigFile: loads the configuration file.
 *****************************************************************************
 * This function is called to load the config options stored in the config
 * file.
 *****************************************************************************/
511
int __config_LoadConfigFile( vlc_object_t *p_this, const char *psz_module_name )
gbazin's avatar
   
gbazin committed
512
{
513
    vlc_list_t *p_list;
gbazin's avatar
   
gbazin committed
514
    module_t *p_parser;
Sam Hocevar's avatar
   
Sam Hocevar committed
515
    module_config_t *p_item;
gbazin's avatar
   
gbazin committed
516
517
518
519
    FILE *file;
    char line[1024];
    char *p_index, *psz_option_name, *psz_option_value;
    char *psz_filename, *psz_homedir;
gbazin's avatar
   
gbazin committed
520
    int i_index;
gbazin's avatar
   
gbazin committed
521

522
    psz_homedir = p_this->p_vlc->psz_homedir;
gbazin's avatar
   
gbazin committed
523
524
    if( !psz_homedir )
    {
525
        msg_Err( p_this, "psz_homedir is null" );
gbazin's avatar
   
gbazin committed
526
527
        return -1;
    }
Sam Hocevar's avatar
   
Sam Hocevar committed
528
    psz_filename = (char *)malloc( strlen("/" CONFIG_DIR "/" CONFIG_FILE) +
gbazin's avatar
   
gbazin committed
529
530
531
                                   strlen(psz_homedir) + 1 );
    if( !psz_filename )
    {
532
        msg_Err( p_this, "out of memory" );
gbazin's avatar
   
gbazin committed
533
534
        return -1;
    }
Sam Hocevar's avatar
   
Sam Hocevar committed
535
    sprintf( psz_filename, "%s/" CONFIG_DIR "/" CONFIG_FILE, psz_homedir );
gbazin's avatar
   
gbazin committed
536

537
    msg_Dbg( p_this, "opening config file %s", psz_filename );
gbazin's avatar
   
gbazin committed
538

539
540
541
    /* Acquire config file lock */
    vlc_mutex_lock( &p_this->p_vlc->config_lock );

gbazin's avatar
   
gbazin committed
542
    file = fopen( psz_filename, "rt" );
gbazin's avatar
   
gbazin committed
543
544
    if( !file )
    {
545
        msg_Warn( p_this, "config file %s does not exist yet", psz_filename );
gbazin's avatar
   
gbazin committed
546
        free( psz_filename );
547
        vlc_mutex_unlock( &p_this->p_vlc->config_lock );
gbazin's avatar
   
gbazin committed
548
549
550
551
        return -1;
    }

    /* Look for the selected module, if NULL then save everything */
552
    p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
553

554
    for( i_index = 0; i_index < p_list->i_count; i_index++ )
gbazin's avatar
   
gbazin committed
555
    {
556
        p_parser = (module_t *)p_list->p_values[i_index].p_object ;
gbazin's avatar
   
gbazin committed
557

558
        if( psz_module_name
gbazin's avatar
   
gbazin committed
559
             && strcmp( psz_module_name, p_parser->psz_object_name ) )
560
        {
gbazin's avatar
   
gbazin committed
561
            continue;
562
        }
gbazin's avatar
   
gbazin committed
563
564
565

        /* The config file is organized in sections, one per module. Look for
         * the interesting section ( a section is of the form [foo] ) */
566
        fseek( file, 0L, SEEK_SET );
gbazin's avatar
   
gbazin committed
567
568
        while( fgets( line, 1024, file ) )
        {
569
570
            if( (line[0] == '[')
               && (p_index = strchr(line,']'))
571
               && (p_index - &line[1]
gbazin's avatar
   
gbazin committed
572
573
574
                    == (int)strlen(p_parser->psz_object_name))
               && !memcmp( &line[1], p_parser->psz_object_name,
                           strlen(p_parser->psz_object_name) ) )
gbazin's avatar
   
gbazin committed
575
            {
576
577
#if 0
                msg_Dbg( p_this, "loading config for module \"%s\"",
gbazin's avatar
   
gbazin committed
578
                                 p_parser->psz_object_name );
579
#endif
gbazin's avatar
   
gbazin committed
580
581
582
583
584
585
586
587
588
589
590
591

                break;
            }
        }
        /* either we found the section or we're at the EOF */

        /* Now try to load the options in this section */
        while( fgets( line, 1024, file ) )
        {
            if( line[0] == '[' ) break; /* end of section */

            /* ignore comments or empty lines */
gbazin's avatar
   
gbazin committed
592
593
            if( (line[0] == '#') || (line[0] == '\n') || (line[0] == (char)0) )
                continue;
gbazin's avatar
   
gbazin committed
594
595
596
597
598
599
600
601
602
603
604
605
606
607

            /* get rid of line feed */
            if( line[strlen(line)-1] == '\n' )
                line[strlen(line)-1] = (char)0;

            /* look for option name */
            psz_option_name = line;
            psz_option_value = NULL;
            p_index = strchr( line, '=' );
            if( !p_index ) break; /* this ain't an option!!! */

            *p_index = (char)0;
            psz_option_value = p_index + 1;

gbazin's avatar
   
gbazin committed
608
            if( !p_parser->i_config_items )
609
610
611
612
            {
                continue;
            }

gbazin's avatar
   
gbazin committed
613
            /* try to match this option with one of the module's options */
gbazin's avatar
   
gbazin committed
614
            for( p_item = p_parser->p_config;
gbazin's avatar
   
gbazin committed
615
                 p_item->i_type != CONFIG_HINT_END;
Sam Hocevar's avatar
   
Sam Hocevar committed
616
                 p_item++ )
gbazin's avatar
   
gbazin committed
617
            {
gbazin's avatar
   
gbazin committed
618
                if( p_item->i_type & CONFIG_HINT )
gbazin's avatar
   
gbazin committed
619
620
                    /* ignore hints */
                    continue;
Sam Hocevar's avatar
   
Sam Hocevar committed
621
622

                if( !strcmp( p_item->psz_name, psz_option_name ) )
gbazin's avatar
   
gbazin committed
623
624
                {
                    /* We found it */
Sam Hocevar's avatar
   
Sam Hocevar committed
625
                    switch( p_item->i_type )
gbazin's avatar
   
gbazin committed
626
                    {
gbazin's avatar
   
gbazin committed
627
628
                    case CONFIG_ITEM_BOOL:
                    case CONFIG_ITEM_INTEGER:
gbazin's avatar
   
gbazin committed
629
630
                        if( !*psz_option_value )
                            break;                    /* ignore empty option */
Sam Hocevar's avatar
   
Sam Hocevar committed
631
                        p_item->i_value = atoi( psz_option_value);
632
633
634
635
#if 0
                        msg_Dbg( p_this, "option \"%s\", value %i",
                                 p_item->psz_name, p_item->i_value );
#endif
gbazin's avatar
   
gbazin committed
636
637
                        break;

gbazin's avatar
   
gbazin committed
638
                    case CONFIG_ITEM_FLOAT:
gbazin's avatar
   
gbazin committed
639
640
641
                        if( !*psz_option_value )
                            break;                    /* ignore empty option */
                        p_item->f_value = (float)atof( psz_option_value);
642
643
644
645
#if O
                        msg_Dbg( p_this, "option \"%s\", value %f",
                                 p_item->psz_name, (double)p_item->f_value );
#endif
gbazin's avatar
   
gbazin committed
646
647
                        break;

gbazin's avatar
   
gbazin committed
648
                    default:
Sam Hocevar's avatar
   
Sam Hocevar committed
649
                        vlc_mutex_lock( p_item->p_lock );
gbazin's avatar
   
gbazin committed
650
651

                        /* free old string */
Sam Hocevar's avatar
   
Sam Hocevar committed
652
653
                        if( p_item->psz_value )
                            free( p_item->psz_value );
gbazin's avatar
   
gbazin committed
654

Sam Hocevar's avatar
   
Sam Hocevar committed
655
                        p_item->psz_value = *psz_option_value ?
gbazin's avatar
   
gbazin committed
656
                            strdup( psz_option_value ) : NULL;
gbazin's avatar
   
gbazin committed
657

Sam Hocevar's avatar
   
Sam Hocevar committed
658
                        vlc_mutex_unlock( p_item->p_lock );
gbazin's avatar
   
gbazin committed
659

660
661
662
663
664
#if 0
                        msg_Dbg( p_this, "option \"%s\", value \"%s\"",
                                 p_item->psz_name,
                                 p_item->psz_value ? p_item->psz_value : "" );
#endif
gbazin's avatar
   
gbazin committed
665
666
667
668
669
670
671
                        break;
                    }
                }
            }
        }

    }
672
673

    vlc_list_release( p_list );
674

gbazin's avatar
   
gbazin committed
675
676
677
    fclose( file );
    free( psz_filename );

678
    vlc_mutex_unlock( &p_this->p_vlc->config_lock );
gbazin's avatar
   
gbazin committed
679
680
681
682
683
684
685
686
687
688
689
690

    return 0;
}

/*****************************************************************************
 * config_SaveConfigFile: Save a module's config options.
 *****************************************************************************
 * This will save the specified module's config options to the config file.
 * If psz_module_name is NULL then we save all the modules config options.
 * It's no use to save the config options that kept their default values, so
 * we'll try to be a bit clever here.
 *
691
 * When we save we mustn't delete the config options of the modules that
gbazin's avatar
   
gbazin committed
692
 * haven't been loaded. So we cannot just create a new config file with the
693
 * config structures we've got in memory.
gbazin's avatar
   
gbazin committed
694
695
696
697
698
699
700
701
 * I don't really know how to deal with this nicely, so I will use a completly
 * dumb method ;-)
 * I will load the config file in memory, but skipping all the sections of the
 * modules we want to save. Then I will create a brand new file, dump the file
 * loaded in memory and then append the sections of the modules we want to
 * save.
 * Really stupid no ?
 *****************************************************************************/
702
int __config_SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name )
gbazin's avatar
   
gbazin committed
703
{
gbazin's avatar
   
gbazin committed
704
    module_t *p_parser;
705
    vlc_list_t *p_list;
Sam Hocevar's avatar
   
Sam Hocevar committed
706
    module_config_t *p_item;
gbazin's avatar
   
gbazin committed
707
708
    FILE *file;
    char p_line[1024], *p_index2;
Sam Hocevar's avatar
   
Sam Hocevar committed
709
    int i_sizebuf = 0;
gbazin's avatar
   
gbazin committed
710
    char *p_bigbuffer, *p_index;
711
    vlc_bool_t b_backup;
gbazin's avatar
   
gbazin committed
712
    char *psz_filename, *psz_homedir;
gbazin's avatar
   
gbazin committed
713
    int i_index;
gbazin's avatar
   
gbazin committed
714
715

    /* Acquire config file lock */
716
    vlc_mutex_lock( &p_this->p_vlc->config_lock );
gbazin's avatar
   
gbazin committed
717

718
    psz_homedir = p_this->p_vlc->psz_homedir;
gbazin's avatar
   
gbazin committed
719
720
    if( !psz_homedir )
    {
721
722
        msg_Err( p_this, "psz_homedir is null" );
        vlc_mutex_unlock( &p_this->p_vlc->config_lock );
gbazin's avatar
   
gbazin committed
723
724
        return -1;
    }
Sam Hocevar's avatar
   
Sam Hocevar committed
725
    psz_filename = (char *)malloc( strlen("/" CONFIG_DIR "/" CONFIG_FILE) +
gbazin's avatar
   
gbazin committed
726
727
728
                                   strlen(psz_homedir) + 1 );
    if( !psz_filename )
    {
729
730
        msg_Err( p_this, "out of memory" );
        vlc_mutex_unlock( &p_this->p_vlc->config_lock );
gbazin's avatar
   
gbazin committed
731
732
        return -1;
    }
Sam Hocevar's avatar
   
Sam Hocevar committed
733
    sprintf( psz_filename, "%s/" CONFIG_DIR, psz_homedir );
Sam Hocevar's avatar
   
Sam Hocevar committed
734

735
736
737
738
739
740
741
742
743
744
745
#if defined( UNDER_CE )
    {
        wchar_t psz_new[ MAX_PATH ];
        MultiByteToWideChar( CP_ACP, 0, psz_filename, -1, psz_new, MAX_PATH );
        if( CreateDirectory( psz_new, NULL ) )
        {
            msg_Err( p_this, "could not create %s", psz_filename );
        }
    }

#elif defined( HAVE_ERRNO_H )
746
#   if defined( WIN32 )
Sam Hocevar's avatar
   
Sam Hocevar committed
747
    if( mkdir( psz_filename ) && errno != EEXIST )
748
749
750
#   else
    if( mkdir( psz_filename, 0755 ) && errno != EEXIST )
#   endif
Sam Hocevar's avatar
   
Sam Hocevar committed
751
    {
752
753
        msg_Err( p_this, "could not create %s (%s)",
                         psz_filename, strerror(errno) );
Sam Hocevar's avatar
   
Sam Hocevar committed
754
755
    }

756
757
758
759
760
761
762
763
#else
    if( mkdir( psz_filename ) )
    {
        msg_Err( p_this, "could not create %s", psz_filename );
    }

#endif

Sam Hocevar's avatar
   
Sam Hocevar committed
764
    strcat( psz_filename, "/" CONFIG_FILE );
gbazin's avatar
   
gbazin committed
765
766


767
    msg_Dbg( p_this, "opening config file %s", psz_filename );
gbazin's avatar
   
gbazin committed
768

gbazin's avatar
   
gbazin committed
769
    file = fopen( psz_filename, "rt" );
gbazin's avatar
   
gbazin committed
770
771
    if( !file )
    {
772
        msg_Warn( p_this, "config file %s does not exist yet", psz_filename );
gbazin's avatar
   
gbazin committed
773
774
775
776
    }
    else
    {
        /* look for file size */
777
        fseek( file, 0L, SEEK_END );
gbazin's avatar
   
gbazin committed
778
        i_sizebuf = ftell( file );
779
        fseek( file, 0L, SEEK_SET );
gbazin's avatar
   
gbazin committed
780
781
782
783
784
    }

    p_bigbuffer = p_index = malloc( i_sizebuf+1 );
    if( !p_bigbuffer )
    {
785
        msg_Err( p_this, "out of memory" );
gbazin's avatar
   
gbazin committed
786
787
        if( file ) fclose( file );
        free( psz_filename );
788
        vlc_mutex_unlock( &p_this->p_vlc->config_lock );
gbazin's avatar
   
gbazin committed
789
790
791
792
        return -1;
    }
    p_bigbuffer[0] = 0;

793
    /* List all available modules */
794
    p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
795

gbazin's avatar
   
gbazin committed
796
797
798
799
800
801
802
    /* backup file into memory, we only need to backup the sections we won't
     * save later on */
    b_backup = 0;
    while( file && fgets( p_line, 1024, file ) )
    {
        if( (p_line[0] == '[') && (p_index2 = strchr(p_line,']')))
        {
803

gbazin's avatar
   
gbazin committed
804
            /* we found a section, check if we need to do a backup */
805
            for( i_index = 0; i_index < p_list->i_count; i_index++ )
gbazin's avatar
   
gbazin committed
806
            {
807
                p_parser = (module_t *)p_list->p_values[i_index].p_object ;
gbazin's avatar
   
gbazin committed
808

809
                if( ((p_index2 - &p_line[1])
gbazin's avatar
   
gbazin committed
810
811
812
                       == (int)strlen(p_parser->psz_object_name) )
                    && !memcmp( &p_line[1], p_parser->psz_object_name,
                                strlen(p_parser->psz_object_name) ) )
gbazin's avatar
   
gbazin committed
813
814
815
                {
                    if( !psz_module_name )
                        break;
816
                    else if( !strcmp( psz_module_name,
gbazin's avatar
   
gbazin committed
817
                                      p_parser->psz_object_name ) )
gbazin's avatar
   
gbazin committed
818
819
820
821
                        break;
                }
            }

822
            if( i_index == p_list->i_count )
gbazin's avatar
   
gbazin committed
823
824
825
826
            {
                /* we don't have this section in our list so we need to back
                 * it up */
                *p_index2 = 0;
827
                msg_Dbg( p_this, "backing up config for unknown module \"%s\"",
828
                                 &p_line[1] );
gbazin's avatar
   
gbazin committed
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
                *p_index2 = ']';

                b_backup = 1;
            }
            else
            {
                b_backup = 0;
            }
        }

        /* save line if requested and line is valid (doesn't begin with a
         * space, tab, or eol) */
        if( b_backup && (p_line[0] != '\n') && (p_line[0] != ' ')
            && (p_line[0] != '\t') )
        {
            strcpy( p_index, p_line );
            p_index += strlen( p_line );
        }
    }
    if( file ) fclose( file );


    /*
     * Save module config in file
     */

gbazin's avatar
   
gbazin committed
855
    file = fopen( psz_filename, "wt" );
gbazin's avatar
   
gbazin committed
856
857
    if( !file )
    {
858
859
        msg_Warn( p_this, "could not open config file %s for writing",
                          psz_filename );
gbazin's avatar
   
gbazin committed
860
        free( psz_filename );
861
        vlc_list_release( p_list );
862
        vlc_mutex_unlock( &p_this->p_vlc->config_lock );
gbazin's avatar
   
gbazin committed
863
864
865
        return -1;
    }

Sam Hocevar's avatar
   
Sam Hocevar committed
866
    fprintf( file, "###\n###  " COPYRIGHT_MESSAGE "\n###\n\n" );
gbazin's avatar
   
gbazin committed
867
868

    /* Look for the selected module, if NULL then save everything */
869
    for( i_index = 0; i_index < p_list->i_count; i_index++ )
gbazin's avatar
   
gbazin committed
870
    {
871
        p_parser = (module_t *)p_list->p_values[i_index].p_object ;
gbazin's avatar
   
gbazin committed
872

873
        if( psz_module_name && strcmp( psz_module_name,
gbazin's avatar
   
gbazin committed
874
                                       p_parser->psz_object_name ) )
gbazin's avatar
   
gbazin committed
875
876
            continue;

gbazin's avatar
   
gbazin committed
877
        if( !p_parser->i_config_items )
gbazin's avatar
   
gbazin committed
878
879
            continue;

880
        msg_Dbg( p_this, "saving config for module \"%s\"",
gbazin's avatar
   
gbazin committed
881
                         p_parser->psz_object_name );
gbazin's avatar
   
gbazin committed
882

gbazin's avatar
   
gbazin committed
883
884
885
        fprintf( file, "[%s]", p_parser->psz_object_name );
        if( p_parser->psz_longname )
            fprintf( file, " # %s\n\n", p_parser->psz_longname );
gbazin's avatar
   
gbazin committed
886
887
        else
            fprintf( file, "\n\n" );
Sam Hocevar's avatar
   
Sam Hocevar committed
888

gbazin's avatar
   
gbazin committed
889
        for( p_item = p_parser->p_config;
gbazin's avatar
   
gbazin committed
890
             p_item->i_type != CONFIG_HINT_END;
Sam Hocevar's avatar
   
Sam Hocevar committed
891
             p_item++ )
gbazin's avatar
   
gbazin committed
892
        {
gbazin's avatar
   
gbazin committed
893
            if( p_item->i_type & CONFIG_HINT )
gbazin's avatar
   
gbazin committed
894
895
896
                /* ignore hints */
                continue;

Sam Hocevar's avatar
   
Sam Hocevar committed
897
            switch( p_item->i_type )
gbazin's avatar
   
gbazin committed
898
            {
gbazin's avatar
   
gbazin committed
899
900
            case CONFIG_ITEM_BOOL:
            case CONFIG_ITEM_INTEGER:
Sam Hocevar's avatar
   
Sam Hocevar committed
901
                if( p_item->psz_text )
902
                    fprintf( file, "# %s (%s)\n", p_item->psz_text,
gbazin's avatar
   
gbazin committed
903
                             (p_item->i_type == CONFIG_ITEM_BOOL) ?
904
                             _("boolean") : _("integer") );
905
                fprintf( file, "%s=%i\n", p_item->psz_name, p_item->i_value );
gbazin's avatar
   
gbazin committed
906
907
                break;

gbazin's avatar
   
gbazin committed
908
            case CONFIG_ITEM_FLOAT:
gbazin's avatar
   
gbazin committed
909
                if( p_item->psz_text )
910
911
                    fprintf( file, "# %s (%s)\n", p_item->psz_text,
                             _("float") );
gbazin's avatar
   
gbazin committed
912
913
914
915
                fprintf( file, "%s=%f\n", p_item->psz_name,
                         (double)p_item->f_value );
                break;

gbazin's avatar
   
gbazin committed
916
            default:
Sam Hocevar's avatar
   
Sam Hocevar committed
917
                if( p_item->psz_text )
918
919
                    fprintf( file, "# %s (%s)\n", p_item->psz_text,
                             _("string") );
Sam Hocevar's avatar
   
Sam Hocevar committed
920
921
                fprintf( file, "%s=%s\n", p_item->psz_name,
                         p_item->psz_value ? p_item->psz_value : "" );
gbazin's avatar
   
gbazin committed
922
923
924
925
926
927
            }
        }

        fprintf( file, "\n" );
    }

928
    vlc_list_release( p_list );
gbazin's avatar
   
gbazin committed
929
930
931
932
933
934
935
936
937

    /*
     * Restore old settings from the config in file
     */
    fputs( p_bigbuffer, file );
    free( p_bigbuffer );

    fclose( file );
    free( psz_filename );
938
    vlc_mutex_unlock( &p_this->p_vlc->config_lock );
gbazin's avatar
   
gbazin committed
939
940
941
942

    return 0;
}

gbazin's avatar
   
gbazin committed
943
944
945
946
947
948
949
950
951
/*****************************************************************************
 * config_LoadCmdLine: parse command line
 *****************************************************************************
 * Parse command line for configuration options.
 * Now that the module_bank has been initialized, we can dynamically
 * generate the longopts structure used by getops. We have to do it this way
 * because we don't know (and don't want to know) in advance the configuration
 * options used (ie. exported) by each module.
 *****************************************************************************/
952
953
int __config_LoadCmdLine( vlc_object_t *p_this, int *pi_argc, char *ppsz_argv[],
                          vlc_bool_t b_ignore_errors )
gbazin's avatar
   
gbazin committed
954
{
955
    int i_cmd, i_index, i_opts, i_shortopts, flag, i_verbose = 0;
gbazin's avatar
   
gbazin committed
956
    module_t *p_parser;
957
    vlc_list_t *p_list;
Sam Hocevar's avatar
   
Sam Hocevar committed
958
    module_config_t *p_item;
gbazin's avatar
   
gbazin committed
959
    struct option *p_longopts;
gbazin's avatar