~ubuntu-branches/ubuntu/maverick/vlc/maverick

« back to all changes in this revision

Viewing changes to src/config/file.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler
  • Date: 2008-09-17 21:56:14 UTC
  • mfrom: (1.1.17 upstream)
  • Revision ID: james.westby@ubuntu.com-20080917215614-tj0vx8xzd57e52t8
Tags: 0.9.2-1ubuntu1
* New Upstream Release, exception granted by
    - dktrkranz, norsetto, Hobbsee (via irc). LP: #270404

Changes done in ubuntu:

* add libxul-dev to build-depends
* make sure that vlc is build against libxul in configure. This doesn't
  change anything in the package, but makes it more robust if building
  in an 'unclean' chroot or when modifying the package.
* debian/control: make Vcs-* fields point to the motumedia branch
* add libx264-dev and libass-dev to build-depends
  LP: #210354, #199870
* actually enable libass support by passing --enable-libass to configure
* enable libdca: add libdca-dev to build depends and --enable-libdca
* install the x264 plugin.

Changes already in the pkg-multimedia branch in debian:

* don't install usr/share/vlc/mozilla in debian/mozilla-plugin-vlc.install  
* new upstream .desktop file now registers flash video mimetype LP: #261567
* add Xb-Npp-Applications to mozilla-plugin-vlc
* remove duplicate entries in debian/vlc-nox.install

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*****************************************************************************
 
2
 * file.c: configuration file handling
 
3
 *****************************************************************************
 
4
 * Copyright (C) 2001-2007 the VideoLAN team
 
5
 * $Id: 894ebbb14e081062cd69a7f446e5881b0612b9a4 $
 
6
 *
 
7
 * Authors: Gildas Bazin <gbazin@videolan.org>
 
8
 *
 
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.
 
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 General Public License for more details.
 
18
 *
 
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
 *****************************************************************************/
 
23
 
 
24
#ifdef HAVE_CONFIG_H
 
25
# include "config.h"
 
26
#endif
 
27
 
 
28
#include <vlc_common.h>
 
29
#include "../libvlc.h"
 
30
#include "vlc_charset.h"
 
31
#include "vlc_keys.h"
 
32
 
 
33
#include <errno.h>                                                  /* errno */
 
34
#include <assert.h>
 
35
#include <limits.h>
 
36
#ifdef __APPLE__
 
37
#   include <xlocale.h>
 
38
#else
 
39
#include <locale.h>
 
40
#endif
 
41
 
 
42
#include "configuration.h"
 
43
#include "modules/modules.h"
 
44
 
 
45
static char *ConfigKeyToString( int );
 
46
 
 
47
static inline char *strdupnull (const char *src)
 
48
{
 
49
    return src ? strdup (src) : NULL;
 
50
}
 
51
 
 
52
/**
 
53
 * Get the user's configuration file
 
54
 */
 
55
static char *config_GetConfigFile( void )
 
56
{
 
57
    char *psz_dir = config_GetUserConfDir();
 
58
    char *psz_configfile;
 
59
 
 
60
    if( asprintf( &psz_configfile, "%s" DIR_SEP CONFIG_FILE, psz_dir ) == -1 )
 
61
        psz_configfile = NULL;
 
62
    free( psz_dir );
 
63
    return psz_configfile;
 
64
}
 
65
 
 
66
static FILE *config_OpenConfigFile( vlc_object_t *p_obj, const char *mode )
 
67
{
 
68
    char *psz_filename = libvlc_priv (p_obj->p_libvlc)->psz_configfile;
 
69
    FILE *p_stream;
 
70
 
 
71
    if( !psz_filename )
 
72
    {
 
73
        psz_filename = config_GetConfigFile();
 
74
    }
 
75
 
 
76
    msg_Dbg( p_obj, "opening config file (%s)", psz_filename );
 
77
 
 
78
    p_stream = utf8_fopen( psz_filename, mode );
 
79
    if( p_stream == NULL && errno != ENOENT )
 
80
    {
 
81
        msg_Err( p_obj, "cannot open config file (%s): %m",
 
82
                 psz_filename );
 
83
 
 
84
    }
 
85
#if !( defined(WIN32) || defined(__APPLE__) || defined(SYS_BEOS) )
 
86
    else if( p_stream == NULL && errno == ENOENT && mode[0] == 'r' )
 
87
    {
 
88
        /* This is the fallback for pre XDG Base Directory
 
89
         * Specification configs */
 
90
        char *psz_old;
 
91
        if( asprintf( &psz_old, "%s" DIR_SEP CONFIG_DIR DIR_SEP CONFIG_FILE,
 
92
                      config_GetHomeDir() ) != -1 )
 
93
        {
 
94
            p_stream = utf8_fopen( psz_old, mode );
 
95
            if( p_stream )
 
96
            {
 
97
                /* Old config file found. We want to write it at the
 
98
                 * new location now. */
 
99
                msg_Info( p_obj->p_libvlc, "Found old config file at %s. "
 
100
                          "VLC will now use %s.", psz_old, psz_filename );
 
101
                char *psz_readme;
 
102
                if( asprintf(&psz_readme,"%s"DIR_SEP CONFIG_DIR DIR_SEP"README",
 
103
                              config_GetHomeDir() ) != -1 )
 
104
                {
 
105
                    FILE *p_readme = utf8_fopen( psz_readme, "wt" );
 
106
                    if( p_readme )
 
107
                    {
 
108
                        fprintf( p_readme, "The VLC media player "
 
109
                                 "configuration folder has moved to comply\n"
 
110
                                 "with the XDG Base Directory Specification "
 
111
                                 "version 0.6. Your\nconfiguration has been "
 
112
                                 "copied to the new location:\n%s\nYou can "
 
113
                                 "delete this directory and all its contents.",
 
114
                                  psz_filename);
 
115
                        fclose( p_readme );
 
116
                    }
 
117
                    free( psz_readme );
 
118
                }
 
119
            }
 
120
            free( psz_old );
 
121
        }
 
122
    }
 
123
#endif
 
124
    else if( p_stream != NULL )
 
125
    {
 
126
        libvlc_priv (p_obj->p_libvlc)->psz_configfile = psz_filename;
 
127
    }
 
128
 
 
129
    return p_stream;
 
130
}
 
131
 
 
132
 
 
133
static int strtoi (const char *str)
 
134
{
 
135
    char *end;
 
136
    long l;
 
137
 
 
138
    errno = 0;
 
139
    l = strtol (str, &end, 0);
 
140
 
 
141
    if (!errno)
 
142
    {
 
143
        if ((l > INT_MAX) || (l < INT_MIN))
 
144
            errno = ERANGE;
 
145
        if (*end)
 
146
            errno = EINVAL;
 
147
    }
 
148
    return (int)l;
 
149
}
 
150
 
 
151
 
 
152
/*****************************************************************************
 
153
 * config_LoadConfigFile: loads the configuration file.
 
154
 *****************************************************************************
 
155
 * This function is called to load the config options stored in the config
 
156
 * file.
 
157
 *****************************************************************************/
 
158
int __config_LoadConfigFile( vlc_object_t *p_this, const char *psz_module_name )
 
159
{
 
160
    libvlc_priv_t *priv = libvlc_priv (p_this->p_libvlc);
 
161
    vlc_list_t *p_list;
 
162
    FILE *file;
 
163
 
 
164
    file = config_OpenConfigFile (p_this, "rt");
 
165
    if (file == NULL)
 
166
        return VLC_EGENERIC;
 
167
 
 
168
    /* Acquire config file lock */
 
169
    vlc_mutex_lock( &priv->config_lock );
 
170
 
 
171
    /* Look for the selected module, if NULL then save everything */
 
172
    p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
 
173
 
 
174
    /* Look for UTF-8 Byte Order Mark */
 
175
    char * (*convert) (const char *) = strdupnull;
 
176
    char bom[3];
 
177
 
 
178
    if ((fread (bom, 1, 3, file) != 3)
 
179
     || memcmp (bom, "\xEF\xBB\xBF", 3))
 
180
    {
 
181
        convert = FromLocaleDup;
 
182
        rewind (file); /* no BOM, rewind */
 
183
    }
 
184
 
 
185
    module_t *module = NULL;
 
186
    char line[1024], section[1022];
 
187
    section[0] = '\0';
 
188
 
 
189
    /* Ensure consistent number formatting... */
 
190
    locale_t loc = newlocale (LC_NUMERIC_MASK, "C", NULL);
 
191
    locale_t baseloc = uselocale (loc);
 
192
 
 
193
    while (fgets (line, 1024, file) != NULL)
 
194
    {
 
195
        /* Ignore comments and empty lines */
 
196
        switch (line[0])
 
197
        {
 
198
            case '#':
 
199
            case '\n':
 
200
            case '\0':
 
201
                continue;
 
202
        }
 
203
 
 
204
        if (line[0] == '[')
 
205
        {
 
206
            char *ptr = strchr (line, ']');
 
207
            if (ptr == NULL)
 
208
                continue; /* syntax error; */
 
209
            *ptr = '\0';
 
210
 
 
211
            /* New section ( = a given module) */
 
212
            strcpy (section, line + 1);
 
213
            module = NULL;
 
214
 
 
215
            if ((psz_module_name == NULL)
 
216
             || (strcmp (psz_module_name, section) == 0))
 
217
            {
 
218
                for (int i = 0; i < p_list->i_count; i++)
 
219
                {
 
220
                    module_t *m = (module_t *)p_list->p_values[i].p_object;
 
221
 
 
222
                    if ((strcmp (section, m->psz_object_name) == 0)
 
223
                     && (m->i_config_items > 0)) /* ignore config-less modules */
 
224
                    {
 
225
                        module = m;
 
226
                        if (psz_module_name != NULL)
 
227
                            msg_Dbg (p_this,
 
228
                                     "loading config for module \"%s\"",
 
229
                                     section);
 
230
                        break;
 
231
                    }
 
232
                }
 
233
            }
 
234
 
 
235
            continue;
 
236
        }
 
237
 
 
238
        if (module == NULL)
 
239
            continue; /* no need to parse if there is no matching module */
 
240
 
 
241
        char *ptr = strchr (line, '\n');
 
242
        if (ptr != NULL)
 
243
            *ptr = '\0';
 
244
 
 
245
        /* look for option name */
 
246
        const char *psz_option_name = line;
 
247
 
 
248
        ptr = strchr (line, '=');
 
249
        if (ptr == NULL)
 
250
            continue; /* syntax error */
 
251
 
 
252
        *ptr = '\0';
 
253
        const char *psz_option_value = ptr + 1;
 
254
 
 
255
        /* try to match this option with one of the module's options */
 
256
        for (size_t i = 0; i < module->confsize; i++)
 
257
        {
 
258
            module_config_t *p_item = module->p_config + i;
 
259
 
 
260
            if ((p_item->i_type & CONFIG_HINT)
 
261
             || strcmp (p_item->psz_name, psz_option_name))
 
262
                continue;
 
263
 
 
264
            /* We found it */
 
265
            errno = 0;
 
266
 
 
267
            switch( p_item->i_type )
 
268
            {
 
269
                case CONFIG_ITEM_BOOL:
 
270
                case CONFIG_ITEM_INTEGER:
 
271
                {
 
272
                    long l = strtoi (psz_option_value);
 
273
                    if (errno)
 
274
                        msg_Warn (p_this, "Integer value (%s) for %s: %m",
 
275
                                  psz_option_value, psz_option_name);
 
276
                    else
 
277
                        p_item->saved.i = p_item->value.i = (int)l;
 
278
                    break;
 
279
                }
 
280
 
 
281
                case CONFIG_ITEM_FLOAT:
 
282
                    if( !*psz_option_value )
 
283
                        break;                    /* ignore empty option */
 
284
                    p_item->value.f = (float)atof (psz_option_value);
 
285
                    p_item->saved.f = p_item->value.f;
 
286
                    break;
 
287
 
 
288
                case CONFIG_ITEM_KEY:
 
289
                    if( !*psz_option_value )
 
290
                        break;                    /* ignore empty option */
 
291
                    p_item->value.i = ConfigStringToKey(psz_option_value);
 
292
                    p_item->saved.i = p_item->value.i;
 
293
                    break;
 
294
 
 
295
                default:
 
296
                    vlc_mutex_lock( p_item->p_lock );
 
297
 
 
298
                    /* free old string */
 
299
                    free( (char*) p_item->value.psz );
 
300
                    free( (char*) p_item->saved.psz );
 
301
 
 
302
                    p_item->value.psz = convert (psz_option_value);
 
303
                    p_item->saved.psz = strdupnull (p_item->value.psz);
 
304
 
 
305
                    vlc_mutex_unlock( p_item->p_lock );
 
306
                    break;
 
307
            }
 
308
 
 
309
            break;
 
310
        }
 
311
    }
 
312
 
 
313
    if (ferror (file))
 
314
    {
 
315
        msg_Err (p_this, "error reading configuration: %m");
 
316
        clearerr (file);
 
317
    }
 
318
    fclose (file);
 
319
 
 
320
    vlc_list_release( p_list );
 
321
    if (loc != (locale_t)0)
 
322
    {
 
323
        uselocale (baseloc);
 
324
        freelocale (loc);
 
325
    }
 
326
 
 
327
    vlc_mutex_unlock( &priv->config_lock );
 
328
    return 0;
 
329
}
 
330
 
 
331
/*****************************************************************************
 
332
 * config_CreateDir: Create configuration directory if it doesn't exist.
 
333
 *****************************************************************************/
 
334
int config_CreateDir( vlc_object_t *p_this, const char *psz_dirname )
 
335
{
 
336
    if( !psz_dirname || !*psz_dirname ) return -1;
 
337
 
 
338
    if( utf8_mkdir( psz_dirname, 0700 ) == 0 )
 
339
        return 0;
 
340
 
 
341
    switch( errno )
 
342
    {
 
343
        case EEXIST:
 
344
            return 0;
 
345
 
 
346
        case ENOENT:
 
347
        {
 
348
            /* Let's try to create the parent directory */
 
349
            char psz_parent[strlen( psz_dirname ) + 1], *psz_end;
 
350
            strcpy( psz_parent, psz_dirname );
 
351
 
 
352
            psz_end = strrchr( psz_parent, DIR_SEP_CHAR );
 
353
            if( psz_end && psz_end != psz_parent )
 
354
            {
 
355
                *psz_end = '\0';
 
356
                if( config_CreateDir( p_this, psz_parent ) == 0 )
 
357
                {
 
358
                    if( !utf8_mkdir( psz_dirname, 0700 ) )
 
359
                        return 0;
 
360
                }
 
361
            }
 
362
        }
 
363
    }
 
364
 
 
365
    msg_Err( p_this, "could not create %s: %m", psz_dirname );
 
366
    return -1;
 
367
}
 
368
 
 
369
static int
 
370
config_Write (FILE *file, const char *type, const char *desc,
 
371
              bool comment, const char *name, const char *fmt, ...)
 
372
{
 
373
    va_list ap;
 
374
    int ret;
 
375
 
 
376
    if (desc == NULL)
 
377
        desc = "?";
 
378
 
 
379
    if (fprintf (file, "# %s (%s)\n%s%s=", desc, _(type),
 
380
                 comment ? "#" : "", name) < 0)
 
381
        return -1;
 
382
 
 
383
    va_start (ap, fmt);
 
384
    ret = vfprintf (file, fmt, ap);
 
385
    va_end (ap);
 
386
    if (ret < 0)
 
387
        return -1;
 
388
 
 
389
    if (fputs ("\n\n", file) == EOF)
 
390
        return -1;
 
391
    return 0;
 
392
}
 
393
 
 
394
 
 
395
/*****************************************************************************
 
396
 * config_SaveConfigFile: Save a module's config options.
 
397
 *****************************************************************************
 
398
 * This will save the specified module's config options to the config file.
 
399
 * If psz_module_name is NULL then we save all the modules config options.
 
400
 * It's no use to save the config options that kept their default values, so
 
401
 * we'll try to be a bit clever here.
 
402
 *
 
403
 * When we save we mustn't delete the config options of the modules that
 
404
 * haven't been loaded. So we cannot just create a new config file with the
 
405
 * config structures we've got in memory.
 
406
 * I don't really know how to deal with this nicely, so I will use a completly
 
407
 * dumb method ;-)
 
408
 * I will load the config file in memory, but skipping all the sections of the
 
409
 * modules we want to save. Then I will create a brand new file, dump the file
 
410
 * loaded in memory and then append the sections of the modules we want to
 
411
 * save.
 
412
 * Really stupid no ?
 
413
 *****************************************************************************/
 
414
static int SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name,
 
415
                           bool b_autosave )
 
416
{
 
417
    libvlc_priv_t *priv = libvlc_priv (p_this->p_libvlc);
 
418
    module_t *p_parser;
 
419
    vlc_list_t *p_list;
 
420
    FILE *file;
 
421
    char p_line[1024], *p_index2;
 
422
    int i_sizebuf = 0;
 
423
    char *p_bigbuffer, *p_index;
 
424
    bool b_backup;
 
425
    int i_index;
 
426
 
 
427
    /* Acquire config file lock */
 
428
    vlc_mutex_lock( &priv->config_lock );
 
429
 
 
430
    if( libvlc_priv (p_this->p_libvlc)->psz_configfile == NULL )
 
431
    {
 
432
        char *psz_configdir = config_GetUserConfDir();
 
433
        if( !psz_configdir ) /* XXX: This should never happen */
 
434
        {
 
435
            msg_Err( p_this, "no configuration directory defined" );
 
436
            vlc_mutex_unlock( &priv->config_lock );
 
437
            return -1;
 
438
        }
 
439
 
 
440
        config_CreateDir( p_this, psz_configdir );
 
441
        free( psz_configdir );
 
442
    }
 
443
 
 
444
    file = config_OpenConfigFile( p_this, "rt" );
 
445
    if( file != NULL )
 
446
    {
 
447
        /* look for file size */
 
448
        fseek( file, 0L, SEEK_END );
 
449
        i_sizebuf = ftell( file );
 
450
        fseek( file, 0L, SEEK_SET );
 
451
    }
 
452
 
 
453
    p_bigbuffer = p_index = malloc( i_sizebuf+1 );
 
454
    if( !p_bigbuffer )
 
455
    {
 
456
        if( file ) fclose( file );
 
457
        vlc_mutex_unlock( &priv->config_lock );
 
458
        return -1;
 
459
    }
 
460
    p_bigbuffer[0] = 0;
 
461
 
 
462
    /* List all available modules */
 
463
    p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
 
464
 
 
465
    /* backup file into memory, we only need to backup the sections we won't
 
466
     * save later on */
 
467
    b_backup = 0;
 
468
    while( file && fgets( p_line, 1024, file ) )
 
469
    {
 
470
        if( (p_line[0] == '[') && (p_index2 = strchr(p_line,']')))
 
471
        {
 
472
 
 
473
            /* we found a section, check if we need to do a backup */
 
474
            for( i_index = 0; i_index < p_list->i_count; i_index++ )
 
475
            {
 
476
                p_parser = (module_t *)p_list->p_values[i_index].p_object ;
 
477
 
 
478
                if( ((p_index2 - &p_line[1])
 
479
                       == (int)strlen(p_parser->psz_object_name) )
 
480
                    && !memcmp( &p_line[1], p_parser->psz_object_name,
 
481
                                strlen(p_parser->psz_object_name) ) )
 
482
                {
 
483
                    if( !psz_module_name )
 
484
                        break;
 
485
                    else if( !strcmp( psz_module_name,
 
486
                                      p_parser->psz_object_name ) )
 
487
                        break;
 
488
                }
 
489
            }
 
490
 
 
491
            if( i_index == p_list->i_count )
 
492
            {
 
493
                /* we don't have this section in our list so we need to back
 
494
                 * it up */
 
495
                *p_index2 = 0;
 
496
#if 0
 
497
                msg_Dbg( p_this, "backing up config for unknown module \"%s\"",
 
498
                                 &p_line[1] );
 
499
#endif
 
500
                *p_index2 = ']';
 
501
 
 
502
                b_backup = 1;
 
503
            }
 
504
            else
 
505
            {
 
506
                b_backup = 0;
 
507
            }
 
508
        }
 
509
 
 
510
        /* save line if requested and line is valid (doesn't begin with a
 
511
         * space, tab, or eol) */
 
512
        if( b_backup && (p_line[0] != '\n') && (p_line[0] != ' ')
 
513
            && (p_line[0] != '\t') )
 
514
        {
 
515
            strcpy( p_index, p_line );
 
516
            p_index += strlen( p_line );
 
517
        }
 
518
    }
 
519
    if( file ) fclose( file );
 
520
 
 
521
 
 
522
    /*
 
523
     * Save module config in file
 
524
     */
 
525
 
 
526
    file = config_OpenConfigFile (p_this, "wt");
 
527
    if( !file )
 
528
    {
 
529
        vlc_list_release( p_list );
 
530
        free( p_bigbuffer );
 
531
        vlc_mutex_unlock( &priv->config_lock );
 
532
        return -1;
 
533
    }
 
534
 
 
535
    fprintf( file, "\xEF\xBB\xBF###\n###  " COPYRIGHT_MESSAGE "\n###\n\n"
 
536
       "###\n### lines beginning with a '#' character are comments\n###\n\n" );
 
537
 
 
538
    /* Ensure consistent number formatting... */
 
539
    locale_t loc = newlocale (LC_NUMERIC_MASK, "C", NULL);
 
540
    locale_t baseloc = uselocale (loc);
 
541
 
 
542
    /* Look for the selected module, if NULL then save everything */
 
543
    for( i_index = 0; i_index < p_list->i_count; i_index++ )
 
544
    {
 
545
        module_config_t *p_item, *p_end;
 
546
        p_parser = (module_t *)p_list->p_values[i_index].p_object ;
 
547
 
 
548
        if( psz_module_name && strcmp( psz_module_name,
 
549
                                       p_parser->psz_object_name ) )
 
550
            continue;
 
551
 
 
552
        if( !p_parser->i_config_items )
 
553
            continue;
 
554
 
 
555
        if( psz_module_name )
 
556
            msg_Dbg( p_this, "saving config for module \"%s\"",
 
557
                     p_parser->psz_object_name );
 
558
 
 
559
        fprintf( file, "[%s]", p_parser->psz_object_name );
 
560
        if( p_parser->psz_longname )
 
561
            fprintf( file, " # %s\n\n", p_parser->psz_longname );
 
562
        else
 
563
            fprintf( file, "\n\n" );
 
564
 
 
565
        for( p_item = p_parser->p_config, p_end = p_item + p_parser->confsize;
 
566
             p_item < p_end;
 
567
             p_item++ )
 
568
        {
 
569
            /* Do not save the new value in the configuration file
 
570
             * if doing an autosave, and the item is not an "autosaved" one. */
 
571
            bool b_retain = b_autosave && !p_item->b_autosave;
 
572
 
 
573
            if ((p_item->i_type & CONFIG_HINT) /* ignore hint */
 
574
             || p_item->b_removed              /* ignore deprecated option */
 
575
             || p_item->b_unsaveable)          /* ignore volatile option */
 
576
                continue;
 
577
 
 
578
            if (IsConfigIntegerType (p_item->i_type))
 
579
            {
 
580
                int val = b_retain ? p_item->saved.i : p_item->value.i;
 
581
                if (p_item->i_type == CONFIG_ITEM_KEY)
 
582
                {
 
583
                    char *psz_key = ConfigKeyToString (val);
 
584
                    config_Write (file, p_item->psz_text, N_("key"),
 
585
                                  val == p_item->orig.i,
 
586
                                  p_item->psz_name, "%s",
 
587
                                  psz_key ? psz_key : "");
 
588
                    free (psz_key);
 
589
                }
 
590
                else
 
591
                    config_Write (file, p_item->psz_text,
 
592
                                  (p_item->i_type == CONFIG_ITEM_BOOL)
 
593
                                      ? N_("boolean") : N_("integer"),
 
594
                                  val == p_item->orig.i,
 
595
                                  p_item->psz_name, "%d", val);
 
596
                p_item->saved.i = val;
 
597
            }
 
598
            else
 
599
            if (IsConfigFloatType (p_item->i_type))
 
600
            {
 
601
                float val = b_retain ? p_item->saved.f : p_item->value.f;
 
602
                config_Write (file, p_item->psz_text, N_("float"),
 
603
                              val == p_item->orig.f,
 
604
                              p_item->psz_name, "%f", val);
 
605
                p_item->saved.f = val;
 
606
            }
 
607
            else
 
608
            {
 
609
                const char *psz_value = b_retain ? p_item->saved.psz
 
610
                                                 : p_item->value.psz;
 
611
                bool modified;
 
612
 
 
613
                assert (IsConfigStringType (p_item->i_type));
 
614
 
 
615
                if (b_retain && (psz_value == NULL)) /* FIXME: hack */
 
616
                    psz_value = p_item->orig.psz;
 
617
 
 
618
                modified =
 
619
                    (psz_value != NULL)
 
620
                        ? ((p_item->orig.psz != NULL)
 
621
                            ? (strcmp (psz_value, p_item->orig.psz) != 0)
 
622
                            : true)
 
623
                        : (p_item->orig.psz != NULL);
 
624
 
 
625
                config_Write (file, p_item->psz_text, N_("string"),
 
626
                              !modified, p_item->psz_name, "%s",
 
627
                              psz_value ? psz_value : "");
 
628
 
 
629
                if ( !b_retain )
 
630
                {
 
631
 
 
632
                    free ((char *)p_item->saved.psz);
 
633
                    if( (psz_value && p_item->orig.psz &&
 
634
                         strcmp( psz_value, p_item->orig.psz )) ||
 
635
                        !psz_value || !p_item->orig.psz)
 
636
                        p_item->saved.psz = strdupnull (psz_value);
 
637
                    else
 
638
                        p_item->saved.psz = NULL;
 
639
                }
 
640
            }
 
641
 
 
642
            if (!b_retain)
 
643
                p_item->b_dirty = false;
 
644
        }
 
645
    }
 
646
 
 
647
    vlc_list_release( p_list );
 
648
    if (loc != (locale_t)0)
 
649
    {
 
650
        uselocale (baseloc);
 
651
        freelocale (loc);
 
652
    }
 
653
 
 
654
    /*
 
655
     * Restore old settings from the config in file
 
656
     */
 
657
    fputs( p_bigbuffer, file );
 
658
    free( p_bigbuffer );
 
659
 
 
660
    fclose( file );
 
661
    vlc_mutex_unlock( &priv->config_lock );
 
662
 
 
663
    return 0;
 
664
}
 
665
 
 
666
int config_AutoSaveConfigFile( vlc_object_t *p_this )
 
667
{
 
668
    libvlc_priv_t *priv = libvlc_priv (p_this->p_libvlc);
 
669
    vlc_list_t *p_list;
 
670
    int i_index, i_count;
 
671
 
 
672
    assert( p_this );
 
673
 
 
674
    /* Check if there's anything to save */
 
675
    vlc_mutex_lock( &priv->config_lock );
 
676
    p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
 
677
    i_count = p_list->i_count;
 
678
    for( i_index = 0; i_index < i_count; i_index++ )
 
679
    {
 
680
        module_t *p_parser = (module_t *)p_list->p_values[i_index].p_object ;
 
681
        module_config_t *p_item, *p_end;
 
682
 
 
683
        if( !p_parser->i_config_items ) continue;
 
684
 
 
685
        for( p_item = p_parser->p_config, p_end = p_item + p_parser->confsize;
 
686
             p_item < p_end;
 
687
             p_item++ )
 
688
        {
 
689
            if( p_item->b_autosave && p_item->b_dirty ) break;
 
690
        }
 
691
        if( p_item < p_end ) break;
 
692
    }
 
693
    vlc_list_release( p_list );
 
694
    vlc_mutex_unlock( &priv->config_lock );
 
695
 
 
696
    if( i_index == i_count ) return VLC_SUCCESS;
 
697
    return SaveConfigFile( p_this, 0, true );
 
698
}
 
699
 
 
700
int __config_SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name )
 
701
{
 
702
    return SaveConfigFile( p_this, psz_module_name, false );
 
703
}
 
704
 
 
705
/**
 
706
 * Get the user's configuration file when given with the --config option
 
707
 */
 
708
char *config_GetCustomConfigFile( libvlc_int_t *p_libvlc )
 
709
{
 
710
    char *psz_configfile = config_GetPsz( p_libvlc, "config" );
 
711
    if( psz_configfile != NULL )
 
712
    {
 
713
        if( psz_configfile[0] == '~' && psz_configfile[1] == '/' )
 
714
        {
 
715
            /* This is incomplete: we should also support the ~cmassiot/ syntax */
 
716
            char *psz_buf;
 
717
            if( asprintf( &psz_buf, "%s/%s", config_GetHomeDir(),
 
718
                          psz_configfile + 2 ) == -1 )
 
719
            {
 
720
                free( psz_configfile );
 
721
                return NULL;
 
722
            }
 
723
            free( psz_configfile );
 
724
            psz_configfile = psz_buf;
 
725
        }
 
726
    }
 
727
    return psz_configfile;
 
728
}
 
729
 
 
730
int ConfigStringToKey( const char *psz_key )
 
731
{
 
732
    int i_key = 0;
 
733
    unsigned int i;
 
734
    const char *psz_parser = strchr( psz_key, '-' );
 
735
    while( psz_parser && psz_parser != psz_key )
 
736
    {
 
737
        for( i = 0; i < sizeof(vlc_modifiers) / sizeof(key_descriptor_t); i++ )
 
738
        {
 
739
            if( !strncasecmp( vlc_modifiers[i].psz_key_string, psz_key,
 
740
                              strlen( vlc_modifiers[i].psz_key_string ) ) )
 
741
            {
 
742
                i_key |= vlc_modifiers[i].i_key_code;
 
743
            }
 
744
        }
 
745
        psz_key = psz_parser + 1;
 
746
        psz_parser = strchr( psz_key, '-' );
 
747
    }
 
748
    for( i = 0; i < sizeof(vlc_keys) / sizeof( key_descriptor_t ); i++ )
 
749
    {
 
750
        if( !strcasecmp( vlc_keys[i].psz_key_string, psz_key ) )
 
751
        {
 
752
            i_key |= vlc_keys[i].i_key_code;
 
753
            break;
 
754
        }
 
755
    }
 
756
    return i_key;
 
757
}
 
758
 
 
759
char *ConfigKeyToString( int i_key )
 
760
{
 
761
    char *psz_key = malloc( 100 );
 
762
    char *p;
 
763
    size_t index;
 
764
 
 
765
    if ( !psz_key )
 
766
    {
 
767
        return NULL;
 
768
    }
 
769
    *psz_key = '\0';
 
770
    p = psz_key;
 
771
 
 
772
    for( index = 0; index < (sizeof(vlc_modifiers) / sizeof(key_descriptor_t));
 
773
         index++ )
 
774
    {
 
775
        if( i_key & vlc_modifiers[index].i_key_code )
 
776
        {
 
777
            p += sprintf( p, "%s-", vlc_modifiers[index].psz_key_string );
 
778
        }
 
779
    }
 
780
    for( index = 0; index < (sizeof(vlc_keys) / sizeof( key_descriptor_t));
 
781
         index++)
 
782
    {
 
783
        if( (int)( i_key & ~KEY_MODIFIER ) == vlc_keys[index].i_key_code )
 
784
        {
 
785
            p += sprintf( p, "%s", vlc_keys[index].psz_key_string );
 
786
            break;
 
787
        }
 
788
    }
 
789
    return psz_key;
 
790
}
 
791