configuration.c 62 KB
Newer Older
gbazin's avatar
   
gbazin committed
1
2
3
/*****************************************************************************
 * configuration.c management of the modules configuration
 *****************************************************************************
4
 * Copyright (C) 2001-2004 the VideoLAN team
5
 * $Id$
gbazin's avatar
   
gbazin committed
6
 *
7
 * Authors: Gildas Bazin <gbazin@videolan.org>
gbazin's avatar
   
gbazin committed
8
9
10
11
12
13
14
15
16
17
18
19
20
 *
 * 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
dionoea's avatar
dionoea committed
21
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
gbazin's avatar
   
gbazin committed
22
 *****************************************************************************/
Sam Hocevar's avatar
   
Sam Hocevar committed
23

24
#include <vlc/vlc.h>
25
#include "vlc_keys.h"
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
26
#include "charset.h"
gbazin's avatar
   
gbazin committed
27

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

dionoea's avatar
dionoea committed
33
34
35
36
#ifdef HAVE_LIMITS_H
#   include <limits.h>
#endif

gbazin's avatar
   
gbazin committed
37
38
39
#ifdef HAVE_UNISTD_H
#    include <unistd.h>                                          /* getuid() */
#endif
gbazin's avatar
   
gbazin committed
40

gbazin's avatar
   
gbazin committed
41
42
43
44
45
#ifdef HAVE_GETOPT_LONG
#   ifdef HAVE_GETOPT_H
#       include <getopt.h>                                       /* getopt() */
#   endif
#else
46
#   include "../extras/getopt.h"
gbazin's avatar
   
gbazin committed
47
48
49
#endif

#if defined(HAVE_GETPWUID)
50
#   include <pwd.h>                                            /* getpwuid() */
gbazin's avatar
   
gbazin committed
51
52
#endif

53
54
55
56
57
58
#if defined( HAVE_SYS_STAT_H )
#   include <sys/stat.h>
#endif
#if defined( HAVE_SYS_TYPES_H )
#   include <sys/types.h>
#endif
59
60
61
62
63
#if defined( WIN32 )
#   if !defined( UNDER_CE )
#       include <direct.h>
#   endif
#include <tchar.h>
64
#endif
gbazin's avatar
   
gbazin committed
65

66
static int ConfigStringToKey( char * );
67
static char *ConfigKeyToString( int );
68

gbazin's avatar
   
gbazin committed
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
/*****************************************************************************
 * config_GetType: get the type of a variable (bool, int, float, string)
 *****************************************************************************
 * This function is used to get the type of a variable from its name.
 * Beware, this is quite slow.
 *****************************************************************************/
int __config_GetType( vlc_object_t *p_this, const char *psz_name )
{
    module_config_t *p_config;
    int i_type;

    p_config = config_FindConfig( p_this, psz_name );

    /* sanity checks */
    if( !p_config )
    {
        return 0;
    }

    switch( p_config->i_type )
    {
    case CONFIG_ITEM_BOOL:
        i_type = VLC_VAR_BOOL;
        break;

    case CONFIG_ITEM_INTEGER:
        i_type = VLC_VAR_INTEGER;
        break;

    case CONFIG_ITEM_FLOAT:
        i_type = VLC_VAR_FLOAT;
        break;

    case CONFIG_ITEM_MODULE:
103
104
105
    case CONFIG_ITEM_MODULE_CAT:
    case CONFIG_ITEM_MODULE_LIST:
    case CONFIG_ITEM_MODULE_LIST_CAT:
gbazin's avatar
   
gbazin committed
106
107
108
        i_type = VLC_VAR_MODULE;
        break;

gbazin's avatar
   
gbazin committed
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
    case CONFIG_ITEM_STRING:
        i_type = VLC_VAR_STRING;
        break;

    case CONFIG_ITEM_FILE:
        i_type = VLC_VAR_FILE;
        break;

    case CONFIG_ITEM_DIRECTORY:
        i_type = VLC_VAR_DIRECTORY;
        break;

    default:
        i_type = 0;
        break;
    }

    return i_type;
}

gbazin's avatar
   
gbazin committed
129
/*****************************************************************************
130
 * config_GetInt: get the value of an int variable
gbazin's avatar
   
gbazin committed
131
132
 *****************************************************************************
 * This function is used to get the value of variables which are internally
gbazin's avatar
   
gbazin committed
133
134
 * represented by an integer (CONFIG_ITEM_INTEGER and
 * CONFIG_ITEM_BOOL).
gbazin's avatar
   
gbazin committed
135
 *****************************************************************************/
136
int __config_GetInt( vlc_object_t *p_this, const char *psz_name )
gbazin's avatar
   
gbazin committed
137
138
139
{
    module_config_t *p_config;

140
    p_config = config_FindConfig( p_this, psz_name );
gbazin's avatar
   
gbazin committed
141
142
143
144

    /* sanity checks */
    if( !p_config )
    {
145
        msg_Err( p_this, "option %s does not exist", psz_name );
gbazin's avatar
   
gbazin committed
146
147
        return -1;
    }
gbazin's avatar
   
gbazin committed
148
    if( (p_config->i_type!=CONFIG_ITEM_INTEGER) &&
149
        (p_config->i_type!=CONFIG_ITEM_KEY) &&
gbazin's avatar
   
gbazin committed
150
        (p_config->i_type!=CONFIG_ITEM_BOOL) )
gbazin's avatar
   
gbazin committed
151
    {
152
        msg_Err( p_this, "option %s does not refer to an int", psz_name );
gbazin's avatar
   
gbazin committed
153
154
155
156
157
158
        return -1;
    }

    return p_config->i_value;
}

gbazin's avatar
   
gbazin committed
159
/*****************************************************************************
160
 * config_GetFloat: get the value of a float variable
gbazin's avatar
   
gbazin committed
161
162
 *****************************************************************************
 * This function is used to get the value of variables which are internally
gbazin's avatar
   
gbazin committed
163
 * represented by a float (CONFIG_ITEM_FLOAT).
gbazin's avatar
   
gbazin committed
164
 *****************************************************************************/
165
float __config_GetFloat( vlc_object_t *p_this, const char *psz_name )
gbazin's avatar
   
gbazin committed
166
167
168
{
    module_config_t *p_config;

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

    /* sanity checks */
    if( !p_config )
    {
174
        msg_Err( p_this, "option %s does not exist", psz_name );
gbazin's avatar
   
gbazin committed
175
176
        return -1;
    }
gbazin's avatar
   
gbazin committed
177
    if( p_config->i_type != CONFIG_ITEM_FLOAT )
gbazin's avatar
   
gbazin committed
178
    {
179
        msg_Err( p_this, "option %s does not refer to a float", psz_name );
gbazin's avatar
   
gbazin committed
180
181
182
183
184
185
        return -1;
    }

    return p_config->f_value;
}

gbazin's avatar
   
gbazin committed
186
/*****************************************************************************
187
 * config_GetPsz: get the string value of a string variable
gbazin's avatar
   
gbazin committed
188
189
 *****************************************************************************
 * This function is used to get the value of variables which are internally
gbazin's avatar
   
gbazin committed
190
 * represented by a string (CONFIG_ITEM_STRING, CONFIG_ITEM_FILE,
gbazin's avatar
   
gbazin committed
191
 * CONFIG_ITEM_DIRECTORY, and CONFIG_ITEM_MODULE).
gbazin's avatar
   
gbazin committed
192
 *
gbazin's avatar
   
gbazin committed
193
194
195
 * 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
196
 *****************************************************************************/
197
char * __config_GetPsz( vlc_object_t *p_this, const char *psz_name )
gbazin's avatar
   
gbazin committed
198
199
200
201
{
    module_config_t *p_config;
    char *psz_value = NULL;

202
    p_config = config_FindConfig( p_this, psz_name );
gbazin's avatar
   
gbazin committed
203
204
205
206

    /* sanity checks */
    if( !p_config )
    {
207
        msg_Err( p_this, "option %s does not exist", psz_name );
gbazin's avatar
   
gbazin committed
208
209
        return NULL;
    }
gbazin's avatar
   
gbazin committed
210
211
    if( (p_config->i_type!=CONFIG_ITEM_STRING) &&
        (p_config->i_type!=CONFIG_ITEM_FILE) &&
gbazin's avatar
   
gbazin committed
212
        (p_config->i_type!=CONFIG_ITEM_DIRECTORY) &&
zorglub's avatar
zorglub committed
213
214
        (p_config->i_type!=CONFIG_ITEM_MODULE_LIST) &&
        (p_config->i_type!=CONFIG_ITEM_MODULE_LIST_CAT) &&
215
        (p_config->i_type!=CONFIG_ITEM_MODULE_CAT) &&
gbazin's avatar
   
gbazin committed
216
        (p_config->i_type!=CONFIG_ITEM_MODULE) )
gbazin's avatar
   
gbazin committed
217
    {
218
        msg_Err( p_this, "option %s does not refer to a string", psz_name );
gbazin's avatar
   
gbazin committed
219
220
221
        return NULL;
    }

zorglub's avatar
zorglub committed
222

gbazin's avatar
   
gbazin committed
223
    /* return a copy of the string */
gbazin's avatar
   
gbazin committed
224
    vlc_mutex_lock( p_config->p_lock );
gbazin's avatar
   
gbazin committed
225
    if( p_config->psz_value ) psz_value = strdup( p_config->psz_value );
gbazin's avatar
   
gbazin committed
226
    vlc_mutex_unlock( p_config->p_lock );
gbazin's avatar
   
gbazin committed
227
228
229
230
231

    return psz_value;
}

/*****************************************************************************
232
 * config_PutPsz: set the string value of a string variable
gbazin's avatar
   
gbazin committed
233
234
 *****************************************************************************
 * This function is used to set the value of variables which are internally
gbazin's avatar
   
gbazin committed
235
 * represented by a string (CONFIG_ITEM_STRING, CONFIG_ITEM_FILE,
gbazin's avatar
   
gbazin committed
236
 * CONFIG_ITEM_DIRECTORY, and CONFIG_ITEM_MODULE).
gbazin's avatar
   
gbazin committed
237
 *****************************************************************************/
238
void __config_PutPsz( vlc_object_t *p_this,
239
                      const char *psz_name, const char *psz_value )
gbazin's avatar
   
gbazin committed
240
241
{
    module_config_t *p_config;
gbazin's avatar
   
gbazin committed
242
    vlc_value_t oldval, val;
gbazin's avatar
   
gbazin committed
243

244
    p_config = config_FindConfig( p_this, psz_name );
gbazin's avatar
   
gbazin committed
245

zorglub's avatar
zorglub committed
246

gbazin's avatar
   
gbazin committed
247
248
249
    /* sanity checks */
    if( !p_config )
    {
250
        msg_Warn( p_this, "option %s does not exist", psz_name );
gbazin's avatar
   
gbazin committed
251
252
        return;
    }
gbazin's avatar
   
gbazin committed
253
254
    if( (p_config->i_type!=CONFIG_ITEM_STRING) &&
        (p_config->i_type!=CONFIG_ITEM_FILE) &&
gbazin's avatar
   
gbazin committed
255
        (p_config->i_type!=CONFIG_ITEM_DIRECTORY) &&
zorglub's avatar
zorglub committed
256
        (p_config->i_type!=CONFIG_ITEM_MODULE_LIST) &&
zorglub's avatar
zorglub committed
257
        (p_config->i_type!=CONFIG_ITEM_MODULE_CAT) &&
zorglub's avatar
zorglub committed
258
        (p_config->i_type!=CONFIG_ITEM_MODULE_LIST_CAT) &&
gbazin's avatar
   
gbazin committed
259
        (p_config->i_type!=CONFIG_ITEM_MODULE) )
gbazin's avatar
   
gbazin committed
260
    {
261
        msg_Err( p_this, "option %s does not refer to a string", psz_name );
gbazin's avatar
   
gbazin committed
262
263
264
        return;
    }

gbazin's avatar
   
gbazin committed
265
266
    vlc_mutex_lock( p_config->p_lock );

gbazin's avatar
   
gbazin committed
267
268
    /* backup old value */
    oldval.psz_string = p_config->psz_value;
gbazin's avatar
   
gbazin committed
269

270
    if( psz_value && *psz_value ) p_config->psz_value = strdup( psz_value );
gbazin's avatar
   
gbazin committed
271
272
    else p_config->psz_value = NULL;

273
274
    p_config->b_dirty = VLC_TRUE;

gbazin's avatar
   
gbazin committed
275
276
    val.psz_string = p_config->psz_value;

gbazin's avatar
   
gbazin committed
277
    vlc_mutex_unlock( p_config->p_lock );
gbazin's avatar
   
gbazin committed
278

279
    if( p_config->pf_callback )
280
    {
gbazin's avatar
   
gbazin committed
281
282
        p_config->pf_callback( p_this, psz_name, oldval, val,
                               p_config->p_callback_data );
283
    }
gbazin's avatar
   
gbazin committed
284
285
286

    /* free old string */
    if( oldval.psz_string ) free( oldval.psz_string );
gbazin's avatar
   
gbazin committed
287
288
289
}

/*****************************************************************************
290
 * config_PutInt: set the integer value of an int variable
gbazin's avatar
   
gbazin committed
291
292
 *****************************************************************************
 * This function is used to set the value of variables which are internally
gbazin's avatar
   
gbazin committed
293
294
 * represented by an integer (CONFIG_ITEM_INTEGER and
 * CONFIG_ITEM_BOOL).
gbazin's avatar
   
gbazin committed
295
 *****************************************************************************/
296
void __config_PutInt( vlc_object_t *p_this, const char *psz_name, int i_value )
gbazin's avatar
   
gbazin committed
297
298
{
    module_config_t *p_config;
gbazin's avatar
   
gbazin committed
299
    vlc_value_t oldval, val;
gbazin's avatar
   
gbazin committed
300

301
    p_config = config_FindConfig( p_this, psz_name );
gbazin's avatar
   
gbazin committed
302
303
304
305

    /* sanity checks */
    if( !p_config )
    {
306
        msg_Warn( p_this, "option %s does not exist", psz_name );
gbazin's avatar
   
gbazin committed
307
308
        return;
    }
gbazin's avatar
   
gbazin committed
309
    if( (p_config->i_type!=CONFIG_ITEM_INTEGER) &&
310
        (p_config->i_type!=CONFIG_ITEM_KEY) &&
gbazin's avatar
   
gbazin committed
311
        (p_config->i_type!=CONFIG_ITEM_BOOL) )
gbazin's avatar
   
gbazin committed
312
    {
313
        msg_Err( p_this, "option %s does not refer to an int", psz_name );
gbazin's avatar
   
gbazin committed
314
315
316
        return;
    }

gbazin's avatar
   
gbazin committed
317
318
319
    /* backup old value */
    oldval.i_int = p_config->i_value;

320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
    /* 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;
    }
337

338
339
    p_config->b_dirty = VLC_TRUE;

gbazin's avatar
   
gbazin committed
340
341
    val.i_int = p_config->i_value;

342
    if( p_config->pf_callback )
343
    {
gbazin's avatar
   
gbazin committed
344
345
        p_config->pf_callback( p_this, psz_name, oldval, val,
                               p_config->p_callback_data );
346
    }
gbazin's avatar
   
gbazin committed
347
348
}

gbazin's avatar
   
gbazin committed
349
/*****************************************************************************
350
 * config_PutFloat: set the value of a float variable
gbazin's avatar
   
gbazin committed
351
352
 *****************************************************************************
 * This function is used to set the value of variables which are internally
gbazin's avatar
   
gbazin committed
353
 * represented by a float (CONFIG_ITEM_FLOAT).
gbazin's avatar
   
gbazin committed
354
 *****************************************************************************/
355
356
void __config_PutFloat( vlc_object_t *p_this,
                        const char *psz_name, float f_value )
gbazin's avatar
   
gbazin committed
357
358
{
    module_config_t *p_config;
gbazin's avatar
   
gbazin committed
359
    vlc_value_t oldval, val;
gbazin's avatar
   
gbazin committed
360

361
    p_config = config_FindConfig( p_this, psz_name );
gbazin's avatar
   
gbazin committed
362
363
364
365

    /* sanity checks */
    if( !p_config )
    {
366
        msg_Warn( p_this, "option %s does not exist", psz_name );
gbazin's avatar
   
gbazin committed
367
368
        return;
    }
gbazin's avatar
   
gbazin committed
369
    if( p_config->i_type != CONFIG_ITEM_FLOAT )
gbazin's avatar
   
gbazin committed
370
    {
371
        msg_Err( p_this, "option %s does not refer to a float", psz_name );
gbazin's avatar
   
gbazin committed
372
373
374
        return;
    }

gbazin's avatar
   
gbazin committed
375
376
377
    /* backup old value */
    oldval.f_float = p_config->f_value;

378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
    /* 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;
    }
395

396
397
    p_config->b_dirty = VLC_TRUE;

gbazin's avatar
   
gbazin committed
398
399
    val.f_float = p_config->f_value;

400
    if( p_config->pf_callback )
401
    {
gbazin's avatar
   
gbazin committed
402
403
        p_config->pf_callback( p_this, psz_name, oldval, val,
                               p_config->p_callback_data );
404
    }
gbazin's avatar
   
gbazin committed
405
406
}

gbazin's avatar
   
gbazin committed
407
408
409
410
/*****************************************************************************
 * config_FindConfig: find the config structure associated with an option.
 *****************************************************************************
 * FIXME: This function really needs to be optimized.
411
 * FIXME: And now even more.
gbazin's avatar
   
gbazin committed
412
 *****************************************************************************/
413
module_config_t *config_FindConfig( vlc_object_t *p_this, const char *psz_name )
gbazin's avatar
   
gbazin committed
414
{
415
    vlc_list_t *p_list;
gbazin's avatar
   
gbazin committed
416
    module_t *p_parser;
Sam Hocevar's avatar
   
Sam Hocevar committed
417
    module_config_t *p_item;
gbazin's avatar
   
gbazin committed
418
    int i_index;
gbazin's avatar
   
gbazin committed
419
420
421

    if( !psz_name ) return NULL;

422
    p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
423

424
    for( i_index = 0; i_index < p_list->i_count; i_index++ )
gbazin's avatar
   
gbazin committed
425
    {
426
        p_parser = (module_t *)p_list->p_values[i_index].p_object ;
gbazin's avatar
   
gbazin committed
427
428

        if( !p_parser->i_config_items )
429
430
            continue;

gbazin's avatar
   
gbazin committed
431
        for( p_item = p_parser->p_config;
gbazin's avatar
   
gbazin committed
432
             p_item->i_type != CONFIG_HINT_END;
Sam Hocevar's avatar
   
Sam Hocevar committed
433
             p_item++ )
gbazin's avatar
   
gbazin committed
434
        {
gbazin's avatar
   
gbazin committed
435
            if( p_item->i_type & CONFIG_HINT )
gbazin's avatar
   
gbazin committed
436
                /* ignore hints */
gbazin's avatar
   
gbazin committed
437
                continue;
Sam Hocevar's avatar
   
Sam Hocevar committed
438
            if( !strcmp( psz_name, p_item->psz_name ) )
439
            {
440
                vlc_list_release( p_list );
Sam Hocevar's avatar
   
Sam Hocevar committed
441
                return p_item;
442
            }
gbazin's avatar
   
gbazin committed
443
444
445
        }
    }

446
    vlc_list_release( p_list );
447

gbazin's avatar
   
gbazin committed
448
449
450
    return NULL;
}

451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
/*****************************************************************************
 * config_FindModule: find a specific module structure.
 *****************************************************************************/
module_t *config_FindModule( vlc_object_t *p_this, const char *psz_name )
{
    vlc_list_t *p_list;
    module_t *p_module, *p_result = NULL;
    int i_index;

    if( !psz_name ) return NULL;

    p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );

    for( i_index = 0; i_index < p_list->i_count; i_index++ )
    {
        p_module = (module_t *)p_list->p_values[i_index].p_object;
        if( !strcmp( p_module->psz_object_name, psz_name ) )
        {
             p_result = p_module;
             break;
        }
    }

    vlc_list_release( p_list );

    return p_result;
}

gbazin's avatar
   
gbazin committed
479
480
481
482
483
484
485
/*****************************************************************************
 * 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.
 *****************************************************************************/
486
void config_Duplicate( module_t *p_module, const module_config_t *p_orig )
gbazin's avatar
   
gbazin committed
487
{
gbazin's avatar
   
gbazin committed
488
    int i, j, i_lines = 1;
489
    module_config_t *p_item;
gbazin's avatar
   
gbazin committed
490

Sam Hocevar's avatar
   
Sam Hocevar committed
491
    /* Calculate the structure length */
492
493
494
    p_module->i_config_items = 0;
    p_module->i_bool_items = 0;

gbazin's avatar
   
gbazin committed
495
    for( p_item = p_orig; p_item->i_type != CONFIG_HINT_END; p_item++ )
496
497
498
    {
        i_lines++;

gbazin's avatar
   
gbazin committed
499
        if( p_item->i_type & CONFIG_ITEM )
500
501
502
503
        {
            p_module->i_config_items++;
        }

gbazin's avatar
   
gbazin committed
504
        if( p_item->i_type == CONFIG_ITEM_BOOL )
505
506
507
508
        {
            p_module->i_bool_items++;
        }
    }
Sam Hocevar's avatar
   
Sam Hocevar committed
509
510

    /* Allocate memory */
511
512
513
    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
514
    {
515
516
        msg_Err( p_module, "config error: can't duplicate p_config" );
        return;
gbazin's avatar
   
gbazin committed
517
518
    }

Sam Hocevar's avatar
   
Sam Hocevar committed
519
520
    /* Do the duplication job */
    for( i = 0; i < i_lines ; i++ )
gbazin's avatar
   
gbazin committed
521
    {
522
        p_module->p_config[i] = p_orig[i];
Sam Hocevar's avatar
   
Sam Hocevar committed
523

gbazin's avatar
   
gbazin committed
524
525
        p_module->p_config[i].i_value_orig = p_orig[i].i_value;
        p_module->p_config[i].f_value_orig = p_orig[i].f_value;
526
527
528
        p_module->p_config[i].i_value_saved = p_orig[i].i_value;
        p_module->p_config[i].f_value_saved = p_orig[i].f_value;
        p_module->p_config[i].psz_value_saved = 0;
gbazin's avatar
   
gbazin committed
529

530
        p_module->p_config[i].psz_type = p_orig[i].psz_type ?
gbazin's avatar
   
gbazin committed
531
                                   strdup( p_orig[i].psz_type ) : NULL;
532
        p_module->p_config[i].psz_name = p_orig[i].psz_name ?
gbazin's avatar
   
gbazin committed
533
                                   strdup( p_orig[i].psz_name ) : NULL;
534
535
        p_module->p_config[i].psz_current = p_orig[i].psz_current?
                                   strdup( p_orig[i].psz_current ) : NULL;
536
        p_module->p_config[i].psz_text = p_orig[i].psz_text ?
Sam Hocevar's avatar
   
Sam Hocevar committed
537
                                   strdup( _(p_orig[i].psz_text) ) : NULL;
538
        p_module->p_config[i].psz_longtext = p_orig[i].psz_longtext ?
Sam Hocevar's avatar
   
Sam Hocevar committed
539
                                   strdup( _(p_orig[i].psz_longtext) ) : NULL;
540
        p_module->p_config[i].psz_value = p_orig[i].psz_value ?
gbazin's avatar
   
gbazin committed
541
                                   strdup( p_orig[i].psz_value ) : NULL;
gbazin's avatar
   
gbazin committed
542
543
        p_module->p_config[i].psz_value_orig = p_orig[i].psz_value ?
                                   strdup( p_orig[i].psz_value ) : NULL;
gbazin's avatar
   
gbazin committed
544

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

gbazin's avatar
   
gbazin committed
547
        /* duplicate the string list */
548
        if( p_orig[i].i_list )
gbazin's avatar
   
gbazin committed
549
        {
550
            if( p_orig[i].ppsz_list )
gbazin's avatar
   
gbazin committed
551
            {
552
553
554
555
556
                p_module->p_config[i].ppsz_list =
                    malloc( (p_orig[i].i_list + 1) * sizeof(char *) );
                if( p_module->p_config[i].ppsz_list )
                {
                    for( j = 0; j < p_orig[i].i_list; j++ )
557
558
                        p_module->p_config[i].ppsz_list[j] = p_orig[i].ppsz_list[j] ?
                            strdup( p_orig[i].ppsz_list[j] ) : NULL ;
559
560
561
562
563
564
565
566
567
568
                    p_module->p_config[i].ppsz_list[j] = NULL;
                }
            }
            if( p_orig[i].ppsz_list_text )
            {
                p_module->p_config[i].ppsz_list_text =
                    malloc( (p_orig[i].i_list + 1) * sizeof(char *) );
                if( p_module->p_config[i].ppsz_list_text )
                {
                    for( j = 0; j < p_orig[i].i_list; j++ )
569
570
                        p_module->p_config[i].ppsz_list_text[j] = _(p_orig[i].ppsz_list_text[j]) ?
                            strdup( _(p_orig[i].ppsz_list_text[j] ) ) : NULL ;
571
572
573
574
575
576
577
578
579
580
581
582
583
                    p_module->p_config[i].ppsz_list_text[j] = NULL;
                }
            }
            if( p_orig[i].pi_list )
            {
                p_module->p_config[i].pi_list =
                    malloc( (p_orig[i].i_list + 1) * sizeof(int) );
                if( p_module->p_config[i].pi_list )
                {
                    for( j = 0; j < p_orig[i].i_list; j++ )
                        p_module->p_config[i].pi_list[j] =
                            p_orig[i].pi_list[j];
                }
gbazin's avatar
   
gbazin committed
584
585
586
            }
        }

587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
        /* duplicate the actions list */
        if( p_orig[i].i_action )
        {
            int j;

            p_module->p_config[i].ppf_action =
                malloc( p_orig[i].i_action * sizeof(void *) );
            p_module->p_config[i].ppsz_action_text =
                malloc( p_orig[i].i_action * sizeof(char *) );

            for( j = 0; j < p_orig[i].i_action; j++ )
            {
                p_module->p_config[i].ppf_action[j] =
                    p_orig[i].ppf_action[j];
                p_module->p_config[i].ppsz_action_text[j] =
                    p_orig[i].ppsz_action_text[j] ?
                    strdup( p_orig[i].ppsz_action_text[j] ) : NULL;
            }
        }

607
        p_module->p_config[i].pf_callback = p_orig[i].pf_callback;
gbazin's avatar
   
gbazin committed
608
    }
609
610
611
612
613
614
615
616
617
618
}

/*****************************************************************************
 * 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
619
    int i;
620

621
622
623
624
625
    if( p_item == NULL )
    {
        return;
    }

gbazin's avatar
   
gbazin committed
626
    for( ; p_item->i_type != CONFIG_HINT_END ; p_item++ )
627
    {
628
629
630
        if( p_item->psz_type )
            free( p_item->psz_type );

631
632
        if( p_item->psz_name )
            free( p_item->psz_name );
gbazin's avatar
   
gbazin committed
633

634
635
636
        if( p_item->psz_current )
            free( p_item->psz_current );

637
638
639
640
641
642
643
644
        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
645

gbazin's avatar
   
gbazin committed
646
647
648
        if( p_item->psz_value_orig )
            free( p_item->psz_value_orig );

649
650
651
        if( p_item->psz_value_saved )
            free( p_item->psz_value_saved );

652
        if( p_item->i_list )
gbazin's avatar
   
gbazin committed
653
        {
654
655
656
657
658
659
660
661
662
663
            for( i = 0; i < p_item->i_list; i++ )
            {
                if( p_item->ppsz_list && p_item->ppsz_list[i] )
                    free( p_item->ppsz_list[i] );
                if( p_item->ppsz_list_text && p_item->ppsz_list_text[i] )
                    free( p_item->ppsz_list_text[i] );
            }
            if( p_item->ppsz_list ) free( p_item->ppsz_list );
            if( p_item->ppsz_list_text ) free( p_item->ppsz_list_text );
            if( p_item->pi_list ) free( p_item->pi_list );
gbazin's avatar
   
gbazin committed
664
        }
665
666
667
668
669
670
671
672
673
674
675

        if( p_item->i_action )
        {
            for( i = 0; i < p_item->i_action; i++ )
            {
                if( p_item->ppsz_action_text[i] )
                    free( p_item->ppsz_action_text[i] );
            }
            if( p_item->ppf_action ) free( p_item->ppf_action );
            if( p_item->ppsz_action_text ) free( p_item->ppsz_action_text );
        }
676
677
678
679
    }

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

682
683
684
685
686
687
688
689
690
/*****************************************************************************
 * 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
691
    while( p_new->i_type != CONFIG_HINT_END )
692
    {
693
        p_new->pf_callback = p_orig->pf_callback;
694
695
696
697
698
699
700
701
702
703
704
705
        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
706
    while( p_new->i_type != CONFIG_HINT_END )
707
    {
708
        p_new->pf_callback = NULL;
709
710
711
712
        p_new++;
    }
}

gbazin's avatar
   
gbazin committed
713
714
715
716
717
718
719
720
721
722
/*****************************************************************************
 * config_ResetAll: reset the configuration data for all the modules.
 *****************************************************************************/
void __config_ResetAll( vlc_object_t *p_this )
{
    int i_index, i;
    vlc_list_t *p_list;
    module_t *p_module;

    /* Acquire config file lock */
723
    vlc_mutex_lock( &p_this->p_libvlc->config_lock );
gbazin's avatar
   
gbazin committed
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744

    p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );

    for( i_index = 0; i_index < p_list->i_count; i_index++ )
    {
        p_module = (module_t *)p_list->p_values[i_index].p_object ;
        if( p_module->b_submodule ) continue;

        for( i = 0; p_module->p_config[i].i_type != CONFIG_HINT_END; i++ )
        {
            p_module->p_config[i].i_value = p_module->p_config[i].i_value_orig;
            p_module->p_config[i].f_value = p_module->p_config[i].f_value_orig;
            if( p_module->p_config[i].psz_value )
                free( p_module->p_config[i].psz_value );
            p_module->p_config[i].psz_value =
                p_module->p_config[i].psz_value_orig ?
                strdup( p_module->p_config[i].psz_value_orig ) : NULL;
        }
    }

    vlc_list_release( p_list );
745
    vlc_mutex_unlock( &p_this->p_libvlc->config_lock );
gbazin's avatar
   
gbazin committed
746
747
}

gbazin's avatar
   
gbazin committed
748
749
750
751
752
753
/*****************************************************************************
 * config_LoadConfigFile: loads the configuration file.
 *****************************************************************************
 * This function is called to load the config options stored in the config
 * file.
 *****************************************************************************/
754
int __config_LoadConfigFile( vlc_object_t *p_this, const char *psz_module_name )
gbazin's avatar
   
gbazin committed
755
{
756
    vlc_list_t *p_list;
gbazin's avatar
   
gbazin committed
757
    module_t *p_parser;
Sam Hocevar's avatar
   
Sam Hocevar committed
758
    module_config_t *p_item;
gbazin's avatar
   
gbazin committed
759
760
761
    FILE *file;
    char line[1024];
    char *p_index, *psz_option_name, *psz_option_value;
gbazin's avatar
   
gbazin committed
762
    char *psz_filename, *psz_homedir, *psz_configfile;
gbazin's avatar
   
gbazin committed
763
    int i_index;
gbazin's avatar
   
gbazin committed
764

765
    psz_configfile = p_this->p_libvlc->psz_configfile;
gbazin's avatar
   
gbazin committed
766
    if( !psz_configfile || !psz_configfile )
gbazin's avatar
   
gbazin committed
767
    {
768
        psz_homedir = p_this->p_libvlc->psz_homedir;
gbazin's avatar
   
gbazin committed
769
770
771
772
773
774
775
776
        if( !psz_homedir )
        {
            msg_Err( p_this, "psz_homedir is null" );
            return -1;
        }
        psz_filename = (char *)malloc( sizeof("/" CONFIG_DIR "/" CONFIG_FILE) +
                                       strlen(psz_homedir) );
        if( psz_filename )
777
778
            sprintf( psz_filename,
                     "%s" DIR_SEP CONFIG_DIR DIR_SEP CONFIG_FILE,
gbazin's avatar
   
gbazin committed
779
780
781
782
783
                     psz_homedir );
    }
    else
    {
        psz_filename = strdup( psz_configfile );
gbazin's avatar
   
gbazin committed
784
    }
gbazin's avatar
   
gbazin committed
785

gbazin's avatar
   
gbazin committed
786
787
    if( !psz_filename )
    {
788
        msg_Err( p_this, "out of memory" );
gbazin's avatar
   
gbazin committed
789
790
791
        return -1;
    }

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

794
    /* Acquire config file lock */
795
    vlc_mutex_lock( &p_this->p_libvlc->config_lock );
796

797
    file = utf8_fopen( psz_filename, "rt" );
gbazin's avatar
   
gbazin committed
798
799
    if( !file )
    {
800
        msg_Warn( p_this, "config file %s does not exist yet", psz_filename );
gbazin's avatar
   
gbazin committed
801
        free( psz_filename );
802
        vlc_mutex_unlock( &p_this->p_libvlc->config_lock );
gbazin's avatar
   
gbazin committed
803
804
805
806
        return -1;
    }

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

809
    for( i_index = 0; i_index < p_list->i_count; i_index++ )
gbazin's avatar
   
gbazin committed
810
    {
811
        p_parser = (module_t *)p_list->p_values[i_index].p_object ;
gbazin's avatar
   
gbazin committed
812

813
        if( psz_module_name
gbazin's avatar
   
gbazin committed
814
             && strcmp( psz_module_name, p_parser->psz_object_name ) )
815
        {
gbazin's avatar
   
gbazin committed
816
            continue;
817
        }
gbazin's avatar
   
gbazin committed
818
819
820

        /* The config file is organized in sections, one per module. Look for
         * the interesting section ( a section is of the form [foo] ) */
821
        fseek( file, 0L, SEEK_SET );
gbazin's avatar
   
gbazin committed
822
823
        while( fgets( line, 1024, file ) )
        {
824
825
            if( (line[0] == '[')
               && (p_index = strchr(line,']'))
826
               && (p_index - &line[1]
gbazin's avatar
   
gbazin committed
827
828
829
                    == (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
830
            {
831
832
#if 0
                msg_Dbg( p_this, "loading config for module \"%s\"",
gbazin's avatar
   
gbazin committed
833
                                 p_parser->psz_object_name );
834
#endif
gbazin's avatar
   
gbazin committed
835
836
837
838
839
840
841
842
843
844
845
846

                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
847
848
            if( (line[0] == '#') || (line[0] == '\n') || (line[0] == (char)0) )
                continue;
gbazin's avatar
   
gbazin committed
849
850
851
852
853
854
855
856
857
858
859
860
861
862

            /* 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
863
            if( !p_parser->i_config_items )
864
865
866
867
            {
                continue;
            }

gbazin's avatar
   
gbazin committed
868
            /* try to match this option with one of the module's options */
gbazin's avatar
   
gbazin committed
869
            for( p_item = p_parser->p_config;
gbazin's avatar
   
gbazin committed
870
                 p_item->i_type != CONFIG_HINT_END;
Sam Hocevar's avatar
   
Sam Hocevar committed
871
                 p_item++ )
gbazin's avatar
   
gbazin committed
872
            {
gbazin's avatar
   
gbazin committed
873
                if( p_item->i_type & CONFIG_HINT )
gbazin's avatar
   
gbazin committed
874
875
                    /* ignore hints */
                    continue;
Sam Hocevar's avatar
   
Sam Hocevar committed
876
877

                if( !strcmp( p_item->psz_name, psz_option_name ) )
gbazin's avatar
   
gbazin committed
878
879
                {
                    /* We found it */
Sam Hocevar's avatar
   
Sam Hocevar committed
880
                    switch( p_item->i_type )
gbazin's avatar
   
gbazin committed
881
                    {
gbazin's avatar
   
gbazin committed
882
883
                    case CONFIG_ITEM_BOOL:
                    case CONFIG_ITEM_INTEGER:
gbazin's avatar
   
gbazin committed
884
885
                        if( !*psz_option_value )
                            break;                    /* ignore empty option */
gbazin's avatar
   
gbazin committed
886
                        p_item->i_value = strtol( psz_option_value, 0, 0 );
887
                        p_item->i_value_saved = p_item->i_value;
888
889
890
891
#if 0
                        msg_Dbg( p_this, "option \"%s\", value %i",
                                 p_item->psz_name, p_item->i_value );
#endif
gbazin's avatar
   
gbazin committed
892
893
                        break;

gbazin's avatar
   
gbazin committed
894
                    case CONFIG_ITEM_FLOAT:
gbazin's avatar
   
gbazin committed
895
896
                        if( !*psz_option_value )
                            break;                    /* ignore empty option */
897
                        p_item->f_value = (float)i18n_atof( psz_option_value);
898
899
                        p_item->f_value_saved = p_item->f_value;
#if 0
900
901
902
                        msg_Dbg( p_this, "option \"%s\", value %f",
                                 p_item->psz_name, (double)p_item->f_value );
#endif
gbazin's avatar
   
gbazin committed
903
                        break;
904
905
906
                    case CONFIG_ITEM_KEY:
                        if( !*psz_option_value )
                            break;                    /* ignore empty option */
907
908
                        p_item->i_value = ConfigStringToKey(psz_option_value);
                        p_item->i_value_saved = p_item->i_value;
909
                        break;
gbazin's avatar
   
gbazin committed
910

gbazin's avatar
   
gbazin committed
911
                    default:
Sam Hocevar's avatar
   
Sam Hocevar committed
912
                        vlc_mutex_lock( p_item->p_lock );
gbazin's avatar
   
gbazin committed
913
914

                        /* free old string */
Sam Hocevar's avatar
   
Sam Hocevar committed
915
916
                        if( p_item->psz_value )
                            free( p_item->psz_value );
gbazin's avatar
   
gbazin committed
917

Sam Hocevar's avatar
   
Sam Hocevar committed
918
                        p_item->psz_value = *psz_option_value ?
gbazin's avatar
   
gbazin committed
919
                            strdup( psz_option_value ) : NULL;
gbazin's avatar
   
gbazin committed
920

921
922
                        if( p_item->psz_value_saved )
                            free( p_item->psz_value_saved );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
923
                        p_item->psz_value_saved = NULL;
924
925
926
                        if( !p_item->psz_value || !p_item->psz_value_orig ||
                            (p_item->psz_value && p_item->psz_value_orig &&
                             strcmp(p_item->psz_value,p_item->psz_value_orig)))
927
                            p_item->psz_value_saved = p_item->psz_value ?
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
928
                                strdup( p_item->psz_value ) : NULL;
929

Sam Hocevar's avatar
   
Sam Hocevar committed
930
                        vlc_mutex_unlock( p_item->p_lock );
gbazin's avatar
   
gbazin committed
931

932
933
934
935
936
#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
937
938
939
940
941
942
943
                        break;
                    }
                }
            }
        }

    }
944
945

    vlc_list_release( p_list );
946

gbazin's avatar
   
gbazin committed
947
948
949
    fclose( file );
    free( psz_filename );

950
    vlc_mutex_unlock( &p_this->p_libvlc->config_lock );
gbazin's avatar
   
gbazin committed
951
952
953
954

    return 0;
}

955
/*****************************************************************************
956
 * config_CreateDir: Create configuration directory if it doesn't exist.
957
 *****************************************************************************/
958
int config_CreateDir( vlc_object_t *p_this, const char *psz_dirname )
959
960
961
{
    if( !psz_dirname && !*psz_dirname ) return -1;

962
    if( utf8_mkdir( psz_dirname ) && ( errno != EEXIST ) )
963
964
965
    {
        msg_Err( p_this, "could not create %s (%s)",
                 psz_dirname, strerror(errno) );
966
        return -1;
967
968
969
970
971
    }

    return 0;
}

gbazin's avatar
   
gbazin committed
972
973
974
975
976
977
978
979
/*****************************************************************************
 * 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.
 *
980
 * When we save we mustn't delete the config options of the modules that
gbazin's avatar
   
gbazin committed
981
 * haven't been loaded. So we cannot just create a new config file with the
982
 * config structures we've got in memory.
gbazin's avatar
   
gbazin committed
983
984
985
986
987
988
989
990
 * 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 ?
 *****************************************************************************/
991
992
static int SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name,
                           vlc_bool_t b_autosave )
gbazin's avatar
   
gbazin committed
993
{
gbazin's avatar
   
gbazin committed
994
    module_t *p_parser;
995
    vlc_list_t *p_list;
Sam Hocevar's avatar
   
Sam Hocevar committed
996
    module_config_t *p_item;
gbazin's avatar
   
gbazin committed
997
998
    FILE *file;
    char p_line[1024], *p_index2;
Sam Hocevar's avatar
   
Sam Hocevar committed
999
    int i_sizebuf = 0;