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 *****************************************************************************/
29 # if !defined( UNDER_CE )
30 # define _WIN32_IE IE5
39 #include "../libvlc.h"
41 #include "vlc_charset.h"
42 #include "vlc_configuration.h"
44 #include <errno.h> /* errno */
49 # include <unistd.h> /* getuid() */
52 #if defined(HAVE_GETPWUID_R)
56 #if defined( HAVE_SYS_STAT_H )
57 # include <sys/stat.h>
59 #if defined( HAVE_SYS_TYPES_H )
60 # include <sys/types.h>
63 #include "configuration.h"
64 #include "modules/modules.h"
66 static inline char *strdupnull (const char *src)
68 return src ? strdup (src) : NULL;
71 /* Item types that use a string value (i.e. serialized in the module cache) */
72 int IsConfigStringType (int type)
74 static const unsigned char config_types[] =
76 CONFIG_ITEM_STRING, CONFIG_ITEM_FILE, CONFIG_ITEM_MODULE,
77 CONFIG_ITEM_DIRECTORY, CONFIG_ITEM_MODULE_CAT, CONFIG_ITEM_PASSWORD,
78 CONFIG_ITEM_MODULE_LIST, CONFIG_ITEM_MODULE_LIST_CAT
81 /* NOTE: this needs to be changed if we ever get more than 255 types */
82 return memchr (config_types, type, sizeof (config_types)) != NULL;
86 int IsConfigIntegerType (int type)
88 static const unsigned char config_types[] =
90 CONFIG_ITEM_INTEGER, CONFIG_ITEM_KEY, CONFIG_ITEM_BOOL,
91 CONFIG_CATEGORY, CONFIG_SUBCATEGORY
94 return memchr (config_types, type, sizeof (config_types)) != NULL;
98 /*****************************************************************************
99 * config_GetType: get the type of a variable (bool, int, float, string)
100 *****************************************************************************
101 * This function is used to get the type of a variable from its name.
102 * Beware, this is quite slow.
103 *****************************************************************************/
104 int __config_GetType( vlc_object_t *p_this, const char *psz_name )
106 module_config_t *p_config;
109 p_config = config_FindConfig( p_this, psz_name );
117 switch( p_config->i_type )
119 case CONFIG_ITEM_BOOL:
120 i_type = VLC_VAR_BOOL;
123 case CONFIG_ITEM_INTEGER:
124 case CONFIG_ITEM_KEY:
125 i_type = VLC_VAR_INTEGER;
128 case CONFIG_ITEM_FLOAT:
129 i_type = VLC_VAR_FLOAT;
132 case CONFIG_ITEM_MODULE:
133 case CONFIG_ITEM_MODULE_CAT:
134 case CONFIG_ITEM_MODULE_LIST:
135 case CONFIG_ITEM_MODULE_LIST_CAT:
136 i_type = VLC_VAR_MODULE;
139 case CONFIG_ITEM_STRING:
140 i_type = VLC_VAR_STRING;
143 case CONFIG_ITEM_PASSWORD:
144 i_type = VLC_VAR_STRING;
147 case CONFIG_ITEM_FILE:
148 i_type = VLC_VAR_FILE;
151 case CONFIG_ITEM_DIRECTORY:
152 i_type = VLC_VAR_DIRECTORY;
163 /*****************************************************************************
164 * config_GetInt: get the value of an int variable
165 *****************************************************************************
166 * This function is used to get the value of variables which are internally
167 * represented by an integer (CONFIG_ITEM_INTEGER and
169 *****************************************************************************/
170 int __config_GetInt( vlc_object_t *p_this, const char *psz_name )
172 module_config_t *p_config;
174 p_config = config_FindConfig( p_this, psz_name );
179 msg_Err( p_this, "option %s does not exist", psz_name );
183 if (!IsConfigIntegerType (p_config->i_type))
185 msg_Err( p_this, "option %s does not refer to an int", psz_name );
189 return p_config->value.i;
192 /*****************************************************************************
193 * config_GetFloat: get the value of a float variable
194 *****************************************************************************
195 * This function is used to get the value of variables which are internally
196 * represented by a float (CONFIG_ITEM_FLOAT).
197 *****************************************************************************/
198 float __config_GetFloat( vlc_object_t *p_this, const char *psz_name )
200 module_config_t *p_config;
202 p_config = config_FindConfig( p_this, psz_name );
207 msg_Err( p_this, "option %s does not exist", psz_name );
211 if (!IsConfigFloatType (p_config->i_type))
213 msg_Err( p_this, "option %s does not refer to a float", psz_name );
217 return p_config->value.f;
220 /*****************************************************************************
221 * config_GetPsz: get the string value of a string variable
222 *****************************************************************************
223 * This function is used to get the value of variables which are internally
224 * represented by a string (CONFIG_ITEM_STRING, CONFIG_ITEM_FILE,
225 * CONFIG_ITEM_DIRECTORY, CONFIG_ITEM_PASSWORD, and CONFIG_ITEM_MODULE).
227 * Important note: remember to free() the returned char* because it's a
228 * duplicate of the actual value. It isn't safe to return a pointer to the
229 * actual value as it can be modified at any time.
230 *****************************************************************************/
231 char * __config_GetPsz( vlc_object_t *p_this, const char *psz_name )
233 module_config_t *p_config;
235 p_config = config_FindConfig( p_this, psz_name );
240 msg_Err( p_this, "option %s does not exist", psz_name );
244 if (!IsConfigStringType (p_config->i_type))
246 msg_Err( p_this, "option %s does not refer to a string", psz_name );
250 /* return a copy of the string */
251 vlc_mutex_lock( p_config->p_lock );
252 char *psz_value = strdupnull (p_config->value.psz);
253 vlc_mutex_unlock( p_config->p_lock );
258 /*****************************************************************************
259 * config_PutPsz: set the string value of a string variable
260 *****************************************************************************
261 * This function is used to set the value of variables which are internally
262 * represented by a string (CONFIG_ITEM_STRING, CONFIG_ITEM_FILE,
263 * CONFIG_ITEM_DIRECTORY, CONFIG_ITEM_PASSWORD, and CONFIG_ITEM_MODULE).
264 *****************************************************************************/
265 void __config_PutPsz( vlc_object_t *p_this,
266 const char *psz_name, const char *psz_value )
268 module_config_t *p_config;
269 vlc_value_t oldval, val;
271 p_config = config_FindConfig( p_this, psz_name );
277 msg_Warn( p_this, "option %s does not exist", psz_name );
281 if (!IsConfigStringType (p_config->i_type))
283 msg_Err( p_this, "option %s does not refer to a string", psz_name );
287 vlc_mutex_lock( p_config->p_lock );
289 /* backup old value */
290 oldval.psz_string = (char *)p_config->value.psz;
292 if ((psz_value != NULL) && *psz_value)
293 p_config->value.psz = strdup (psz_value);
295 p_config->value.psz = NULL;
297 p_config->b_dirty = true;
299 val.psz_string = (char *)p_config->value.psz;
301 vlc_mutex_unlock( p_config->p_lock );
303 if( p_config->pf_callback )
305 p_config->pf_callback( p_this, psz_name, oldval, val,
306 p_config->p_callback_data );
309 /* free old string */
310 free( oldval.psz_string );
313 /*****************************************************************************
314 * config_PutInt: set the integer value of an int variable
315 *****************************************************************************
316 * This function is used to set the value of variables which are internally
317 * represented by an integer (CONFIG_ITEM_INTEGER and
319 *****************************************************************************/
320 void __config_PutInt( vlc_object_t *p_this, const char *psz_name, int i_value )
322 module_config_t *p_config;
323 vlc_value_t oldval, val;
325 p_config = config_FindConfig( p_this, psz_name );
330 msg_Warn( p_this, "option %s does not exist", psz_name );
334 if (!IsConfigIntegerType (p_config->i_type))
336 msg_Err( p_this, "option %s does not refer to an int", psz_name );
340 /* backup old value */
341 oldval.i_int = p_config->value.i;
343 /* if i_min == i_max == 0, then do not use them */
344 if ((p_config->min.i == 0) && (p_config->max.i == 0))
346 p_config->value.i = i_value;
348 else if (i_value < p_config->min.i)
350 p_config->value.i = p_config->min.i;
352 else if (i_value > p_config->max.i)
354 p_config->value.i = p_config->max.i;
358 p_config->value.i = i_value;
361 p_config->b_dirty = true;
363 val.i_int = p_config->value.i;
365 if( p_config->pf_callback )
367 p_config->pf_callback( p_this, psz_name, oldval, val,
368 p_config->p_callback_data );
372 /*****************************************************************************
373 * config_PutFloat: set the value of a float variable
374 *****************************************************************************
375 * This function is used to set the value of variables which are internally
376 * represented by a float (CONFIG_ITEM_FLOAT).
377 *****************************************************************************/
378 void __config_PutFloat( vlc_object_t *p_this,
379 const char *psz_name, float f_value )
381 module_config_t *p_config;
382 vlc_value_t oldval, val;
384 p_config = config_FindConfig( p_this, psz_name );
389 msg_Warn( p_this, "option %s does not exist", psz_name );
393 if (!IsConfigFloatType (p_config->i_type))
395 msg_Err( p_this, "option %s does not refer to a float", psz_name );
399 /* backup old value */
400 oldval.f_float = p_config->value.f;
402 /* if f_min == f_max == 0, then do not use them */
403 if ((p_config->min.f == 0) && (p_config->max.f == 0))
405 p_config->value.f = f_value;
407 else if (f_value < p_config->min.f)
409 p_config->value.f = p_config->min.f;
411 else if (f_value > p_config->max.f)
413 p_config->value.f = p_config->max.f;
417 p_config->value.f = f_value;
420 p_config->b_dirty = true;
422 val.f_float = p_config->value.f;
424 if( p_config->pf_callback )
426 p_config->pf_callback( p_this, psz_name, oldval, val,
427 p_config->p_callback_data );
431 /*****************************************************************************
432 * config_FindConfig: find the config structure associated with an option.
433 *****************************************************************************
434 * FIXME: This function really needs to be optimized.
435 * FIXME: And now even more.
436 *****************************************************************************/
437 module_config_t *config_FindConfig( vlc_object_t *p_this, const char *psz_name )
442 if( !psz_name ) return NULL;
444 p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
446 for( i_index = 0; i_index < p_list->i_count; i_index++ )
448 module_config_t *p_item, *p_end;
449 module_t *p_parser = (module_t *)p_list->p_values[i_index].p_object;
451 if( !p_parser->i_config_items )
454 for( p_item = p_parser->p_config, p_end = p_item + p_parser->confsize;
458 if( p_item->i_type & CONFIG_HINT )
461 if( !strcmp( psz_name, p_item->psz_name )
462 || ( p_item->psz_oldname
463 && !strcmp( psz_name, p_item->psz_oldname ) ) )
465 vlc_list_release( p_list );
471 vlc_list_release( p_list );
476 /*****************************************************************************
477 * config_Free: frees a duplicated module's configuration data.
478 *****************************************************************************
479 * This function frees all the data duplicated by config_Duplicate.
480 *****************************************************************************/
481 void config_Free( module_t *p_module )
485 for (size_t j = 0; j < p_module->confsize; j++)
487 module_config_t *p_item = p_module->p_config + j;
489 free( p_item->psz_type );
490 free( p_item->psz_name );
491 free( p_item->psz_text );
492 free( p_item->psz_longtext );
493 free( p_item->psz_oldname );
495 if (IsConfigStringType (p_item->i_type))
497 free (p_item->value.psz);
498 free (p_item->orig.psz);
499 free (p_item->saved.psz);
502 if( p_item->ppsz_list )
503 for( i = 0; i < p_item->i_list; i++ )
504 free( p_item->ppsz_list[i] );
505 if( p_item->ppsz_list_text )
506 for( i = 0; i < p_item->i_list; i++ )
507 free( p_item->ppsz_list_text[i] );
508 free( p_item->ppsz_list );
509 free( p_item->ppsz_list_text );
510 free( p_item->pi_list );
512 if( p_item->i_action )
514 for( i = 0; i < p_item->i_action; i++ )
516 free( p_item->ppsz_action_text[i] );
518 free( p_item->ppf_action );
519 free( p_item->ppsz_action_text );
523 free (p_module->p_config);
524 p_module->p_config = NULL;
527 /*****************************************************************************
528 * config_SetCallbacks: sets callback functions in the duplicate p_config.
529 *****************************************************************************
530 * Unfortunatly we cannot work directly with the module's config data as
531 * this module might be unloaded from memory at any time (remember HideModule).
532 * This is why we need to duplicate callbacks each time we reload the module.
533 *****************************************************************************/
534 void config_SetCallbacks( module_config_t *p_new, module_config_t *p_orig,
537 for (size_t i = 0; i < n; i++)
539 p_new->pf_callback = p_orig->pf_callback;
545 /*****************************************************************************
546 * config_UnsetCallbacks: unsets callback functions in the duplicate p_config.
547 *****************************************************************************
548 * We simply undo what we did in config_SetCallbacks.
549 *****************************************************************************/
550 void config_UnsetCallbacks( module_config_t *p_new, size_t n )
552 for (size_t i = 0; i < n; i++)
554 p_new->pf_callback = NULL;
559 /*****************************************************************************
560 * config_ResetAll: reset the configuration data for all the modules.
561 *****************************************************************************/
562 void __config_ResetAll( vlc_object_t *p_this )
564 libvlc_priv_t *priv = libvlc_priv (p_this->p_libvlc);
569 /* Acquire config file lock */
570 vlc_mutex_lock( &priv->config_lock );
572 p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
574 for( i_index = 0; i_index < p_list->i_count; i_index++ )
576 p_module = (module_t *)p_list->p_values[i_index].p_object ;
577 if( p_module->b_submodule ) continue;
579 for (size_t i = 0; i < p_module->confsize; i++ )
581 if (IsConfigIntegerType (p_module->p_config[i].i_type))
582 p_module->p_config[i].value.i = p_module->p_config[i].orig.i;
584 if (IsConfigFloatType (p_module->p_config[i].i_type))
585 p_module->p_config[i].value.f = p_module->p_config[i].orig.f;
587 if (IsConfigStringType (p_module->p_config[i].i_type))
589 free ((char *)p_module->p_config[i].value.psz);
590 p_module->p_config[i].value.psz =
591 strdupnull (p_module->p_config[i].orig.psz);
596 vlc_list_release( p_list );
597 vlc_mutex_unlock( &priv->config_lock );
601 * config_GetDataDir: find directory where shared data is installed
603 * @return a string (always succeeds).
605 const char *config_GetDataDir( void )
607 #if defined (WIN32) || defined (UNDER_CE)
608 return vlc_global()->psz_vlcpath;
609 #elif defined(__APPLE__) || defined (SYS_BEOS)
610 static char path[PATH_MAX] = "";
614 snprintf( path, sizeof( path ), "%s/share",
615 vlc_global()->psz_vlcpath );
616 path[sizeof( path ) - 1] = '\0';
625 * Determines the system configuration directory.
627 * @return a string (always succeeds).
629 const char *config_GetConfDir( void )
631 #if defined (WIN32) || defined (UNDER_CE)
632 return vlc_global()->psz_vlcpath;
633 #elif defined(__APPLE__) || defined (SYS_BEOS)
634 static char path[PATH_MAX] = "";
638 snprintf( path, sizeof( path ), "%s/share", /* FIXME: Duh? */
639 vlc_global()->psz_vlcpath );
640 path[sizeof( path ) - 1] = '\0';
648 static char *GetDir( bool b_appdata )
650 const char *psz_localhome = NULL;
652 #if defined(WIN32) && !defined(UNDER_CE)
653 wchar_t whomedir[MAX_PATH];
654 /* Get the "Application Data" folder for the current user */
655 if( S_OK == SHGetFolderPathW( NULL,
656 (b_appdata ? CSIDL_APPDATA : CSIDL_PROFILE) | CSIDL_FLAG_CREATE,
657 NULL, SHGFP_TYPE_CURRENT, whomedir ) )
658 return FromWide( whomedir );
660 #elif defined(UNDER_CE)
662 #ifndef CSIDL_APPDATA
663 # define CSIDL_APPDATA 0x1A
666 wchar_t whomedir[MAX_PATH];
668 /* get the "Application Data" folder for the current user */
669 if( SHGetSpecialFolderPath( NULL, whomedir, CSIDL_APPDATA, 1 ) )
670 return FromWide( whomedir );
675 psz_localhome = getenv( "HOME" );
676 #if defined(HAVE_GETPWUID_R)
677 char buf[sysconf (_SC_GETPW_R_SIZE_MAX)];
678 if( psz_localhome == NULL )
680 struct passwd pw, *res;
682 if (!getpwuid_r (getuid (), &pw, buf, sizeof (buf), &res) && res)
683 psz_localhome = pw.pw_dir;
686 if (psz_localhome == NULL)
687 psz_localhome = getenv( "TMP" );
688 if (psz_localhome == NULL)
689 psz_localhome = "/tmp";
691 return FromLocaleDup( psz_localhome );
695 * Get the user's home directory
697 char *config_GetHomeDir( void )
699 return GetDir( false );
702 static char *config_GetFooDir (const char *xdg_name, const char *xdg_default)
705 #if defined(WIN32) || defined(__APPLE__) || defined(SYS_BEOS)
706 char *psz_parent = GetDir (true);
708 if( asprintf( &psz_dir, "%s" DIR_SEP CONFIG_DIR, psz_parent ) == -1 )
712 (void)xdg_name; (void)xdg_default;
714 char var[sizeof ("XDG__HOME") + strlen (xdg_name)];
716 /* XDG Base Directory Specification - Version 0.6 */
717 snprintf (var, sizeof (var), "XDG_%s_HOME", xdg_name);
718 char *psz_home = getenv( var );
719 psz_home = psz_home ? FromLocaleDup( psz_home ) : NULL;
722 if( asprintf( &psz_dir, "%s/vlc", psz_home ) == -1 )
727 /* Try HOME, then fallback to non-XDG dirs */
728 psz_home = config_GetHomeDir();
729 if( asprintf( &psz_dir, "%s/%s/vlc", psz_home, xdg_default ) == -1 )
739 * Get the user's VLC configuration directory
741 char *config_GetUserConfDir( void )
743 return config_GetFooDir ("CONFIG", ".config");
747 * Get the user's VLC data directory
748 * (used for stuff like the skins, custom lua modules, ...)
750 char *config_GetUserDataDir( void )
752 return config_GetFooDir ("DATA", ".local/share");
756 * Get the user's VLC cache directory
757 * (used for stuff like the modules cache, the album art cache, ...)
759 char *config_GetCacheDir( void )
761 return config_GetFooDir ("CACHE", ".cache");