default: esd is obsolete, hence don't load it anymore by default
[pulseaudio-mirror.git] / src / pulsecore / modargs.c
blob45ffba23574918cd5cd83b278a3c12be98636e52
1 /***
2 This file is part of PulseAudio.
4 Copyright 2004-2006 Lennart Poettering
6 PulseAudio is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published
8 by the Free Software Foundation; either version 2.1 of the License,
9 or (at your option) any later version.
11 PulseAudio is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with PulseAudio; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19 USA.
20 ***/
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
26 #include <ctype.h>
27 #include <stdlib.h>
28 #include <string.h>
30 #include <pulse/xmalloc.h>
32 #include <pulsecore/hashmap.h>
33 #include <pulsecore/idxset.h>
34 #include <pulsecore/core-util.h>
35 #include <pulsecore/macro.h>
37 #include "modargs.h"
39 struct entry {
40 char *key, *value;
43 static int add_key_value(pa_hashmap *map, char *key, char *value, const char* const valid_keys[]) {
44 struct entry *e;
46 pa_assert(map);
47 pa_assert(key);
48 pa_assert(value);
50 if (pa_hashmap_get(map, key)) {
51 pa_xfree(key);
52 pa_xfree(value);
53 return -1;
56 if (valid_keys) {
57 const char*const* v;
58 for (v = valid_keys; *v; v++)
59 if (strcmp(*v, key) == 0)
60 break;
62 if (!*v) {
63 pa_xfree(key);
64 pa_xfree(value);
65 return -1;
69 e = pa_xnew(struct entry, 1);
70 e->key = key;
71 e->value = value;
72 pa_hashmap_put(map, key, e);
74 return 0;
77 pa_modargs *pa_modargs_new(const char *args, const char* const* valid_keys) {
78 enum {
79 WHITESPACE,
80 KEY,
81 VALUE_START,
82 VALUE_SIMPLE,
83 VALUE_SIMPLE_ESCAPED,
84 VALUE_DOUBLE_QUOTES,
85 VALUE_DOUBLE_QUOTES_ESCAPED,
86 VALUE_TICKS,
87 VALUE_TICKS_ESCAPED
88 } state;
90 const char *p, *key = NULL, *value = NULL;
91 size_t key_len = 0, value_len = 0;
92 pa_hashmap *map;
94 map = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
96 if (!args)
97 return (pa_modargs*) map;
99 state = WHITESPACE;
101 for (p = args; *p; p++) {
102 switch (state) {
104 case WHITESPACE:
105 if (*p == '=')
106 goto fail;
107 else if (!isspace(*p)) {
108 key = p;
109 state = KEY;
110 key_len = 1;
112 break;
114 case KEY:
115 if (*p == '=')
116 state = VALUE_START;
117 else if (isspace(*p))
118 goto fail;
119 else
120 key_len++;
121 break;
123 case VALUE_START:
124 if (*p == '\'') {
125 state = VALUE_TICKS;
126 value = p+1;
127 value_len = 0;
128 } else if (*p == '"') {
129 state = VALUE_DOUBLE_QUOTES;
130 value = p+1;
131 value_len = 0;
132 } else if (isspace(*p)) {
133 if (add_key_value(map,
134 pa_xstrndup(key, key_len),
135 pa_xstrdup(""),
136 valid_keys) < 0)
137 goto fail;
138 state = WHITESPACE;
139 } else if (*p == '\\') {
140 state = VALUE_SIMPLE_ESCAPED;
141 value = p;
142 value_len = 1;
143 } else {
144 state = VALUE_SIMPLE;
145 value = p;
146 value_len = 1;
148 break;
150 case VALUE_SIMPLE:
151 if (isspace(*p)) {
152 if (add_key_value(map,
153 pa_xstrndup(key, key_len),
154 pa_unescape(pa_xstrndup(value, value_len)),
155 valid_keys) < 0)
156 goto fail;
157 state = WHITESPACE;
158 } else if (*p == '\\') {
159 state = VALUE_SIMPLE_ESCAPED;
160 value_len++;
161 } else
162 value_len++;
163 break;
165 case VALUE_SIMPLE_ESCAPED:
166 state = VALUE_SIMPLE;
167 value_len++;
168 break;
170 case VALUE_DOUBLE_QUOTES:
171 if (*p == '"') {
172 if (add_key_value(map,
173 pa_xstrndup(key, key_len),
174 pa_unescape(pa_xstrndup(value, value_len)),
175 valid_keys) < 0)
176 goto fail;
177 state = WHITESPACE;
178 } else if (*p == '\\') {
179 state = VALUE_DOUBLE_QUOTES_ESCAPED;
180 value_len++;
181 } else
182 value_len++;
183 break;
185 case VALUE_DOUBLE_QUOTES_ESCAPED:
186 state = VALUE_DOUBLE_QUOTES;
187 value_len++;
188 break;
190 case VALUE_TICKS:
191 if (*p == '\'') {
192 if (add_key_value(map,
193 pa_xstrndup(key, key_len),
194 pa_unescape(pa_xstrndup(value, value_len)),
195 valid_keys) < 0)
196 goto fail;
197 state = WHITESPACE;
198 } else if (*p == '\\') {
199 state = VALUE_TICKS_ESCAPED;
200 value_len++;
201 } else
202 value_len++;
203 break;
205 case VALUE_TICKS_ESCAPED:
206 state = VALUE_TICKS;
207 value_len++;
208 break;
212 if (state == VALUE_START) {
213 if (add_key_value(map, pa_xstrndup(key, key_len), pa_xstrdup(""), valid_keys) < 0)
214 goto fail;
215 } else if (state == VALUE_SIMPLE) {
216 if (add_key_value(map, pa_xstrndup(key, key_len), pa_xstrdup(value), valid_keys) < 0)
217 goto fail;
218 } else if (state != WHITESPACE)
219 goto fail;
221 return (pa_modargs*) map;
223 fail:
225 pa_modargs_free((pa_modargs*) map);
227 return NULL;
230 static void free_func(void *p, void*userdata) {
231 struct entry *e = p;
232 pa_assert(e);
234 pa_xfree(e->key);
235 pa_xfree(e->value);
236 pa_xfree(e);
239 void pa_modargs_free(pa_modargs*ma) {
240 pa_hashmap *map = (pa_hashmap*) ma;
241 pa_hashmap_free(map, free_func, NULL);
244 const char *pa_modargs_get_value(pa_modargs *ma, const char *key, const char *def) {
245 pa_hashmap *map = (pa_hashmap*) ma;
246 struct entry*e;
248 if (!(e = pa_hashmap_get(map, key)))
249 return def;
251 return e->value;
254 int pa_modargs_get_value_u32(pa_modargs *ma, const char *key, uint32_t *value) {
255 const char *v;
257 pa_assert(ma);
258 pa_assert(key);
259 pa_assert(value);
261 if (!(v = pa_modargs_get_value(ma, key, NULL)))
262 return 0;
264 if (pa_atou(v, value) < 0)
265 return -1;
267 return 0;
270 int pa_modargs_get_value_s32(pa_modargs *ma, const char *key, int32_t *value) {
271 const char *v;
273 pa_assert(ma);
274 pa_assert(key);
275 pa_assert(value);
277 if (!(v = pa_modargs_get_value(ma, key, NULL)))
278 return 0;
280 if (pa_atoi(v, value) < 0)
281 return -1;
283 return 0;
286 int pa_modargs_get_value_boolean(pa_modargs *ma, const char *key, pa_bool_t *value) {
287 const char *v;
288 int r;
290 pa_assert(ma);
291 pa_assert(key);
292 pa_assert(value);
294 if (!(v = pa_modargs_get_value(ma, key, NULL)))
295 return 0;
297 if (!*v)
298 return -1;
300 if ((r = pa_parse_boolean(v)) < 0)
301 return -1;
303 *value = r;
304 return 0;
307 int pa_modargs_get_sample_spec(pa_modargs *ma, pa_sample_spec *rss) {
308 const char *format;
309 uint32_t channels;
310 pa_sample_spec ss;
312 pa_assert(ma);
313 pa_assert(rss);
315 ss = *rss;
316 if ((pa_modargs_get_value_u32(ma, "rate", &ss.rate)) < 0 ||
317 ss.rate <= 0 ||
318 ss.rate > PA_RATE_MAX)
319 return -1;
321 channels = ss.channels;
322 if ((pa_modargs_get_value_u32(ma, "channels", &channels)) < 0 ||
323 channels <= 0 ||
324 channels >= PA_CHANNELS_MAX)
325 return -1;
326 ss.channels = (uint8_t) channels;
328 if ((format = pa_modargs_get_value(ma, "format", NULL)))
329 if ((ss.format = pa_parse_sample_format(format)) < 0)
330 return -1;
332 if (!pa_sample_spec_valid(&ss))
333 return -1;
335 *rss = ss;
337 return 0;
340 int pa_modargs_get_channel_map(pa_modargs *ma, const char *name, pa_channel_map *rmap) {
341 pa_channel_map map;
342 const char *cm;
344 pa_assert(ma);
345 pa_assert(rmap);
347 map = *rmap;
349 if ((cm = pa_modargs_get_value(ma, name ? name : "channel_map", NULL)))
350 if (!pa_channel_map_parse(&map, cm))
351 return -1;
353 if (!pa_channel_map_valid(&map))
354 return -1;
356 *rmap = map;
357 return 0;
360 int pa_modargs_get_sample_spec_and_channel_map(
361 pa_modargs *ma,
362 pa_sample_spec *rss,
363 pa_channel_map *rmap,
364 pa_channel_map_def_t def) {
366 pa_sample_spec ss;
367 pa_channel_map map;
369 pa_assert(ma);
370 pa_assert(rss);
371 pa_assert(rmap);
373 ss = *rss;
375 if (pa_modargs_get_sample_spec(ma, &ss) < 0)
376 return -1;
378 map = *rmap;
380 if (ss.channels != map.channels)
381 pa_channel_map_init_extend(&map, ss.channels, def);
383 if (pa_modargs_get_channel_map(ma, NULL, &map) < 0)
384 return -1;
386 if (map.channels != ss.channels)
387 return -1;
389 *rmap = map;
390 *rss = ss;
392 return 0;
395 int pa_modargs_get_proplist(pa_modargs *ma, const char *name, pa_proplist *p, pa_update_mode_t m) {
396 const char *v;
397 pa_proplist *n;
399 pa_assert(ma);
400 pa_assert(name);
401 pa_assert(p);
403 if (!(v = pa_modargs_get_value(ma, name, NULL)))
404 return 0;
406 if (!(n = pa_proplist_from_string(v)))
407 return -1;
409 pa_proplist_update(p, m, n);
410 pa_proplist_free(n);
412 return 0;
415 const char *pa_modargs_iterate(pa_modargs *ma, void **state) {
416 pa_hashmap *map = (pa_hashmap*) ma;
417 struct entry *e;
419 if (!(e = pa_hashmap_iterate(map, state, NULL)))
420 return NULL;
422 return e->key;