1 /**
2 * \file timer/timer_query.c
3 * \author Jaroslav Kysela <perex@perex.cz>
4 * \date 2001
5 *
6 * Timer Query Interface is designed to obtain identification of timers.
7 */
8 /*
9 * Timer Query Interface - main file
10 * Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz>
11 *
12 *
13 * This library is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU Lesser General Public License as
15 * published by the Free Software Foundation; either version 2.1 of
16 * the License, or (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License for more details.
22 *
23 * You should have received a copy of the GNU Lesser General Public
24 * License along with this library; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 *
27 */
28
29 #include "timer_local.h"
30
snd_timer_query_open_conf(snd_timer_query_t ** timer,const char * name,snd_config_t * timer_root,snd_config_t * timer_conf,int mode)31 static int snd_timer_query_open_conf(snd_timer_query_t **timer,
32 const char *name, snd_config_t *timer_root,
33 snd_config_t *timer_conf, int mode)
34 {
35 const char *str;
36 char buf[256], errbuf[256];
37 int err;
38 snd_config_t *conf, *type_conf = NULL;
39 snd_config_iterator_t i, next;
40 const char *id;
41 const char *lib = NULL, *open_name = NULL;
42 int (*open_func)(snd_timer_query_t **, const char *, snd_config_t *, snd_config_t *, int) = NULL;
43 #ifndef PIC
44 extern void *snd_timer_query_open_symbols(void);
45 #endif
46 void *h = NULL;
47 if (snd_config_get_type(timer_conf) != SND_CONFIG_TYPE_COMPOUND) {
48 if (name)
49 SNDERR("Invalid type for TIMER %s definition", name);
50 else
51 SNDERR("Invalid type for TIMER definition");
52 return -EINVAL;
53 }
54 err = snd_config_search(timer_conf, "type", &conf);
55 if (err < 0) {
56 SNDERR("type is not defined");
57 return err;
58 }
59 err = snd_config_get_id(conf, &id);
60 if (err < 0) {
61 SNDERR("unable to get id");
62 return err;
63 }
64 err = snd_config_get_string(conf, &str);
65 if (err < 0) {
66 SNDERR("Invalid type for %s", id);
67 return err;
68 }
69 err = snd_config_search_definition(timer_root, "timer_query_type", str, &type_conf);
70 if (err >= 0) {
71 if (snd_config_get_type(type_conf) != SND_CONFIG_TYPE_COMPOUND) {
72 SNDERR("Invalid type for TIMER type %s definition", str);
73 err = -EINVAL;
74 goto _err;
75 }
76 snd_config_for_each(i, next, type_conf) {
77 snd_config_t *n = snd_config_iterator_entry(i);
78 const char *id;
79 if (snd_config_get_id(n, &id) < 0)
80 continue;
81 if (strcmp(id, "comment") == 0)
82 continue;
83 if (strcmp(id, "lib") == 0) {
84 err = snd_config_get_string(n, &lib);
85 if (err < 0) {
86 SNDERR("Invalid type for %s", id);
87 goto _err;
88 }
89 continue;
90 }
91 if (strcmp(id, "open") == 0) {
92 err = snd_config_get_string(n, &open_name);
93 if (err < 0) {
94 SNDERR("Invalid type for %s", id);
95 goto _err;
96 }
97 continue;
98 }
99 SNDERR("Unknown field %s", id);
100 err = -EINVAL;
101 goto _err;
102 }
103 }
104 if (!open_name) {
105 open_name = buf;
106 snprintf(buf, sizeof(buf), "_snd_timer_query_%s_open", str);
107 }
108 #ifndef PIC
109 snd_timer_query_open_symbols();
110 #endif
111 h = INTERNAL(snd_dlopen)(lib, RTLD_NOW, errbuf, sizeof(errbuf));
112 if (h)
113 open_func = snd_dlsym(h, open_name, SND_DLSYM_VERSION(SND_TIMER_QUERY_DLSYM_VERSION));
114 err = 0;
115 if (!h) {
116 SNDERR("Cannot open shared library %s (%s)", lib, errbuf);
117 err = -ENOENT;
118 } else if (!open_func) {
119 SNDERR("symbol %s is not defined inside %s", open_name, lib);
120 snd_dlclose(h);
121 err = -ENXIO;
122 }
123 _err:
124 if (type_conf)
125 snd_config_delete(type_conf);
126 if (! err) {
127 err = open_func(timer, name, timer_root, timer_conf, mode);
128 if (err < 0)
129 snd_dlclose(h);
130 else
131 (*timer)->dl_handle = h;
132 }
133 return err;
134 }
135
snd_timer_query_open_noupdate(snd_timer_query_t ** timer,snd_config_t * root,const char * name,int mode)136 static int snd_timer_query_open_noupdate(snd_timer_query_t **timer, snd_config_t *root, const char *name, int mode)
137 {
138 int err;
139 snd_config_t *timer_conf;
140 err = snd_config_search_definition(root, "timer_query", name, &timer_conf);
141 if (err < 0) {
142 SNDERR("Unknown timer %s", name);
143 return err;
144 }
145 err = snd_timer_query_open_conf(timer, name, root, timer_conf, mode);
146 snd_config_delete(timer_conf);
147 return err;
148 }
149
150 /**
151 * \brief Opens a new connection to the timer query interface.
152 * \param timer Returned handle (NULL if not wanted)
153 * \param name ASCII identifier of the RawMidi handle
154 * \param mode Open mode
155 * \return 0 on success otherwise a negative error code
156 *
157 * Opens a new connection to the RawMidi interface specified with
158 * an ASCII identifier and mode.
159 */
snd_timer_query_open(snd_timer_query_t ** timer,const char * name,int mode)160 int snd_timer_query_open(snd_timer_query_t **timer, const char *name, int mode)
161 {
162 snd_config_t *top;
163 int err;
164
165 assert(timer && name);
166 err = snd_config_update_ref(&top);
167 if (err < 0)
168 return err;
169 err = snd_timer_query_open_noupdate(timer, top, name, mode);
170 snd_config_unref(top);
171 return err;
172 }
173
174 /**
175 * \brief Opens a new connection to the timer query interface using local configuration
176 * \param timer Returned handle (NULL if not wanted)
177 * \param name ASCII identifier of the RawMidi handle
178 * \param mode Open mode
179 * \param lconf Local configuration
180 * \return 0 on success otherwise a negative error code
181 *
182 * Opens a new connection to the RawMidi interface specified with
183 * an ASCII identifier and mode.
184 */
snd_timer_query_open_lconf(snd_timer_query_t ** timer,const char * name,int mode,snd_config_t * lconf)185 int snd_timer_query_open_lconf(snd_timer_query_t **timer, const char *name,
186 int mode, snd_config_t *lconf)
187 {
188 assert(timer && name && lconf);
189 return snd_timer_query_open_noupdate(timer, lconf, name, mode);
190 }
191
192 /**
193 * \brief close timer query handle
194 * \param timer timer handle
195 * \return 0 on success otherwise a negative error code
196 *
197 * Closes the specified timer handle and frees all associated
198 * resources.
199 */
snd_timer_query_close(snd_timer_query_t * timer)200 int snd_timer_query_close(snd_timer_query_t *timer)
201 {
202 int err;
203 assert(timer);
204 err = timer->ops->close(timer);
205 if (timer->dl_handle)
206 snd_dlclose(timer->dl_handle);
207 free(timer->name);
208 free(timer);
209 return err;
210 }
211
212 /**
213 * \brief obtain the next timer identification
214 * \param timer timer handle
215 * \param tid timer identification
216 * \return 0 on success otherwise a negative error code
217 *
218 * if tid->dev_class is -1, then the first device is returned
219 * if result tid->dev_class is -1, no more devices are left
220 */
snd_timer_query_next_device(snd_timer_query_t * timer,snd_timer_id_t * tid)221 int snd_timer_query_next_device(snd_timer_query_t *timer, snd_timer_id_t *tid)
222 {
223 assert(timer);
224 assert(tid);
225 return timer->ops->next_device(timer, tid);
226 }
227
228 /**
229 * \brief get size of the snd_timer_ginfo_t structure in bytes
230 * \return size of the snd_timer_ginfo_t structure in bytes
231 */
snd_timer_ginfo_sizeof(void)232 size_t snd_timer_ginfo_sizeof(void)
233 {
234 return sizeof(snd_timer_ginfo_t);
235 }
236
237 /**
238 * \brief allocate a new snd_timer_ginfo_t structure
239 * \param info returned pointer
240 * \return 0 on success otherwise a negative error code if fails
241 *
242 * Allocates a new snd_timer_info_t structure using the standard
243 * malloc C library function.
244 */
snd_timer_ginfo_malloc(snd_timer_ginfo_t ** info)245 int snd_timer_ginfo_malloc(snd_timer_ginfo_t **info)
246 {
247 assert(info);
248 *info = calloc(1, sizeof(snd_timer_ginfo_t));
249 if (!*info)
250 return -ENOMEM;
251 return 0;
252 }
253
254 /**
255 * \brief frees the snd_timer_ginfo_t structure
256 * \param info pointer to the snd_timer_ginfo_t structure to free
257 *
258 * Frees the given snd_timer_info_t structure using the standard
259 * free C library function.
260 */
snd_timer_ginfo_free(snd_timer_ginfo_t * info)261 void snd_timer_ginfo_free(snd_timer_ginfo_t *info)
262 {
263 assert(info);
264 free(info);
265 }
266
267 /**
268 * \brief copy one snd_timer_info_t structure to another
269 * \param dst destination snd_timer_info_t structure
270 * \param src source snd_timer_info_t structure
271 */
snd_timer_ginfo_copy(snd_timer_ginfo_t * dst,const snd_timer_ginfo_t * src)272 void snd_timer_ginfo_copy(snd_timer_ginfo_t *dst, const snd_timer_ginfo_t *src)
273 {
274 assert(dst && src);
275 *dst = *src;
276 }
277
278 /**
279 * \brief set timer identification
280 * \param obj pointer to #snd_timer_ginfo_t structure
281 * \param tid pointer to #snd_timer_id_t structure
282 * \return zero on success otherwise a negative error number
283 */
snd_timer_ginfo_set_tid(snd_timer_ginfo_t * obj,snd_timer_id_t * tid)284 int snd_timer_ginfo_set_tid(snd_timer_ginfo_t *obj, snd_timer_id_t *tid)
285 {
286 obj->tid = *((snd_timer_id_t *)tid);
287 return 0;
288 }
289
290 /**
291 * \brief get timer identification
292 * \param obj pointer to #snd_timer_ginfo_t structure
293 * \return pointer to snd_timer_id_t
294 */
snd_timer_ginfo_get_tid(snd_timer_ginfo_t * obj)295 snd_timer_id_t *snd_timer_ginfo_get_tid(snd_timer_ginfo_t *obj)
296 {
297 return (snd_timer_id_t *)&obj->tid;
298 }
299
300 /**
301 * \brief get timer flags
302 * \param obj pointer to #snd_timer_ginfo_t structure
303 * \return timer flags
304 */
snd_timer_ginfo_get_flags(snd_timer_ginfo_t * obj)305 unsigned int snd_timer_ginfo_get_flags(snd_timer_ginfo_t *obj)
306 {
307 return obj->flags;
308 }
309
310 /**
311 * \brief get associated card with timer
312 * \param obj pointer to #snd_timer_ginfo_t structure
313 * \return associated card
314 */
snd_timer_ginfo_get_card(snd_timer_ginfo_t * obj)315 int snd_timer_ginfo_get_card(snd_timer_ginfo_t *obj)
316 {
317 return obj->card;
318 }
319
320 /**
321 * \brief get timer identification
322 * \param obj pointer to #snd_timer_ginfo_t structure
323 * \return timer identification
324 */
snd_timer_ginfo_get_id(snd_timer_ginfo_t * obj)325 char *snd_timer_ginfo_get_id(snd_timer_ginfo_t *obj)
326 {
327 return (char *)obj->id;
328 }
329
330 /**
331 * \brief get timer name
332 * \param obj pointer to #snd_timer_ginfo_t structure
333 * \return timer name
334 */
snd_timer_ginfo_get_name(snd_timer_ginfo_t * obj)335 char *snd_timer_ginfo_get_name(snd_timer_ginfo_t *obj)
336 {
337 return (char *)obj->name;
338 }
339
340 /**
341 * \brief get timer resolution in ns
342 * \param obj pointer to #snd_timer_ginfo_t structure
343 * \return timer resolution in ns
344 */
snd_timer_ginfo_get_resolution(snd_timer_ginfo_t * obj)345 unsigned long snd_timer_ginfo_get_resolution(snd_timer_ginfo_t *obj)
346 {
347 return obj->resolution;
348 }
349
350 /**
351 * \brief get timer minimal resolution in ns
352 * \param obj pointer to #snd_timer_ginfo_t structure
353 * \return timer minimal resolution in ns
354 */
snd_timer_ginfo_get_resolution_min(snd_timer_ginfo_t * obj)355 unsigned long snd_timer_ginfo_get_resolution_min(snd_timer_ginfo_t *obj)
356 {
357 return obj->resolution_min;
358 }
359
360 /**
361 * \brief get timer maximal resolution in ns
362 * \param obj pointer to #snd_timer_ginfo_t structure
363 * \return timer maximal resolution in ns
364 */
snd_timer_ginfo_get_resolution_max(snd_timer_ginfo_t * obj)365 unsigned long snd_timer_ginfo_get_resolution_max(snd_timer_ginfo_t *obj)
366 {
367 return obj->resolution_max;
368 }
369
370 /**
371 * \brief get current timer clients
372 * \param obj pointer to #snd_timer_ginfo_t structure
373 * \return current timer clients
374 */
snd_timer_ginfo_get_clients(snd_timer_ginfo_t * obj)375 unsigned int snd_timer_ginfo_get_clients(snd_timer_ginfo_t *obj)
376 {
377 return obj->clients;
378 }
379
380 /**
381 * \brief obtain the timer global information
382 * \param timer timer handle
383 * \param info timer information
384 * \return 0 on success otherwise a negative error code
385 */
386 #ifndef DOXYGEN
INTERNAL(snd_timer_query_info)387 EXPORT_SYMBOL int INTERNAL(snd_timer_query_info)(snd_timer_query_t *timer, snd_timer_ginfo_t *info)
388 #else
389 int snd_timer_query_info(snd_timer_query_t *timer, snd_timer_ginfo_t *info)
390 #endif
391 {
392 assert(timer);
393 assert(info);
394 return timer->ops->info(timer, info);
395 }
396 use_default_symbol_version(__snd_timer_query_info, snd_timer_query_info, ALSA_0.9.0);
397
398 /**
399 * \brief set the timer global parameters
400 * \param timer timer handle
401 * \param params timer parameters
402 * \return 0 on success otherwise a negative error code
403 */
404 #ifndef DOXYGEN
INTERNAL(snd_timer_query_params)405 EXPORT_SYMBOL int INTERNAL(snd_timer_query_params)(snd_timer_query_t *timer, snd_timer_gparams_t *params)
406 #else
407 int snd_timer_query_params(snd_timer_query_t *timer, snd_timer_gparams_t *params)
408 #endif
409 {
410 assert(timer);
411 assert(params);
412 return timer->ops->params(timer, params);
413 }
414 use_default_symbol_version(__snd_timer_query_params, snd_timer_query_params, ALSA_0.9.0);
415
416 /**
417 * \brief get the timer global status
418 * \param timer timer handle
419 * \param status timer status
420 * \return 0 on success otherwise a negative error code
421 */
422 #ifndef DOXYGEN
INTERNAL(snd_timer_query_status)423 EXPORT_SYMBOL int INTERNAL(snd_timer_query_status)(snd_timer_query_t *timer, snd_timer_gstatus_t *status)
424 #else
425 int snd_timer_query_status(snd_timer_query_t *timer, snd_timer_gstatus_t *status)
426 #endif
427 {
428 assert(timer);
429 assert(status);
430 return timer->ops->status(timer, status);
431 }
432 use_default_symbol_version(__snd_timer_query_status, snd_timer_query_status, ALSA_0.9.0);
433
434 /**
435 * \brief get size of the snd_timer_id_t structure in bytes
436 * \return size of the snd_timer_id_t structure in bytes
437 */
snd_timer_id_sizeof()438 size_t snd_timer_id_sizeof()
439 {
440 return sizeof(snd_timer_id_t);
441 }
442
443 /**
444 * \brief allocate a new snd_timer_id_t structure
445 * \param info returned pointer
446 * \return 0 on success otherwise a negative error code if fails
447 *
448 * Allocates a new snd_timer_id_t structure using the standard
449 * malloc C library function.
450 */
snd_timer_id_malloc(snd_timer_id_t ** info)451 int snd_timer_id_malloc(snd_timer_id_t **info)
452 {
453 assert(info);
454 *info = calloc(1, sizeof(snd_timer_id_t));
455 if (!*info)
456 return -ENOMEM;
457 return 0;
458 }
459
460 /**
461 * \brief frees the snd_timer_id_t structure
462 * \param info pointer to the snd_timer_id_t structure to free
463 *
464 * Frees the given snd_timer_id_t structure using the standard
465 * free C library function.
466 */
snd_timer_id_free(snd_timer_id_t * info)467 void snd_timer_id_free(snd_timer_id_t *info)
468 {
469 assert(info);
470 free(info);
471 }
472
473 /**
474 * \brief copy one snd_timer_id_t structure to another
475 * \param dst destination snd_timer_id_t structure
476 * \param src source snd_timer_id_t structure
477 */
snd_timer_id_copy(snd_timer_id_t * dst,const snd_timer_id_t * src)478 void snd_timer_id_copy(snd_timer_id_t *dst, const snd_timer_id_t *src)
479 {
480 assert(dst && src);
481 *dst = *src;
482 }
483
484 /**
485 * \brief set timer class
486 * \param tid pointer to #snd_timer_id_t structure
487 * \param dev_class class of timer device
488 */
snd_timer_id_set_class(snd_timer_id_t * tid,int dev_class)489 void snd_timer_id_set_class(snd_timer_id_t * tid, int dev_class)
490 {
491 assert(tid);
492 tid->dev_class = dev_class;
493 }
494
495 /**
496 * \brief get timer class
497 * \param tid pointer to #snd_timer_id_t structure
498 * \return timer class
499 */
snd_timer_id_get_class(snd_timer_id_t * tid)500 int snd_timer_id_get_class(snd_timer_id_t * tid)
501 {
502 assert(tid);
503 return tid->dev_class;
504 }
505
506 /**
507 * \brief set timer sub-class
508 * \param tid pointer to #snd_timer_id_t structure
509 * \param dev_sclass sub-class of timer device
510 */
snd_timer_id_set_sclass(snd_timer_id_t * tid,int dev_sclass)511 void snd_timer_id_set_sclass(snd_timer_id_t * tid, int dev_sclass)
512 {
513 assert(tid);
514 tid->dev_sclass = dev_sclass;
515 }
516
517 /**
518 * \brief get timer sub-class
519 * \param tid pointer to #snd_timer_id_t structure
520 * \return timer sub-class
521 */
snd_timer_id_get_sclass(snd_timer_id_t * tid)522 int snd_timer_id_get_sclass(snd_timer_id_t * tid)
523 {
524 assert(tid);
525 return tid->dev_sclass;
526 }
527
528 /**
529 * \brief set timer card
530 * \param tid pointer to #snd_timer_id_t structure
531 * \param card card number
532 */
snd_timer_id_set_card(snd_timer_id_t * tid,int card)533 void snd_timer_id_set_card(snd_timer_id_t * tid, int card)
534 {
535 assert(tid);
536 tid->card = card;
537 }
538
539 /**
540 * \brief get timer card
541 * \param tid pointer to #snd_timer_id_t structure
542 * \return timer card number
543 */
snd_timer_id_get_card(snd_timer_id_t * tid)544 int snd_timer_id_get_card(snd_timer_id_t * tid)
545 {
546 assert(tid);
547 return tid->card;
548 }
549
550 /**
551 * \brief set timer device
552 * \param tid pointer to #snd_timer_id_t structure
553 * \param device device number
554 */
snd_timer_id_set_device(snd_timer_id_t * tid,int device)555 void snd_timer_id_set_device(snd_timer_id_t * tid, int device)
556 {
557 assert(tid);
558 tid->device = device;
559 }
560
561 /**
562 * \brief get timer device
563 * \param tid pointer to #snd_timer_id_t structure
564 * \return timer device number
565 */
snd_timer_id_get_device(snd_timer_id_t * tid)566 int snd_timer_id_get_device(snd_timer_id_t * tid)
567 {
568 assert(tid);
569 return tid->device;
570 }
571
572 /**
573 * \brief set timer subdevice
574 * \param tid pointer to #snd_timer_id_t structure
575 * \param subdevice subdevice number
576 */
snd_timer_id_set_subdevice(snd_timer_id_t * tid,int subdevice)577 void snd_timer_id_set_subdevice(snd_timer_id_t * tid, int subdevice)
578 {
579 assert(tid);
580 tid->subdevice = subdevice;
581 }
582
583 /**
584 * \brief get timer subdevice
585 * \param tid pointer to #snd_timer_id_t structure
586 * \return timer subdevice number
587 */
snd_timer_id_get_subdevice(snd_timer_id_t * tid)588 int snd_timer_id_get_subdevice(snd_timer_id_t * tid)
589 {
590 assert(tid);
591 return tid->subdevice;
592 }
593