1 /*****************************************************************************
2 * core.c management of the modules configuration
3 *****************************************************************************
4 * Copyright (C) 2001-2007 the VideoLAN team
7 * Authors: Gildas Bazin <gbazin@videolan.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
28 #include <vlc_common.h>
29 #include "../libvlc.h"
31 #include "vlc_charset.h"
32 #include "vlc_configuration.h"
36 #include "configuration.h"
37 #include "modules/modules.h"
39 static inline char *strdupnull (const char *src)
41 return src ? strdup (src) : NULL;
44 /* Item types that use a string value (i.e. serialized in the module cache) */
45 int IsConfigStringType (int type)
47 static const unsigned char config_types[] =
49 CONFIG_ITEM_STRING, CONFIG_ITEM_FILE, CONFIG_ITEM_MODULE,
50 CONFIG_ITEM_DIRECTORY, CONFIG_ITEM_MODULE_CAT, CONFIG_ITEM_PASSWORD,
51 CONFIG_ITEM_MODULE_LIST, CONFIG_ITEM_MODULE_LIST_CAT
54 /* NOTE: this needs to be changed if we ever get more than 255 types */
55 return memchr (config_types, type, sizeof (config_types)) != NULL;
59 int IsConfigIntegerType (int type)
61 static const unsigned char config_types[] =
63 CONFIG_ITEM_INTEGER, CONFIG_ITEM_KEY, CONFIG_ITEM_BOOL,
64 CONFIG_CATEGORY, CONFIG_SUBCATEGORY
67 return memchr (config_types, type, sizeof (config_types)) != NULL;
71 /*****************************************************************************
72 * config_GetType: get the type of a variable (bool, int, float, string)
73 *****************************************************************************
74 * This function is used to get the type of a variable from its name.
75 * Beware, this is quite slow.
76 *****************************************************************************/
77 int __config_GetType( vlc_object_t *p_this, const char *psz_name )
79 module_config_t *p_config;
82 p_config = config_FindConfig( p_this, psz_name );
90 switch( p_config->i_type )
92 case CONFIG_ITEM_BOOL:
93 i_type = VLC_VAR_BOOL;
96 case CONFIG_ITEM_INTEGER:
98 i_type = VLC_VAR_INTEGER;
101 case CONFIG_ITEM_FLOAT:
102 i_type = VLC_VAR_FLOAT;
105 case CONFIG_ITEM_MODULE:
106 case CONFIG_ITEM_MODULE_CAT:
107 case CONFIG_ITEM_MODULE_LIST:
108 case CONFIG_ITEM_MODULE_LIST_CAT:
109 i_type = VLC_VAR_MODULE;
112 case CONFIG_ITEM_STRING:
113 i_type = VLC_VAR_STRING;
116 case CONFIG_ITEM_PASSWORD:
117 i_type = VLC_VAR_STRING;
120 case CONFIG_ITEM_FILE:
121 i_type = VLC_VAR_FILE;
124 case CONFIG_ITEM_DIRECTORY:
125 i_type = VLC_VAR_DIRECTORY;
136 /*****************************************************************************
137 * config_GetInt: get the value of an int variable
138 *****************************************************************************
139 * This function is used to get the value of variables which are internally
140 * represented by an integer (CONFIG_ITEM_INTEGER and
142 *****************************************************************************/
143 int __config_GetInt( vlc_object_t *p_this, const char *psz_name )
145 module_config_t *p_config;
147 p_config = config_FindConfig( p_this, psz_name );
152 msg_Err( p_this, "option %s does not exist", psz_name );
156 if (!IsConfigIntegerType (p_config->i_type))
158 msg_Err( p_this, "option %s does not refer to an int", psz_name );
162 return p_config->value.i;
165 /*****************************************************************************
166 * config_GetFloat: get the value of a float variable
167 *****************************************************************************
168 * This function is used to get the value of variables which are internally
169 * represented by a float (CONFIG_ITEM_FLOAT).
170 *****************************************************************************/
171 float __config_GetFloat( vlc_object_t *p_this, const char *psz_name )
173 module_config_t *p_config;
175 p_config = config_FindConfig( p_this, psz_name );
180 msg_Err( p_this, "option %s does not exist", psz_name );
184 if (!IsConfigFloatType (p_config->i_type))
186 msg_Err( p_this, "option %s does not refer to a float", psz_name );
190 return p_config->value.f;
193 /*****************************************************************************
194 * config_GetPsz: get the string value of a string variable
195 *****************************************************************************
196 * This function is used to get the value of variables which are internally
197 * represented by a string (CONFIG_ITEM_STRING, CONFIG_ITEM_FILE,
198 * CONFIG_ITEM_DIRECTORY, CONFIG_ITEM_PASSWORD, and CONFIG_ITEM_MODULE).
200 * Important note: remember to free() the returned char* because it's a
201 * duplicate of the actual value. It isn't safe to return a pointer to the
202 * actual value as it can be modified at any time.
203 *****************************************************************************/
204 char * __config_GetPsz( vlc_object_t *p_this, const char *psz_name )
206 module_config_t *p_config;
208 p_config = config_FindConfig( p_this, psz_name );
213 msg_Err( p_this, "option %s does not exist", psz_name );
217 if (!IsConfigStringType (p_config->i_type))
219 msg_Err( p_this, "option %s does not refer to a string", psz_name );
223 /* return a copy of the string */
224 vlc_mutex_lock( p_config->p_lock );
225 char *psz_value = strdupnull (p_config->value.psz);
226 vlc_mutex_unlock( p_config->p_lock );
231 /*****************************************************************************
232 * config_PutPsz: set the string value of a string variable
233 *****************************************************************************
234 * This function is used to set the value of variables which are internally
235 * represented by a string (CONFIG_ITEM_STRING, CONFIG_ITEM_FILE,
236 * CONFIG_ITEM_DIRECTORY, CONFIG_ITEM_PASSWORD, and CONFIG_ITEM_MODULE).
237 *****************************************************************************/
238 void __config_PutPsz( vlc_object_t *p_this,
239 const char *psz_name, const char *psz_value )
241 module_config_t *p_config;
242 vlc_value_t oldval, val;
244 p_config = config_FindConfig( p_this, psz_name );
250 msg_Warn( p_this, "option %s does not exist", psz_name );
254 if (!IsConfigStringType (p_config->i_type))
256 msg_Err( p_this, "option %s does not refer to a string", psz_name );
260 vlc_mutex_lock( p_config->p_lock );
262 /* backup old value */
263 oldval.psz_string = (char *)p_config->value.psz;
265 if ((psz_value != NULL) && *psz_value)
266 p_config->value.psz = strdup (psz_value);
268 p_config->value.psz = NULL;
270 p_config->b_dirty = true;
272 val.psz_string = (char *)p_config->value.psz;
274 vlc_mutex_unlock( p_config->p_lock );
276 if( p_config->pf_callback )
278 p_config->pf_callback( p_this, psz_name, oldval, val,
279 p_config->p_callback_data );
282 /* free old string */
283 free( oldval.psz_string );
286 /*****************************************************************************
287 * config_PutInt: set the integer value of an int variable
288 *****************************************************************************
289 * This function is used to set the value of variables which are internally
290 * represented by an integer (CONFIG_ITEM_INTEGER and
292 *****************************************************************************/
293 void __config_PutInt( vlc_object_t *p_this, const char *psz_name, int i_value )
295 module_config_t *p_config;
296 vlc_value_t oldval, val;
298 p_config = config_FindConfig( p_this, psz_name );
303 msg_Warn( p_this, "option %s does not exist", psz_name );
307 if (!IsConfigIntegerType (p_config->i_type))
309 msg_Err( p_this, "option %s does not refer to an int", psz_name );
313 /* backup old value */
314 oldval.i_int = p_config->value.i;
316 /* if i_min == i_max == 0, then do not use them */
317 if ((p_config->min.i == 0) && (p_config->max.i == 0))
319 p_config->value.i = i_value;
321 else if (i_value < p_config->min.i)
323 p_config->value.i = p_config->min.i;
325 else if (i_value > p_config->max.i)
327 p_config->value.i = p_config->max.i;
331 p_config->value.i = i_value;
334 p_config->b_dirty = true;
336 val.i_int = p_config->value.i;
338 if( p_config->pf_callback )
340 p_config->pf_callback( p_this, psz_name, oldval, val,
341 p_config->p_callback_data );
345 /*****************************************************************************
346 * config_PutFloat: set the value of a float variable
347 *****************************************************************************
348 * This function is used to set the value of variables which are internally
349 * represented by a float (CONFIG_ITEM_FLOAT).
350 *****************************************************************************/
351 void __config_PutFloat( vlc_object_t *p_this,
352 const char *psz_name, float f_value )
354 module_config_t *p_config;
355 vlc_value_t oldval, val;
357 p_config = config_FindConfig( p_this, psz_name );
362 msg_Warn( p_this, "option %s does not exist", psz_name );
366 if (!IsConfigFloatType (p_config->i_type))
368 msg_Err( p_this, "option %s does not refer to a float", psz_name );
372 /* backup old value */
373 oldval.f_float = p_config->value.f;
375 /* if f_min == f_max == 0, then do not use them */
376 if ((p_config->min.f == 0) && (p_config->max.f == 0))
378 p_config->value.f = f_value;
380 else if (f_value < p_config->min.f)
382 p_config->value.f = p_config->min.f;
384 else if (f_value > p_config->max.f)
386 p_config->value.f = p_config->max.f;
390 p_config->value.f = f_value;
393 p_config->b_dirty = true;
395 val.f_float = p_config->value.f;
397 if( p_config->pf_callback )
399 p_config->pf_callback( p_this, psz_name, oldval, val,
400 p_config->p_callback_data );
404 /*****************************************************************************
405 * config_FindConfig: find the config structure associated with an option.
406 *****************************************************************************
407 * FIXME: This function really needs to be optimized.
408 * FIXME: And now even more.
409 *****************************************************************************/
410 module_config_t *config_FindConfig( vlc_object_t *p_this, const char *psz_name )
414 if( !psz_name ) return NULL;
416 module_t **list = module_list_get (NULL);
420 for (size_t i = 0; (p_parser = list[i]) != NULL; i++)
422 module_config_t *p_item, *p_end;
424 if( !p_parser->i_config_items )
427 for( p_item = p_parser->p_config, p_end = p_item + p_parser->confsize;
431 if( p_item->i_type & CONFIG_HINT )
434 if( !strcmp( psz_name, p_item->psz_name )
435 || ( p_item->psz_oldname
436 && !strcmp( psz_name, p_item->psz_oldname ) ) )
438 module_list_free (list);
444 module_list_free (list);
448 /*****************************************************************************
449 * config_Free: frees a duplicated module's configuration data.
450 *****************************************************************************
451 * This function frees all the data duplicated by config_Duplicate.
452 *****************************************************************************/
453 void config_Free( module_t *p_module )
457 for (size_t j = 0; j < p_module->confsize; j++)
459 module_config_t *p_item = p_module->p_config + j;
461 free( p_item->psz_type );
462 free( p_item->psz_name );
463 free( p_item->psz_text );
464 free( p_item->psz_longtext );
465 free( p_item->psz_oldname );
467 if (IsConfigStringType (p_item->i_type))
469 free (p_item->value.psz);
470 free (p_item->orig.psz);
471 free (p_item->saved.psz);
474 if( p_item->ppsz_list )
475 for( i = 0; i < p_item->i_list; i++ )
476 free( p_item->ppsz_list[i] );
477 if( p_item->ppsz_list_text )
478 for( i = 0; i < p_item->i_list; i++ )
479 free( p_item->ppsz_list_text[i] );
480 free( p_item->ppsz_list );
481 free( p_item->ppsz_list_text );
482 free( p_item->pi_list );
484 if( p_item->i_action )
486 for( i = 0; i < p_item->i_action; i++ )
488 free( p_item->ppsz_action_text[i] );
490 free( p_item->ppf_action );
491 free( p_item->ppsz_action_text );
495 free (p_module->p_config);
496 p_module->p_config = NULL;
499 /*****************************************************************************
500 * config_SetCallbacks: sets callback functions in the duplicate p_config.
501 *****************************************************************************
502 * Unfortunatly we cannot work directly with the module's config data as
503 * this module might be unloaded from memory at any time (remember HideModule).
504 * This is why we need to duplicate callbacks each time we reload the module.
505 *****************************************************************************/
506 void config_SetCallbacks( module_config_t *p_new, module_config_t *p_orig,
509 for (size_t i = 0; i < n; i++)
511 p_new->pf_callback = p_orig->pf_callback;
517 /*****************************************************************************
518 * config_UnsetCallbacks: unsets callback functions in the duplicate p_config.
519 *****************************************************************************
520 * We simply undo what we did in config_SetCallbacks.
521 *****************************************************************************/
522 void config_UnsetCallbacks( module_config_t *p_new, size_t n )
524 for (size_t i = 0; i < n; i++)
526 p_new->pf_callback = NULL;
531 /*****************************************************************************
532 * config_ResetAll: reset the configuration data for all the modules.
533 *****************************************************************************/
534 void __config_ResetAll( vlc_object_t *p_this )
536 libvlc_priv_t *priv = libvlc_priv (p_this->p_libvlc);
538 module_t **list = module_list_get (NULL);
540 /* Acquire config file lock */
541 vlc_mutex_lock( &priv->config_lock );
544 for (size_t j = 0; (p_module = list[j]) != NULL; j++)
546 if( p_module->b_submodule ) continue;
548 for (size_t i = 0; i < p_module->confsize; i++ )
550 if (IsConfigIntegerType (p_module->p_config[i].i_type))
551 p_module->p_config[i].value.i = p_module->p_config[i].orig.i;
553 if (IsConfigFloatType (p_module->p_config[i].i_type))
554 p_module->p_config[i].value.f = p_module->p_config[i].orig.f;
556 if (IsConfigStringType (p_module->p_config[i].i_type))
558 free ((char *)p_module->p_config[i].value.psz);
559 p_module->p_config[i].value.psz =
560 strdupnull (p_module->p_config[i].orig.psz);
565 module_list_free (list);
566 vlc_mutex_unlock( &priv->config_lock );