]> git.sesse.net Git - vlc/blob - src/config/core.c
Move configuration defines to <vlc_plugin.h>
[vlc] / src / config / core.c
1 /*****************************************************************************
2  * core.c management of the modules configuration
3  *****************************************************************************
4  * Copyright (C) 2001-2007 VLC authors and VideoLAN
5  * $Id$
6  *
7  * Authors: Gildas Bazin <gbazin@videolan.org>
8  *
9  * This program is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation; either version 2.1 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 #ifdef HAVE_CONFIG_H
25 # include "config.h"
26 #endif
27
28 #include <vlc_common.h>
29 #include <vlc_keys.h>
30 #include <vlc_modules.h>
31 #include <vlc_plugin.h>
32
33 #include "vlc_configuration.h"
34
35 #include <assert.h>
36
37 #include "configuration.h"
38 #include "modules/modules.h"
39
40 vlc_rwlock_t config_lock = VLC_STATIC_RWLOCK;
41
42 static inline char *strdupnull (const char *src)
43 {
44     return src ? strdup (src) : NULL;
45 }
46
47 #undef config_GetType
48 /*****************************************************************************
49  * config_GetType: get the type of a variable (bool, int, float, string)
50  *****************************************************************************
51  * This function is used to get the type of a variable from its name.
52  * Beware, this is quite slow.
53  *****************************************************************************/
54 int config_GetType( vlc_object_t *p_this, const char *psz_name )
55 {
56     module_config_t *p_config;
57     int i_type;
58
59     p_config = config_FindConfig( p_this, psz_name );
60
61     /* sanity checks */
62     if( !p_config )
63     {
64         return 0;
65     }
66
67     switch( CONFIG_CLASS(p_config->i_type) )
68     {
69     case CONFIG_ITEM_FLOAT:
70         i_type = VLC_VAR_FLOAT;
71         break;
72
73     case CONFIG_ITEM_INTEGER:
74         i_type = VLC_VAR_INTEGER;
75         break;
76
77     case CONFIG_ITEM_BOOL:
78         i_type = VLC_VAR_BOOL;
79         break;
80
81     case CONFIG_ITEM_STRING:
82         i_type = VLC_VAR_STRING;
83         break;
84
85     default:
86         i_type = 0;
87         break;
88     }
89
90     return i_type;
91 }
92
93 bool config_IsSafe( const char *name )
94 {
95     module_config_t *p_config = config_FindConfig( NULL, name );
96     return p_config != NULL && p_config->b_safe;
97 }
98
99 #undef config_GetInt
100 /*****************************************************************************
101  * config_GetInt: get the value of an int variable
102  *****************************************************************************
103  * This function is used to get the value of variables which are internally
104  * represented by an integer (CONFIG_ITEM_INTEGER and
105  * CONFIG_ITEM_BOOL).
106  *****************************************************************************/
107 int64_t config_GetInt( vlc_object_t *p_this, const char *psz_name )
108 {
109     module_config_t *p_config;
110
111     p_config = config_FindConfig( p_this, psz_name );
112
113     /* sanity checks */
114     if( !p_config )
115     {
116         msg_Err( p_this, "option %s does not exist", psz_name );
117         return -1;
118     }
119
120     if (!IsConfigIntegerType (p_config->i_type))
121     {
122         msg_Err( p_this, "option %s does not refer to an int", psz_name );
123         return -1;
124     }
125
126     int64_t val;
127
128     vlc_rwlock_rdlock (&config_lock);
129     val = p_config->value.i;
130     vlc_rwlock_unlock (&config_lock);
131     return val;
132 }
133
134 #undef config_GetFloat
135 /*****************************************************************************
136  * config_GetFloat: get the value of a float variable
137  *****************************************************************************
138  * This function is used to get the value of variables which are internally
139  * represented by a float (CONFIG_ITEM_FLOAT).
140  *****************************************************************************/
141 float config_GetFloat( vlc_object_t *p_this, const char *psz_name )
142 {
143     module_config_t *p_config;
144
145     p_config = config_FindConfig( p_this, psz_name );
146
147     /* sanity checks */
148     if( !p_config )
149     {
150         msg_Err( p_this, "option %s does not exist", psz_name );
151         return -1;
152     }
153
154     if (!IsConfigFloatType (p_config->i_type))
155     {
156         msg_Err( p_this, "option %s does not refer to a float", psz_name );
157         return -1;
158     }
159
160     float val;
161
162     vlc_rwlock_rdlock (&config_lock);
163     val = p_config->value.f;
164     vlc_rwlock_unlock (&config_lock);
165     return val;
166 }
167
168 #undef config_GetPsz
169 /*****************************************************************************
170  * config_GetPsz: get the string value of a string variable
171  *****************************************************************************
172  * This function is used to get the value of variables which are internally
173  * represented by a string (CONFIG_ITEM_STRING, CONFIG_ITEM_*FILE,
174  * CONFIG_ITEM_DIRECTORY, CONFIG_ITEM_PASSWORD, and CONFIG_ITEM_MODULE).
175  *
176  * Important note: remember to free() the returned char* because it's a
177  *   duplicate of the actual value. It isn't safe to return a pointer to the
178  *   actual value as it can be modified at any time.
179  *****************************************************************************/
180 char * config_GetPsz( vlc_object_t *p_this, const char *psz_name )
181 {
182     module_config_t *p_config;
183
184     p_config = config_FindConfig( p_this, psz_name );
185
186     /* sanity checks */
187     if( !p_config )
188     {
189         msg_Err( p_this, "option %s does not exist", psz_name );
190         return NULL;
191     }
192
193     if (!IsConfigStringType (p_config->i_type))
194     {
195         msg_Err( p_this, "option %s does not refer to a string", psz_name );
196         return NULL;
197     }
198
199     /* return a copy of the string */
200     vlc_rwlock_rdlock (&config_lock);
201     char *psz_value = strdupnull (p_config->value.psz);
202     vlc_rwlock_unlock (&config_lock);
203
204     return psz_value;
205 }
206
207 #undef config_PutPsz
208 /*****************************************************************************
209  * config_PutPsz: set the string value of a string variable
210  *****************************************************************************
211  * This function is used to set the value of variables which are internally
212  * represented by a string (CONFIG_ITEM_STRING, CONFIG_ITEM_*FILE,
213  * CONFIG_ITEM_DIRECTORY, CONFIG_ITEM_PASSWORD, and CONFIG_ITEM_MODULE).
214  *****************************************************************************/
215 void config_PutPsz( vlc_object_t *p_this,
216                       const char *psz_name, const char *psz_value )
217 {
218     module_config_t *p_config;
219
220     p_config = config_FindConfig( p_this, psz_name );
221
222
223     /* sanity checks */
224     if( !p_config )
225     {
226         msg_Warn( p_this, "option %s does not exist", psz_name );
227         return;
228     }
229
230     if (!IsConfigStringType (p_config->i_type))
231     {
232         msg_Err( p_this, "option %s does not refer to a string", psz_name );
233         return;
234     }
235
236     char *str, *oldstr;
237     if ((psz_value != NULL) && *psz_value)
238         str = strdup (psz_value);
239     else
240         str = NULL;
241
242     vlc_rwlock_wrlock (&config_lock);
243     oldstr = (char *)p_config->value.psz;
244     p_config->value.psz = str;
245     p_config->b_dirty = true;
246     vlc_rwlock_unlock (&config_lock);
247
248     free (oldstr);
249 }
250
251 #undef config_PutInt
252 /*****************************************************************************
253  * config_PutInt: set the integer value of an int variable
254  *****************************************************************************
255  * This function is used to set the value of variables which are internally
256  * represented by an integer (CONFIG_ITEM_INTEGER and
257  * CONFIG_ITEM_BOOL).
258  *****************************************************************************/
259 void config_PutInt( vlc_object_t *p_this, const char *psz_name,
260                     int64_t i_value )
261 {
262     module_config_t *p_config;
263
264     p_config = config_FindConfig( p_this, psz_name );
265
266     /* sanity checks */
267     if( !p_config )
268     {
269         msg_Warn( p_this, "option %s does not exist", psz_name );
270         return;
271     }
272
273     if (!IsConfigIntegerType (p_config->i_type))
274     {
275         msg_Err( p_this, "option %s does not refer to an int", psz_name );
276         return;
277     }
278
279     if (i_value < p_config->min.i)
280         i_value = p_config->min.i;
281     if (i_value > p_config->max.i)
282         i_value = p_config->max.i;
283
284     vlc_rwlock_wrlock (&config_lock);
285     p_config->value.i = i_value;
286     p_config->b_dirty = true;
287     vlc_rwlock_unlock (&config_lock);
288 }
289
290 #undef config_PutFloat
291 /*****************************************************************************
292  * config_PutFloat: set the value of a float variable
293  *****************************************************************************
294  * This function is used to set the value of variables which are internally
295  * represented by a float (CONFIG_ITEM_FLOAT).
296  *****************************************************************************/
297 void config_PutFloat( vlc_object_t *p_this,
298                       const char *psz_name, float f_value )
299 {
300     module_config_t *p_config;
301
302     p_config = config_FindConfig( p_this, psz_name );
303
304     /* sanity checks */
305     if( !p_config )
306     {
307         msg_Warn( p_this, "option %s does not exist", psz_name );
308         return;
309     }
310
311     if (!IsConfigFloatType (p_config->i_type))
312     {
313         msg_Err( p_this, "option %s does not refer to a float", psz_name );
314         return;
315     }
316
317     /* if f_min == f_max == 0, then do not use them */
318     if ((p_config->min.f == 0) && (p_config->max.f == 0))
319         ;
320     else if (f_value < p_config->min.f)
321         f_value = p_config->min.f;
322     else if (f_value > p_config->max.f)
323         f_value = p_config->max.f;
324
325     vlc_rwlock_wrlock (&config_lock);
326     p_config->value.f = f_value;
327     p_config->b_dirty = true;
328     vlc_rwlock_unlock (&config_lock);
329 }
330
331 static int confcmp (const void *a, const void *b)
332 {
333     const module_config_t *const *ca = a, *const *cb = b;
334
335     return strcmp ((*ca)->psz_name, (*cb)->psz_name);
336 }
337
338 static int confnamecmp (const void *key, const void *elem)
339 {
340     const module_config_t *const *conf = elem;
341
342     return strcmp (key, (*conf)->psz_name);
343 }
344
345 static struct
346 {
347     module_config_t **list;
348     size_t count;
349 } config = { NULL, 0 };
350
351 /**
352  * Index the configuration items by name for faster lookups.
353  */
354 int config_SortConfig (void)
355 {
356     size_t nmod;
357     module_t **mlist = module_list_get (&nmod);
358     if (unlikely(mlist == NULL))
359         return VLC_ENOMEM;
360
361     size_t nconf = 0;
362     for (size_t i = 0; i < nmod; i++)
363          nconf  += mlist[i]->confsize;
364
365     module_config_t **clist = malloc (sizeof (*clist) * nconf);
366     if (unlikely(clist == NULL))
367     {
368         module_list_free (mlist);
369         return VLC_ENOMEM;
370     }
371
372     nconf = 0;
373     for (size_t i = 0; i < nmod; i++)
374     {
375         module_t *parser = mlist[i];
376         module_config_t *item, *end;
377
378         for (item = parser->p_config, end = item + parser->confsize;
379              item < end;
380              item++)
381         {
382             if (!CONFIG_ITEM(item->i_type))
383                 continue; /* ignore hints */
384             clist[nconf++] = item;
385         }
386     }
387     module_list_free (mlist);
388
389     qsort (clist, nconf, sizeof (*clist), confcmp);
390
391     config.list = clist;
392     config.count = nconf;
393     return VLC_SUCCESS;
394 }
395
396 void config_UnsortConfig (void)
397 {
398     module_config_t **clist;
399
400     clist = config.list;
401     config.list = NULL;
402     config.count = 0;
403
404     free (clist);
405 }
406
407 /*****************************************************************************
408  * config_FindConfig: find the config structure associated with an option.
409  *****************************************************************************
410  * FIXME: remove p_this pointer parameter (or use it)
411  *****************************************************************************/
412 module_config_t *config_FindConfig (vlc_object_t *p_this, const char *name)
413 {
414     VLC_UNUSED(p_this);
415
416     if (unlikely(name == NULL))
417         return NULL;
418
419     module_config_t *const *p;
420     p = bsearch (name, config.list, config.count, sizeof (*p), confnamecmp);
421     return p ? *p : NULL;
422 }
423
424 /**
425  * Destroys an array of configuration items.
426  * \param config start of array of items
427  * \param confsize number of items in the array
428  */
429 void config_Free (module_config_t *config, size_t confsize)
430 {
431     for (size_t j = 0; j < confsize; j++)
432     {
433         module_config_t *p_item = config + j;
434
435         free( p_item->psz_type );
436         free( p_item->psz_name );
437         free( p_item->psz_text );
438         free( p_item->psz_longtext );
439
440         if (IsConfigStringType (p_item->i_type))
441         {
442             free (p_item->value.psz);
443             free (p_item->orig.psz);
444         }
445
446         if( p_item->ppsz_list )
447             for (int i = 0; i < p_item->i_list; i++)
448                 free( p_item->ppsz_list[i] );
449         if( p_item->ppsz_list_text )
450             for (int i = 0; i < p_item->i_list; i++)
451                 free( p_item->ppsz_list_text[i] );
452         free( p_item->ppsz_list );
453         free( p_item->ppsz_list_text );
454         free( p_item->pi_list );
455
456         if( p_item->i_action )
457         {
458             for (int i = 0; i < p_item->i_action; i++)
459                 free( p_item->ppsz_action_text[i] );
460             free( p_item->ppf_action );
461             free( p_item->ppsz_action_text );
462         }
463     }
464
465     free (config);
466 }
467
468 #undef config_ResetAll
469 /*****************************************************************************
470  * config_ResetAll: reset the configuration data for all the modules.
471  *****************************************************************************/
472 void config_ResetAll( vlc_object_t *p_this )
473 {
474     VLC_UNUSED(p_this);
475     module_t *p_module;
476     module_t **list = module_list_get (NULL);
477
478     vlc_rwlock_wrlock (&config_lock);
479     for (size_t j = 0; (p_module = list[j]) != NULL; j++)
480         for (size_t i = 0; i < p_module->confsize; i++ )
481         {
482             module_config_t *p_config = p_module->p_config + i;
483
484             if (IsConfigIntegerType (p_config->i_type))
485                 p_config->value.i = p_config->orig.i;
486             else
487             if (IsConfigFloatType (p_config->i_type))
488                 p_config->value.f = p_config->orig.f;
489             else
490             if (IsConfigStringType (p_config->i_type))
491             {
492                 free ((char *)p_config->value.psz);
493                 p_config->value.psz =
494                         strdupnull (p_config->orig.psz);
495             }
496         }
497     vlc_rwlock_unlock (&config_lock);
498
499     module_list_free (list);
500 }