Search
lxdream.org :: lxdream/src/config.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/config.c
changeset 1024:c67f2d61ab97
prev1015:ad448bedc48a
next1034:7044e01148f0
author nkeynes
date Sat Jun 13 00:50:48 2009 +0000 (13 years ago)
permissions -rw-r--r--
last change Build drivers with library dependencies as shared objects (ie plugins)
file annotate diff log raw
nkeynes@450
     1
/**
nkeynes@561
     2
 * $Id$
nkeynes@450
     3
 *
nkeynes@450
     4
 * User configuration support
nkeynes@450
     5
 *
nkeynes@450
     6
 * Copyright (c) 2005 Nathan Keynes.
nkeynes@450
     7
 *
nkeynes@450
     8
 * This program is free software; you can redistribute it and/or modify
nkeynes@450
     9
 * it under the terms of the GNU General Public License as published by
nkeynes@450
    10
 * the Free Software Foundation; either version 2 of the License, or
nkeynes@450
    11
 * (at your option) any later version.
nkeynes@450
    12
 *
nkeynes@450
    13
 * This program is distributed in the hope that it will be useful,
nkeynes@450
    14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nkeynes@450
    15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
nkeynes@450
    16
 * GNU General Public License for more details.
nkeynes@450
    17
 */
nkeynes@450
    18
nkeynes@450
    19
#include <unistd.h>
nkeynes@450
    20
#include <stdio.h>
nkeynes@450
    21
#include <errno.h>
nkeynes@450
    22
#include <stdlib.h>
nkeynes@450
    23
#include <string.h>
nkeynes@480
    24
#include <glib/gmem.h>
nkeynes@450
    25
#include <glib/gstrfuncs.h>
nkeynes@450
    26
#include "dream.h"
nkeynes@450
    27
#include "config.h"
nkeynes@450
    28
#include "maple/maple.h"
nkeynes@450
    29
nkeynes@1024
    30
#define MAX_ROOT_GROUPS 16
bhaal22@643
    31
bhaal22@643
    32
extern struct lxdream_config_entry alsa_config[];
nkeynes@1015
    33
extern struct lxdream_config_entry hotkeys_config[];
bhaal22@643
    34
nkeynes@450
    35
gboolean lxdream_load_config_file( const gchar *filename );
nkeynes@450
    36
gboolean lxdream_save_config_file( const gchar *filename );
nkeynes@450
    37
gboolean lxdream_load_config_stream( FILE *f );
nkeynes@450
    38
gboolean lxdream_save_config_stream( FILE *f );
nkeynes@450
    39
nkeynes@450
    40
static struct lxdream_config_entry global_config[] =
nkeynes@736
    41
       {{ "bios", N_("Bios ROM"), CONFIG_TYPE_FILE, "dcboot.rom" },
nkeynes@736
    42
        { "flash", N_("Flash ROM"), CONFIG_TYPE_FILE, "dcflash.rom" },
nkeynes@736
    43
        { "default path", N_("Default disc path"), CONFIG_TYPE_PATH, "." },
nkeynes@736
    44
        { "save path", N_("Save-state path"), CONFIG_TYPE_PATH, "save" },
nkeynes@736
    45
        { "bootstrap", N_("Bootstrap IP.BIN"), CONFIG_TYPE_FILE, "IP.BIN" },
nkeynes@736
    46
        { "gdrom", NULL, CONFIG_TYPE_FILE, NULL },
nkeynes@736
    47
        { "recent", NULL, CONFIG_TYPE_FILE, NULL },
nkeynes@736
    48
        { NULL, CONFIG_TYPE_NONE }};
nkeynes@450
    49
nkeynes@450
    50
static struct lxdream_config_entry serial_config[] =
nkeynes@736
    51
       {{ "device", N_("Serial device"), CONFIG_TYPE_FILE, "/dev/ttyS1" },
nkeynes@736
    52
        { NULL, CONFIG_TYPE_NONE }};
nkeynes@450
    53
nkeynes@1024
    54
struct lxdream_config_group lxdream_config_root[MAX_ROOT_GROUPS+1] = 
nkeynes@736
    55
       {{ "global", global_config },
nkeynes@736
    56
        { "controllers", NULL },
nkeynes@1015
    57
        { "hotkeys", hotkeys_config },
nkeynes@736
    58
        { "serial", serial_config },
nkeynes@736
    59
        { NULL, CONFIG_TYPE_NONE }};
nkeynes@450
    60
nkeynes@450
    61
static gchar *lxdream_config_load_filename = NULL;
nkeynes@450
    62
static gchar *lxdream_config_save_filename = NULL;
nkeynes@450
    63
nkeynes@1024
    64
void lxdream_register_config_group( const gchar *key, lxdream_config_entry_t group )
nkeynes@1024
    65
{
nkeynes@1024
    66
    int i;
nkeynes@1024
    67
    for( i=0; i<MAX_ROOT_GROUPS; i++ ) {
nkeynes@1024
    68
        if( lxdream_config_root[i].key == NULL ) {
nkeynes@1024
    69
            lxdream_config_root[i].key = key;
nkeynes@1024
    70
            lxdream_config_root[i].params = group;
nkeynes@1024
    71
            lxdream_config_root[i+1].key = NULL;
nkeynes@1024
    72
            lxdream_config_root[i+1].params = CONFIG_TYPE_NONE;
nkeynes@1024
    73
            return;
nkeynes@1024
    74
        }
nkeynes@1024
    75
    }
nkeynes@1024
    76
    ERROR( "Unable to register config group '%s': Too many configuration groups", key );
nkeynes@1024
    77
}
nkeynes@1024
    78
nkeynes@450
    79
gboolean lxdream_find_config()
nkeynes@450
    80
{
nkeynes@480
    81
    gboolean result = TRUE;
nkeynes@450
    82
    char *home = getenv("HOME");
nkeynes@450
    83
    if( lxdream_config_save_filename == NULL ) {
nkeynes@736
    84
        lxdream_config_save_filename = g_strdup_printf("%s/.%s", home, DEFAULT_CONFIG_FILENAME);
nkeynes@450
    85
    }
nkeynes@450
    86
    if( lxdream_config_load_filename == NULL ) {
nkeynes@866
    87
        char *sysconfig = g_strdup_printf("%s/%s", get_sysconf_path(), DEFAULT_CONFIG_FILENAME);
nkeynes@736
    88
        if( access(lxdream_config_save_filename, R_OK) == 0 ) {
nkeynes@736
    89
            lxdream_config_load_filename = g_strdup(lxdream_config_save_filename);
nkeynes@866
    90
            g_free(sysconfig);
nkeynes@866
    91
        } else if( access( sysconfig, R_OK ) == 0 ) {
nkeynes@866
    92
            lxdream_config_load_filename = sysconfig;
nkeynes@736
    93
        } else if( access( "./" DEFAULT_CONFIG_FILENAME, R_OK ) == 0 ) {
nkeynes@736
    94
            lxdream_config_load_filename = g_strdup("./" DEFAULT_CONFIG_FILENAME);
nkeynes@866
    95
            g_free(sysconfig);
nkeynes@736
    96
        } else {
nkeynes@736
    97
            lxdream_config_load_filename = g_strdup(lxdream_config_save_filename);
nkeynes@866
    98
            g_free(sysconfig);
nkeynes@736
    99
            result = FALSE;
nkeynes@736
   100
        }	
nkeynes@480
   101
    }
nkeynes@480
   102
    return result;
nkeynes@450
   103
}
nkeynes@450
   104
nkeynes@450
   105
void lxdream_set_config_filename( const gchar *filename )
nkeynes@450
   106
{
nkeynes@450
   107
    if( lxdream_config_load_filename != NULL ) {
nkeynes@736
   108
        g_free(lxdream_config_load_filename);
nkeynes@450
   109
    }
nkeynes@450
   110
    lxdream_config_load_filename = g_strdup(filename);
nkeynes@450
   111
    if( lxdream_config_save_filename != NULL ) {
nkeynes@736
   112
        g_free(lxdream_config_save_filename);
nkeynes@450
   113
    }
nkeynes@450
   114
    lxdream_config_save_filename = g_strdup(filename);
nkeynes@450
   115
}
nkeynes@450
   116
nkeynes@450
   117
void lxdream_set_default_config( )
nkeynes@450
   118
{
nkeynes@450
   119
    struct lxdream_config_group *group = lxdream_config_root;
nkeynes@450
   120
    while( group->key != NULL ) {
nkeynes@736
   121
        struct lxdream_config_entry *param = group->params;
nkeynes@736
   122
        if( param != NULL ) {
nkeynes@736
   123
            while( param->key != NULL ) {
nkeynes@736
   124
                if( param->value != param->default_value ) {
nkeynes@736
   125
                    if( param->value != NULL )
nkeynes@736
   126
                        free( param->value );
nkeynes@736
   127
                    param->value = (gchar *)param->default_value;
nkeynes@736
   128
                }
nkeynes@736
   129
                param++;
nkeynes@736
   130
            }
nkeynes@736
   131
        }
nkeynes@736
   132
        group++;
nkeynes@450
   133
    }
nkeynes@450
   134
    maple_detach_all();
nkeynes@450
   135
}
nkeynes@450
   136
nkeynes@450
   137
const gchar *lxdream_get_config_value( int key )
nkeynes@450
   138
{
nkeynes@450
   139
    return global_config[key].value;
nkeynes@450
   140
}
nkeynes@450
   141
nkeynes@460
   142
void lxdream_set_config_value( lxdream_config_entry_t param, const gchar *value )
nkeynes@450
   143
{
nkeynes@475
   144
    if( param->value != value ) {
nkeynes@736
   145
        if( param->value != param->default_value && param->value != NULL ) {
nkeynes@736
   146
            free( param->value );
nkeynes@736
   147
        }
nkeynes@736
   148
        param->value = g_strdup(value);
nkeynes@450
   149
    }
nkeynes@450
   150
}
nkeynes@450
   151
nkeynes@460
   152
void lxdream_set_global_config_value( int key, const gchar *value )
nkeynes@460
   153
{
nkeynes@460
   154
    lxdream_set_config_value(&global_config[key], value);
nkeynes@460
   155
}
nkeynes@460
   156
nkeynes@759
   157
const struct lxdream_config_entry * lxdream_get_config_entry( int key )
nkeynes@724
   158
{
nkeynes@724
   159
    return &global_config[key];
nkeynes@724
   160
}
nkeynes@724
   161
nkeynes@458
   162
gboolean lxdream_set_group_value( lxdream_config_group_t group, const gchar *key, const gchar *value )
nkeynes@458
   163
{
nkeynes@458
   164
    int i;
nkeynes@458
   165
    for( i=0; group->params[i].key != NULL; i++ ) {
nkeynes@736
   166
        if( strcasecmp( group->params[i].key, key ) == 0 ) {
nkeynes@736
   167
            lxdream_set_config_value( &group->params[i], value );
nkeynes@736
   168
            return TRUE;
nkeynes@736
   169
        }
nkeynes@458
   170
    }
nkeynes@458
   171
    return FALSE;
nkeynes@458
   172
}
nkeynes@458
   173
nkeynes@460
   174
void lxdream_copy_config_list( lxdream_config_entry_t dest, lxdream_config_entry_t src )
nkeynes@460
   175
{
nkeynes@460
   176
    int i;
nkeynes@460
   177
    for( i=0; src[i].key != NULL; i++ ) {
nkeynes@736
   178
        lxdream_set_config_value( &dest[i], src[i].value );
nkeynes@460
   179
    }
nkeynes@460
   180
}
nkeynes@460
   181
nkeynes@450
   182
gboolean lxdream_load_config( )
nkeynes@450
   183
{
nkeynes@450
   184
    if( lxdream_config_load_filename == NULL ) {
nkeynes@736
   185
        lxdream_find_config();
nkeynes@450
   186
    }
nkeynes@450
   187
    return lxdream_load_config_file(lxdream_config_load_filename);
nkeynes@450
   188
}
nkeynes@450
   189
nkeynes@450
   190
gboolean lxdream_save_config( )
nkeynes@450
   191
{
nkeynes@450
   192
    if( lxdream_config_save_filename == NULL ) {
nkeynes@736
   193
        lxdream_find_config();
nkeynes@450
   194
    }
nkeynes@450
   195
    return lxdream_save_config_file(lxdream_config_save_filename);
nkeynes@450
   196
}
nkeynes@450
   197
nkeynes@450
   198
gboolean lxdream_load_config_file( const gchar *filename )
nkeynes@450
   199
{
nkeynes@450
   200
    FILE *f;
nkeynes@450
   201
    gboolean result;
nkeynes@450
   202
nkeynes@450
   203
    if( access(filename, F_OK) != 0 ) {
nkeynes@736
   204
        INFO( "Configuration file '%s' does not exist, creating from defaults" );
nkeynes@736
   205
        lxdream_set_default_config();
nkeynes@736
   206
        lxdream_save_config();
nkeynes@450
   207
    }
nkeynes@450
   208
nkeynes@450
   209
    f = fopen(filename, "ro");
nkeynes@450
   210
    if( f == NULL ) {
nkeynes@736
   211
        ERROR( "Unable to open configuration file '%s': %s", filename, strerror(errno) );
nkeynes@736
   212
        lxdream_set_default_config();
nkeynes@736
   213
        return FALSE;
nkeynes@450
   214
    }
nkeynes@450
   215
nkeynes@450
   216
    result = lxdream_load_config_stream( f );
nkeynes@450
   217
    fclose(f);
nkeynes@450
   218
    return result;
nkeynes@450
   219
}
nkeynes@450
   220
nkeynes@450
   221
gboolean lxdream_load_config_stream( FILE *f )
nkeynes@450
   222
{
nkeynes@450
   223
nkeynes@450
   224
    char buf[512];
nkeynes@450
   225
    int maple_device = -1, maple_subdevice = -1;
nkeynes@450
   226
    struct lxdream_config_group devgroup;
nkeynes@450
   227
    struct lxdream_config_group *group = NULL;
nkeynes@450
   228
    maple_device_t device = NULL;
nkeynes@450
   229
    lxdream_set_default_config();
nkeynes@450
   230
nkeynes@450
   231
    while( fgets( buf, sizeof(buf), f ) != NULL ) {
nkeynes@736
   232
        g_strstrip(buf);
nkeynes@736
   233
        if( buf[0] == '#' )
nkeynes@736
   234
            continue;
nkeynes@736
   235
        if( *buf == '[' ) {
nkeynes@736
   236
            char *p = strchr(buf, ']');
nkeynes@736
   237
            if( p != NULL ) {
nkeynes@736
   238
                struct lxdream_config_group *tmp_group;
nkeynes@736
   239
                maple_device = maple_subdevice = -1;
nkeynes@736
   240
                *p = '\0';
nkeynes@736
   241
                g_strstrip(buf+1);
nkeynes@736
   242
                tmp_group = &lxdream_config_root[0];
nkeynes@736
   243
                while( tmp_group->key != NULL ) {
nkeynes@736
   244
                    if( strcasecmp(tmp_group->key, buf+1) == 0 ) {
nkeynes@736
   245
                        group = tmp_group;
nkeynes@736
   246
                        break;
nkeynes@736
   247
                    }
nkeynes@736
   248
                    tmp_group++;
nkeynes@736
   249
                }
nkeynes@736
   250
            }
nkeynes@736
   251
        } else if( group != NULL ) {
nkeynes@736
   252
            char *value = strchr( buf, '=' );
nkeynes@736
   253
            if( value != NULL ) {
nkeynes@736
   254
                struct lxdream_config_entry *param = group->params;
nkeynes@736
   255
                *value = '\0';
nkeynes@736
   256
                value++;
nkeynes@736
   257
                g_strstrip(buf);
nkeynes@736
   258
                g_strstrip(value);
nkeynes@736
   259
                if( strcmp(group->key,"controllers") == 0  ) {
nkeynes@736
   260
                    if( g_strncasecmp( buf, "device ", 7 ) == 0 ) {
nkeynes@736
   261
                        maple_device = strtoul( buf+7, NULL, 0 );
nkeynes@736
   262
                        if( maple_device < 0 || maple_device > 3 ) {
nkeynes@736
   263
                            ERROR( "Device number must be between 0..3 (not '%s')", buf+7);
nkeynes@736
   264
                            continue;
nkeynes@736
   265
                        }
nkeynes@736
   266
                        maple_subdevice = 0;
nkeynes@736
   267
                        device = maple_new_device( value );
nkeynes@736
   268
                        if( device == NULL ) {
nkeynes@736
   269
                            ERROR( "Unrecognized device '%s'", value );
nkeynes@736
   270
                        } else {
nkeynes@736
   271
                            devgroup.key = "controllers";
nkeynes@736
   272
                            devgroup.params = maple_get_device_config(device);
nkeynes@736
   273
                            maple_attach_device( device, maple_device, maple_subdevice );
nkeynes@736
   274
                            group = &devgroup;
nkeynes@736
   275
                        }
nkeynes@736
   276
                        continue;
nkeynes@736
   277
                    } else if( g_strncasecmp( buf, "subdevice ", 10 ) == 0 ) {
nkeynes@736
   278
                        maple_subdevice = strtoul( buf+10, NULL, 0 );
nkeynes@736
   279
                        if( maple_device == -1 ) {
nkeynes@736
   280
                            ERROR( "Subdevice not allowed without primary device" );
nkeynes@736
   281
                        } else if( maple_subdevice < 1 || maple_subdevice > 5 ) {
nkeynes@736
   282
                            ERROR( "Subdevice must be between 1..5 (not '%s')", buf+10 );
nkeynes@736
   283
                        } else if( (device = maple_new_device(value)) == NULL ) {
nkeynes@736
   284
                            ERROR( "Unrecognized subdevice '%s'", value );
nkeynes@736
   285
                        } else {
nkeynes@736
   286
                            devgroup.key = "controllers";
nkeynes@736
   287
                            devgroup.params = maple_get_device_config(device);
nkeynes@736
   288
                            maple_attach_device( device, maple_device, maple_subdevice );
nkeynes@736
   289
                            group = &devgroup;
nkeynes@736
   290
                        }
nkeynes@736
   291
                        continue;
nkeynes@736
   292
                    }
nkeynes@736
   293
                }
nkeynes@736
   294
                while( param->key != NULL ) {
nkeynes@736
   295
                    if( strcasecmp( param->key, buf ) == 0 ) {
nkeynes@736
   296
                        param->value = g_strdup(value);
nkeynes@736
   297
                        break;
nkeynes@736
   298
                    }
nkeynes@736
   299
                    param++;
nkeynes@736
   300
                }
nkeynes@736
   301
            }
nkeynes@736
   302
        }
nkeynes@450
   303
    }
nkeynes@450
   304
    return TRUE;
nkeynes@450
   305
}
nkeynes@450
   306
nkeynes@450
   307
gboolean lxdream_save_config_file( const gchar *filename )
nkeynes@450
   308
{
nkeynes@450
   309
    FILE *f = fopen(filename, "wo");
nkeynes@450
   310
    gboolean result;
nkeynes@450
   311
    if( f == NULL ) {
nkeynes@736
   312
        ERROR( "Unable to open '%s': %s", filename, strerror(errno) );
nkeynes@736
   313
        return FALSE;
nkeynes@450
   314
    }
nkeynes@450
   315
    result = lxdream_save_config_stream(f);
nkeynes@450
   316
    fclose(f);
nkeynes@450
   317
    return TRUE;
nkeynes@450
   318
}    
nkeynes@450
   319
nkeynes@450
   320
gboolean lxdream_save_config_stream( FILE *f )
nkeynes@450
   321
{
nkeynes@450
   322
    struct lxdream_config_group *group = &lxdream_config_root[0];
nkeynes@736
   323
nkeynes@450
   324
    while( group->key != NULL ) {
nkeynes@736
   325
        struct lxdream_config_entry *entry = group->params;
nkeynes@736
   326
        fprintf( f, "[%s]\n", group->key );
nkeynes@736
   327
nkeynes@736
   328
        if( entry != NULL ) {
nkeynes@736
   329
            while( entry->key != NULL ) {
nkeynes@736
   330
                if( entry->value != NULL ) {
nkeynes@736
   331
                    fprintf( f, "%s = %s\n", entry->key, entry->value );
nkeynes@736
   332
                }
nkeynes@736
   333
                entry++;
nkeynes@736
   334
            }
nkeynes@736
   335
        } else if( strcmp(group->key, "controllers") == 0 ) {
nkeynes@736
   336
            int i,j;
nkeynes@736
   337
            for( i=0; i<4; i++ ) {
nkeynes@736
   338
                for( j=0; j<6; j++ ) {
nkeynes@736
   339
                    maple_device_t dev = maple_get_device( i, j );
nkeynes@736
   340
                    if( dev != NULL ) {
nkeynes@736
   341
                        if( j == 0 )
nkeynes@736
   342
                            fprintf( f, "Device %d = %s\n", i, dev->device_class->name );
nkeynes@736
   343
                        else 
nkeynes@736
   344
                            fprintf( f, "Subdevice %d = %s\n", j, dev->device_class->name );
nkeynes@736
   345
                        if( dev->get_config != NULL && ((entry = dev->get_config(dev)) != NULL) ) {
nkeynes@736
   346
                            while( entry->key != NULL ) {
nkeynes@736
   347
                                if( entry->value != NULL ) {
nkeynes@736
   348
                                    fprintf( f, "%*c%s = %s\n", j==0?4:8, ' ',entry->key, entry->value );
nkeynes@736
   349
                                }
nkeynes@736
   350
                                entry++;
nkeynes@736
   351
                            }
nkeynes@736
   352
                        }
nkeynes@736
   353
                    }
nkeynes@736
   354
                }
nkeynes@736
   355
            }
nkeynes@736
   356
        }
nkeynes@736
   357
        fprintf( f, "\n" );
nkeynes@736
   358
        group++;
nkeynes@450
   359
    }
nkeynes@450
   360
    return TRUE;
nkeynes@450
   361
}
.