configuration.h 18.8 KB
Newer Older
gbazin's avatar
   
gbazin committed
1
2
3
4
5
/*****************************************************************************
 * configuration.h : configuration management module
 * This file describes the programming interface for the configuration module.
 * It includes functions allowing to declare, get or set configuration options.
 *****************************************************************************
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
6
 * Copyright (C) 1999-2006 the VideoLAN team
7
 * $Id$
gbazin's avatar
   
gbazin committed
8
 *
9
 * Authors: Gildas Bazin <gbazin@videolan.org>
gbazin's avatar
   
gbazin committed
10
11
12
13
14
 *
 * 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.
zorglub's avatar
zorglub committed
15
 *
gbazin's avatar
   
gbazin committed
16
17
18
19
20
21
22
 * 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
23
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
gbazin's avatar
   
gbazin committed
24
25
26
27
28
29
 *****************************************************************************/

/*****************************************************************************
 * Macros used to build the configuration structure.
 *****************************************************************************/

gbazin's avatar
   
gbazin committed
30
/* Configuration hint types */
zorglub's avatar
zorglub committed
31
32


gbazin's avatar
   
gbazin committed
33
34
35
36
37
#define CONFIG_HINT_END                     0x0001  /* End of config */
#define CONFIG_HINT_CATEGORY                0x0002  /* Start of new category */
#define CONFIG_HINT_SUBCATEGORY             0x0003  /* Start of sub-category */
#define CONFIG_HINT_SUBCATEGORY_END         0x0004  /* End of sub-category */
#define CONFIG_HINT_USAGE                   0x0005  /* Usage information */
gbazin's avatar
   
gbazin committed
38

zorglub's avatar
zorglub committed
39
40
41
42
#define CONFIG_CATEGORY                     0x0006 /* Set category */
#define CONFIG_SUBCATEGORY                  0x0007 /* Set subcategory */
#define CONFIG_SECTION                      0x0008 /* Start of new section */

gbazin's avatar
   
gbazin committed
43
#define CONFIG_HINT                         0x000F
gbazin's avatar
   
gbazin committed
44
45

/* Configuration item types */
gbazin's avatar
   
gbazin committed
46
47
48
49
50
51
#define CONFIG_ITEM_STRING                  0x0010  /* String option */
#define CONFIG_ITEM_FILE                    0x0020  /* File option */
#define CONFIG_ITEM_MODULE                  0x0030  /* Module option */
#define CONFIG_ITEM_INTEGER                 0x0040  /* Integer option */
#define CONFIG_ITEM_BOOL                    0x0050  /* Bool option */
#define CONFIG_ITEM_FLOAT                   0x0060  /* Float option */
gbazin's avatar
   
gbazin committed
52
#define CONFIG_ITEM_DIRECTORY               0x0070  /* Directory option */
53
#define CONFIG_ITEM_KEY                     0x0080  /* Hot key option */
54
55
56
#define CONFIG_ITEM_MODULE_CAT              0x0090  /* Module option */
#define CONFIG_ITEM_MODULE_LIST             0x00A0  /* Module option */
#define CONFIG_ITEM_MODULE_LIST_CAT         0x00B0  /* Module option */
gbazin's avatar
   
gbazin committed
57

gbazin's avatar
   
gbazin committed
58
#define CONFIG_ITEM                         0x00F0
gbazin's avatar
   
gbazin committed
59

zorglub's avatar
zorglub committed
60
61
62
63
64
/*******************************************************************
 * All predefined categories and subcategories
 *******************************************************************/
#define CAT_INTERFACE 1
   #define SUBCAT_INTERFACE_GENERAL 101
zorglub's avatar
zorglub committed
65
66
67
   #define SUBCAT_INTERFACE_MAIN 102
   #define SUBCAT_INTERFACE_CONTROL 103
   #define SUBCAT_INTERFACE_HOTKEYS 104
zorglub's avatar
zorglub committed
68
69
70
71
72
73
74
75
76
77
78
79
80
81

#define CAT_AUDIO 2
   #define SUBCAT_AUDIO_GENERAL 201
   #define SUBCAT_AUDIO_AOUT 202
   #define SUBCAT_AUDIO_AFILTER 203
   #define SUBCAT_AUDIO_VISUAL 204
   #define SUBCAT_AUDIO_MISC 205

#define CAT_VIDEO 3
   #define SUBCAT_VIDEO_GENERAL 301
   #define SUBCAT_VIDEO_VOUT 302
   #define SUBCAT_VIDEO_VFILTER 303
   #define SUBCAT_VIDEO_TEXT 304
   #define SUBCAT_VIDEO_SUBPIC 305
82
   #define SUBCAT_VIDEO_VFILTER2 306
zorglub's avatar
zorglub committed
83
84

#define CAT_INPUT 4
85
86
87
88
89
90
91
   #define SUBCAT_INPUT_GENERAL 401
   #define SUBCAT_INPUT_ACCESS 402
   #define SUBCAT_INPUT_ACCESS_FILTER 403
   #define SUBCAT_INPUT_DEMUX 404
   #define SUBCAT_INPUT_VCODEC 405
   #define SUBCAT_INPUT_ACODEC 406
   #define SUBCAT_INPUT_SCODEC 407
zorglub's avatar
zorglub committed
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115

#define CAT_SOUT 5
   #define SUBCAT_SOUT_GENERAL 501
   #define SUBCAT_SOUT_STREAM 502
   #define SUBCAT_SOUT_MUX 503
   #define SUBCAT_SOUT_ACO 504
   #define SUBCAT_SOUT_PACKETIZER 505
   #define SUBCAT_SOUT_SAP 506
   #define SUBCAT_SOUT_VOD 507

#define CAT_ADVANCED 6
   #define SUBCAT_ADVANCED_CPU 601
   #define SUBCAT_ADVANCED_MISC 602
   #define SUBCAT_ADVANCED_NETWORK 603
   #define SUBCAT_ADVANCED_XML 604

#define CAT_PLAYLIST 7
   #define SUBCAT_PLAYLIST_GENERAL 701
   #define SUBCAT_PLAYLIST_SD 702
   #define SUBCAT_PLAYLIST_EXPORT 703

struct config_category_t
{
    int         i_id;
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
116
117
    const char *psz_name;
    const char *psz_help;
zorglub's avatar
zorglub committed
118
119
};

120
struct module_config_t
gbazin's avatar
   
gbazin committed
121
{
Sam Hocevar's avatar
   
Sam Hocevar committed
122
    int          i_type;                               /* Configuration type */
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
123
124
    const char  *psz_type;                          /* Configuration subtype */
    const char  *psz_name;                                    /* Option name */
Sam Hocevar's avatar
   
Sam Hocevar committed
125
    char         i_short;                      /* Optional short option name */
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
126
127
    const char  *psz_text;      /* Short comment on the configuration option */
    const char  *psz_longtext;   /* Long comment on the configuration option */
Rémi Denis-Courmont's avatar
Fix    
Rémi Denis-Courmont committed
128
    const char  *psz_value;                                  /* Option value */
Sam Hocevar's avatar
   
Sam Hocevar committed
129
130
    int          i_value;                                    /* Option value */
    float        f_value;                                    /* Option value */
131
132
133
134
    int         i_min;                               /* Option minimum value */
    int         i_max;                               /* Option maximum value */
    float       f_min;                               /* Option minimum value */
    float       f_max;                               /* Option maximum value */
gbazin's avatar
   
gbazin committed
135

136
    /* Function to call when commiting a change */
gbazin's avatar
   
gbazin committed
137
138
    vlc_callback_t pf_callback;
    void          *p_callback_data;
139

140
    /* Values list */
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
141
    const char **ppsz_list;        /* List of possible values for the option */
142
    int         *pi_list;          /* Idem for integers */
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
143
    const char **ppsz_list_text;   /* Friendly names for list values */
144
    int          i_list;           /* Options list size */
gbazin's avatar
   
gbazin committed
145

146
147
    /* Actions list */
    vlc_callback_t *ppf_action;    /* List of possible actions for a config */
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
148
    const char    **ppsz_action_text;         /* Friendly names for actions */
149
150
    int            i_action;                            /* actions list size */

151
    /* Deprecated */
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
152
    const char    *psz_current;   /* Good option name */
153
    vlc_bool_t     b_strict;      /* Transitionnal or strict */
154
    /* Misc */
gbazin's avatar
   
gbazin committed
155
    vlc_mutex_t *p_lock;            /* Lock to use when modifying the config */
156
    vlc_bool_t   b_dirty;          /* Dirty flag to indicate a config change */
gbazin's avatar
   
gbazin committed
157
    vlc_bool_t   b_advanced;          /* Flag to indicate an advanced option */
dionoea's avatar
dionoea committed
158
    vlc_bool_t   b_internal;   /* Flag to indicate option is not to be shown */
159
160
    vlc_bool_t   b_restart;    /* Flag to indicate the option need a restart */
                               /* to take effect */
gbazin's avatar
   
gbazin committed
161
162

    /* Original option values */
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
163
    const char  *psz_value_orig;
gbazin's avatar
   
gbazin committed
164
165
    int          i_value_orig;
    float        f_value_orig;
166
167

    /* Option values loaded from config file */
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
168
    const char  *psz_value_saved;
169
170
171
    int          i_value_saved;
    float        f_value_saved;
    vlc_bool_t   b_autosave;       /* Config will be auto-saved at exit time */
172
};
gbazin's avatar
   
gbazin committed
173
174
175
176
177

/*****************************************************************************
 * Prototypes - these methods are used to get, set or manipulate configuration
 * data.
 *****************************************************************************/
gbazin's avatar
   
gbazin committed
178
VLC_EXPORT( int,    __config_GetType,  (vlc_object_t *, const char *) );
179
180
181
182
183
VLC_EXPORT( int,    __config_GetInt,   (vlc_object_t *, const char *) );
VLC_EXPORT( void,   __config_PutInt,   (vlc_object_t *, const char *, int) );
VLC_EXPORT( float,  __config_GetFloat, (vlc_object_t *, const char *) );
VLC_EXPORT( void,   __config_PutFloat, (vlc_object_t *, const char *, float) );
VLC_EXPORT( char *, __config_GetPsz,   (vlc_object_t *, const char *) );
184
VLC_EXPORT( void,   __config_PutPsz,   (vlc_object_t *, const char *, const char *) );
185

186
187
VLC_EXPORT( int,    __config_LoadCmdLine,  ( vlc_object_t *, int *, char *[], vlc_bool_t ) );
VLC_EXPORT( char *,   config_GetHomeDir,     ( void ) );
188
VLC_EXPORT( char *,   config_GetUserDir,     ( void ) );
189
VLC_EXPORT( const char *, config_GetDataDir, ( const vlc_object_t * ) );
190
191
VLC_EXPORT( int,    __config_LoadConfigFile, ( vlc_object_t *, const char * ) );
VLC_EXPORT( int,    __config_SaveConfigFile, ( vlc_object_t *, const char * ) );
gbazin's avatar
   
gbazin committed
192
193
VLC_EXPORT( void,   __config_ResetAll, ( vlc_object_t * ) );

194
195
VLC_EXPORT( module_config_t *, config_FindConfig,( vlc_object_t *, const char * ) );
VLC_EXPORT( module_t *, config_FindModule,( vlc_object_t *, const char * ) );
gbazin's avatar
   
gbazin committed
196

197
198
VLC_EXPORT( void, config_Duplicate, ( module_t *, module_config_t * ) );
            void  config_Free       ( module_t * );
199

200
201
VLC_EXPORT( void, config_SetCallbacks, ( module_config_t *, module_config_t * ) );
VLC_EXPORT( void, config_UnsetCallbacks, ( module_config_t * ) );
gbazin's avatar
   
gbazin committed
202

gbazin's avatar
   
gbazin committed
203
#define config_GetType(a,b) __config_GetType(VLC_OBJECT(a),b)
204
205
206
207
208
209
#define config_GetInt(a,b) __config_GetInt(VLC_OBJECT(a),b)
#define config_PutInt(a,b,c) __config_PutInt(VLC_OBJECT(a),b,c)
#define config_GetFloat(a,b) __config_GetFloat(VLC_OBJECT(a),b)
#define config_PutFloat(a,b,c) __config_PutFloat(VLC_OBJECT(a),b,c)
#define config_GetPsz(a,b) __config_GetPsz(VLC_OBJECT(a),b)
#define config_PutPsz(a,b,c) __config_PutPsz(VLC_OBJECT(a),b,c)
gbazin's avatar
   
gbazin committed
210

211
212
213
#define config_LoadCmdLine(a,b,c,d) __config_LoadCmdLine(VLC_OBJECT(a),b,c,d)
#define config_LoadConfigFile(a,b) __config_LoadConfigFile(VLC_OBJECT(a),b)
#define config_SaveConfigFile(a,b) __config_SaveConfigFile(VLC_OBJECT(a),b)
gbazin's avatar
   
gbazin committed
214
#define config_ResetAll(a) __config_ResetAll(VLC_OBJECT(a))
215

216
/* internal only */
217
int config_CreateDir( vlc_object_t *, const char * );
218
int config_AutoSaveConfigFile( vlc_object_t * );
219

gbazin's avatar
   
gbazin committed
220
221
222
/*****************************************************************************
 * Macros used to build the configuration structure.
 *
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
223
 * Note that internally we support only 3 types of config data: int, float
gbazin's avatar
   
gbazin committed
224
225
 *   and string.
 *   The other types declared here just map to one of these 3 basic types but
gbazin's avatar
   
gbazin committed
226
227
228
 *   have the advantage of also providing very good hints to a configuration
 *   interface so as to make it more user friendly.
 * The configuration structure also includes category hints. These hints can
gbazin's avatar
   
gbazin committed
229
230
 *   provide a configuration interface with some very useful data and again
 *   allow for a more user friendly interface.
gbazin's avatar
   
gbazin committed
231
232
 *****************************************************************************/

233
#define add_config_inner( ) \
234
    i_config++; \
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
    if( (i_config % 10) == 0 ) \
        p_config = (module_config_t *) \
             realloc(p_config, (i_config+11) * sizeof(module_config_t)); \
    memset( p_config + i_config, 0, sizeof( *p_config ) )

#define add_type_inner( type ) \
    add_config_inner( ); \
    p_config[i_config].i_type = type

#define add_typedesc_inner( type, text, longtext ) \
    add_type_inner( type ); \
    p_config[i_config].psz_text = text; \
    p_config[i_config].psz_longtext = longtext

#define add_typeadv_inner( type, text, longtext, advc ) \
    add_typedesc_inner( type, text, longtext ); \
    p_config[i_config].b_advanced = advc

#define add_typename_inner( type, name, text, longtext, advc, cb ) \
    add_typeadv_inner( type, text, longtext, advc ); \
    p_config[i_config].psz_name = name; \
    p_config[i_config].pf_callback = cb

#define add_string_inner( type, name, text, longtext, advc, cb, value ) \
    add_typename_inner( type, name, text, longtext, advc, cb ); \
    p_config[i_config].psz_value = value

#define add_int_inner( type, name, text, longtext, advc, cb, value ) \
    add_typename_inner( type, name, text, longtext, advc, cb ); \
    p_config[i_config].i_value = value


#define set_category( i_id ) \
    add_type_inner( CONFIG_CATEGORY ); \
    p_config[i_config].i_value = i_id
zorglub's avatar
zorglub committed
270
271

#define set_subcategory( i_id ) \
272
273
274
275
276
    add_type_inner( CONFIG_SUBCATEGORY ); \
    p_config[i_config].i_value = i_id

#define set_section( text, longtext ) \
    add_typedesc_inner( CONFIG_SECTION, text, longtext )
zorglub's avatar
zorglub committed
277
278

#define add_category_hint( text, longtext, advc ) \
279
    add_typeadv_inner( CONFIG_HINT_CATEGORY, text, longtext, advc )
zorglub's avatar
zorglub committed
280
281

#define add_subcategory_hint( text, longtext ) \
282
    add_typedesc_inner( CONFIG_HINT_SUBCATEGORY, text, longtext )
zorglub's avatar
zorglub committed
283

284
#define end_subcategory_hint \
285
286
    add_type_inner( CONFIG_HINT_SUBCATEGORY_END )

287
#define add_usage_hint( text ) \
288
    add_typedesc_inner( CONFIG_HINT_USAGE, text, NULL )
289

290
291
#define add_string( name, value, p_callback, text, longtext, advc ) \
    add_string_inner( CONFIG_ITEM_STRING, name, text, longtext, advc, p_callback, value )
zorglub's avatar
zorglub committed
292

293
294
#define add_file( name, value, p_callback, text, longtext, advc ) \
    add_string_inner( CONFIG_ITEM_FILE, name, text, longtext, advc, p_callback, value )
zorglub's avatar
zorglub committed
295

296
297
#define add_directory( name, value, p_callback, text, longtext, advc ) \
    add_string_inner( CONFIG_ITEM_DIRECTORY, name, text, longtext, advc, p_callback, value )
zorglub's avatar
zorglub committed
298

299
300
301
#define add_module( name, psz_caps, value, p_callback, text, longtext, advc ) \
    add_string_inner( CONFIG_ITEM_MODULE, name, text, longtext, advc, p_callback, value ); \
    p_config[i_config].psz_type = psz_caps
zorglub's avatar
zorglub committed
302

303
304
305
#define add_module_cat( name, i_subcategory, value, p_callback, text, longtext, advc ) \
    add_string_inner( CONFIG_ITEM_MODULE_CAT, name, text, longtext, advc, p_callback, value ); \
    p_config[i_config].i_min = i_subcategory /* gruik */
zorglub's avatar
zorglub committed
306

307
308
309
#define add_module_list( name, psz_caps, value, p_callback, text, longtext, advc ) \
    add_string_inner( CONFIG_ITEM_MODULE_LIST, name, text, longtext, advc, p_callback, value ); \
    p_config[i_config].psz_type = psz_caps
zorglub's avatar
zorglub committed
310

311
312
313
#define add_module_list_cat( name, i_subcategory, value, p_callback, text, longtext, advc ) \
    add_string_inner( CONFIG_ITEM_MODULE_LIST_CAT, name, text, longtext, advc, p_callback, value ); \
    p_config[i_config].i_min = i_subcategory /* gruik */
zorglub's avatar
zorglub committed
314

315
316
#define add_integer( name, value, p_callback, text, longtext, advc ) \
    add_int_inner( CONFIG_ITEM_INTEGER, name, text, longtext, advc, p_callback, value )
zorglub's avatar
zorglub committed
317

318
319
#define add_key( name, value, p_callback, text, longtext, advc ) \
    add_int_inner( CONFIG_ITEM_KEY, name, text, longtext, advc, p_callback, value )
zorglub's avatar
zorglub committed
320

321
322
323
#define add_integer_with_range( name, value, i_min, i_max, p_callback, text, longtext, advc ) \
    add_integer( name, value, p_callback, text, longtext, advc ); \
    change_integer_range( i_min, i_max )
zorglub's avatar
zorglub committed
324

325
326
327
#define add_float( name, value, p_callback, text, longtext, advc ) \
    add_typename_inner( CONFIG_ITEM_FLOAT, name, text, longtext, advc, p_callback ); \
    p_config[i_config].f_value = value
zorglub's avatar
zorglub committed
328

329
330
331
332
333
334
335
#define add_float_with_range( name, value, f_min, f_max, p_callback, text, longtext, advc ) \
    add_float( name, value, p_callback, text, longtext, advc ); \
    change_float_range( f_min, f_max )

#define add_bool( name, value, p_callback, text, longtext, advc ) \
    add_typename_inner( CONFIG_ITEM_BOOL, name, text, longtext, advc, p_callback ); \
    p_config[i_config].i_value = value
zorglub's avatar
zorglub committed
336

Rémi Denis-Courmont's avatar
Grammar    
Rémi Denis-Courmont committed
337
/* For renamed option */
338
#define add_deprecated( name, strict ) \
339
340
341
342
343
344
345
    add_config_inner( ); \
    p_config[ i_config ].i_type = p_config[ i_config -1 ].i_type; \
    p_config[ i_config ].psz_name = name; \
    p_config[i_config].b_strict = strict; \
    p_config[ i_config ].psz_current = p_config[ i_config-1].psz_current \
        ? p_config[ i_config-1 ].psz_current \
        : p_config[ i_config-1 ].psz_name;
346

Rémi Denis-Courmont's avatar
Grammar    
Rémi Denis-Courmont committed
347
/* For removed option */
348
#define add_suppressed_inner( name, type ) \
349
350
351
    add_type_inner( type ); \
    p_config[ i_config ].psz_name = name; \
    p_config[ i_config ].psz_current = "SUPPRESSED";
352

353
354
355
#define add_suppressed_bool( name ) \
        add_suppressed_inner( name, CONFIG_ITEM_BOOL )

356
#define add_suppressed_integer( name ) \
357
358
        add_suppressed_inner( name, CONFIG_ITEM_INTEGER )

359
#define add_suppressed_float( name ) \
360
361
        add_suppressed_inner( name, CONFIG_ITEM_FLOAT )

362
#define add_suppressed_string( name ) \
363
364
        add_suppressed_inner( name, CONFIG_ITEM_STRING )

365
366
367
368
369
370
371
/* Modifier macros for the config options (used for fine tuning) */
#define change_short( ch ) \
    p_config[i_config].i_short = ch;

#define change_string_list( list, list_text, list_update_func ) \
    p_config[i_config].i_list = sizeof(list)/sizeof(char *); \
    p_config[i_config].ppsz_list = list; \
372
    p_config[i_config].ppsz_list_text = list_text;
373
374
375

#define change_integer_list( list, list_text, list_update_func ) \
    p_config[i_config].i_list = sizeof(list)/sizeof(int); \
376
    p_config[i_config].pi_list = (int *)list; \
377
378
    p_config[i_config].ppsz_list_text = list_text;

379
380
381
382
383
384
385
386
#define change_integer_range( min, max ) \
    p_config[i_config].i_min = min; \
    p_config[i_config].i_max = max;

#define change_float_range( min, max ) \
    p_config[i_config].f_min = min; \
    p_config[i_config].f_max = max;

387
388
389
390
391
392
393
#define change_action_add( pf_action, action_text ) \
    if( !p_config[i_config].i_action ) \
    { p_config[i_config].ppsz_action_text = 0; \
      p_config[i_config].ppf_action = 0; } \
    p_config[i_config].ppf_action = (vlc_callback_t *) \
      realloc( p_config[i_config].ppf_action, \
      (p_config[i_config].i_action + 1) * sizeof(void *) ); \
394
    p_config[i_config].ppsz_action_text = (const char **)\
395
396
397
398
399
400
      realloc( p_config[i_config].ppsz_action_text, \
      (p_config[i_config].i_action + 1) * sizeof(void *) ); \
    p_config[i_config].ppf_action[p_config[i_config].i_action] = pf_action; \
    p_config[i_config].ppsz_action_text[p_config[i_config].i_action] = \
      action_text; \
    p_config[i_config].i_action++;
401

402
403
404
#define change_internal() \
    p_config[i_config].b_internal = VLC_TRUE;

405
406
407
#define change_need_restart() \
    p_config[i_config].b_restart = VLC_TRUE;

408
409
#define change_autosave() \
    p_config[i_config].b_autosave = VLC_TRUE;
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451


/****************************************************************************
 * config_chain_t:
 ****************************************************************************/
struct config_chain_t
{
    config_chain_t *p_next;

    char        *psz_name;
    char        *psz_value;
};

#define config_ChainParse( a, b, c, d ) __config_ChainParse( VLC_OBJECT(a), b, c, d )
VLC_EXPORT( void,   __config_ChainParse, ( vlc_object_t *, char *psz_prefix, const char **ppsz_options, config_chain_t * ) );
VLC_EXPORT( char *, config_ChainCreate, ( char **, config_chain_t **, char * ) );
VLC_EXPORT( void, config_ChainDestroy, ( config_chain_t * ) );

static inline config_chain_t *config_chain_find( config_chain_t *p_cfg, char *psz_name )
{
    while( p_cfg && strcmp( p_cfg->psz_name, psz_name ) )
    {
        p_cfg = p_cfg->p_next;
    }

    return p_cfg;
}

static inline char *config_chain_find_value( config_chain_t *p_cfg, char *psz_name )
{
    while( p_cfg && strcmp( p_cfg->psz_name, psz_name ) )
    {
        p_cfg = p_cfg->p_next;
    }

    if( p_cfg && p_cfg->psz_value )
    {
        return( p_cfg->psz_value );
    }

    return NULL;
}