• Home
  • History
  • Annotate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/ap/gpl/iserver/alsa-lib-1.0.26/src/mixer/

Lines Matching defs:*

2  * \file mixer/simple_abst.c
3 * \brief Mixer Simple Element Class Interface - Module Abstraction
4 * \author Jaroslav Kysela <perex@perex.cz>
5 * \date 2005
7 * Mixer simple element class interface.
10 * Mixer Interface - simple controls - abstraction module
11 * Copyright (c) 2005 by Jaroslav Kysela <perex@perex.cz>
14 * This library is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License as
16 * published by the Free Software Foundation; either version 2.1 of
17 * the License, or (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Lesser General Public License for more details.
24 * You should have received a copy of the GNU Lesser General Public
25 * License along with this library; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <unistd.h>
33 #include <string.h>
34 #include <fcntl.h>
35 #include <sys/ioctl.h>
36 #include <math.h>
37 #include <dlfcn.h>
38 #include "config.h"
39 #include "asoundlib.h"
40 #include "mixer_simple.h"
42 #ifndef DOC_HIDDEN
44 #define SO_PATH ALSA_PLUGIN_DIR "/smixer"
46 typedef struct _class_priv {
47 char *device;
48 snd_ctl_t *ctl;
49 snd_hctl_t *hctl;
50 int attach_flag;
51 snd_ctl_card_info_t *info;
52 void *dlhandle;
53 void *private_data;
54 void (*private_free)(snd_mixer_class_t *class);
55 } class_priv_t;
57 typedef int (*snd_mixer_sbasic_init_t)(snd_mixer_class_t *class);
58 typedef int (*snd_mixer_sfbasic_init_t)(snd_mixer_class_t *class,
59 snd_mixer_t *mixer,
60 const char *device);
62 #endif /* !DOC_HIDDEN */
64 static int try_open(snd_mixer_class_t *class, const char *lib)
66 class_priv_t *priv = snd_mixer_class_get_private(class);
67 snd_mixer_event_t event_func;
68 snd_mixer_sbasic_init_t init_func = NULL;
69 char *xlib, *path;
70 void *h;
71 int err = 0;
73 path = getenv("ALSA_MIXER_SIMPLE_MODULES");
74 if (!path)
75 path = SO_PATH;
76 xlib = malloc(strlen(lib) + strlen(path) + 1 + 1);
77 if (xlib == NULL)
78 return -ENOMEM;
79 strcpy(xlib, path);
80 strcat(xlib, "/");
81 strcat(xlib, lib);
82 h = snd_dlopen(xlib, RTLD_NOW);
83 if (h == NULL) {
84 SNDERR("Unable to open library '%s'", xlib);
85 free(xlib);
86 return -ENXIO;
88 priv->dlhandle = h;
89 event_func = snd_dlsym(h, "alsa_mixer_simple_event", NULL);
90 if (event_func == NULL) {
91 SNDERR("Symbol 'alsa_mixer_simple_event' was not found in '%s'", xlib);
92 err = -ENXIO;
94 if (err == 0) {
95 init_func = snd_dlsym(h, "alsa_mixer_simple_init", NULL);
96 if (init_func == NULL) {
97 SNDERR("Symbol 'alsa_mixer_simple_init' was not found in '%s'", xlib);
98 err = -ENXIO;
101 free(xlib);
102 err = err == 0 ? init_func(class) : err;
103 if (err < 0)
104 return err;
105 snd_mixer_class_set_event(class, event_func);
106 return 1;
109 static int try_open_full(snd_mixer_class_t *class, snd_mixer_t *mixer,
110 const char *lib, const char *device)
112 class_priv_t *priv = snd_mixer_class_get_private(class);
113 snd_mixer_event_t event_func;
114 snd_mixer_sfbasic_init_t init_func = NULL;
115 char *xlib, *path;
116 void *h;
117 int err = 0;
119 path = getenv("ALSA_MIXER_SIMPLE_MODULES");
120 if (!path)
121 path = SO_PATH;
122 xlib = malloc(strlen(lib) + strlen(path) + 1 + 1);
123 if (xlib == NULL)
124 return -ENOMEM;
125 strcpy(xlib, path);
126 strcat(xlib, "/");
127 strcat(xlib, lib);
128 /* note python modules requires RTLD_GLOBAL */
129 h = snd_dlopen(xlib, RTLD_NOW|RTLD_GLOBAL);
130 if (h == NULL) {
131 SNDERR("Unable to open library '%s'", xlib);
132 free(xlib);
133 return -ENXIO;
135 priv->dlhandle = h;
136 event_func = snd_dlsym(h, "alsa_mixer_simple_event", NULL);
137 if (event_func == NULL) {
138 SNDERR("Symbol 'alsa_mixer_simple_event' was not found in '%s'", xlib);
139 err = -ENXIO;
141 if (err == 0) {
142 init_func = snd_dlsym(h, "alsa_mixer_simple_finit", NULL);
143 if (init_func == NULL) {
144 SNDERR("Symbol 'alsa_mixer_simple_finit' was not found in '%s'", xlib);
145 err = -ENXIO;
148 free(xlib);
149 err = err == 0 ? init_func(class, mixer, device) : err;
150 if (err < 0)
151 return err;
152 snd_mixer_class_set_event(class, event_func);
153 return 1;
156 static int match(snd_mixer_class_t *class, const char *lib, const char *searchl)
158 class_priv_t *priv = snd_mixer_class_get_private(class);
159 const char *components;
161 if (searchl == NULL)
162 return try_open(class, lib);
163 components = snd_ctl_card_info_get_components(priv->info);
164 while (*components != '\0') {
165 if (!strncmp(components, searchl, strlen(searchl)))
166 return try_open(class, lib);
167 while (*components != ' ' && *components != '\0')
168 components++;
169 while (*components == ' ' && *components != '\0')
170 components++;
172 return 0;
175 static int find_full(snd_mixer_class_t *class, snd_mixer_t *mixer,
176 snd_config_t *top, const char *device)
178 snd_config_iterator_t i, next;
179 char *lib;
180 const char *id;
181 int err;
183 snd_config_for_each(i, next, top) {
184 snd_config_t *n = snd_config_iterator_entry(i);
185 if (snd_config_get_id(n, &id) < 0)
186 continue;
187 if (strcmp(id, "_full"))
188 continue;
189 err = snd_config_get_string(n, (const char **)&lib);
190 if (err < 0)
191 return err;
192 err = try_open_full(class, mixer, lib, device);
193 if (err < 0)
194 return err;
195 return 0;
197 return -ENOENT;
200 static int find_module(snd_mixer_class_t *class, snd_config_t *top)
202 snd_config_iterator_t i, next;
203 snd_config_iterator_t j, jnext;
204 char *lib, *searchl;
205 const char *id;
206 int err;
208 snd_config_for_each(i, next, top) {
209 snd_config_t *n = snd_config_iterator_entry(i);
210 if (snd_config_get_id(n, &id) < 0)
211 continue;
212 if (*id == '_')
213 continue;
214 searchl = NULL;
215 lib = NULL;
216 snd_config_for_each(j, jnext, n) {
217 snd_config_t *m = snd_config_iterator_entry(j);
218 if (snd_config_get_id(m, &id) < 0)
219 continue;
220 if (!strcmp(id, "searchl")) {
221 err = snd_config_get_string(m, (const char **)&searchl);
222 if (err < 0)
223 return err;
224 continue;
226 if (!strcmp(id, "lib")) {
227 err = snd_config_get_string(m, (const char **)&lib);
228 if (err < 0)
229 return err;
230 continue;
233 err = match(class, lib, searchl);
234 if (err == 1)
235 return 0;
236 if (err < 0)
237 return err;
239 return -ENOENT;
242 static void private_free(snd_mixer_class_t *class)
244 class_priv_t *priv = snd_mixer_class_get_private(class);
246 if (priv->private_free)
247 priv->private_free(class);
248 if (priv->dlhandle)
249 snd_dlclose(priv->dlhandle);
250 if (priv->info)
251 snd_ctl_card_info_free(priv->info);
252 if (priv->hctl) {
253 if (priv->attach_flag)
254 snd_mixer_detach_hctl(snd_mixer_class_get_mixer(class), priv->hctl);
255 snd_hctl_close(priv->hctl);
256 } else if (priv->ctl)
257 snd_ctl_close(priv->ctl);
258 free(priv->device);
259 free(priv);
263 * \brief Register mixer simple element class - basic abstraction
264 * \param mixer Mixer handle
265 * \param options Options container
266 * \param classp Pointer to returned mixer simple element class handle (or NULL
267 * \return 0 on success otherwise a negative error code
269 int snd_mixer_simple_basic_register(snd_mixer_t *mixer,
270 struct snd_mixer_selem_regopt *options,
271 snd_mixer_class_t **classp)
273 snd_mixer_class_t *class;
274 class_priv_t *priv = calloc(1, sizeof(*priv));
275 const char *file;
276 snd_input_t *input;
277 snd_config_t *top = NULL;
278 int err;
280 if (priv == NULL)
281 return -ENOMEM;
282 if (options->device == NULL) {
283 free(priv);
284 return -EINVAL;
286 if (snd_mixer_class_malloc(&class)) {
287 free(priv);
288 return -ENOMEM;
290 priv->device = strdup(options->device);
291 if (priv->device == NULL) {
292 free(priv);
293 snd_mixer_class_free(class);
294 return -ENOMEM;
296 snd_mixer_class_set_compare(class, snd_mixer_selem_compare);
297 snd_mixer_class_set_private(class, priv);
298 snd_mixer_class_set_private_free(class, private_free);
299 file = getenv("ALSA_MIXER_SIMPLE");
300 if (!file)
301 file = ALSA_CONFIG_DIR "/smixer.conf";
302 err = snd_config_top(&top);
303 if (err >= 0) {
304 err = snd_input_stdio_open(&input, file, "r");
305 if (err < 0) {
306 SNDERR("unable to open simple mixer configuration file '%s'", file);
307 goto __error;
309 err = snd_config_load(top, input);
310 snd_input_close(input);
311 if (err < 0) {
312 SNDERR("%s may be old or corrupted: consider to remove or fix it", file);
313 goto __error;
315 err = find_full(class, mixer, top, priv->device);
316 if (err >= 0)
317 goto __full;
319 if (err >= 0) {
320 err = snd_ctl_open(&priv->ctl, priv->device, 0);
321 if (err < 0) {
322 SNDERR("unable to open control device '%s': %s", priv->device, snd_strerror(err));
323 goto __error;
325 err = snd_hctl_open_ctl(&priv->hctl, priv->ctl);
326 if (err < 0)
327 goto __error;
328 err = snd_ctl_card_info_malloc(&priv->info);
329 if (err < 0)
330 goto __error;
331 err = snd_ctl_card_info(priv->ctl, priv->info);
332 if (err < 0)
333 goto __error;
335 if (err >= 0)
336 err = find_module(class, top);
337 if (err >= 0)
338 err = snd_mixer_attach_hctl(mixer, priv->hctl);
339 if (err >= 0) {
340 priv->attach_flag = 1;
341 err = snd_mixer_class_register(class, mixer);
343 __full:
344 if (err < 0) {
345 __error:
346 if (top)
347 snd_config_delete(top);
348 if (class)
349 snd_mixer_class_free(class);
350 return err;
352 if (top)
353 snd_config_delete(top);
354 if (classp)
355 *classp = class;
356 return 0;
360 * \brief Basic Mixer Abstraction - Get information about device
361 * \param class Mixer class
362 * \param info Info structure
363 * \return 0 on success otherwise a negative error code
365 int snd_mixer_sbasic_info(const snd_mixer_class_t *class, sm_class_basic_t *info)
367 class_priv_t *priv = snd_mixer_class_get_private(class);
369 if (class == NULL || info == NULL)
370 return -EINVAL;
371 info->device = priv->device;
372 info->ctl = priv->ctl;
373 info->hctl = priv->hctl;
374 info->info = priv->info;
375 return 0;
379 * \brief Get private data for basic abstraction
380 * \param class Mixer class
381 * \return private data
383 void *snd_mixer_sbasic_get_private(const snd_mixer_class_t *class)
385 class_priv_t *priv = snd_mixer_class_get_private(class);
387 if (class == NULL)
388 return NULL;
389 return priv->private_data;
393 * \brief Set private data for basic abstraction
394 * \param class Mixer class
395 * \param private_data Private data
397 void snd_mixer_sbasic_set_private(const snd_mixer_class_t *class, void *private_data)
399 class_priv_t *priv;
401 if (class == NULL)
402 return;
403 priv = snd_mixer_class_get_private(class);
404 priv->private_data = private_data;
408 * \brief Set private data free callback for basic abstraction
409 * \param class Mixer class
410 * \param private_free free callback for private data
412 void snd_mixer_sbasic_set_private_free(const snd_mixer_class_t *class, void (*private_free)(snd_mixer_class_t *class))
414 class_priv_t *priv;
416 if (class == NULL)
417 return;
418 priv = snd_mixer_class_get_private(class);
419 priv->private_free = private_free;