OSDN Git Service

292563e3b391869292fafa07e4f37588a437af38
[android-x86/external-alsa-lib.git] / src / control / control.c
1 /*
2  *  Control Interface - main file
3  *  Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org>
4  *
5  *
6  *   This library is free software; you can redistribute it and/or modify
7  *   it under the terms of the GNU Library General Public License as
8  *   published by the Free Software Foundation; either version 2 of
9  *   the License, or (at your option) any later version.
10  *
11  *   This program is distributed in the hope that it will be useful,
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *   GNU Library General Public License for more details.
15  *
16  *   You should have received a copy of the GNU Library General Public
17  *   License along with this library; if not, write to the Free Software
18  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  *
20  */
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <stdarg.h>
25 #include <unistd.h>
26 #include <string.h>
27 #include <fcntl.h>
28 #include <dlfcn.h>
29 #include <sys/poll.h>
30 #include "control_local.h"
31
32 const char *snd_ctl_name(snd_ctl_t *ctl)
33 {
34         assert(ctl);
35         return ctl->name;
36 }
37
38 snd_ctl_type_t snd_ctl_type(snd_ctl_t *ctl)
39 {
40         assert(ctl);
41         return ctl->type;
42 }
43
44 int snd_ctl_close(snd_ctl_t *ctl)
45 {
46         int res;
47         res = ctl->ops->close(ctl);
48         if (ctl->name)
49                 free(ctl->name);
50         free(ctl);
51         return res;
52 }
53
54 int snd_ctl_nonblock(snd_ctl_t *ctl, int nonblock)
55 {
56         int err;
57         assert(ctl);
58         err = ctl->ops->nonblock(ctl, nonblock);
59         if (err < 0)
60                 return err;
61         ctl->nonblock = nonblock;
62         return 0;
63 }
64
65 int snd_ctl_async(snd_ctl_t *ctl, int sig, pid_t pid)
66 {
67         assert(ctl);
68         return ctl->ops->async(ctl, sig, pid);
69 }
70
71 int _snd_ctl_poll_descriptor(snd_ctl_t *ctl)
72 {
73         assert(ctl);
74         return ctl->ops->poll_descriptor(ctl);
75 }
76
77 int snd_ctl_poll_descriptors_count(snd_ctl_t *ctl)
78 {
79         assert(ctl);
80         return 1;
81 }
82
83 int snd_ctl_poll_descriptors(snd_ctl_t *ctl, struct pollfd *pfds, unsigned int space)
84 {
85         assert(ctl);
86         if (space > 0) {
87                 pfds->fd = ctl->ops->poll_descriptor(ctl);
88                 pfds->events = POLLIN;
89                 return 1;
90         }
91         return 0;
92 }
93
94 int snd_ctl_subscribe_events(snd_ctl_t *ctl, int subscribe)
95 {
96         assert(ctl);
97         return ctl->ops->subscribe_events(ctl, subscribe);
98 }
99
100 int snd_ctl_card_info(snd_ctl_t *ctl, snd_ctl_card_info_t *info)
101 {
102         assert(ctl && info);
103         return ctl->ops->card_info(ctl, info);
104 }
105
106 int snd_ctl_elem_list(snd_ctl_t *ctl, snd_ctl_elem_list_t *list)
107 {
108         assert(ctl && list);
109         assert(list->space == 0 || list->pids);
110         return ctl->ops->element_list(ctl, list);
111 }
112
113 int snd_ctl_elem_info(snd_ctl_t *ctl, snd_ctl_elem_info_t *info)
114 {
115         assert(ctl && info && (info->id.name[0] || info->id.numid));
116         return ctl->ops->element_info(ctl, info);
117 }
118
119 int snd_ctl_elem_read(snd_ctl_t *ctl, snd_ctl_elem_value_t *control)
120 {
121         assert(ctl && control && (control->id.name[0] || control->id.numid));
122         return ctl->ops->element_read(ctl, control);
123 }
124
125 int snd_ctl_elem_write(snd_ctl_t *ctl, snd_ctl_elem_value_t *control)
126 {
127         assert(ctl && control && (control->id.name[0] || control->id.numid));
128         return ctl->ops->element_write(ctl, control);
129 }
130
131 int snd_ctl_hwdep_next_device(snd_ctl_t *ctl, int *device)
132 {
133         assert(ctl && device);
134         return ctl->ops->hwdep_next_device(ctl, device);
135 }
136
137 int snd_ctl_hwdep_info(snd_ctl_t *ctl, snd_hwdep_info_t * info)
138 {
139         assert(ctl && info);
140         return ctl->ops->hwdep_info(ctl, info);
141 }
142
143 int snd_ctl_pcm_next_device(snd_ctl_t *ctl, int * device)
144 {
145         assert(ctl && device);
146         return ctl->ops->pcm_next_device(ctl, device);
147 }
148
149 int snd_ctl_pcm_info(snd_ctl_t *ctl, snd_pcm_info_t * info)
150 {
151         assert(ctl && info);
152         return ctl->ops->pcm_info(ctl, info);
153 }
154
155 int snd_ctl_pcm_prefer_subdevice(snd_ctl_t *ctl, int subdev)
156 {
157         assert(ctl);
158         return ctl->ops->pcm_prefer_subdevice(ctl, subdev);
159 }
160
161 int snd_ctl_rawmidi_next_device(snd_ctl_t *ctl, int * device)
162 {
163         assert(ctl && device);
164         return ctl->ops->rawmidi_next_device(ctl, device);
165 }
166
167 int snd_ctl_rawmidi_info(snd_ctl_t *ctl, snd_rawmidi_info_t * info)
168 {
169         assert(ctl && info);
170         return ctl->ops->rawmidi_info(ctl, info);
171 }
172
173 int snd_ctl_rawmidi_prefer_subdevice(snd_ctl_t *ctl, int subdev)
174 {
175         assert(ctl);
176         return ctl->ops->rawmidi_prefer_subdevice(ctl, subdev);
177 }
178
179 int snd_ctl_read(snd_ctl_t *ctl, snd_ctl_event_t *event)
180 {
181         assert(ctl && event);
182         return ctl->ops->read(ctl, event);
183 }
184
185 int snd_ctl_wait(snd_ctl_t *ctl, int timeout)
186 {
187         struct pollfd pfd;
188         int err;
189         err = snd_ctl_poll_descriptors(ctl, &pfd, 1);
190         assert(err == 1);
191         err = poll(&pfd, 1, timeout);
192         if (err < 0)
193                 return -errno;
194         return 0;
195 }
196
197 int snd_ctl_open(snd_ctl_t **ctlp, const char *name)
198 {
199         const char *str;
200         char buf[256];
201         int err;
202         snd_config_t *ctl_conf, *conf, *type_conf;
203         snd_config_iterator_t i, next;
204         const char *lib = NULL, *open = NULL;
205         int (*open_func)(snd_ctl_t **ctlp, const char *name, snd_config_t *conf);
206         void *h;
207         assert(ctlp && name);
208         err = snd_config_update();
209         if (err < 0)
210                 return err;
211         err = snd_config_searchv(snd_config, &ctl_conf, "ctl", name, 0);
212         if (err < 0) {
213                 int card;
214                 char socket[256], sname[256];
215                 err = sscanf(name, "hw:%d", &card);
216                 if (err == 1)
217                         return snd_ctl_hw_open(ctlp, name, card);
218                 err = sscanf(name, "shm:%256[^,],%256[^,]", socket, sname);
219                 if (err == 2)
220                         return snd_ctl_shm_open(ctlp, name, socket, sname);
221                 SNDERR("Unknown control %s", name);
222                 return -ENOENT;
223         }
224         if (snd_config_get_type(ctl_conf) != SND_CONFIG_TYPE_COMPOUND)
225                 return -EINVAL;
226         err = snd_config_search(ctl_conf, "type", &conf);
227         if (err < 0)
228                 return err;
229         err = snd_config_get_string(conf, &str);
230         if (err < 0)
231                 return err;
232         err = snd_config_searchv(snd_config, &type_conf, "ctltype", str, 0);
233         if (err >= 0) {
234                 snd_config_for_each(i, next, type_conf) {
235                         snd_config_t *n = snd_config_iterator_entry(i);
236                         const char *id = snd_config_get_id(n);
237                         if (strcmp(id, "comment") == 0)
238                                 continue;
239                         if (strcmp(id, "lib") == 0) {
240                                 err = snd_config_get_string(n, &lib);
241                                 if (err < 0)
242                                         return -EINVAL;
243                                 continue;
244                         }
245                         if (strcmp(id, "open") == 0) {
246                                 err = snd_config_get_string(n, &open);
247                                 if (err < 0)
248                                         return -EINVAL;
249                                 continue;
250                         }
251                         SNDERR("Unknown field %s", id);
252                         return -EINVAL;
253                 }
254         }
255         if (!open) {
256                 open = buf;
257                 snprintf(buf, sizeof(buf), "_snd_ctl_%s_open", str);
258         }
259         if (!lib)
260                 lib = "libasound.so";
261         h = dlopen(lib, RTLD_NOW);
262         if (!h) {
263                 SNDERR("Cannot open shared library %s", lib);
264                 return -ENOENT;
265         }
266         open_func = dlsym(h, open);
267         if (!open_func) {
268                 SNDERR("symbol %s is not defined inside %s", open, lib);
269                 dlclose(h);
270                 return -ENXIO;
271         }
272         return open_func(ctlp, name, ctl_conf);
273 }
274
275 void snd_ctl_elem_set_bytes(snd_ctl_elem_value_t *obj, void *data, size_t size)
276 {
277         assert(obj);
278         assert(size <= sizeof(obj->value.bytes.data));
279         memcpy(obj->value.bytes.data, data, size);
280 }
281
282 #define TYPE(v) [SND_CTL_ELEM_TYPE_##v] = #v
283 #define IFACE(v) [SND_CTL_ELEM_IFACE_##v] = #v
284 #define EVENT(v) [SND_CTL_EVENT_##v] = #v
285
286 const char *snd_ctl_elem_type_names[] = {
287         TYPE(NONE),
288         TYPE(BOOLEAN),
289         TYPE(INTEGER),
290         TYPE(ENUMERATED),
291         TYPE(BYTES),
292         TYPE(IEC958),
293 };
294
295 const char *snd_ctl_elem_iface_names[] = {
296         IFACE(CARD),
297         IFACE(HWDEP),
298         IFACE(MIXER),
299         IFACE(PCM),
300         IFACE(RAWMIDI),
301         IFACE(TIMER),
302         IFACE(SEQUENCER),
303 };
304
305 const char *snd_ctl_event_type_names[] = {
306         EVENT(ELEM),
307 };
308
309 const char *snd_ctl_elem_type_name(snd_ctl_elem_type_t type)
310 {
311         assert(type <= SND_CTL_ELEM_TYPE_LAST);
312         return snd_ctl_elem_type_names[snd_enum_to_int(type)];
313 }
314
315 const char *snd_ctl_elem_iface_name(snd_ctl_elem_iface_t iface)
316 {
317         assert(iface <= SND_CTL_ELEM_IFACE_LAST);
318         return snd_ctl_elem_iface_names[snd_enum_to_int(iface)];
319 }
320
321 const char *snd_ctl_event_type_name(snd_ctl_event_type_t type)
322 {
323         assert(type <= SND_CTL_EVENT_LAST);
324         return snd_ctl_event_type_names[snd_enum_to_int(type)];
325 }
326
327 int snd_ctl_elem_list_alloc_space(snd_ctl_elem_list_t *obj, unsigned int entries)
328 {
329         if (obj->pids)
330                 free(obj->pids);
331         obj->pids = calloc(entries, sizeof(*obj->pids));
332         if (!obj->pids) {
333                 obj->space = 0;
334                 return -ENOMEM;
335         }
336         obj->space = entries;
337         return 0;
338 }  
339
340 void snd_ctl_elem_list_free_space(snd_ctl_elem_list_t *obj)
341 {
342         free(obj->pids);
343         obj->pids = NULL;
344 }
345
346 unsigned int snd_ctl_event_elem_get_mask(const snd_ctl_event_t *obj)
347 {
348         assert(obj);
349         assert(obj->type == SND_CTL_EVENT_ELEM);
350         return obj->data.elem.mask;
351 }
352
353 unsigned int snd_ctl_event_elem_get_numid(const snd_ctl_event_t *obj)
354 {
355         assert(obj);
356         assert(obj->type == SND_CTL_EVENT_ELEM);
357         return obj->data.elem.id.numid;
358 }
359
360 void snd_ctl_event_elem_get_id(const snd_ctl_event_t *obj, snd_ctl_elem_id_t *ptr)
361 {
362         assert(obj && ptr);
363         assert(obj->type == SND_CTL_EVENT_ELEM);
364         *ptr = obj->data.elem.id;
365 }
366
367 snd_ctl_elem_iface_t snd_ctl_event_elem_get_interface(const snd_ctl_event_t *obj)
368 {
369         assert(obj);
370         assert(obj->type == SND_CTL_EVENT_ELEM);
371         return snd_int_to_enum(obj->data.elem.id.iface);
372 }
373
374 unsigned int snd_ctl_event_elem_get_device(const snd_ctl_event_t *obj)
375 {
376         assert(obj);
377         assert(obj->type == SND_CTL_EVENT_ELEM);
378         return obj->data.elem.id.device;
379 }
380
381 unsigned int snd_ctl_event_elem_get_subdevice(const snd_ctl_event_t *obj)
382 {
383         assert(obj);
384         assert(obj->type == SND_CTL_EVENT_ELEM);
385         return obj->data.elem.id.subdevice;
386 }
387
388 const char *snd_ctl_event_elem_get_name(const snd_ctl_event_t *obj)
389 {
390         assert(obj);
391         assert(obj->type == SND_CTL_EVENT_ELEM);
392         return obj->data.elem.id.name;
393 }
394
395 unsigned int snd_ctl_event_elem_get_index(const snd_ctl_event_t *obj)
396 {
397         assert(obj);
398         assert(obj->type == SND_CTL_EVENT_ELEM);
399         return obj->data.elem.id.index;
400 }
401