Comment out the URL to the Doxygen page.
[herrie-working.git] / herrie / src / config.c
blobce4ee12821effc985141d2cba991d58f311adf80
1 /*
2 * Copyright (c) 2006-2008 Ed Schouten <ed@80386.nl>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
26 /**
27 * @file config.c
28 * @brief Configuration file handling.
31 #include "stdinc.h"
33 #include "config.h"
34 #include "gui.h"
35 #include "vfs.h"
37 /**
38 * @brief Convert a "yes"/"no" string to a boolean value.
40 static int
41 string_to_bool(const char *val)
43 if (strcmp(val, "yes") == 0)
44 return (1);
45 else if (strcmp(val, "no") == 0)
46 return (0);
47 else
48 return (-1);
52 * Configuration value validation
55 /**
56 * @brief Determine if a boolean string is valid
58 static int
59 valid_bool(char *val)
61 return (string_to_bool(val) == -1);
64 /**
65 * @brief Determine if a color string is valid
67 static int
68 valid_color(char *val)
70 return (gui_draw_color_number(val) < -1);
73 #ifdef BUILD_SCROBBLER
74 /**
75 * @brief Determine if a string containing an MD5 hash is valid
77 static int
78 valid_md5(char *val)
80 int i;
82 if (val[0] == '\0')
83 return (0);
85 for (i = 0; i < 32; i++) {
86 /* Silently convert hash to lowercase */
87 val[i] = g_ascii_tolower(val[i]);
89 if (!g_ascii_isxdigit(val[i]))
90 /* Invalid character found */
91 return (-1);
94 if (val[i] != '\0')
95 /* String too long */
96 return (-1);
98 return (0);
100 #endif /* BUILD_SCROBBLER */
103 * @brief Structure containing a single configuration entry of the
104 * application.
106 struct config_entry {
108 * @brief Name it can be located at.
110 const char *name;
112 * @brief Default value.
114 const char *defval;
116 * @brief Function to validate when set.
118 int (*validator)(char *val);
120 * @brief Current value if not equal to the default.
122 char *curval;
126 * List of available configuration switches. Keep this list sorted at
127 * all time; the config lookups have been optimised to expect an
128 * alphabetical lookup. Looking up switches starting with 'z' will take
129 * longer than 'a'.
132 * @brief List of configuration switches.
134 static struct config_entry configlist[] = {
135 #ifdef BUILD_ALSA
136 { "audio.output.alsa.device", "default", NULL, NULL },
137 #ifdef BUILD_VOLUME
138 { "audio.output.alsa.mixer", "PCM", NULL, NULL },
139 #endif /* BUILD_VOLUME */
140 #endif /* BUILD_ALSA */
141 #ifdef BUILD_AO
142 { "audio.output.ao.driver", "", NULL, NULL },
143 { "audio.output.ao.host", "", NULL, NULL },
144 #endif /* BUILD_AO */
145 #ifdef BUILD_OSS
146 { "audio.output.oss.device", OSS_DEVICE, NULL, NULL },
147 #ifdef BUILD_VOLUME
148 { "audio.output.oss.mixer", "/dev/mixer", NULL, NULL },
149 #endif /* BUILD_VOLUME */
150 #endif /* BUILD_OSS */
151 { "gui.browser.defaultpath", "", NULL, NULL },
152 { "gui.color.bar.bg", "blue", valid_color, NULL },
153 { "gui.color.bar.fg", "white", valid_color, NULL },
154 { "gui.color.block.bg", "black", valid_color, NULL },
155 { "gui.color.block.fg", "white", valid_color, NULL },
156 { "gui.color.deselect.bg", "white", valid_color, NULL },
157 { "gui.color.deselect.fg", "black", valid_color, NULL },
158 { "gui.color.enabled", "yes", valid_bool, NULL },
159 { "gui.color.marked.bg", "yellow", valid_color, NULL },
160 { "gui.color.marked.fg", "black", valid_color, NULL },
161 { "gui.color.select.bg", "cyan", valid_color, NULL },
162 { "gui.color.select.fg", "black", valid_color, NULL },
163 { "gui.input.confirm", "yes", valid_bool, NULL },
164 { "gui.input.may_quit", "yes", valid_bool, NULL },
165 { "gui.vfslist.scrollpages", "no", valid_bool, NULL },
166 { "playq.autoplay", "no", valid_bool, NULL },
167 { "playq.dumpfile", CONFHOMEDIR PLAYQ_DUMPFILE, NULL, NULL },
168 { "playq.xmms", "no", valid_bool, NULL },
169 #ifdef BUILD_SCROBBLER
170 { "scrobbler.dumpfile", CONFHOMEDIR "scrobbler.queue", NULL, NULL },
171 { "scrobbler.password", "", valid_md5, NULL },
172 { "scrobbler.username", "", NULL, NULL },
173 #endif /* BUILD_SCROBBLER */
174 { "vfs.dir.hide_dotfiles", "yes", valid_bool, NULL },
175 #ifdef G_OS_UNIX
176 { "vfs.lockup.chroot", "", NULL, NULL },
177 { "vfs.lockup.user", "", NULL, NULL },
178 #endif /* G_OS_UNIX */
181 * @brief The amount of configuration switches available.
183 #define NUM_SWITCHES (sizeof configlist / sizeof(struct config_entry))
186 * @brief Search for an entry in the configlist by name.
188 static struct config_entry *
189 config_search(const char *opt)
191 unsigned int i;
192 int c;
194 for (i = 0; i < NUM_SWITCHES; i++) {
195 c = strcmp(opt, configlist[i].name);
197 if (c == 0)
198 /* Found it */
199 return (&configlist[i]);
200 else if (c < 0)
201 /* We're already too far */
202 break;
205 /* Not found */
206 return (NULL);
210 * @brief Set a value to a configuration switch
212 static int
213 config_setopt(const char *opt, char *val)
215 struct config_entry *ent;
216 char *newval = NULL;
218 if ((ent = config_search(opt)) == NULL)
219 return (-1);
221 if (strcmp(val, ent->defval) != 0) {
222 /* Just unset the value when it's the default */
224 if (ent->validator != NULL) {
225 /* Do not set invalid values */
226 if (ent->validator(val) != 0)
227 return (-1);
229 newval = g_strdup(val);
232 /* Free the current contents */
233 g_free(ent->curval);
234 ent->curval = newval;
236 return (0);
240 * Public configuration file functions
243 void
244 config_load(const char *file, int expand)
246 FILE *fio;
247 char fbuf[512]; /* Should be long enough */
248 char *split;
250 if (expand)
251 fio = vfs_fopen(file, "r");
252 else
253 fio = fopen(file, "r");
254 if (fio == NULL)
255 return;
257 while (vfs_fgets(fbuf, sizeof fbuf, fio) == 0) {
258 /* Split at the : and set the option */
259 split = strchr(fbuf, '=');
260 if (split != NULL) {
261 /* Split the option and value */
262 *split++ = '\0';
263 config_setopt(fbuf, split);
267 fclose(fio);
270 const char *
271 config_getopt(const char *opt)
273 struct config_entry *ent;
275 ent = config_search(opt);
276 g_assert(ent != NULL);
278 /* Return the default if it is unset */
279 return (ent->curval ? ent->curval : ent->defval);
283 config_getopt_bool(const char *val)
285 int bval;
287 bval = string_to_bool(config_getopt(val));
288 g_assert(bval != -1);
289 return (bval);
293 config_getopt_color(const char *val)
295 int col;
297 col = gui_draw_color_number(config_getopt(val));
298 g_assert(col >= -1);
299 return (col);