00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00031 #include "stdinc.h"
00032
00033 #include "config.h"
00034 #include "gui.h"
00035 #include "vfs.h"
00036
00040 static int
00041 string_to_bool(const char *val)
00042 {
00043 if (strcmp(val, "yes") == 0)
00044 return (1);
00045 else if (strcmp(val, "no") == 0)
00046 return (0);
00047 else
00048 return (-1);
00049 }
00050
00051
00052
00053
00054
00058 static int
00059 valid_bool(char *val)
00060 {
00061 return (string_to_bool(val) == -1);
00062 }
00063
00067 static int
00068 valid_color(char *val)
00069 {
00070 return (gui_draw_color_number(val) < -1);
00071 }
00072
00076 static int
00077 valid_percentage(char *val)
00078 {
00079 unsigned long pct;
00080 char *end = NULL;
00081
00082 pct = strtol(val, &end, 10);
00083 return (pct > 100 || end == NULL || *end != '\0');
00084 }
00085
00086 #ifdef BUILD_SCROBBLER
00087
00090 static int
00091 valid_md5(char *val)
00092 {
00093 int i;
00094
00095 if (val[0] == '\0')
00096 return (0);
00097
00098 for (i = 0; i < 32; i++) {
00099
00100 val[i] = g_ascii_tolower(val[i]);
00101
00102 if (!g_ascii_isxdigit(val[i]))
00103
00104 return (-1);
00105 }
00106
00107 if (val[i] != '\0')
00108
00109 return (-1);
00110
00111 return (0);
00112 }
00113 #endif
00114
00119 struct config_entry {
00123 const char *name;
00127 const char *defval;
00131 int (*validator)(char *val);
00135 char *curval;
00136 };
00137
00138
00139
00140
00141
00142
00143
00147 static struct config_entry configlist[] = {
00148 #ifdef BUILD_ALSA
00149 { "audio.output.alsa.device", "default", NULL, NULL },
00150 #ifdef BUILD_VOLUME
00151 { "audio.output.alsa.mixer", "PCM", NULL, NULL },
00152 #endif
00153 #endif
00154 #ifdef BUILD_AO
00155 { "audio.output.ao.driver", "", NULL, NULL },
00156 { "audio.output.ao.host", "", NULL, NULL },
00157 #endif
00158 #ifdef BUILD_OSS
00159 { "audio.output.oss.device", OSS_DEVICE, NULL, NULL },
00160 #ifdef BUILD_VOLUME
00161 { "audio.output.oss.mixer", "/dev/mixer", NULL, NULL },
00162 #endif
00163 #endif
00164 { "gui.browser.defaultpath", "", NULL, NULL },
00165 { "gui.color.bar.bg", "blue", valid_color, NULL },
00166 { "gui.color.bar.fg", "white", valid_color, NULL },
00167 { "gui.color.block.bg", "black", valid_color, NULL },
00168 { "gui.color.block.fg", "white", valid_color, NULL },
00169 { "gui.color.deselect.bg", "white", valid_color, NULL },
00170 { "gui.color.deselect.fg", "black", valid_color, NULL },
00171 { "gui.color.enabled", "yes", valid_bool, NULL },
00172 { "gui.color.marked.bg", "yellow", valid_color, NULL },
00173 { "gui.color.marked.fg", "black", valid_color, NULL },
00174 { "gui.color.select.bg", "cyan", valid_color, NULL },
00175 { "gui.color.select.fg", "black", valid_color, NULL },
00176 { "gui.input.confirm", "yes", valid_bool, NULL },
00177 { "gui.input.may_quit", "yes", valid_bool, NULL },
00178 { "gui.ratio", "50", valid_percentage, NULL },
00179 { "gui.vfslist.scrollpages", "no", valid_bool, NULL },
00180 { "playq.autoplay", "no", valid_bool, NULL },
00181 { "playq.dumpfile", CONFHOMEDIR PLAYQ_DUMPFILE, NULL, NULL },
00182 { "playq.xmms", "no", valid_bool, NULL },
00183 #ifdef BUILD_SCROBBLER
00184 { "scrobbler.dumpfile", CONFHOMEDIR "scrobbler.queue", NULL, NULL },
00185 { "scrobbler.hostname", "post.audioscrobbler.com", NULL, NULL },
00186 { "scrobbler.password", "", valid_md5, NULL },
00187 { "scrobbler.username", "", NULL, NULL },
00188 #endif
00189 { "vfs.dir.hide_dotfiles", "yes", valid_bool, NULL },
00190 #ifdef G_OS_UNIX
00191 { "vfs.lockup.chroot", "", NULL, NULL },
00192 { "vfs.lockup.user", "", NULL, NULL },
00193 #endif
00194 };
00198 #define NUM_SWITCHES (sizeof configlist / sizeof(struct config_entry))
00199
00203 static struct config_entry *
00204 config_search(const char *opt)
00205 {
00206 unsigned int i;
00207 int c;
00208
00209 for (i = 0; i < NUM_SWITCHES; i++) {
00210 c = strcmp(opt, configlist[i].name);
00211
00212 if (c == 0)
00213
00214 return (&configlist[i]);
00215 else if (c < 0)
00216
00217 break;
00218 }
00219
00220
00221 return (NULL);
00222 }
00223
00227 static int
00228 config_setopt(const char *opt, char *val)
00229 {
00230 struct config_entry *ent;
00231 char *newval = NULL;
00232
00233 if ((ent = config_search(opt)) == NULL)
00234 return (-1);
00235
00236 if (strcmp(val, ent->defval) != 0) {
00237
00238
00239 if (ent->validator != NULL) {
00240
00241 if (ent->validator(val) != 0)
00242 return (-1);
00243 }
00244 newval = g_strdup(val);
00245 }
00246
00247
00248 g_free(ent->curval);
00249 ent->curval = newval;
00250
00251 return (0);
00252 }
00253
00254
00255
00256
00257
00258 void
00259 config_load(const char *file, int expand)
00260 {
00261 FILE *fio;
00262 char fbuf[512];
00263 char *split;
00264
00265 if (expand)
00266 fio = vfs_fopen(file, "r");
00267 else
00268 fio = fopen(file, "r");
00269 if (fio == NULL)
00270 return;
00271
00272 while (vfs_fgets(fbuf, sizeof fbuf, fio) == 0) {
00273
00274 split = strchr(fbuf, '=');
00275 if (split != NULL) {
00276
00277 *split++ = '\0';
00278 config_setopt(fbuf, split);
00279 }
00280 }
00281
00282 fclose(fio);
00283 }
00284
00285 const char *
00286 config_getopt(const char *opt)
00287 {
00288 struct config_entry *ent;
00289
00290 ent = config_search(opt);
00291 g_assert(ent != NULL);
00292
00293
00294 return (ent->curval ? ent->curval : ent->defval);
00295 }
00296
00297 int
00298 config_getopt_bool(const char *val)
00299 {
00300 int bval;
00301
00302 bval = string_to_bool(config_getopt(val));
00303 g_assert(bval != -1);
00304 return (bval);
00305 }
00306
00307 int
00308 config_getopt_color(const char *val)
00309 {
00310 int col;
00311
00312 col = gui_draw_color_number(config_getopt(val));
00313 g_assert(col >= -1);
00314 return (col);
00315 }
00316
00317 int
00318 config_getopt_percentage(const char *val)
00319 {
00320 return strtoul(config_getopt(val), NULL, 10);
00321 }