rename configuration file
[profile/ivi/pulseaudio-panda.git] / polyp / modargs.c
1 /* $Id$ */
2
3 /***
4   This file is part of polypaudio.
5  
6   polypaudio is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published
8   by the Free Software Foundation; either version 2 of the License,
9   or (at your option) any later version.
10  
11   polypaudio 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.
15  
16   You should have received a copy of the GNU General Public License
17   along with polypaudio; if not, write to the Free Software
18   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19   USA.
20 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <ctype.h>
27 #include <assert.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #include "hashmap.h"
32 #include "modargs.h"
33 #include "idxset.h"
34 #include "sample-util.h"
35 #include "namereg.h"
36 #include "sink.h"
37 #include "source.h"
38
39 struct pa_modargs;
40
41 struct entry {
42     char *key, *value;
43 };
44
45 static int add_key_value(struct pa_hashmap *map, char *key, char *value, const char* const* valid_keys) {
46     struct entry *e;
47     assert(map && key && value);
48
49     if (valid_keys) {
50         const char*const* v;
51         for (v = valid_keys; *v; v++)
52             if (strcmp(*v, key) == 0)
53                 break;
54
55         if (!*v) {
56             free(key);
57             free(value);
58             return -1;
59         }
60     }
61     
62     e = malloc(sizeof(struct entry));
63     assert(e);
64     e->key = key;
65     e->value = value;
66     pa_hashmap_put(map, key, e);
67     return 0;
68 }
69
70 struct pa_modargs *pa_modargs_new(const char *args, const char* const* valid_keys) {
71     struct pa_hashmap *map = NULL;
72
73     map = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
74     assert(map);
75
76     if (args) {
77         enum { WHITESPACE, KEY, VALUE_START, VALUE_SIMPLE, VALUE_DOUBLE_QUOTES, VALUE_TICKS } state;
78         const char *p, *key, *value;
79         size_t key_len, value_len;
80         
81         key = value = NULL;
82         state = WHITESPACE;
83         for (p = args; *p; p++) {
84             switch (state) {
85                 case WHITESPACE:
86                     if (*p == '=')
87                         goto fail;
88                     else if (!isspace(*p)) {
89                         key = p;
90                         state = KEY;
91                         key_len = 1;
92                     }
93                     break;
94                 case KEY:
95                     if (*p == '=')
96                         state = VALUE_START;
97                     else
98                         key_len++;
99                     break;
100                 case  VALUE_START:
101                     if (*p == '\'') {
102                         state = VALUE_TICKS;
103                         value = p+1;
104                         value_len = 0;
105                     } else if (*p == '"') {
106                         state = VALUE_DOUBLE_QUOTES;
107                         value = p+1;
108                         value_len = 0;
109                     } else if (isspace(*p)) {
110                         if (add_key_value(map, strndup(key, key_len), strdup(""), valid_keys) < 0)
111                             goto fail;
112                         state = WHITESPACE;
113                     } else {
114                         state = VALUE_SIMPLE;
115                         value = p;
116                         value_len = 1;
117                     }
118                     break;
119                 case VALUE_SIMPLE:
120                     if (isspace(*p)) {
121                         if (add_key_value(map, strndup(key, key_len), strndup(value, value_len), valid_keys) < 0)
122                             goto fail;
123                         state = WHITESPACE;
124                     } else
125                         value_len++;
126                     break;
127                 case VALUE_DOUBLE_QUOTES:
128                     if (*p == '"') {
129                         if (add_key_value(map, strndup(key, key_len), strndup(value, value_len), valid_keys) < 0)
130                             goto fail;
131                         state = WHITESPACE;
132                     } else
133                         value_len++;
134                     break;
135                 case VALUE_TICKS:
136                     if (*p == '\'') {
137                         if (add_key_value(map, strndup(key, key_len), strndup(value, value_len), valid_keys) < 0)
138                             goto fail;
139                         state = WHITESPACE;
140                     } else
141                         value_len++;
142                     break;
143             }
144         }
145
146         if (state == VALUE_START) {
147             if (add_key_value(map, strndup(key, key_len), strdup(""), valid_keys) < 0)
148                 goto fail;
149         } else if (state == VALUE_SIMPLE) {
150             if (add_key_value(map, strndup(key, key_len), strdup(value), valid_keys) < 0)
151                 goto fail;
152         } else if (state != WHITESPACE)
153             goto fail;
154     }
155
156     return (struct pa_modargs*) map;
157
158 fail:
159
160     if (map)
161         pa_modargs_free((struct pa_modargs*) map);
162                       
163     return NULL;
164 }
165
166
167 static void free_func(void *p, void*userdata) {
168     struct entry *e = p;
169     assert(e);
170     free(e->key);
171     free(e->value);
172     free(e);
173 }
174
175 void pa_modargs_free(struct pa_modargs*ma) {
176     struct pa_hashmap *map = (struct pa_hashmap*) ma;
177     pa_hashmap_free(map, free_func, NULL);
178 }
179
180 const char *pa_modargs_get_value(struct pa_modargs *ma, const char *key, const char *def) {
181     struct pa_hashmap *map = (struct pa_hashmap*) ma;
182     struct entry*e;
183
184     if (!(e = pa_hashmap_get(map, key)))
185         return def;
186
187     return e->value;
188 }
189
190 int pa_modargs_get_value_u32(struct pa_modargs *ma, const char *key, uint32_t *value) {
191     const char *v;
192     char *e;
193     unsigned long l;
194     assert(ma && key && value);
195
196     if (!(v = pa_modargs_get_value(ma, key, NULL)))
197         return 0;
198
199     if (!*v)
200         return -1;
201     
202     l = strtoul(v, &e, 0);
203     if (*e)
204         return -1;
205
206     *value = (uint32_t) l;
207     return 0;
208 }
209
210 int pa_modargs_get_sample_spec(struct pa_modargs *ma, struct pa_sample_spec *rss) {
211     const char *format;
212     uint32_t channels;
213     struct pa_sample_spec ss;
214     assert(ma && rss);
215
216     ss = *rss;
217     if ((pa_modargs_get_value_u32(ma, "rate", &ss.rate)) < 0)
218         return -1;
219
220     channels = ss.channels;
221     if ((pa_modargs_get_value_u32(ma, "channels", &channels)) < 0)
222         return -1;
223     ss.channels = (uint8_t) channels;
224
225     if ((format = pa_modargs_get_value(ma, "format", NULL))) {
226         if (strcmp(format, "s16le") == 0)
227             ss.format = PA_SAMPLE_S16LE;
228         else if (strcmp(format, "s16be") == 0)
229             ss.format = PA_SAMPLE_S16BE;
230         else if (strcmp(format, "s16ne") == 0 || strcmp(format, "s16") == 0 || strcmp(format, "16") == 0)
231             ss.format = PA_SAMPLE_S16NE;
232         else if (strcmp(format, "u8") == 0 || strcmp(format, "8") == 0)
233             ss.format = PA_SAMPLE_U8;
234         else if (strcmp(format, "float32") == 0 || strcmp(format, "float32ne") == 0)
235             ss.format = PA_SAMPLE_FLOAT32;
236         else if (strcmp(format, "float32le") == 0)
237             ss.format = PA_SAMPLE_FLOAT32LE;
238         else if (strcmp(format, "float32be") == 0)
239             ss.format = PA_SAMPLE_FLOAT32BE;
240         else if (strcmp(format, "ulaw") == 0)
241             ss.format = PA_SAMPLE_ULAW;
242         else if (strcmp(format, "alaw") == 0)
243             ss.format = PA_SAMPLE_ALAW;
244         else
245             return -1;
246     }
247
248     if (!pa_sample_spec_valid(&ss))
249         return -1;
250
251     *rss = ss;
252     
253     return 0;
254 }
255
256 int pa_modargs_get_source_index(struct pa_modargs *ma, struct pa_core *c, uint32_t *index) {
257     const char *t;
258     assert(ma && index);
259     
260     if (!(t = pa_modargs_get_value(ma, "source", NULL)))
261         *index = PA_IDXSET_INVALID;
262     else {
263         struct pa_source *source;
264         if (!(source = pa_namereg_get(c, t, PA_NAMEREG_SOURCE)))
265             return -1;
266
267         *index = source->index;
268     }
269
270     return 0;
271 }
272
273 int pa_modargs_get_sink_index(struct pa_modargs *ma, struct pa_core *c, uint32_t *index) {
274     const char *t;
275     assert(ma && index);
276
277     if (!(t = pa_modargs_get_value(ma, "sink", NULL)))
278         *index = PA_IDXSET_INVALID;
279     else {
280         struct pa_sink *sink;
281         if (!(sink = pa_namereg_get(c, t, PA_NAMEREG_SINK)))
282             return -1;
283
284         *index = sink->index;
285     }
286
287     return 0;
288 }