2 * Copyright (c) 2006-2008 Ed Schouten <ed@80386.nl>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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
28 * @brief Configuration file handling.
38 * @brief Convert a "yes"/"no" string to a boolean value.
41 string_to_bool(const char *val
)
43 if (strcmp(val
, "yes") == 0)
45 else if (strcmp(val
, "no") == 0)
52 * Configuration value validation
56 * @brief Determine if a boolean string is valid
61 return (string_to_bool(val
) == -1);
65 * @brief Determine if a color string is valid
68 valid_color(char *val
)
70 return (gui_draw_color_number(val
) < -1);
73 #ifdef BUILD_SCROBBLER
75 * @brief Determine if a string containing an MD5 hash is valid
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 */
100 #endif /* BUILD_SCROBBLER */
103 * @brief Structure containing a single configuration entry of the
106 struct config_entry
{
108 * @brief Name it can be located at.
112 * @brief Default value.
116 * @brief Function to validate when set.
118 int (*validator
)(char *val
);
120 * @brief Current value if not equal to the default.
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
132 * @brief List of configuration switches.
134 static struct config_entry configlist
[] = {
136 { "audio.output.alsa.device", "default", NULL
, NULL
},
138 { "audio.output.alsa.mixer", "PCM", NULL
, NULL
},
139 #endif /* BUILD_VOLUME */
140 #endif /* BUILD_ALSA */
142 { "audio.output.ao.driver", "", NULL
, NULL
},
143 { "audio.output.ao.host", "", NULL
, NULL
},
144 #endif /* BUILD_AO */
146 { "audio.output.oss.device", OSS_DEVICE
, NULL
, NULL
},
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
},
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
)
194 for (i
= 0; i
< NUM_SWITCHES
; i
++) {
195 c
= strcmp(opt
, configlist
[i
].name
);
199 return (&configlist
[i
]);
201 /* We're already too far */
210 * @brief Set a value to a configuration switch
213 config_setopt(const char *opt
, char *val
)
215 struct config_entry
*ent
;
218 if ((ent
= config_search(opt
)) == NULL
)
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)
229 newval
= g_strdup(val
);
232 /* Free the current contents */
234 ent
->curval
= newval
;
240 * Public configuration file functions
244 config_load(const char *file
, int expand
)
247 char fbuf
[512]; /* Should be long enough */
251 fio
= vfs_fopen(file
, "r");
253 fio
= fopen(file
, "r");
257 while (vfs_fgets(fbuf
, sizeof fbuf
, fio
) == 0) {
258 /* Split at the : and set the option */
259 split
= strchr(fbuf
, '=');
261 /* Split the option and value */
263 config_setopt(fbuf
, split
);
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
)
287 bval
= string_to_bool(config_getopt(val
));
288 g_assert(bval
!= -1);
293 config_getopt_color(const char *val
)
297 col
= gui_draw_color_number(config_getopt(val
));