2 * ALSA lisp implementation - sound related commands
3 * Copyright (c) 2003 by Jaroslav Kysela <perex@perex.cz>
6 * This library is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as
8 * published by the Free Software Foundation; either version 2.1 of
9 * the License, or (at your option) any later version.
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 Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 struct alisp_object * (*func) (struct alisp_instance *instance, struct acall_table * item, struct alisp_object * args);
33 static inline int get_integer(struct alisp_object * obj)
35 if (alisp_compare_type(obj, ALISP_OBJ_INTEGER))
40 static inline const void *get_pointer(struct alisp_object * obj)
42 if (alisp_compare_type(obj, ALISP_OBJ_POINTER))
43 return obj->value.ptr;
47 static const char *get_string(struct alisp_object * obj, const char * deflt)
49 if (obj == &alsa_lisp_t)
51 if (alisp_compare_type(obj, ALISP_OBJ_STRING) ||
52 alisp_compare_type(obj, ALISP_OBJ_IDENTIFIER))
62 static unsigned int get_flags(struct alisp_instance * instance,
63 struct alisp_object * obj,
64 const struct flags * flags,
70 const struct flags *ptr;
71 struct alisp_object *n;
73 if (obj == &alsa_lisp_nil)
77 key = get_string(obj, NULL);
79 invert = key[0] == '!';
83 if (!strcmp(ptr->key, key)) {
93 delete_tree(instance, car(obj));
95 delete_object(instance, n);
96 } while (obj != &alsa_lisp_nil);
100 static const void *get_ptr(struct alisp_instance * instance,
101 struct alisp_object * obj,
107 ptr_id = get_string(car(obj), NULL);
108 if (ptr_id == NULL) {
109 delete_tree(instance, obj);
112 if (strcmp(ptr_id, _ptr_id)) {
113 delete_tree(instance, obj);
116 ptr = get_pointer(cdr(obj));
117 delete_tree(instance, obj);
121 static struct alisp_object * new_lexpr(struct alisp_instance * instance, int err)
123 struct alisp_object * lexpr;
125 lexpr = new_object(instance, ALISP_OBJ_CONS);
128 lexpr->value.c.car = new_integer(instance, err);
129 if (lexpr->value.c.car == NULL) {
130 delete_object(instance, lexpr);
133 lexpr->value.c.cdr = new_object(instance, ALISP_OBJ_CONS);
134 if (lexpr->value.c.cdr == NULL) {
135 delete_object(instance, lexpr->value.c.car);
136 delete_object(instance, lexpr);
142 static struct alisp_object * add_cons(struct alisp_instance * instance,
143 struct alisp_object *lexpr,
144 int cdr, const char *id,
145 struct alisp_object *obj)
147 struct alisp_object * p1, * p2;
149 if (lexpr == NULL || obj == NULL) {
150 delete_tree(instance, obj);
154 p1 = lexpr->value.c.cdr = new_object(instance, ALISP_OBJ_CONS);
156 p1 = lexpr->value.c.car = new_object(instance, ALISP_OBJ_CONS);
160 delete_tree(instance, obj);
163 p1->value.c.car = new_object(instance, ALISP_OBJ_CONS);
164 if ((p2 = p1->value.c.car) == NULL)
166 p2->value.c.car = new_string(instance, id);
167 if (p2->value.c.car == NULL) {
170 lexpr->value.c.cdr = NULL;
172 lexpr->value.c.car = NULL;
173 delete_tree(instance, p1);
174 delete_tree(instance, obj);
177 p2->value.c.cdr = obj;
181 static struct alisp_object * add_cons2(struct alisp_instance * instance,
182 struct alisp_object *lexpr,
183 int cdr, struct alisp_object *obj)
185 struct alisp_object * p1;
187 if (lexpr == NULL || obj == NULL) {
188 delete_tree(instance, obj);
192 p1 = lexpr->value.c.cdr = new_object(instance, ALISP_OBJ_CONS);
194 p1 = lexpr->value.c.car = new_object(instance, ALISP_OBJ_CONS);
198 delete_tree(instance, obj);
201 p1->value.c.car = obj;
205 static struct alisp_object * new_result1(struct alisp_instance * instance,
206 int err, const char *ptr_id, void *ptr)
208 struct alisp_object * lexpr, * p1;
212 lexpr = new_object(instance, ALISP_OBJ_CONS);
215 lexpr->value.c.car = new_integer(instance, err);
216 if (lexpr->value.c.car == NULL) {
217 delete_object(instance, lexpr);
220 p1 = add_cons(instance, lexpr, 1, ptr_id, new_pointer(instance, ptr));
222 delete_object(instance, lexpr);
228 static struct alisp_object * new_result2(struct alisp_instance * instance,
231 struct alisp_object * lexpr, * p1;
235 lexpr = new_lexpr(instance, err);
238 p1 = lexpr->value.c.cdr;
239 p1->value.c.car = new_integer(instance, val);
240 if (p1->value.c.car == NULL) {
241 delete_object(instance, lexpr);
247 static struct alisp_object * new_result3(struct alisp_instance * instance,
248 int err, const char *str)
250 struct alisp_object * lexpr, * p1;
254 lexpr = new_lexpr(instance, err);
257 p1 = lexpr->value.c.cdr;
258 p1->value.c.car = new_string(instance, str);
259 if (p1->value.c.car == NULL) {
260 delete_object(instance, lexpr);
274 typedef int (*snd_int_pp_strp_int_t)(void **rctl, const char *name, int mode);
275 typedef int (*snd_int_pp_p_t)(void **rctl, void *handle);
276 typedef int (*snd_int_p_t)(void *rctl);
277 typedef char * (*snd_str_p_t)(void *rctl);
278 typedef int (*snd_int_intp_t)(int *val);
279 typedef int (*snd_int_str_t)(const char *str);
280 typedef int (*snd_int_int_strp_t)(int val, char **str);
281 typedef void *(*snd_p_p_t)(void *handle);
283 static struct alisp_object * FA_int_pp_strp_int(struct alisp_instance * instance, struct acall_table * item, struct alisp_object * args)
288 struct alisp_object *p1, *p2;
289 static struct flags flags[] = {
290 { "nonblock", SND_CTL_NONBLOCK },
291 { "async", SND_CTL_ASYNC },
292 { "readonly", SND_CTL_READONLY },
296 name = get_string(p1 = eval(instance, car(args)), NULL);
298 return &alsa_lisp_nil;
299 mode = get_flags(instance, p2 = eval(instance, car(cdr(args))), flags, 0);
300 delete_tree(instance, cdr(cdr(args)));
301 delete_object(instance, cdr(args));
302 delete_object(instance, args);
303 delete_tree(instance, p2);
304 err = ((snd_int_pp_strp_int_t)item->xfunc)(&handle, name, mode);
305 delete_tree(instance, p1);
306 return new_result1(instance, err, item->prefix, handle);
309 static struct alisp_object * FA_int_pp_p(struct alisp_instance * instance, struct acall_table * item, struct alisp_object * args)
314 struct alisp_object *p1;
316 if (item->xfunc == &snd_hctl_open_ctl)
319 delete_tree(instance, args);
320 return &alsa_lisp_nil;
322 p1 = eval(instance, car(args));
323 delete_tree(instance, cdr(args));
324 delete_object(instance, args);
325 handle = (void *)get_ptr(instance, p1, prefix1);
327 return &alsa_lisp_nil;
328 err = ((snd_int_pp_p_t)item->xfunc)(&handle, handle);
329 return new_result1(instance, err, item->prefix, handle);
332 static struct alisp_object * FA_p_p(struct alisp_instance * instance, struct acall_table * item, struct alisp_object * args)
336 struct alisp_object * p1;
338 if (item->xfunc == &snd_hctl_first_elem ||
339 item->xfunc == &snd_hctl_last_elem ||
340 item->xfunc == &snd_hctl_elem_next ||
341 item->xfunc == &snd_hctl_elem_prev)
342 prefix1 = "hctl_elem";
343 else if (item->xfunc == &snd_hctl_ctl)
346 delete_tree(instance, args);
347 return &alsa_lisp_nil;
349 p1 = eval(instance, car(args));
350 delete_tree(instance, cdr(args));
351 delete_object(instance, args);
352 handle = (void *)get_ptr(instance, p1, item->prefix);
354 return &alsa_lisp_nil;
355 handle = ((snd_p_p_t)item->xfunc)(handle);
356 return new_cons_pointer(instance, prefix1, handle);
359 static struct alisp_object * FA_int_p(struct alisp_instance * instance, struct acall_table * item, struct alisp_object * args)
362 struct alisp_object * p1;
364 p1 = eval(instance, car(args));
365 delete_tree(instance, cdr(args));
366 delete_object(instance, args);
367 handle = (void *)get_ptr(instance, p1, item->prefix);
369 return &alsa_lisp_nil;
370 return new_integer(instance, ((snd_int_p_t)item->xfunc)(handle));
373 static struct alisp_object * FA_str_p(struct alisp_instance * instance, struct acall_table * item, struct alisp_object * args)
376 struct alisp_object * p1;
378 p1 = eval(instance, car(args));
379 delete_tree(instance, cdr(args));
380 delete_object(instance, args);
381 handle = (void *)get_ptr(instance, p1, item->prefix);
383 return &alsa_lisp_nil;
384 return new_string(instance, ((snd_str_p_t)item->xfunc)(handle));
387 static struct alisp_object * FA_int_intp(struct alisp_instance * instance, struct acall_table * item, struct alisp_object * args)
390 struct alisp_object * p1;
392 p1 = eval(instance, car(args));
393 delete_tree(instance, cdr(args));
394 delete_object(instance, args);
395 if (!alisp_compare_type(p1, ALISP_OBJ_INTEGER)) {
396 delete_tree(instance, p1);
397 return &alsa_lisp_nil;
400 delete_tree(instance, p1);
401 err = ((snd_int_intp_t)item->xfunc)(&val);
402 return new_result2(instance, err, val);
405 static struct alisp_object * FA_int_str(struct alisp_instance * instance, struct acall_table * item, struct alisp_object * args)
408 struct alisp_object * p1;
410 p1 = eval(instance, car(args));
411 delete_tree(instance, cdr(args));
412 delete_object(instance, args);
413 if (!alisp_compare_type(p1, ALISP_OBJ_STRING) &&
414 !alisp_compare_type(p1, ALISP_OBJ_IDENTIFIER)) {
415 delete_tree(instance, p1);
416 return &alsa_lisp_nil;
418 err = ((snd_int_str_t)item->xfunc)(p1->value.s);
419 delete_tree(instance, p1);
420 return new_integer(instance, err);
423 static struct alisp_object * FA_int_int_strp(struct alisp_instance * instance, struct acall_table * item, struct alisp_object * args)
428 struct alisp_object * p1;
430 p1 = eval(instance, car(args));
431 delete_tree(instance, cdr(args));
432 delete_object(instance, args);
433 if (!alisp_compare_type(p1, ALISP_OBJ_INTEGER)) {
434 delete_tree(instance, p1);
435 return &alsa_lisp_nil;
438 delete_tree(instance, p1);
439 err = ((snd_int_int_strp_t)item->xfunc)(val, &str);
440 return new_result3(instance, err, str);
443 static struct alisp_object * FA_card_info(struct alisp_instance * instance, struct acall_table * item, struct alisp_object * args)
446 struct alisp_object * lexpr, * p1;
447 snd_ctl_card_info_t * info;
450 p1 = eval(instance, car(args));
451 delete_tree(instance, cdr(args));
452 delete_object(instance, args);
453 handle = (snd_ctl_t *)get_ptr(instance, p1, item->prefix);
455 return &alsa_lisp_nil;
456 snd_ctl_card_info_alloca(&info);
457 err = snd_ctl_card_info(handle, info);
458 lexpr = new_lexpr(instance, err);
461 p1 = add_cons(instance, lexpr->value.c.cdr, 0, "id", new_string(instance, snd_ctl_card_info_get_id(info)));
462 p1 = add_cons(instance, p1, 1, "driver", new_string(instance, snd_ctl_card_info_get_driver(info)));
463 p1 = add_cons(instance, p1, 1, "name", new_string(instance, snd_ctl_card_info_get_name(info)));
464 p1 = add_cons(instance, p1, 1, "longname", new_string(instance, snd_ctl_card_info_get_longname(info)));
465 p1 = add_cons(instance, p1, 1, "mixername", new_string(instance, snd_ctl_card_info_get_mixername(info)));
466 p1 = add_cons(instance, p1, 1, "components", new_string(instance, snd_ctl_card_info_get_components(info)));
468 delete_tree(instance, lexpr);
474 static struct alisp_object * create_ctl_elem_id(struct alisp_instance * instance, snd_ctl_elem_id_t * id, struct alisp_object * cons)
476 cons = add_cons(instance, cons, 0, "numid", new_integer(instance, snd_ctl_elem_id_get_numid(id)));
477 cons = add_cons(instance, cons, 1, "iface", new_string(instance, snd_ctl_elem_iface_name(snd_ctl_elem_id_get_interface(id))));
478 cons = add_cons(instance, cons, 1, "dev", new_integer(instance, snd_ctl_elem_id_get_device(id)));
479 cons = add_cons(instance, cons, 1, "subdev", new_integer(instance, snd_ctl_elem_id_get_subdevice(id)));
480 cons = add_cons(instance, cons, 1, "name", new_string(instance, snd_ctl_elem_id_get_name(id)));
481 cons = add_cons(instance, cons, 1, "index", new_integer(instance, snd_ctl_elem_id_get_index(id)));
485 static int parse_ctl_elem_id(struct alisp_instance * instance,
486 struct alisp_object * cons,
487 snd_ctl_elem_id_t * id)
489 struct alisp_object *p1;
494 snd_ctl_elem_id_clear(id);
498 if (alisp_compare_type(p1, ALISP_OBJ_CONS)) {
499 xid = get_string(p1->value.c.car, NULL);
502 } else if (!strcmp(xid, "numid")) {
503 snd_ctl_elem_id_set_numid(id, get_integer(p1->value.c.cdr));
504 } else if (!strcmp(xid, "iface")) {
505 snd_ctl_elem_id_set_interface(id, snd_config_get_ctl_iface_ascii(get_string(p1->value.c.cdr, "0")));
506 } else if (!strcmp(xid, "dev")) {
507 snd_ctl_elem_id_set_device(id, get_integer(p1->value.c.cdr));
508 } else if (!strcmp(xid, "subdev")) {
509 snd_ctl_elem_id_set_subdevice(id, get_integer(p1->value.c.cdr));
510 } else if (!strcmp(xid, "name")) {
511 snd_ctl_elem_id_set_name(id, get_string(p1->value.c.cdr, "?"));
512 } else if (!strcmp(xid, "index")) {
513 snd_ctl_elem_id_set_index(id, get_integer(p1->value.c.cdr));
516 delete_tree(instance, p1);
517 cons = cdr(p1 = cons);
518 delete_object(instance, p1);
519 } while (cons != &alsa_lisp_nil);
523 static struct alisp_object * FA_hctl_find_elem(struct alisp_instance * instance, struct acall_table * item, struct alisp_object * args)
526 snd_ctl_elem_id_t *id;
527 struct alisp_object *p1;
529 handle = (snd_hctl_t *)get_ptr(instance, car(args), item->prefix);
530 if (handle == NULL) {
531 delete_tree(instance, cdr(args));
532 delete_object(instance, args);
533 return &alsa_lisp_nil;
535 snd_ctl_elem_id_alloca(&id);
537 delete_tree(instance, cdr(cdr(args)));
538 delete_object(instance, cdr(args));
539 delete_object(instance, args);
540 if (parse_ctl_elem_id(instance, eval(instance, p1), id) < 0)
541 return &alsa_lisp_nil;
542 return new_cons_pointer(instance, "hctl_elem", snd_hctl_find_elem(handle, id));
545 static struct alisp_object * FA_hctl_elem_info(struct alisp_instance * instance, struct acall_table * item, struct alisp_object * args)
547 snd_hctl_elem_t *handle;
548 struct alisp_object * lexpr, * p1, * p2;
549 snd_ctl_elem_info_t *info;
550 snd_ctl_elem_id_t *id;
551 snd_ctl_elem_type_t type;
554 p1 = eval(instance, car(args));
555 delete_tree(instance, cdr(args));
556 delete_object(instance, args);
557 handle = (snd_hctl_elem_t *)get_ptr(instance, p1, item->prefix);
559 return &alsa_lisp_nil;
560 snd_ctl_elem_info_alloca(&info);
561 snd_ctl_elem_id_alloca(&id);
562 err = snd_hctl_elem_info(handle, info);
563 lexpr = new_lexpr(instance, err);
566 type = snd_ctl_elem_info_get_type(info);
567 p1 = add_cons(instance, lexpr->value.c.cdr, 0, "id", p2 = new_object(instance, ALISP_OBJ_CONS));
568 snd_ctl_elem_info_get_id(info, id);
569 if (create_ctl_elem_id(instance, id, p2) == NULL) {
570 delete_tree(instance, lexpr);
573 p1 = add_cons(instance, p1, 1, "type", new_string(instance, snd_ctl_elem_type_name(type)));
574 p1 = add_cons(instance, p1, 1, "readable", new_integer(instance, snd_ctl_elem_info_is_readable(info)));
575 p1 = add_cons(instance, p1, 1, "writeable", new_integer(instance, snd_ctl_elem_info_is_writable(info)));
576 p1 = add_cons(instance, p1, 1, "volatile", new_integer(instance, snd_ctl_elem_info_is_volatile(info)));
577 p1 = add_cons(instance, p1, 1, "inactive", new_integer(instance, snd_ctl_elem_info_is_inactive(info)));
578 p1 = add_cons(instance, p1, 1, "locked", new_integer(instance, snd_ctl_elem_info_is_locked(info)));
579 p1 = add_cons(instance, p1, 1, "isowner", new_integer(instance, snd_ctl_elem_info_is_owner(info)));
580 p1 = add_cons(instance, p1, 1, "owner", new_integer(instance, snd_ctl_elem_info_get_owner(info)));
581 p1 = add_cons(instance, p1, 1, "count", new_integer(instance, snd_ctl_elem_info_get_count(info)));
582 err = snd_ctl_elem_info_get_dimensions(info);
585 p1 = add_cons(instance, p1, 1, "dimensions", p2 = new_object(instance, ALISP_OBJ_CONS));
586 for (idx = 0; idx < err; idx++)
587 p2 = add_cons2(instance, p2, idx > 0, new_integer(instance, snd_ctl_elem_info_get_dimension(info, idx)));
590 case SND_CTL_ELEM_TYPE_ENUMERATED: {
591 unsigned int items, item;
592 items = snd_ctl_elem_info_get_items(info);
593 p1 = add_cons(instance, p1, 1, "items", p2 = new_object(instance, ALISP_OBJ_CONS));
594 for (item = 0; item < items; item++) {
595 snd_ctl_elem_info_set_item(info, item);
596 err = snd_hctl_elem_info(handle, info);
598 p2 = add_cons2(instance, p2, item, &alsa_lisp_nil);
600 p2 = add_cons2(instance, p2, item, new_string(instance, snd_ctl_elem_info_get_item_name(info)));
605 case SND_CTL_ELEM_TYPE_INTEGER:
606 p1 = add_cons(instance, p1, 1, "min", new_integer(instance, snd_ctl_elem_info_get_min(info)));
607 p1 = add_cons(instance, p1, 1, "max", new_integer(instance, snd_ctl_elem_info_get_max(info)));
608 p1 = add_cons(instance, p1, 1, "step", new_integer(instance, snd_ctl_elem_info_get_step(info)));
610 case SND_CTL_ELEM_TYPE_INTEGER64:
611 p1 = add_cons(instance, p1, 1, "min64", new_float(instance, snd_ctl_elem_info_get_min64(info)));
612 p1 = add_cons(instance, p1, 1, "max64", new_float(instance, snd_ctl_elem_info_get_max64(info)));
613 p1 = add_cons(instance, p1, 1, "step64", new_float(instance, snd_ctl_elem_info_get_step64(info)));
619 delete_tree(instance, lexpr);
625 static struct alisp_object * FA_hctl_elem_read(struct alisp_instance * instance, struct acall_table * item, struct alisp_object * args)
627 snd_hctl_elem_t *handle;
628 struct alisp_object * lexpr, * p1 = NULL, * obj;
629 snd_ctl_elem_info_t *info;
630 snd_ctl_elem_value_t *value;
631 snd_ctl_elem_type_t type;
632 unsigned int idx, count;
635 p1 = eval(instance, car(args));
636 delete_tree(instance, cdr(args));
637 delete_object(instance, args);
638 handle = (snd_hctl_elem_t *)get_ptr(instance, p1, item->prefix);
640 return &alsa_lisp_nil;
641 snd_ctl_elem_info_alloca(&info);
642 snd_ctl_elem_value_alloca(&value);
643 err = snd_hctl_elem_info(handle, info);
645 err = snd_hctl_elem_read(handle, value);
646 lexpr = new_lexpr(instance, err);
649 type = snd_ctl_elem_info_get_type(info);
650 count = snd_ctl_elem_info_get_count(info);
651 if (type == SND_CTL_ELEM_TYPE_IEC958) {
652 count = sizeof(snd_aes_iec958_t);
653 type = SND_CTL_ELEM_TYPE_BYTES;
655 for (idx = 0; idx < count; idx++) {
657 case SND_CTL_ELEM_TYPE_BOOLEAN:
658 obj = new_integer(instance, snd_ctl_elem_value_get_boolean(value, idx));
660 case SND_CTL_ELEM_TYPE_INTEGER:
661 obj = new_integer(instance, snd_ctl_elem_value_get_integer(value, idx));
663 case SND_CTL_ELEM_TYPE_INTEGER64:
664 obj = new_integer(instance, snd_ctl_elem_value_get_integer64(value, idx));
666 case SND_CTL_ELEM_TYPE_ENUMERATED:
667 obj = new_integer(instance, snd_ctl_elem_value_get_enumerated(value, idx));
669 case SND_CTL_ELEM_TYPE_BYTES:
670 obj = new_integer(instance, snd_ctl_elem_value_get_byte(value, idx));
677 p1 = add_cons2(instance, lexpr->value.c.cdr, 0, obj);
679 p1 = add_cons2(instance, p1, 1, obj);
683 delete_tree(instance, lexpr);
684 return &alsa_lisp_nil;
689 static struct alisp_object * FA_hctl_elem_write(struct alisp_instance * instance, struct acall_table * item, struct alisp_object * args)
691 snd_hctl_elem_t *handle;
692 struct alisp_object * p1 = NULL, * obj;
693 snd_ctl_elem_info_t *info;
694 snd_ctl_elem_value_t *value;
695 snd_ctl_elem_type_t type;
696 unsigned int idx, count;
700 obj = eval(instance, car(args));
701 delete_tree(instance, cdr(cdr(args)));
702 delete_object(instance, cdr(args));
703 delete_object(instance, args);
704 handle = (snd_hctl_elem_t *)get_ptr(instance, obj, item->prefix);
705 if (handle == NULL) {
706 delete_tree(instance, p1);
707 return &alsa_lisp_nil;
709 snd_ctl_elem_info_alloca(&info);
710 snd_ctl_elem_value_alloca(&value);
711 err = snd_hctl_elem_info(handle, info);
713 delete_tree(instance, p1);
714 return new_integer(instance, err);
716 type = snd_ctl_elem_info_get_type(info);
717 count = snd_ctl_elem_info_get_count(info);
718 if (type == SND_CTL_ELEM_TYPE_IEC958) {
719 count = sizeof(snd_aes_iec958_t);
720 type = SND_CTL_ELEM_TYPE_BYTES;
724 if (++idx >= count) {
725 delete_tree(instance, p1);
730 case SND_CTL_ELEM_TYPE_BOOLEAN:
731 snd_ctl_elem_value_set_boolean(value, idx, get_integer(obj));
733 case SND_CTL_ELEM_TYPE_INTEGER:
734 snd_ctl_elem_value_set_integer(value, idx, get_integer(obj));
736 case SND_CTL_ELEM_TYPE_INTEGER64:
737 snd_ctl_elem_value_set_integer64(value, idx, get_integer(obj));
739 case SND_CTL_ELEM_TYPE_ENUMERATED:
740 snd_ctl_elem_value_set_enumerated(value, idx, get_integer(obj));
742 case SND_CTL_ELEM_TYPE_BYTES:
743 snd_ctl_elem_value_set_byte(value, idx, get_integer(obj));
748 delete_tree(instance, obj);
750 delete_object(instance, obj);
751 } while (p1 != &alsa_lisp_nil);
752 err = snd_hctl_elem_write(handle, value);
753 return new_integer(instance, err);
756 static struct alisp_object * FA_pcm_info(struct alisp_instance * instance, struct acall_table * item, struct alisp_object * args)
759 struct alisp_object * lexpr, * p1;
760 snd_pcm_info_t *info;
763 p1 = eval(instance, car(args));
764 delete_tree(instance, cdr(args));
765 delete_object(instance, args);
766 handle = (snd_pcm_t *)get_ptr(instance, p1, item->prefix);
768 return &alsa_lisp_nil;
769 snd_pcm_info_alloca(&info);
770 err = snd_pcm_info(handle, info);
771 lexpr = new_lexpr(instance, err);
774 p1 = add_cons(instance, lexpr->value.c.cdr, 0, "card", new_integer(instance, snd_pcm_info_get_card(info)));
775 p1 = add_cons(instance, p1, 1, "device", new_integer(instance, snd_pcm_info_get_device(info)));
776 p1 = add_cons(instance, p1, 1, "subdevice", new_integer(instance, snd_pcm_info_get_subdevice(info)));
777 p1 = add_cons(instance, p1, 1, "id", new_string(instance, snd_pcm_info_get_id(info)));
778 p1 = add_cons(instance, p1, 1, "name", new_string(instance, snd_pcm_info_get_name(info)));
779 p1 = add_cons(instance, p1, 1, "subdevice_name", new_string(instance, snd_pcm_info_get_subdevice_name(info)));
780 p1 = add_cons(instance, p1, 1, "class", new_integer(instance, snd_pcm_info_get_class(info)));
781 p1 = add_cons(instance, p1, 1, "subclass", new_integer(instance, snd_pcm_info_get_subclass(info)));
782 p1 = add_cons(instance, p1, 1, "subdevices_count", new_integer(instance, snd_pcm_info_get_subdevices_count(info)));
783 p1 = add_cons(instance, p1, 1, "subdevices_avail", new_integer(instance, snd_pcm_info_get_subdevices_avail(info)));
784 //p1 = add_cons(instance, p1, 1, "sync", new_string(instance, snd_pcm_info_get_sync(info)));
792 static struct acall_table acall_table[] = {
793 { "card_get_index", &FA_int_str, (void *)snd_card_get_index, NULL },
794 { "card_get_longname", &FA_int_int_strp, (void *)snd_card_get_longname, NULL },
795 { "card_get_name", &FA_int_int_strp, (void *)snd_card_get_name, NULL },
796 { "card_next", &FA_int_intp, (void *)&snd_card_next, NULL },
797 { "ctl_card_info", &FA_card_info, NULL, "ctl" },
798 { "ctl_close", &FA_int_p, (void *)&snd_ctl_close, "ctl" },
799 { "ctl_open", &FA_int_pp_strp_int, (void *)&snd_ctl_open, "ctl" },
800 { "hctl_close", &FA_int_p, (void *)&snd_hctl_close, "hctl" },
801 { "hctl_ctl", &FA_p_p, (void *)&snd_hctl_ctl, "hctl" },
802 { "hctl_elem_info", &FA_hctl_elem_info, (void *)&snd_hctl_elem_info, "hctl_elem" },
803 { "hctl_elem_next", &FA_p_p, (void *)&snd_hctl_elem_next, "hctl_elem" },
804 { "hctl_elem_prev", &FA_p_p, (void *)&snd_hctl_elem_prev, "hctl_elem" },
805 { "hctl_elem_read", &FA_hctl_elem_read, (void *)&snd_hctl_elem_read, "hctl_elem" },
806 { "hctl_elem_write", &FA_hctl_elem_write, (void *)&snd_hctl_elem_write, "hctl_elem" },
807 { "hctl_find_elem", &FA_hctl_find_elem, (void *)&snd_hctl_find_elem, "hctl" },
808 { "hctl_first_elem", &FA_p_p, (void *)&snd_hctl_first_elem, "hctl" },
809 { "hctl_free", &FA_int_p, (void *)&snd_hctl_free, "hctl" },
810 { "hctl_last_elem", &FA_p_p, (void *)&snd_hctl_last_elem, "hctl" },
811 { "hctl_load", &FA_int_p, (void *)&snd_hctl_load, "hctl" },
812 { "hctl_open", &FA_int_pp_strp_int, (void *)&snd_hctl_open, "hctl" },
813 { "hctl_open_ctl", &FA_int_pp_p, (void *)&snd_hctl_open_ctl, "hctl" },
814 { "pcm_info", &FA_pcm_info, NULL, "pcm" },
815 { "pcm_name", &FA_str_p, (void *)&snd_pcm_name, "pcm" },
818 static int acall_compar(const void *p1, const void *p2)
820 return strcmp(((struct acall_table *)p1)->name,
821 ((struct acall_table *)p2)->name);
824 static struct alisp_object * F_acall(struct alisp_instance *instance, struct alisp_object * args)
826 struct alisp_object * p1, *p2;
827 struct acall_table key, *item;
829 p1 = eval(instance, car(args));
831 delete_object(instance, args);
832 if (!alisp_compare_type(p1, ALISP_OBJ_IDENTIFIER) &&
833 !alisp_compare_type(p1, ALISP_OBJ_STRING)) {
834 delete_tree(instance, p2);
835 return &alsa_lisp_nil;
837 key.name = p1->value.s;
838 if ((item = bsearch(&key, acall_table,
839 sizeof acall_table / sizeof acall_table[0],
840 sizeof acall_table[0], acall_compar)) != NULL) {
841 delete_tree(instance, p1);
842 return item->func(instance, item, p2);
844 delete_tree(instance, p1);
845 delete_tree(instance, p2);
846 lisp_warn(instance, "acall function %s' is undefined", p1->value.s);
847 return &alsa_lisp_nil;
850 static struct alisp_object * F_ahandle(struct alisp_instance *instance, struct alisp_object * args)
852 struct alisp_object *p1;
854 p1 = eval(instance, car(args));
855 delete_tree(instance, cdr(args));
856 delete_object(instance, args);
858 delete_tree(instance, cdr(cdr(p1)));
859 delete_object(instance, cdr(p1));
860 delete_tree(instance, car(p1));
861 delete_object(instance, p1);
865 static struct alisp_object * F_aerror(struct alisp_instance *instance, struct alisp_object * args)
867 struct alisp_object *p1;
869 p1 = eval(instance, car(args));
870 delete_tree(instance, cdr(args));
871 delete_object(instance, args);
873 if (args == &alsa_lisp_nil) {
874 delete_tree(instance, p1);
875 return new_integer(instance, SND_ERROR_ALISP_NIL);
877 delete_tree(instance, cdr(p1));
878 delete_object(instance, p1);
883 static int common_error(snd_output_t **rout, struct alisp_instance *instance, struct alisp_object * args)
885 struct alisp_object * p = args, * p1;
889 err = snd_output_buffer_open(&out);
891 delete_tree(instance, args);
896 p1 = eval(instance, car(p));
897 if (alisp_compare_type(p1, ALISP_OBJ_STRING))
898 snd_output_printf(out, "%s", p1->value.s);
900 princ_object(out, p1);
901 delete_tree(instance, p1);
903 delete_object(instance, p1);
904 } while (p != &alsa_lisp_nil);
910 static struct alisp_object * F_snderr(struct alisp_instance *instance, struct alisp_object * args)
915 if (common_error(&out, instance, args) < 0)
916 return &alsa_lisp_nil;
917 snd_output_buffer_string(out, &str);
919 snd_output_close(out);
923 static struct alisp_object * F_syserr(struct alisp_instance *instance, struct alisp_object * args)
928 if (common_error(&out, instance, args) < 0)
929 return &alsa_lisp_nil;
930 snd_output_buffer_string(out, &str);
932 snd_output_close(out);
936 static struct intrinsic snd_intrinsics[] = {
937 { "Acall", F_acall },
938 { "Aerror", F_aerror },
939 { "Ahandle", F_ahandle },
940 { "Aresult", F_ahandle },
941 { "Asnderr", F_snderr },
942 { "Asyserr", F_syserr }