Search
lxdream.org :: lxdream/src/config.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/config.c
changeset 1072:d82e04e6d497
prev1041:5fcc39857c5c
next1077:136fc24d17ef
author nkeynes
date Tue Jul 21 20:33:21 2009 +1000 (14 years ago)
permissions -rw-r--r--
last change Heavy configuration management refactor
- Configuration groups now take both an on_change event handler and a
default keybinding handler, making most keybinding tasks quite simple
- GUI configuration all merged into a unified model, drastically reducing
the amount of GUI config code.

Bonuses
- OSX now has a hotkey preference pane
- GTK keybinding editor is much more usable
file annotate diff log raw
1.1 --- a/src/config.c Fri Jun 26 05:47:04 2009 +0000
1.2 +++ b/src/config.c Tue Jul 21 20:33:21 2009 +1000
1.3 @@ -25,22 +25,22 @@
1.4 #include <glib/gstrfuncs.h>
1.5 #include <sys/types.h>
1.6 #include <sys/stat.h>
1.7 -#include "dream.h"
1.8 +#include "dreamcast.h"
1.9 #include "config.h"
1.10 #include "lxpaths.h"
1.11 #include "maple/maple.h"
1.12
1.13 #define MAX_ROOT_GROUPS 16
1.14
1.15 -extern struct lxdream_config_entry alsa_config[];
1.16 -extern struct lxdream_config_entry hotkeys_config[];
1.17 +extern struct lxdream_config_group hotkeys_group;
1.18
1.19 gboolean lxdream_load_config_file( const gchar *filename );
1.20 gboolean lxdream_save_config_file( const gchar *filename );
1.21 gboolean lxdream_load_config_stream( FILE *f );
1.22 gboolean lxdream_save_config_stream( FILE *f );
1.23
1.24 -static struct lxdream_config_entry global_config[] =
1.25 +static struct lxdream_config_group global_group =
1.26 + { "global", dreamcast_config_changed, NULL, NULL,
1.27 {{ "bios", N_("Bios ROM"), CONFIG_TYPE_FILE, NULL },
1.28 { "flash", N_("Flash ROM"), CONFIG_TYPE_FILE, NULL },
1.29 { "default path", N_("Default disc path"), CONFIG_TYPE_PATH, "." },
1.30 @@ -51,31 +51,32 @@
1.31 { "recent", NULL, CONFIG_TYPE_FILELIST, NULL },
1.32 { "vmu", NULL, CONFIG_TYPE_FILELIST, NULL },
1.33 { "quick state", NULL, CONFIG_TYPE_INTEGER, "0" },
1.34 - { NULL, CONFIG_TYPE_NONE }};
1.35 + { NULL, CONFIG_TYPE_NONE }} };
1.36
1.37 -static struct lxdream_config_entry serial_config[] =
1.38 +static struct lxdream_config_group serial_group =
1.39 + { "serial", NULL, NULL, NULL,
1.40 {{ "device", N_("Serial device"), CONFIG_TYPE_FILE, "/dev/ttyS1" },
1.41 - { NULL, CONFIG_TYPE_NONE }};
1.42 + { NULL, CONFIG_TYPE_NONE }} };
1.43
1.44 -struct lxdream_config_group lxdream_config_root[MAX_ROOT_GROUPS+1] =
1.45 - {{ "global", global_config },
1.46 - { "controllers", NULL },
1.47 - { "hotkeys", hotkeys_config },
1.48 - { "serial", serial_config },
1.49 - { NULL, CONFIG_TYPE_NONE }};
1.50 +/**
1.51 + * Dummy group for controllers (handled specially)
1.52 + */
1.53 +static struct lxdream_config_group controllers_group =
1.54 + { "controllers", NULL, NULL, NULL, {{NULL, CONFIG_TYPE_NONE}} };
1.55 +
1.56 +struct lxdream_config_group *lxdream_config_root[MAX_ROOT_GROUPS+1] =
1.57 + { &global_group, &controllers_group, &hotkeys_group, &serial_group, NULL };
1.58
1.59 static gchar *lxdream_config_load_filename = NULL;
1.60 static gchar *lxdream_config_save_filename = NULL;
1.61
1.62 -void lxdream_register_config_group( const gchar *key, lxdream_config_entry_t group )
1.63 +void lxdream_register_config_group( const gchar *key, lxdream_config_group_t group )
1.64 {
1.65 int i;
1.66 for( i=0; i<MAX_ROOT_GROUPS; i++ ) {
1.67 - if( lxdream_config_root[i].key == NULL ) {
1.68 - lxdream_config_root[i].key = key;
1.69 - lxdream_config_root[i].params = group;
1.70 - lxdream_config_root[i+1].key = NULL;
1.71 - lxdream_config_root[i+1].params = CONFIG_TYPE_NONE;
1.72 + if( lxdream_config_root[i] == NULL ) {
1.73 + lxdream_config_root[i] = group;
1.74 + lxdream_config_root[i+1] = NULL;
1.75 return;
1.76 }
1.77 }
1.78 @@ -129,16 +130,15 @@
1.79 {
1.80 /* Construct platform dependent defaults */
1.81 const gchar *user_path = get_user_data_path();
1.82 - global_config[CONFIG_BIOS_PATH].default_value = g_strdup_printf( "%s/dcboot.rom", user_path );
1.83 - global_config[CONFIG_FLASH_PATH].default_value = g_strdup_printf( "%s/dcflash.rom", user_path );
1.84 - global_config[CONFIG_SAVE_PATH].default_value = g_strdup_printf( "%s/save", user_path );
1.85 - global_config[CONFIG_VMU_PATH].default_value = g_strdup_printf( "%s/vmu", user_path );
1.86 - global_config[CONFIG_BOOTSTRAP].default_value = g_strdup_printf( "%s/IP.BIN", user_path );
1.87 + global_group.params[CONFIG_BIOS_PATH].default_value = g_strdup_printf( "%s/dcboot.rom", user_path );
1.88 + global_group.params[CONFIG_FLASH_PATH].default_value = g_strdup_printf( "%s/dcflash.rom", user_path );
1.89 + global_group.params[CONFIG_SAVE_PATH].default_value = g_strdup_printf( "%s/save", user_path );
1.90 + global_group.params[CONFIG_VMU_PATH].default_value = g_strdup_printf( "%s/vmu", user_path );
1.91 + global_group.params[CONFIG_BOOTSTRAP].default_value = g_strdup_printf( "%s/IP.BIN", user_path );
1.92
1.93 /* Copy defaults into main values */
1.94 - struct lxdream_config_group *group = lxdream_config_root;
1.95 - while( group->key != NULL ) {
1.96 - struct lxdream_config_entry *param = group->params;
1.97 + for( int i=0; lxdream_config_root[i] != NULL; i++ ) {
1.98 + struct lxdream_config_entry *param = lxdream_config_root[i]->params;
1.99 if( param != NULL ) {
1.100 while( param->key != NULL ) {
1.101 if( param->value != param->default_value ) {
1.102 @@ -149,14 +149,53 @@
1.103 param++;
1.104 }
1.105 }
1.106 - group++;
1.107 }
1.108 maple_detach_all();
1.109 }
1.110
1.111 +const gchar *lxdream_get_config_value( lxdream_config_group_t group, int key )
1.112 +{
1.113 + return group->params[key].value;
1.114 +}
1.115 +
1.116 +
1.117 +gboolean lxdream_set_config_value( lxdream_config_group_t group, int key, const gchar *value )
1.118 +{
1.119 + lxdream_config_entry_t param = &group->params[key];
1.120 + if( param->value != value &&
1.121 + (param->value == NULL || value == NULL || strcmp(param->value,value) != 0) ) {
1.122 +
1.123 + gchar *new_value = g_strdup(value);
1.124 +
1.125 + /* If the group defines an on_change handler, it can block the change
1.126 + * (ie due to an invalid setting).
1.127 + */
1.128 + if( group->on_change == NULL ||
1.129 + group->on_change(group->data, group,key, param->value, new_value) ) {
1.130 +
1.131 + /* Don't free the default value, but otherwise need to release the
1.132 + * old value.
1.133 + */
1.134 + if( param->value != param->default_value && param->value != NULL ) {
1.135 + free( param->value );
1.136 + }
1.137 + param->value = new_value;
1.138 + } else { /* on_change handler said no. */
1.139 + g_free(new_value);
1.140 + return FALSE;
1.141 + }
1.142 + }
1.143 + return TRUE;
1.144 +}
1.145 +
1.146 const gchar *lxdream_get_global_config_value( int key )
1.147 {
1.148 - return global_config[key].value;
1.149 + return global_group.params[key].value;
1.150 +}
1.151 +
1.152 +void lxdream_set_global_config_value( int key, const gchar *value )
1.153 +{
1.154 + lxdream_set_config_value(&global_group, key, value);
1.155 }
1.156
1.157 GList *lxdream_get_global_config_list_value( int key )
1.158 @@ -213,44 +252,38 @@
1.159 return lxdream_get_global_config_value(key);
1.160 }
1.161
1.162 -void lxdream_set_config_value( lxdream_config_entry_t param, const gchar *value )
1.163 +struct lxdream_config_group * lxdream_get_config_group( int group )
1.164 {
1.165 - if( param->value != value ) {
1.166 - if( param->value != param->default_value && param->value != NULL ) {
1.167 - free( param->value );
1.168 - }
1.169 - param->value = g_strdup(value);
1.170 + return lxdream_config_root[group];
1.171 +}
1.172 +
1.173 +void lxdream_copy_config_group( lxdream_config_group_t dest, lxdream_config_group_t src )
1.174 +{
1.175 + int i;
1.176 + for( i=0; src->params[i].key != NULL; i++ ) {
1.177 + lxdream_set_config_value( dest, i, src->params[i].value );
1.178 }
1.179 }
1.180
1.181 -void lxdream_set_global_config_value( int key, const gchar *value )
1.182 -{
1.183 - lxdream_set_config_value(&global_config[key], value);
1.184 -}
1.185 -
1.186 -const struct lxdream_config_entry * lxdream_get_global_config_entry( int key )
1.187 -{
1.188 - return &global_config[key];
1.189 -}
1.190 -
1.191 -gboolean lxdream_set_group_value( lxdream_config_group_t group, const gchar *key, const gchar *value )
1.192 +void lxdream_clone_config_group( lxdream_config_group_t dest, lxdream_config_group_t src )
1.193 {
1.194 int i;
1.195 - for( i=0; group->params[i].key != NULL; i++ ) {
1.196 - if( strcasecmp( group->params[i].key, key ) == 0 ) {
1.197 - lxdream_set_config_value( &group->params[i], value );
1.198 - return TRUE;
1.199 - }
1.200 +
1.201 + dest->key = src->key;
1.202 + dest->on_change = NULL;
1.203 + dest->key_binding = NULL;
1.204 + dest->data = NULL;
1.205 + for( i=0; src->params[i].key != NULL; i++ ) {
1.206 + dest->params[i].key = src->params[i].key;
1.207 + dest->params[i].label = src->params[i].label;
1.208 + dest->params[i].type = src->params[i].type;
1.209 + dest->params[i].tag = src->params[i].tag;
1.210 + dest->params[i].default_value = src->params[i].default_value;
1.211 + dest->params[i].value = NULL;
1.212 + lxdream_set_config_value( dest, i, src->params[i].value );
1.213 }
1.214 - return FALSE;
1.215 -}
1.216 -
1.217 -void lxdream_copy_config_list( lxdream_config_entry_t dest, lxdream_config_entry_t src )
1.218 -{
1.219 - int i;
1.220 - for( i=0; src[i].key != NULL; i++ ) {
1.221 - lxdream_set_config_value( &dest[i], src[i].value );
1.222 - }
1.223 + dest->params[i].key = NULL;
1.224 + dest->params[i].label = NULL;
1.225 }
1.226
1.227 gboolean lxdream_load_config( )
1.228 @@ -296,9 +329,9 @@
1.229 {
1.230
1.231 char buf[512];
1.232 - int maple_device = -1, maple_subdevice = -1;
1.233 - struct lxdream_config_group devgroup;
1.234 + int maple_device = -1, maple_subdevice = -1, i;
1.235 struct lxdream_config_group *group = NULL;
1.236 + struct lxdream_config_group *top_group = NULL;
1.237 maple_device_t device = NULL;
1.238 lxdream_set_default_config();
1.239
1.240 @@ -309,17 +342,14 @@
1.241 if( *buf == '[' ) {
1.242 char *p = strchr(buf, ']');
1.243 if( p != NULL ) {
1.244 - struct lxdream_config_group *tmp_group;
1.245 maple_device = maple_subdevice = -1;
1.246 *p = '\0';
1.247 g_strstrip(buf+1);
1.248 - tmp_group = &lxdream_config_root[0];
1.249 - while( tmp_group->key != NULL ) {
1.250 - if( strcasecmp(tmp_group->key, buf+1) == 0 ) {
1.251 - group = tmp_group;
1.252 + for( i=0; lxdream_config_root[i] != NULL; i++ ) {
1.253 + if( strcasecmp(lxdream_config_root[i]->key, buf+1) == 0 ) {
1.254 + top_group = group = lxdream_config_root[i];
1.255 break;
1.256 }
1.257 - tmp_group++;
1.258 }
1.259 }
1.260 } else if( group != NULL ) {
1.261 @@ -330,7 +360,7 @@
1.262 value++;
1.263 g_strstrip(buf);
1.264 g_strstrip(value);
1.265 - if( strcmp(group->key,"controllers") == 0 ) {
1.266 + if( top_group == &controllers_group ) {
1.267 if( g_strncasecmp( buf, "device ", 7 ) == 0 ) {
1.268 maple_device = strtoul( buf+7, NULL, 0 );
1.269 if( maple_device < 0 || maple_device > 3 ) {
1.270 @@ -342,10 +372,8 @@
1.271 if( device == NULL ) {
1.272 ERROR( "Unrecognized device '%s'", value );
1.273 } else {
1.274 - devgroup.key = "controllers";
1.275 - devgroup.params = maple_get_device_config(device);
1.276 + group = maple_get_device_config(device);
1.277 maple_attach_device( device, maple_device, maple_subdevice );
1.278 - group = &devgroup;
1.279 }
1.280 continue;
1.281 } else if( g_strncasecmp( buf, "subdevice ", 10 ) == 0 ) {
1.282 @@ -357,10 +385,8 @@
1.283 } else if( (device = maple_new_device(value)) == NULL ) {
1.284 ERROR( "Unrecognized subdevice '%s'", value );
1.285 } else {
1.286 - devgroup.key = "controllers";
1.287 - devgroup.params = maple_get_device_config(device);
1.288 + group = maple_get_device_config(device);
1.289 maple_attach_device( device, maple_device, maple_subdevice );
1.290 - group = &devgroup;
1.291 }
1.292 continue;
1.293 }
1.294 @@ -393,20 +419,11 @@
1.295
1.296 gboolean lxdream_save_config_stream( FILE *f )
1.297 {
1.298 - struct lxdream_config_group *group = &lxdream_config_root[0];
1.299 + int i;
1.300 + for( i=0; lxdream_config_root[i] != NULL; i++ ) {
1.301 + fprintf( f, "[%s]\n", lxdream_config_root[i]->key );
1.302
1.303 - while( group->key != NULL ) {
1.304 - struct lxdream_config_entry *entry = group->params;
1.305 - fprintf( f, "[%s]\n", group->key );
1.306 -
1.307 - if( entry != NULL ) {
1.308 - while( entry->key != NULL ) {
1.309 - if( entry->value != NULL ) {
1.310 - fprintf( f, "%s = %s\n", entry->key, entry->value );
1.311 - }
1.312 - entry++;
1.313 - }
1.314 - } else if( strcmp(group->key, "controllers") == 0 ) {
1.315 + if( lxdream_config_root[i] == &controllers_group ) {
1.316 int i,j;
1.317 for( i=0; i<4; i++ ) {
1.318 for( j=0; j<6; j++ ) {
1.319 @@ -416,7 +433,9 @@
1.320 fprintf( f, "Device %d = %s\n", i, dev->device_class->name );
1.321 else
1.322 fprintf( f, "Subdevice %d = %s\n", j, dev->device_class->name );
1.323 - if( dev->get_config != NULL && ((entry = dev->get_config(dev)) != NULL) ) {
1.324 + lxdream_config_group_t group = maple_get_device_config(dev);
1.325 + if( group != NULL ) {
1.326 + lxdream_config_entry_t entry = group->params;
1.327 while( entry->key != NULL ) {
1.328 if( entry->value != NULL ) {
1.329 fprintf( f, "%*c%s = %s\n", j==0?4:8, ' ',entry->key, entry->value );
1.330 @@ -427,9 +446,16 @@
1.331 }
1.332 }
1.333 }
1.334 + } else {
1.335 + struct lxdream_config_entry *entry = lxdream_config_root[i]->params;
1.336 + while( entry->key != NULL ) {
1.337 + if( entry->value != NULL ) {
1.338 + fprintf( f, "%s = %s\n", entry->key, entry->value );
1.339 + }
1.340 + entry++;
1.341 + }
1.342 }
1.343 fprintf( f, "\n" );
1.344 - group++;
1.345 }
1.346 return TRUE;
1.347 }
.