1d5ac70f0Sopenharmony_ci/*
2d5ac70f0Sopenharmony_ci *  ALSA lisp implementation - sound related commands
3d5ac70f0Sopenharmony_ci *  Copyright (c) 2003 by Jaroslav Kysela <perex@perex.cz>
4d5ac70f0Sopenharmony_ci *
5d5ac70f0Sopenharmony_ci *
6d5ac70f0Sopenharmony_ci *   This library is free software; you can redistribute it and/or modify
7d5ac70f0Sopenharmony_ci *   it under the terms of the GNU Lesser General Public License as
8d5ac70f0Sopenharmony_ci *   published by the Free Software Foundation; either version 2.1 of
9d5ac70f0Sopenharmony_ci *   the License, or (at your option) any later version.
10d5ac70f0Sopenharmony_ci *
11d5ac70f0Sopenharmony_ci *   This program is distributed in the hope that it will be useful,
12d5ac70f0Sopenharmony_ci *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13d5ac70f0Sopenharmony_ci *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14d5ac70f0Sopenharmony_ci *   GNU Lesser General Public License for more details.
15d5ac70f0Sopenharmony_ci *
16d5ac70f0Sopenharmony_ci *   You should have received a copy of the GNU Lesser General Public
17d5ac70f0Sopenharmony_ci *   License along with this library; if not, write to the Free Software
18d5ac70f0Sopenharmony_ci *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19d5ac70f0Sopenharmony_ci *
20d5ac70f0Sopenharmony_ci */
21d5ac70f0Sopenharmony_ci
22d5ac70f0Sopenharmony_ci#include "../control/control_local.h"
23d5ac70f0Sopenharmony_ci
24d5ac70f0Sopenharmony_cistruct acall_table {
25d5ac70f0Sopenharmony_ci	const char *name;
26d5ac70f0Sopenharmony_ci	struct alisp_object * (*func) (struct alisp_instance *instance, struct acall_table * item, struct alisp_object * args);
27d5ac70f0Sopenharmony_ci	void * xfunc;
28d5ac70f0Sopenharmony_ci	const char *prefix;
29d5ac70f0Sopenharmony_ci};
30d5ac70f0Sopenharmony_ci
31d5ac70f0Sopenharmony_ci/*
32d5ac70f0Sopenharmony_ci *  helper functions
33d5ac70f0Sopenharmony_ci */
34d5ac70f0Sopenharmony_ci
35d5ac70f0Sopenharmony_cistatic inline int get_integer(struct alisp_object * obj)
36d5ac70f0Sopenharmony_ci{
37d5ac70f0Sopenharmony_ci	if (alisp_compare_type(obj, ALISP_OBJ_INTEGER))
38d5ac70f0Sopenharmony_ci		return obj->value.i;
39d5ac70f0Sopenharmony_ci	return 0;
40d5ac70f0Sopenharmony_ci}
41d5ac70f0Sopenharmony_ci
42d5ac70f0Sopenharmony_cistatic inline const void *get_pointer(struct alisp_object * obj)
43d5ac70f0Sopenharmony_ci{
44d5ac70f0Sopenharmony_ci	if (alisp_compare_type(obj, ALISP_OBJ_POINTER))
45d5ac70f0Sopenharmony_ci		return obj->value.ptr;
46d5ac70f0Sopenharmony_ci	return NULL;
47d5ac70f0Sopenharmony_ci}
48d5ac70f0Sopenharmony_ci
49d5ac70f0Sopenharmony_cistatic const char *get_string(struct alisp_object * obj, const char * deflt)
50d5ac70f0Sopenharmony_ci{
51d5ac70f0Sopenharmony_ci	if (obj == &alsa_lisp_t)
52d5ac70f0Sopenharmony_ci		return "true";
53d5ac70f0Sopenharmony_ci	if (alisp_compare_type(obj, ALISP_OBJ_STRING) ||
54d5ac70f0Sopenharmony_ci	    alisp_compare_type(obj, ALISP_OBJ_IDENTIFIER))
55d5ac70f0Sopenharmony_ci		return obj->value.s;
56d5ac70f0Sopenharmony_ci	return deflt;
57d5ac70f0Sopenharmony_ci}
58d5ac70f0Sopenharmony_ci
59d5ac70f0Sopenharmony_cistruct flags {
60d5ac70f0Sopenharmony_ci	const char *key;
61d5ac70f0Sopenharmony_ci	unsigned int mask;
62d5ac70f0Sopenharmony_ci};
63d5ac70f0Sopenharmony_ci
64d5ac70f0Sopenharmony_cistatic unsigned int get_flags(struct alisp_instance * instance,
65d5ac70f0Sopenharmony_ci			      struct alisp_object * obj,
66d5ac70f0Sopenharmony_ci			      const struct flags * flags,
67d5ac70f0Sopenharmony_ci			      unsigned int deflt)
68d5ac70f0Sopenharmony_ci{
69d5ac70f0Sopenharmony_ci	const char *key;
70d5ac70f0Sopenharmony_ci	int invert;
71d5ac70f0Sopenharmony_ci	unsigned int result;
72d5ac70f0Sopenharmony_ci	const struct flags *ptr;
73d5ac70f0Sopenharmony_ci	struct alisp_object *n;
74d5ac70f0Sopenharmony_ci
75d5ac70f0Sopenharmony_ci	if (obj == &alsa_lisp_nil)
76d5ac70f0Sopenharmony_ci		return deflt;
77d5ac70f0Sopenharmony_ci	result = deflt;
78d5ac70f0Sopenharmony_ci	do {
79d5ac70f0Sopenharmony_ci		key = get_string(obj, NULL);
80d5ac70f0Sopenharmony_ci		if (key) {
81d5ac70f0Sopenharmony_ci			invert = key[0] == '!';
82d5ac70f0Sopenharmony_ci			key += invert;
83d5ac70f0Sopenharmony_ci			ptr = flags;
84d5ac70f0Sopenharmony_ci			while (ptr->key) {
85d5ac70f0Sopenharmony_ci				if (!strcmp(ptr->key, key)) {
86d5ac70f0Sopenharmony_ci					if (invert)
87d5ac70f0Sopenharmony_ci						result &= ~ptr->mask;
88d5ac70f0Sopenharmony_ci					else
89d5ac70f0Sopenharmony_ci						result |= ptr->mask;
90d5ac70f0Sopenharmony_ci					break;
91d5ac70f0Sopenharmony_ci				}
92d5ac70f0Sopenharmony_ci				ptr++;
93d5ac70f0Sopenharmony_ci			}
94d5ac70f0Sopenharmony_ci		}
95d5ac70f0Sopenharmony_ci		delete_tree(instance, car(obj));
96d5ac70f0Sopenharmony_ci		obj = cdr(n = obj);
97d5ac70f0Sopenharmony_ci		delete_object(instance, n);
98d5ac70f0Sopenharmony_ci	} while (obj != &alsa_lisp_nil);
99d5ac70f0Sopenharmony_ci	return result;
100d5ac70f0Sopenharmony_ci}
101d5ac70f0Sopenharmony_ci
102d5ac70f0Sopenharmony_cistatic const void *get_ptr(struct alisp_instance * instance,
103d5ac70f0Sopenharmony_ci			   struct alisp_object * obj,
104d5ac70f0Sopenharmony_ci			   const char *_ptr_id)
105d5ac70f0Sopenharmony_ci{
106d5ac70f0Sopenharmony_ci	const char *ptr_id;
107d5ac70f0Sopenharmony_ci	const void *ptr;
108d5ac70f0Sopenharmony_ci
109d5ac70f0Sopenharmony_ci	ptr_id = get_string(car(obj), NULL);
110d5ac70f0Sopenharmony_ci	if (ptr_id == NULL) {
111d5ac70f0Sopenharmony_ci		delete_tree(instance, obj);
112d5ac70f0Sopenharmony_ci		return NULL;
113d5ac70f0Sopenharmony_ci	}
114d5ac70f0Sopenharmony_ci	if (strcmp(ptr_id, _ptr_id)) {
115d5ac70f0Sopenharmony_ci		delete_tree(instance, obj);
116d5ac70f0Sopenharmony_ci		return NULL;
117d5ac70f0Sopenharmony_ci	}
118d5ac70f0Sopenharmony_ci	ptr = get_pointer(cdr(obj));
119d5ac70f0Sopenharmony_ci	delete_tree(instance, obj);
120d5ac70f0Sopenharmony_ci	return ptr;
121d5ac70f0Sopenharmony_ci}
122d5ac70f0Sopenharmony_ci
123d5ac70f0Sopenharmony_cistatic struct alisp_object * new_lexpr(struct alisp_instance * instance, int err)
124d5ac70f0Sopenharmony_ci{
125d5ac70f0Sopenharmony_ci	struct alisp_object * lexpr;
126d5ac70f0Sopenharmony_ci
127d5ac70f0Sopenharmony_ci	lexpr = new_object(instance, ALISP_OBJ_CONS);
128d5ac70f0Sopenharmony_ci	if (lexpr == NULL)
129d5ac70f0Sopenharmony_ci		return NULL;
130d5ac70f0Sopenharmony_ci	lexpr->value.c.car = new_integer(instance, err);
131d5ac70f0Sopenharmony_ci	if (lexpr->value.c.car == NULL) {
132d5ac70f0Sopenharmony_ci		delete_object(instance, lexpr);
133d5ac70f0Sopenharmony_ci		return NULL;
134d5ac70f0Sopenharmony_ci	}
135d5ac70f0Sopenharmony_ci	lexpr->value.c.cdr = new_object(instance, ALISP_OBJ_CONS);
136d5ac70f0Sopenharmony_ci	if (lexpr->value.c.cdr == NULL) {
137d5ac70f0Sopenharmony_ci		delete_object(instance, lexpr->value.c.car);
138d5ac70f0Sopenharmony_ci		delete_object(instance, lexpr);
139d5ac70f0Sopenharmony_ci		return NULL;
140d5ac70f0Sopenharmony_ci	}
141d5ac70f0Sopenharmony_ci	return lexpr;
142d5ac70f0Sopenharmony_ci}
143d5ac70f0Sopenharmony_ci
144d5ac70f0Sopenharmony_cistatic struct alisp_object * add_cons(struct alisp_instance * instance,
145d5ac70f0Sopenharmony_ci				      struct alisp_object *lexpr,
146d5ac70f0Sopenharmony_ci				      int cdr, const char *id,
147d5ac70f0Sopenharmony_ci				      struct alisp_object *obj)
148d5ac70f0Sopenharmony_ci{
149d5ac70f0Sopenharmony_ci	struct alisp_object * p1, * p2;
150d5ac70f0Sopenharmony_ci
151d5ac70f0Sopenharmony_ci	if (lexpr == NULL || obj == NULL) {
152d5ac70f0Sopenharmony_ci		delete_tree(instance, obj);
153d5ac70f0Sopenharmony_ci		return NULL;
154d5ac70f0Sopenharmony_ci	}
155d5ac70f0Sopenharmony_ci	if (cdr) {
156d5ac70f0Sopenharmony_ci		p1 = lexpr->value.c.cdr = new_object(instance, ALISP_OBJ_CONS);
157d5ac70f0Sopenharmony_ci	} else {
158d5ac70f0Sopenharmony_ci		p1 = lexpr->value.c.car = new_object(instance, ALISP_OBJ_CONS);
159d5ac70f0Sopenharmony_ci	}
160d5ac70f0Sopenharmony_ci	lexpr = p1;
161d5ac70f0Sopenharmony_ci	if (p1 == NULL) {
162d5ac70f0Sopenharmony_ci		delete_tree(instance, obj);
163d5ac70f0Sopenharmony_ci		return NULL;
164d5ac70f0Sopenharmony_ci	}
165d5ac70f0Sopenharmony_ci	p1->value.c.car = new_object(instance, ALISP_OBJ_CONS);
166d5ac70f0Sopenharmony_ci	if ((p2 = p1->value.c.car) == NULL)
167d5ac70f0Sopenharmony_ci		goto __err;
168d5ac70f0Sopenharmony_ci	p2->value.c.car = new_string(instance, id);
169d5ac70f0Sopenharmony_ci	if (p2->value.c.car == NULL) {
170d5ac70f0Sopenharmony_ci	      __err:
171d5ac70f0Sopenharmony_ci		if (cdr)
172d5ac70f0Sopenharmony_ci			lexpr->value.c.cdr = NULL;
173d5ac70f0Sopenharmony_ci		else
174d5ac70f0Sopenharmony_ci			lexpr->value.c.car = NULL;
175d5ac70f0Sopenharmony_ci		delete_tree(instance, p1);
176d5ac70f0Sopenharmony_ci		delete_tree(instance, obj);
177d5ac70f0Sopenharmony_ci		return NULL;
178d5ac70f0Sopenharmony_ci	}
179d5ac70f0Sopenharmony_ci	p2->value.c.cdr = obj;
180d5ac70f0Sopenharmony_ci	return lexpr;
181d5ac70f0Sopenharmony_ci}
182d5ac70f0Sopenharmony_ci
183d5ac70f0Sopenharmony_cistatic struct alisp_object * add_cons2(struct alisp_instance * instance,
184d5ac70f0Sopenharmony_ci				       struct alisp_object *lexpr,
185d5ac70f0Sopenharmony_ci				       int cdr, struct alisp_object *obj)
186d5ac70f0Sopenharmony_ci{
187d5ac70f0Sopenharmony_ci	struct alisp_object * p1;
188d5ac70f0Sopenharmony_ci
189d5ac70f0Sopenharmony_ci	if (lexpr == NULL || obj == NULL) {
190d5ac70f0Sopenharmony_ci		delete_tree(instance, obj);
191d5ac70f0Sopenharmony_ci		return NULL;
192d5ac70f0Sopenharmony_ci	}
193d5ac70f0Sopenharmony_ci	if (cdr) {
194d5ac70f0Sopenharmony_ci		p1 = lexpr->value.c.cdr = new_object(instance, ALISP_OBJ_CONS);
195d5ac70f0Sopenharmony_ci	} else {
196d5ac70f0Sopenharmony_ci		p1 = lexpr->value.c.car = new_object(instance, ALISP_OBJ_CONS);
197d5ac70f0Sopenharmony_ci	}
198d5ac70f0Sopenharmony_ci	lexpr = p1;
199d5ac70f0Sopenharmony_ci	if (p1 == NULL) {
200d5ac70f0Sopenharmony_ci		delete_tree(instance, obj);
201d5ac70f0Sopenharmony_ci		return NULL;
202d5ac70f0Sopenharmony_ci	}
203d5ac70f0Sopenharmony_ci	p1->value.c.car = obj;
204d5ac70f0Sopenharmony_ci	return lexpr;
205d5ac70f0Sopenharmony_ci}
206d5ac70f0Sopenharmony_ci
207d5ac70f0Sopenharmony_cistatic struct alisp_object * new_result1(struct alisp_instance * instance,
208d5ac70f0Sopenharmony_ci					 int err, const char *ptr_id, void *ptr)
209d5ac70f0Sopenharmony_ci{
210d5ac70f0Sopenharmony_ci	struct alisp_object * lexpr, * p1;
211d5ac70f0Sopenharmony_ci
212d5ac70f0Sopenharmony_ci	if (err < 0)
213d5ac70f0Sopenharmony_ci		ptr = NULL;
214d5ac70f0Sopenharmony_ci	lexpr = new_object(instance, ALISP_OBJ_CONS);
215d5ac70f0Sopenharmony_ci	if (lexpr == NULL)
216d5ac70f0Sopenharmony_ci		return NULL;
217d5ac70f0Sopenharmony_ci	lexpr->value.c.car = new_integer(instance, err);
218d5ac70f0Sopenharmony_ci	if (lexpr->value.c.car == NULL) {
219d5ac70f0Sopenharmony_ci		delete_object(instance, lexpr);
220d5ac70f0Sopenharmony_ci		return NULL;
221d5ac70f0Sopenharmony_ci	}
222d5ac70f0Sopenharmony_ci	p1 = add_cons(instance, lexpr, 1, ptr_id, new_pointer(instance, ptr));
223d5ac70f0Sopenharmony_ci	if (p1 == NULL) {
224d5ac70f0Sopenharmony_ci		delete_object(instance, lexpr);
225d5ac70f0Sopenharmony_ci		return NULL;
226d5ac70f0Sopenharmony_ci	}
227d5ac70f0Sopenharmony_ci	return lexpr;
228d5ac70f0Sopenharmony_ci}
229d5ac70f0Sopenharmony_ci
230d5ac70f0Sopenharmony_cistatic struct alisp_object * new_result2(struct alisp_instance * instance,
231d5ac70f0Sopenharmony_ci					 int err, int val)
232d5ac70f0Sopenharmony_ci{
233d5ac70f0Sopenharmony_ci	struct alisp_object * lexpr, * p1;
234d5ac70f0Sopenharmony_ci
235d5ac70f0Sopenharmony_ci	if (err < 0)
236d5ac70f0Sopenharmony_ci		val = 0;
237d5ac70f0Sopenharmony_ci	lexpr = new_lexpr(instance, err);
238d5ac70f0Sopenharmony_ci	if (lexpr == NULL)
239d5ac70f0Sopenharmony_ci		return NULL;
240d5ac70f0Sopenharmony_ci	p1 = lexpr->value.c.cdr;
241d5ac70f0Sopenharmony_ci	p1->value.c.car = new_integer(instance, val);
242d5ac70f0Sopenharmony_ci	if (p1->value.c.car == NULL) {
243d5ac70f0Sopenharmony_ci		delete_object(instance, lexpr);
244d5ac70f0Sopenharmony_ci		return NULL;
245d5ac70f0Sopenharmony_ci	}
246d5ac70f0Sopenharmony_ci	return lexpr;
247d5ac70f0Sopenharmony_ci}
248d5ac70f0Sopenharmony_ci
249d5ac70f0Sopenharmony_cistatic struct alisp_object * new_result3(struct alisp_instance * instance,
250d5ac70f0Sopenharmony_ci					 int err, const char *str)
251d5ac70f0Sopenharmony_ci{
252d5ac70f0Sopenharmony_ci	struct alisp_object * lexpr, * p1;
253d5ac70f0Sopenharmony_ci
254d5ac70f0Sopenharmony_ci	if (err < 0)
255d5ac70f0Sopenharmony_ci		str = "";
256d5ac70f0Sopenharmony_ci	lexpr = new_lexpr(instance, err);
257d5ac70f0Sopenharmony_ci	if (lexpr == NULL)
258d5ac70f0Sopenharmony_ci		return NULL;
259d5ac70f0Sopenharmony_ci	p1 = lexpr->value.c.cdr;
260d5ac70f0Sopenharmony_ci	p1->value.c.car = new_string(instance, str);
261d5ac70f0Sopenharmony_ci	if (p1->value.c.car == NULL) {
262d5ac70f0Sopenharmony_ci		delete_object(instance, lexpr);
263d5ac70f0Sopenharmony_ci		return NULL;
264d5ac70f0Sopenharmony_ci	}
265d5ac70f0Sopenharmony_ci	return lexpr;
266d5ac70f0Sopenharmony_ci}
267d5ac70f0Sopenharmony_ci
268d5ac70f0Sopenharmony_ci/*
269d5ac70f0Sopenharmony_ci *  macros
270d5ac70f0Sopenharmony_ci */
271d5ac70f0Sopenharmony_ci
272d5ac70f0Sopenharmony_ci/*
273d5ac70f0Sopenharmony_ci *  HCTL functions
274d5ac70f0Sopenharmony_ci */
275d5ac70f0Sopenharmony_ci
276d5ac70f0Sopenharmony_citypedef int (*snd_int_pp_strp_int_t)(void **rctl, const char *name, int mode);
277d5ac70f0Sopenharmony_citypedef int (*snd_int_pp_p_t)(void **rctl, void *handle);
278d5ac70f0Sopenharmony_citypedef int (*snd_int_p_t)(void *rctl);
279d5ac70f0Sopenharmony_citypedef char * (*snd_str_p_t)(void *rctl);
280d5ac70f0Sopenharmony_citypedef int (*snd_int_intp_t)(int *val);
281d5ac70f0Sopenharmony_citypedef int (*snd_int_str_t)(const char *str);
282d5ac70f0Sopenharmony_citypedef int (*snd_int_int_strp_t)(int val, char **str);
283d5ac70f0Sopenharmony_citypedef void *(*snd_p_p_t)(void *handle);
284d5ac70f0Sopenharmony_ci
285d5ac70f0Sopenharmony_cistatic struct alisp_object * FA_int_pp_strp_int(struct alisp_instance * instance, struct acall_table * item, struct alisp_object * args)
286d5ac70f0Sopenharmony_ci{
287d5ac70f0Sopenharmony_ci	const char *name;
288d5ac70f0Sopenharmony_ci	int err, mode;
289d5ac70f0Sopenharmony_ci	void *handle;
290d5ac70f0Sopenharmony_ci	struct alisp_object *p1, *p2;
291d5ac70f0Sopenharmony_ci	static const struct flags flags[] = {
292d5ac70f0Sopenharmony_ci		{ "nonblock", SND_CTL_NONBLOCK },
293d5ac70f0Sopenharmony_ci		{ "async", SND_CTL_ASYNC },
294d5ac70f0Sopenharmony_ci		{ "readonly", SND_CTL_READONLY },
295d5ac70f0Sopenharmony_ci		{ NULL, 0 }
296d5ac70f0Sopenharmony_ci	};
297d5ac70f0Sopenharmony_ci
298d5ac70f0Sopenharmony_ci	name = get_string(p1 = eval(instance, car(args)), NULL);
299d5ac70f0Sopenharmony_ci	if (name == NULL)
300d5ac70f0Sopenharmony_ci		return &alsa_lisp_nil;
301d5ac70f0Sopenharmony_ci	mode = get_flags(instance, p2 = eval(instance, car(cdr(args))), flags, 0);
302d5ac70f0Sopenharmony_ci	delete_tree(instance, cdr(cdr(args)));
303d5ac70f0Sopenharmony_ci	delete_object(instance, cdr(args));
304d5ac70f0Sopenharmony_ci	delete_object(instance, args);
305d5ac70f0Sopenharmony_ci	delete_tree(instance, p2);
306d5ac70f0Sopenharmony_ci	err = ((snd_int_pp_strp_int_t)item->xfunc)(&handle, name, mode);
307d5ac70f0Sopenharmony_ci	delete_tree(instance, p1);
308d5ac70f0Sopenharmony_ci	return new_result1(instance, err, item->prefix, handle);
309d5ac70f0Sopenharmony_ci}
310d5ac70f0Sopenharmony_ci
311d5ac70f0Sopenharmony_cistatic struct alisp_object * FA_int_pp_p(struct alisp_instance * instance, struct acall_table * item, struct alisp_object * args)
312d5ac70f0Sopenharmony_ci{
313d5ac70f0Sopenharmony_ci	int err;
314d5ac70f0Sopenharmony_ci	void *handle;
315d5ac70f0Sopenharmony_ci	const char *prefix1;
316d5ac70f0Sopenharmony_ci	struct alisp_object *p1;
317d5ac70f0Sopenharmony_ci
318d5ac70f0Sopenharmony_ci	if (item->xfunc == &snd_hctl_open_ctl)
319d5ac70f0Sopenharmony_ci		prefix1 = "ctl";
320d5ac70f0Sopenharmony_ci	else {
321d5ac70f0Sopenharmony_ci		delete_tree(instance, args);
322d5ac70f0Sopenharmony_ci		return &alsa_lisp_nil;
323d5ac70f0Sopenharmony_ci	}
324d5ac70f0Sopenharmony_ci	p1 = eval(instance, car(args));
325d5ac70f0Sopenharmony_ci	delete_tree(instance, cdr(args));
326d5ac70f0Sopenharmony_ci	delete_object(instance, args);
327d5ac70f0Sopenharmony_ci	handle = (void *)get_ptr(instance, p1, prefix1);
328d5ac70f0Sopenharmony_ci	if (handle == NULL)
329d5ac70f0Sopenharmony_ci		return &alsa_lisp_nil;
330d5ac70f0Sopenharmony_ci	err = ((snd_int_pp_p_t)item->xfunc)(&handle, handle);
331d5ac70f0Sopenharmony_ci	return new_result1(instance, err, item->prefix, handle);
332d5ac70f0Sopenharmony_ci}
333d5ac70f0Sopenharmony_ci
334d5ac70f0Sopenharmony_cistatic struct alisp_object * FA_p_p(struct alisp_instance * instance, struct acall_table * item, struct alisp_object * args)
335d5ac70f0Sopenharmony_ci{
336d5ac70f0Sopenharmony_ci	void *handle;
337d5ac70f0Sopenharmony_ci	const char *prefix1;
338d5ac70f0Sopenharmony_ci	struct alisp_object * p1;
339d5ac70f0Sopenharmony_ci
340d5ac70f0Sopenharmony_ci	if (item->xfunc == &snd_hctl_first_elem ||
341d5ac70f0Sopenharmony_ci	    item->xfunc == &snd_hctl_last_elem ||
342d5ac70f0Sopenharmony_ci	    item->xfunc == &snd_hctl_elem_next ||
343d5ac70f0Sopenharmony_ci	    item->xfunc == &snd_hctl_elem_prev)
344d5ac70f0Sopenharmony_ci		prefix1 = "hctl_elem";
345d5ac70f0Sopenharmony_ci	else if (item->xfunc == &snd_hctl_ctl)
346d5ac70f0Sopenharmony_ci		prefix1 = "ctl";
347d5ac70f0Sopenharmony_ci	else {
348d5ac70f0Sopenharmony_ci		delete_tree(instance, args);
349d5ac70f0Sopenharmony_ci		return &alsa_lisp_nil;
350d5ac70f0Sopenharmony_ci	}
351d5ac70f0Sopenharmony_ci	p1 = eval(instance, car(args));
352d5ac70f0Sopenharmony_ci	delete_tree(instance, cdr(args));
353d5ac70f0Sopenharmony_ci	delete_object(instance, args);
354d5ac70f0Sopenharmony_ci	handle = (void *)get_ptr(instance, p1, item->prefix);
355d5ac70f0Sopenharmony_ci	if (handle == NULL)
356d5ac70f0Sopenharmony_ci		return &alsa_lisp_nil;
357d5ac70f0Sopenharmony_ci	handle = ((snd_p_p_t)item->xfunc)(handle);
358d5ac70f0Sopenharmony_ci	return new_cons_pointer(instance, prefix1, handle);
359d5ac70f0Sopenharmony_ci}
360d5ac70f0Sopenharmony_ci
361d5ac70f0Sopenharmony_cistatic struct alisp_object * FA_int_p(struct alisp_instance * instance, struct acall_table * item, struct alisp_object * args)
362d5ac70f0Sopenharmony_ci{
363d5ac70f0Sopenharmony_ci	void *handle;
364d5ac70f0Sopenharmony_ci	struct alisp_object * p1;
365d5ac70f0Sopenharmony_ci
366d5ac70f0Sopenharmony_ci	p1 = eval(instance, car(args));
367d5ac70f0Sopenharmony_ci	delete_tree(instance, cdr(args));
368d5ac70f0Sopenharmony_ci	delete_object(instance, args);
369d5ac70f0Sopenharmony_ci	handle = (void *)get_ptr(instance, p1, item->prefix);
370d5ac70f0Sopenharmony_ci	if (handle == NULL)
371d5ac70f0Sopenharmony_ci		return &alsa_lisp_nil;
372d5ac70f0Sopenharmony_ci	return new_integer(instance, ((snd_int_p_t)item->xfunc)(handle));
373d5ac70f0Sopenharmony_ci}
374d5ac70f0Sopenharmony_ci
375d5ac70f0Sopenharmony_cistatic struct alisp_object * FA_str_p(struct alisp_instance * instance, struct acall_table * item, struct alisp_object * args)
376d5ac70f0Sopenharmony_ci{
377d5ac70f0Sopenharmony_ci	void *handle;
378d5ac70f0Sopenharmony_ci	struct alisp_object * p1;
379d5ac70f0Sopenharmony_ci
380d5ac70f0Sopenharmony_ci	p1 = eval(instance, car(args));
381d5ac70f0Sopenharmony_ci	delete_tree(instance, cdr(args));
382d5ac70f0Sopenharmony_ci	delete_object(instance, args);
383d5ac70f0Sopenharmony_ci	handle = (void *)get_ptr(instance, p1, item->prefix);
384d5ac70f0Sopenharmony_ci	if (handle == NULL)
385d5ac70f0Sopenharmony_ci		return &alsa_lisp_nil;
386d5ac70f0Sopenharmony_ci	return new_string(instance, ((snd_str_p_t)item->xfunc)(handle));
387d5ac70f0Sopenharmony_ci}
388d5ac70f0Sopenharmony_ci
389d5ac70f0Sopenharmony_cistatic struct alisp_object * FA_int_intp(struct alisp_instance * instance, struct acall_table * item, struct alisp_object * args)
390d5ac70f0Sopenharmony_ci{
391d5ac70f0Sopenharmony_ci	int val, err;
392d5ac70f0Sopenharmony_ci	struct alisp_object * p1;
393d5ac70f0Sopenharmony_ci
394d5ac70f0Sopenharmony_ci	p1 = eval(instance, car(args));
395d5ac70f0Sopenharmony_ci	delete_tree(instance, cdr(args));
396d5ac70f0Sopenharmony_ci	delete_object(instance, args);
397d5ac70f0Sopenharmony_ci	if (!alisp_compare_type(p1, ALISP_OBJ_INTEGER)) {
398d5ac70f0Sopenharmony_ci		delete_tree(instance, p1);
399d5ac70f0Sopenharmony_ci		return &alsa_lisp_nil;
400d5ac70f0Sopenharmony_ci	}
401d5ac70f0Sopenharmony_ci	val = p1->value.i;
402d5ac70f0Sopenharmony_ci	delete_tree(instance, p1);
403d5ac70f0Sopenharmony_ci	err = ((snd_int_intp_t)item->xfunc)(&val);
404d5ac70f0Sopenharmony_ci	return new_result2(instance, err, val);
405d5ac70f0Sopenharmony_ci}
406d5ac70f0Sopenharmony_ci
407d5ac70f0Sopenharmony_cistatic struct alisp_object * FA_int_str(struct alisp_instance * instance, struct acall_table * item, struct alisp_object * args)
408d5ac70f0Sopenharmony_ci{
409d5ac70f0Sopenharmony_ci	int err;
410d5ac70f0Sopenharmony_ci	struct alisp_object * p1;
411d5ac70f0Sopenharmony_ci
412d5ac70f0Sopenharmony_ci	p1 = eval(instance, car(args));
413d5ac70f0Sopenharmony_ci	delete_tree(instance, cdr(args));
414d5ac70f0Sopenharmony_ci	delete_object(instance, args);
415d5ac70f0Sopenharmony_ci	if (!alisp_compare_type(p1, ALISP_OBJ_STRING) &&
416d5ac70f0Sopenharmony_ci	    !alisp_compare_type(p1, ALISP_OBJ_IDENTIFIER)) {
417d5ac70f0Sopenharmony_ci		delete_tree(instance, p1);
418d5ac70f0Sopenharmony_ci		return &alsa_lisp_nil;
419d5ac70f0Sopenharmony_ci	}
420d5ac70f0Sopenharmony_ci	err = ((snd_int_str_t)item->xfunc)(p1->value.s);
421d5ac70f0Sopenharmony_ci	delete_tree(instance, p1);
422d5ac70f0Sopenharmony_ci	return new_integer(instance, err);
423d5ac70f0Sopenharmony_ci}
424d5ac70f0Sopenharmony_ci
425d5ac70f0Sopenharmony_cistatic struct alisp_object * FA_int_int_strp(struct alisp_instance * instance, struct acall_table * item, struct alisp_object * args)
426d5ac70f0Sopenharmony_ci{
427d5ac70f0Sopenharmony_ci	int err;
428d5ac70f0Sopenharmony_ci	char *str;
429d5ac70f0Sopenharmony_ci	long val;
430d5ac70f0Sopenharmony_ci	struct alisp_object * p1;
431d5ac70f0Sopenharmony_ci
432d5ac70f0Sopenharmony_ci	p1 = eval(instance, car(args));
433d5ac70f0Sopenharmony_ci	delete_tree(instance, cdr(args));
434d5ac70f0Sopenharmony_ci	delete_object(instance, args);
435d5ac70f0Sopenharmony_ci	if (!alisp_compare_type(p1, ALISP_OBJ_INTEGER)) {
436d5ac70f0Sopenharmony_ci		delete_tree(instance, p1);
437d5ac70f0Sopenharmony_ci		return &alsa_lisp_nil;
438d5ac70f0Sopenharmony_ci	}
439d5ac70f0Sopenharmony_ci	val = p1->value.i;
440d5ac70f0Sopenharmony_ci	delete_tree(instance, p1);
441d5ac70f0Sopenharmony_ci	err = ((snd_int_int_strp_t)item->xfunc)(val, &str);
442d5ac70f0Sopenharmony_ci	return new_result3(instance, err, str);
443d5ac70f0Sopenharmony_ci}
444d5ac70f0Sopenharmony_ci
445d5ac70f0Sopenharmony_cistatic struct alisp_object * FA_card_info(struct alisp_instance * instance, struct acall_table * item, struct alisp_object * args)
446d5ac70f0Sopenharmony_ci{
447d5ac70f0Sopenharmony_ci	snd_ctl_t *handle;
448d5ac70f0Sopenharmony_ci	struct alisp_object * lexpr, * p1;
449d5ac70f0Sopenharmony_ci	snd_ctl_card_info_t info = {0};
450d5ac70f0Sopenharmony_ci	int err;
451d5ac70f0Sopenharmony_ci
452d5ac70f0Sopenharmony_ci	p1 = eval(instance, car(args));
453d5ac70f0Sopenharmony_ci	delete_tree(instance, cdr(args));
454d5ac70f0Sopenharmony_ci	delete_object(instance, args);
455d5ac70f0Sopenharmony_ci	handle = (snd_ctl_t *)get_ptr(instance, p1, item->prefix);
456d5ac70f0Sopenharmony_ci	if (handle == NULL)
457d5ac70f0Sopenharmony_ci		return &alsa_lisp_nil;
458d5ac70f0Sopenharmony_ci	err = snd_ctl_card_info(handle, &info);
459d5ac70f0Sopenharmony_ci	lexpr = new_lexpr(instance, err);
460d5ac70f0Sopenharmony_ci	if (err < 0)
461d5ac70f0Sopenharmony_ci		return lexpr;
462d5ac70f0Sopenharmony_ci	p1 = add_cons(instance, lexpr->value.c.cdr, 0, "id", new_string(instance, snd_ctl_card_info_get_id(&info)));
463d5ac70f0Sopenharmony_ci	p1 = add_cons(instance, p1, 1, "driver", new_string(instance, snd_ctl_card_info_get_driver(&info)));
464d5ac70f0Sopenharmony_ci	p1 = add_cons(instance, p1, 1, "name", new_string(instance, snd_ctl_card_info_get_name(&info)));
465d5ac70f0Sopenharmony_ci	p1 = add_cons(instance, p1, 1, "longname", new_string(instance, snd_ctl_card_info_get_longname(&info)));
466d5ac70f0Sopenharmony_ci	p1 = add_cons(instance, p1, 1, "mixername", new_string(instance, snd_ctl_card_info_get_mixername(&info)));
467d5ac70f0Sopenharmony_ci	p1 = add_cons(instance, p1, 1, "components", new_string(instance, snd_ctl_card_info_get_components(&info)));
468d5ac70f0Sopenharmony_ci	if (p1 == NULL) {
469d5ac70f0Sopenharmony_ci		delete_tree(instance, lexpr);
470d5ac70f0Sopenharmony_ci		return NULL;
471d5ac70f0Sopenharmony_ci	}
472d5ac70f0Sopenharmony_ci	return lexpr;
473d5ac70f0Sopenharmony_ci}
474d5ac70f0Sopenharmony_ci
475d5ac70f0Sopenharmony_cistatic struct alisp_object * create_ctl_elem_id(struct alisp_instance * instance, snd_ctl_elem_id_t * id, struct alisp_object * cons)
476d5ac70f0Sopenharmony_ci{
477d5ac70f0Sopenharmony_ci	cons = add_cons(instance, cons, 0, "numid", new_integer(instance, snd_ctl_elem_id_get_numid(id)));
478d5ac70f0Sopenharmony_ci	cons = add_cons(instance, cons, 1, "iface", new_string(instance, snd_ctl_elem_iface_name(snd_ctl_elem_id_get_interface(id))));
479d5ac70f0Sopenharmony_ci	cons = add_cons(instance, cons, 1, "dev", new_integer(instance, snd_ctl_elem_id_get_device(id)));
480d5ac70f0Sopenharmony_ci	cons = add_cons(instance, cons, 1, "subdev", new_integer(instance, snd_ctl_elem_id_get_subdevice(id)));
481d5ac70f0Sopenharmony_ci	cons = add_cons(instance, cons, 1, "name", new_string(instance, snd_ctl_elem_id_get_name(id)));
482d5ac70f0Sopenharmony_ci	cons = add_cons(instance, cons, 1, "index", new_integer(instance, snd_ctl_elem_id_get_index(id)));
483d5ac70f0Sopenharmony_ci	return cons;
484d5ac70f0Sopenharmony_ci}
485d5ac70f0Sopenharmony_ci
486d5ac70f0Sopenharmony_cistatic int parse_ctl_elem_id(struct alisp_instance * instance,
487d5ac70f0Sopenharmony_ci			     struct alisp_object * cons,
488d5ac70f0Sopenharmony_ci			     snd_ctl_elem_id_t * id)
489d5ac70f0Sopenharmony_ci{
490d5ac70f0Sopenharmony_ci	struct alisp_object *p1;
491d5ac70f0Sopenharmony_ci	const char *xid;
492d5ac70f0Sopenharmony_ci
493d5ac70f0Sopenharmony_ci	if (cons == NULL)
494d5ac70f0Sopenharmony_ci		return -ENOMEM;
495d5ac70f0Sopenharmony_ci	snd_ctl_elem_id_clear(id);
496d5ac70f0Sopenharmony_ci	id->numid = 0;
497d5ac70f0Sopenharmony_ci	do {
498d5ac70f0Sopenharmony_ci		p1 = car(cons);
499d5ac70f0Sopenharmony_ci		if (alisp_compare_type(p1, ALISP_OBJ_CONS)) {
500d5ac70f0Sopenharmony_ci			xid = get_string(p1->value.c.car, NULL);
501d5ac70f0Sopenharmony_ci			if (xid == NULL) {
502d5ac70f0Sopenharmony_ci				/* noop */
503d5ac70f0Sopenharmony_ci			} else if (!strcmp(xid, "numid")) {
504d5ac70f0Sopenharmony_ci				snd_ctl_elem_id_set_numid(id, get_integer(p1->value.c.cdr));
505d5ac70f0Sopenharmony_ci			} else if (!strcmp(xid, "iface")) {
506d5ac70f0Sopenharmony_ci				snd_ctl_elem_id_set_interface(id, snd_config_get_ctl_iface_ascii(get_string(p1->value.c.cdr, "0")));
507d5ac70f0Sopenharmony_ci			} else if (!strcmp(xid, "dev")) {
508d5ac70f0Sopenharmony_ci				snd_ctl_elem_id_set_device(id, get_integer(p1->value.c.cdr));
509d5ac70f0Sopenharmony_ci			} else if (!strcmp(xid, "subdev")) {
510d5ac70f0Sopenharmony_ci				snd_ctl_elem_id_set_subdevice(id, get_integer(p1->value.c.cdr));
511d5ac70f0Sopenharmony_ci			} else if (!strcmp(xid, "name")) {
512d5ac70f0Sopenharmony_ci				snd_ctl_elem_id_set_name(id, get_string(p1->value.c.cdr, "?"));
513d5ac70f0Sopenharmony_ci			} else if (!strcmp(xid, "index")) {
514d5ac70f0Sopenharmony_ci				snd_ctl_elem_id_set_index(id, get_integer(p1->value.c.cdr));
515d5ac70f0Sopenharmony_ci			}
516d5ac70f0Sopenharmony_ci		}
517d5ac70f0Sopenharmony_ci		delete_tree(instance, p1);
518d5ac70f0Sopenharmony_ci	        cons = cdr(p1 = cons);
519d5ac70f0Sopenharmony_ci	        delete_object(instance, p1);
520d5ac70f0Sopenharmony_ci	} while (cons != &alsa_lisp_nil);
521d5ac70f0Sopenharmony_ci	return 0;
522d5ac70f0Sopenharmony_ci}
523d5ac70f0Sopenharmony_ci
524d5ac70f0Sopenharmony_cistatic struct alisp_object * FA_hctl_find_elem(struct alisp_instance * instance, struct acall_table * item, struct alisp_object * args)
525d5ac70f0Sopenharmony_ci{
526d5ac70f0Sopenharmony_ci	snd_hctl_t *handle;
527d5ac70f0Sopenharmony_ci	snd_ctl_elem_id_t id = {0};
528d5ac70f0Sopenharmony_ci	struct alisp_object *p1;
529d5ac70f0Sopenharmony_ci
530d5ac70f0Sopenharmony_ci	handle = (snd_hctl_t *)get_ptr(instance, car(args), item->prefix);
531d5ac70f0Sopenharmony_ci	if (handle == NULL) {
532d5ac70f0Sopenharmony_ci		delete_tree(instance, cdr(args));
533d5ac70f0Sopenharmony_ci		delete_object(instance, args);
534d5ac70f0Sopenharmony_ci		return &alsa_lisp_nil;
535d5ac70f0Sopenharmony_ci	}
536d5ac70f0Sopenharmony_ci	p1 = car(cdr(args));
537d5ac70f0Sopenharmony_ci	delete_tree(instance, cdr(cdr(args)));
538d5ac70f0Sopenharmony_ci	delete_object(instance, cdr(args));
539d5ac70f0Sopenharmony_ci	delete_object(instance, args);
540d5ac70f0Sopenharmony_ci	if (parse_ctl_elem_id(instance, eval(instance, p1), &id) < 0)
541d5ac70f0Sopenharmony_ci		return &alsa_lisp_nil;
542d5ac70f0Sopenharmony_ci	return new_cons_pointer(instance, "hctl_elem", snd_hctl_find_elem(handle, &id));
543d5ac70f0Sopenharmony_ci}
544d5ac70f0Sopenharmony_ci
545d5ac70f0Sopenharmony_cistatic struct alisp_object * FA_hctl_elem_info(struct alisp_instance * instance, struct acall_table * item, struct alisp_object * args)
546d5ac70f0Sopenharmony_ci{
547d5ac70f0Sopenharmony_ci	snd_hctl_elem_t *handle;
548d5ac70f0Sopenharmony_ci	struct alisp_object * lexpr, * p1, * p2;
549d5ac70f0Sopenharmony_ci	snd_ctl_elem_info_t info = {0};
550d5ac70f0Sopenharmony_ci	snd_ctl_elem_id_t id = {0};
551d5ac70f0Sopenharmony_ci	snd_ctl_elem_type_t type;
552d5ac70f0Sopenharmony_ci	int err;
553d5ac70f0Sopenharmony_ci
554d5ac70f0Sopenharmony_ci	p1 = eval(instance, car(args));
555d5ac70f0Sopenharmony_ci	delete_tree(instance, cdr(args));
556d5ac70f0Sopenharmony_ci	delete_object(instance, args);
557d5ac70f0Sopenharmony_ci	handle = (snd_hctl_elem_t *)get_ptr(instance, p1, item->prefix);
558d5ac70f0Sopenharmony_ci	if (handle == NULL)
559d5ac70f0Sopenharmony_ci		return &alsa_lisp_nil;
560d5ac70f0Sopenharmony_ci	err = snd_hctl_elem_info(handle, &info);
561d5ac70f0Sopenharmony_ci	lexpr = new_lexpr(instance, err);
562d5ac70f0Sopenharmony_ci	if (err < 0)
563d5ac70f0Sopenharmony_ci		return lexpr;
564d5ac70f0Sopenharmony_ci	type = snd_ctl_elem_info_get_type(&info);
565d5ac70f0Sopenharmony_ci	p1 = add_cons(instance, lexpr->value.c.cdr, 0, "id", p2 = new_object(instance, ALISP_OBJ_CONS));
566d5ac70f0Sopenharmony_ci	snd_ctl_elem_info_get_id(&info, &id);
567d5ac70f0Sopenharmony_ci	if (create_ctl_elem_id(instance, &id, p2) == NULL) {
568d5ac70f0Sopenharmony_ci		delete_tree(instance, lexpr);
569d5ac70f0Sopenharmony_ci		return NULL;
570d5ac70f0Sopenharmony_ci	}
571d5ac70f0Sopenharmony_ci	p1 = add_cons(instance, p1, 1, "type", new_string(instance, snd_ctl_elem_type_name(type)));
572d5ac70f0Sopenharmony_ci	p1 = add_cons(instance, p1, 1, "readable", new_integer(instance, snd_ctl_elem_info_is_readable(&info)));
573d5ac70f0Sopenharmony_ci	p1 = add_cons(instance, p1, 1, "writable", new_integer(instance, snd_ctl_elem_info_is_writable(&info)));
574d5ac70f0Sopenharmony_ci	p1 = add_cons(instance, p1, 1, "volatile", new_integer(instance, snd_ctl_elem_info_is_volatile(&info)));
575d5ac70f0Sopenharmony_ci	p1 = add_cons(instance, p1, 1, "inactive", new_integer(instance, snd_ctl_elem_info_is_inactive(&info)));
576d5ac70f0Sopenharmony_ci	p1 = add_cons(instance, p1, 1, "locked", new_integer(instance, snd_ctl_elem_info_is_locked(&info)));
577d5ac70f0Sopenharmony_ci	p1 = add_cons(instance, p1, 1, "isowner", new_integer(instance, snd_ctl_elem_info_is_owner(&info)));
578d5ac70f0Sopenharmony_ci	p1 = add_cons(instance, p1, 1, "owner", new_integer(instance, snd_ctl_elem_info_get_owner(&info)));
579d5ac70f0Sopenharmony_ci	p1 = add_cons(instance, p1, 1, "count", new_integer(instance, snd_ctl_elem_info_get_count(&info)));
580d5ac70f0Sopenharmony_ci	err = INTERNAL(snd_ctl_elem_info_get_dimensions)(&info);
581d5ac70f0Sopenharmony_ci	if (err > 0) {
582d5ac70f0Sopenharmony_ci		int idx;
583d5ac70f0Sopenharmony_ci		p1 = add_cons(instance, p1, 1, "dimensions", p2 = new_object(instance, ALISP_OBJ_CONS));
584d5ac70f0Sopenharmony_ci		for (idx = 0; idx < err; idx++)
585d5ac70f0Sopenharmony_ci			p2 = add_cons2(instance, p2, idx > 0, new_integer(instance, INTERNAL(snd_ctl_elem_info_get_dimension)(&info, idx)));
586d5ac70f0Sopenharmony_ci	}
587d5ac70f0Sopenharmony_ci	switch (type) {
588d5ac70f0Sopenharmony_ci	case SND_CTL_ELEM_TYPE_ENUMERATED: {
589d5ac70f0Sopenharmony_ci		unsigned int items, item;
590d5ac70f0Sopenharmony_ci		items = snd_ctl_elem_info_get_items(&info);
591d5ac70f0Sopenharmony_ci		p1 = add_cons(instance, p1, 1, "items", p2 = new_object(instance, ALISP_OBJ_CONS));
592d5ac70f0Sopenharmony_ci		for (item = 0; item < items; item++) {
593d5ac70f0Sopenharmony_ci			snd_ctl_elem_info_set_item(&info, item);
594d5ac70f0Sopenharmony_ci			err = snd_hctl_elem_info(handle, &info);
595d5ac70f0Sopenharmony_ci			if (err < 0) {
596d5ac70f0Sopenharmony_ci				p2 = add_cons2(instance, p2, item, &alsa_lisp_nil);
597d5ac70f0Sopenharmony_ci			} else {
598d5ac70f0Sopenharmony_ci				p2 = add_cons2(instance, p2, item, new_string(instance, snd_ctl_elem_info_get_item_name(&info)));
599d5ac70f0Sopenharmony_ci			}
600d5ac70f0Sopenharmony_ci		}
601d5ac70f0Sopenharmony_ci		break;
602d5ac70f0Sopenharmony_ci	}
603d5ac70f0Sopenharmony_ci	case SND_CTL_ELEM_TYPE_INTEGER:
604d5ac70f0Sopenharmony_ci		p1 = add_cons(instance, p1, 1, "min", new_integer(instance, snd_ctl_elem_info_get_min(&info)));
605d5ac70f0Sopenharmony_ci		p1 = add_cons(instance, p1, 1, "max", new_integer(instance, snd_ctl_elem_info_get_max(&info)));
606d5ac70f0Sopenharmony_ci		p1 = add_cons(instance, p1, 1, "step", new_integer(instance, snd_ctl_elem_info_get_step(&info)));
607d5ac70f0Sopenharmony_ci		break;
608d5ac70f0Sopenharmony_ci	case SND_CTL_ELEM_TYPE_INTEGER64:
609d5ac70f0Sopenharmony_ci		p1 = add_cons(instance, p1, 1, "min64", new_float(instance, snd_ctl_elem_info_get_min64(&info)));
610d5ac70f0Sopenharmony_ci		p1 = add_cons(instance, p1, 1, "max64", new_float(instance, snd_ctl_elem_info_get_max64(&info)));
611d5ac70f0Sopenharmony_ci		p1 = add_cons(instance, p1, 1, "step64", new_float(instance, snd_ctl_elem_info_get_step64(&info)));
612d5ac70f0Sopenharmony_ci		break;
613d5ac70f0Sopenharmony_ci	default:
614d5ac70f0Sopenharmony_ci		break;
615d5ac70f0Sopenharmony_ci	}
616d5ac70f0Sopenharmony_ci	if (p1 == NULL) {
617d5ac70f0Sopenharmony_ci		delete_tree(instance, lexpr);
618d5ac70f0Sopenharmony_ci		return NULL;
619d5ac70f0Sopenharmony_ci	}
620d5ac70f0Sopenharmony_ci	return lexpr;
621d5ac70f0Sopenharmony_ci}
622d5ac70f0Sopenharmony_ci
623d5ac70f0Sopenharmony_cistatic struct alisp_object * FA_hctl_elem_read(struct alisp_instance * instance, struct acall_table * item, struct alisp_object * args)
624d5ac70f0Sopenharmony_ci{
625d5ac70f0Sopenharmony_ci	snd_hctl_elem_t *handle;
626d5ac70f0Sopenharmony_ci	struct alisp_object * lexpr, * p1 = NULL, * obj;
627d5ac70f0Sopenharmony_ci	snd_ctl_elem_info_t info = {0};
628d5ac70f0Sopenharmony_ci	snd_ctl_elem_value_t value = {0};
629d5ac70f0Sopenharmony_ci	snd_ctl_elem_type_t type;
630d5ac70f0Sopenharmony_ci	unsigned int idx, count;
631d5ac70f0Sopenharmony_ci	int err;
632d5ac70f0Sopenharmony_ci
633d5ac70f0Sopenharmony_ci	p1 = eval(instance, car(args));
634d5ac70f0Sopenharmony_ci	delete_tree(instance, cdr(args));
635d5ac70f0Sopenharmony_ci	delete_object(instance, args);
636d5ac70f0Sopenharmony_ci	handle = (snd_hctl_elem_t *)get_ptr(instance, p1, item->prefix);
637d5ac70f0Sopenharmony_ci	if (handle == NULL)
638d5ac70f0Sopenharmony_ci		return &alsa_lisp_nil;
639d5ac70f0Sopenharmony_ci	err = snd_hctl_elem_info(handle, &info);
640d5ac70f0Sopenharmony_ci	if (err >= 0)
641d5ac70f0Sopenharmony_ci		err = snd_hctl_elem_read(handle, &value);
642d5ac70f0Sopenharmony_ci	lexpr = new_lexpr(instance, err);
643d5ac70f0Sopenharmony_ci	if (err < 0)
644d5ac70f0Sopenharmony_ci		return lexpr;
645d5ac70f0Sopenharmony_ci	type = snd_ctl_elem_info_get_type(&info);
646d5ac70f0Sopenharmony_ci	count = snd_ctl_elem_info_get_count(&info);
647d5ac70f0Sopenharmony_ci	if (type == SND_CTL_ELEM_TYPE_IEC958) {
648d5ac70f0Sopenharmony_ci		count = sizeof(snd_aes_iec958_t);
649d5ac70f0Sopenharmony_ci		type = SND_CTL_ELEM_TYPE_BYTES;
650d5ac70f0Sopenharmony_ci	}
651d5ac70f0Sopenharmony_ci	for (idx = 0; idx < count; idx++) {
652d5ac70f0Sopenharmony_ci		switch (type) {
653d5ac70f0Sopenharmony_ci		case SND_CTL_ELEM_TYPE_BOOLEAN:
654d5ac70f0Sopenharmony_ci			obj = new_integer(instance, snd_ctl_elem_value_get_boolean(&value, idx));
655d5ac70f0Sopenharmony_ci			break;
656d5ac70f0Sopenharmony_ci		case SND_CTL_ELEM_TYPE_INTEGER:
657d5ac70f0Sopenharmony_ci			obj = new_integer(instance, snd_ctl_elem_value_get_integer(&value, idx));
658d5ac70f0Sopenharmony_ci			break;
659d5ac70f0Sopenharmony_ci		case SND_CTL_ELEM_TYPE_INTEGER64:
660d5ac70f0Sopenharmony_ci			obj = new_integer(instance, snd_ctl_elem_value_get_integer64(&value, idx));
661d5ac70f0Sopenharmony_ci			break;
662d5ac70f0Sopenharmony_ci		case SND_CTL_ELEM_TYPE_ENUMERATED:
663d5ac70f0Sopenharmony_ci			obj = new_integer(instance, snd_ctl_elem_value_get_enumerated(&value, idx));
664d5ac70f0Sopenharmony_ci			break;
665d5ac70f0Sopenharmony_ci		case SND_CTL_ELEM_TYPE_BYTES:
666d5ac70f0Sopenharmony_ci			obj = new_integer(instance, snd_ctl_elem_value_get_byte(&value, idx));
667d5ac70f0Sopenharmony_ci			break;
668d5ac70f0Sopenharmony_ci		default:
669d5ac70f0Sopenharmony_ci			obj = NULL;
670d5ac70f0Sopenharmony_ci			break;
671d5ac70f0Sopenharmony_ci		}
672d5ac70f0Sopenharmony_ci		if (idx == 0) {
673d5ac70f0Sopenharmony_ci			p1 = add_cons2(instance, lexpr->value.c.cdr, 0, obj);
674d5ac70f0Sopenharmony_ci		} else {
675d5ac70f0Sopenharmony_ci			p1 = add_cons2(instance, p1, 1, obj);
676d5ac70f0Sopenharmony_ci		}
677d5ac70f0Sopenharmony_ci	}
678d5ac70f0Sopenharmony_ci	if (p1 == NULL) {
679d5ac70f0Sopenharmony_ci		delete_tree(instance, lexpr);
680d5ac70f0Sopenharmony_ci		return &alsa_lisp_nil;
681d5ac70f0Sopenharmony_ci	}
682d5ac70f0Sopenharmony_ci	return lexpr;
683d5ac70f0Sopenharmony_ci}
684d5ac70f0Sopenharmony_ci
685d5ac70f0Sopenharmony_cistatic struct alisp_object * FA_hctl_elem_write(struct alisp_instance * instance, struct acall_table * item, struct alisp_object * args)
686d5ac70f0Sopenharmony_ci{
687d5ac70f0Sopenharmony_ci	snd_hctl_elem_t *handle;
688d5ac70f0Sopenharmony_ci	struct alisp_object * p1 = NULL, * obj;
689d5ac70f0Sopenharmony_ci	snd_ctl_elem_info_t info = {0};
690d5ac70f0Sopenharmony_ci	snd_ctl_elem_value_t value = {0};
691d5ac70f0Sopenharmony_ci	snd_ctl_elem_type_t type;
692d5ac70f0Sopenharmony_ci	unsigned int idx, count;
693d5ac70f0Sopenharmony_ci	int err;
694d5ac70f0Sopenharmony_ci
695d5ac70f0Sopenharmony_ci	p1 = car(cdr(args));
696d5ac70f0Sopenharmony_ci	obj = eval(instance, car(args));
697d5ac70f0Sopenharmony_ci	delete_tree(instance, cdr(cdr(args)));
698d5ac70f0Sopenharmony_ci	delete_object(instance, cdr(args));
699d5ac70f0Sopenharmony_ci	delete_object(instance, args);
700d5ac70f0Sopenharmony_ci	handle = (snd_hctl_elem_t *)get_ptr(instance, obj, item->prefix);
701d5ac70f0Sopenharmony_ci	if (handle == NULL) {
702d5ac70f0Sopenharmony_ci		delete_tree(instance, p1);
703d5ac70f0Sopenharmony_ci		return &alsa_lisp_nil;
704d5ac70f0Sopenharmony_ci	}
705d5ac70f0Sopenharmony_ci	err = snd_hctl_elem_info(handle, &info);
706d5ac70f0Sopenharmony_ci	if (err < 0) {
707d5ac70f0Sopenharmony_ci		delete_tree(instance, p1);
708d5ac70f0Sopenharmony_ci		return new_integer(instance, err);
709d5ac70f0Sopenharmony_ci	}
710d5ac70f0Sopenharmony_ci	type = snd_ctl_elem_info_get_type(&info);
711d5ac70f0Sopenharmony_ci	count = snd_ctl_elem_info_get_count(&info);
712d5ac70f0Sopenharmony_ci	if (type == SND_CTL_ELEM_TYPE_IEC958) {
713d5ac70f0Sopenharmony_ci		count = sizeof(snd_aes_iec958_t);
714d5ac70f0Sopenharmony_ci		type = SND_CTL_ELEM_TYPE_BYTES;
715d5ac70f0Sopenharmony_ci	}
716d5ac70f0Sopenharmony_ci	idx = -1;
717d5ac70f0Sopenharmony_ci	do {
718d5ac70f0Sopenharmony_ci		if (++idx >= count) {
719d5ac70f0Sopenharmony_ci			delete_tree(instance, p1);
720d5ac70f0Sopenharmony_ci			break;
721d5ac70f0Sopenharmony_ci		}
722d5ac70f0Sopenharmony_ci		obj = car(p1);
723d5ac70f0Sopenharmony_ci		switch (type) {
724d5ac70f0Sopenharmony_ci		case SND_CTL_ELEM_TYPE_BOOLEAN:
725d5ac70f0Sopenharmony_ci			snd_ctl_elem_value_set_boolean(&value, idx, get_integer(obj));
726d5ac70f0Sopenharmony_ci			break;
727d5ac70f0Sopenharmony_ci		case SND_CTL_ELEM_TYPE_INTEGER:
728d5ac70f0Sopenharmony_ci			snd_ctl_elem_value_set_integer(&value, idx, get_integer(obj));
729d5ac70f0Sopenharmony_ci			break;
730d5ac70f0Sopenharmony_ci		case SND_CTL_ELEM_TYPE_INTEGER64:
731d5ac70f0Sopenharmony_ci			snd_ctl_elem_value_set_integer64(&value, idx, get_integer(obj));
732d5ac70f0Sopenharmony_ci			break;
733d5ac70f0Sopenharmony_ci		case SND_CTL_ELEM_TYPE_ENUMERATED:
734d5ac70f0Sopenharmony_ci			snd_ctl_elem_value_set_enumerated(&value, idx, get_integer(obj));
735d5ac70f0Sopenharmony_ci			break;
736d5ac70f0Sopenharmony_ci		case SND_CTL_ELEM_TYPE_BYTES:
737d5ac70f0Sopenharmony_ci			snd_ctl_elem_value_set_byte(&value, idx, get_integer(obj));
738d5ac70f0Sopenharmony_ci			break;
739d5ac70f0Sopenharmony_ci		default:
740d5ac70f0Sopenharmony_ci			break;
741d5ac70f0Sopenharmony_ci		}
742d5ac70f0Sopenharmony_ci		delete_tree(instance, obj);
743d5ac70f0Sopenharmony_ci		p1 = cdr(obj = p1);
744d5ac70f0Sopenharmony_ci		delete_object(instance, obj);
745d5ac70f0Sopenharmony_ci	} while (p1 != &alsa_lisp_nil);
746d5ac70f0Sopenharmony_ci	err = snd_hctl_elem_write(handle, &value);
747d5ac70f0Sopenharmony_ci	return new_integer(instance, err);
748d5ac70f0Sopenharmony_ci}
749d5ac70f0Sopenharmony_ci
750d5ac70f0Sopenharmony_cistatic struct alisp_object * FA_pcm_info(struct alisp_instance * instance, struct acall_table * item, struct alisp_object * args)
751d5ac70f0Sopenharmony_ci{
752d5ac70f0Sopenharmony_ci	snd_pcm_t *handle;
753d5ac70f0Sopenharmony_ci	struct alisp_object * lexpr, * p1;
754d5ac70f0Sopenharmony_ci	snd_pcm_info_t info = {0};
755d5ac70f0Sopenharmony_ci	int err;
756d5ac70f0Sopenharmony_ci
757d5ac70f0Sopenharmony_ci	p1 = eval(instance, car(args));
758d5ac70f0Sopenharmony_ci	delete_tree(instance, cdr(args));
759d5ac70f0Sopenharmony_ci	delete_object(instance, args);
760d5ac70f0Sopenharmony_ci	handle = (snd_pcm_t *)get_ptr(instance, p1, item->prefix);
761d5ac70f0Sopenharmony_ci	if (handle == NULL)
762d5ac70f0Sopenharmony_ci		return &alsa_lisp_nil;
763d5ac70f0Sopenharmony_ci	err = snd_pcm_info(handle, &info);
764d5ac70f0Sopenharmony_ci	lexpr = new_lexpr(instance, err);
765d5ac70f0Sopenharmony_ci	if (err < 0)
766d5ac70f0Sopenharmony_ci		return lexpr;
767d5ac70f0Sopenharmony_ci	p1 = add_cons(instance, lexpr->value.c.cdr, 0, "card", new_integer(instance, snd_pcm_info_get_card(&info)));
768d5ac70f0Sopenharmony_ci	p1 = add_cons(instance, p1, 1, "device", new_integer(instance, snd_pcm_info_get_device(&info)));
769d5ac70f0Sopenharmony_ci	p1 = add_cons(instance, p1, 1, "subdevice", new_integer(instance, snd_pcm_info_get_subdevice(&info)));
770d5ac70f0Sopenharmony_ci	p1 = add_cons(instance, p1, 1, "id", new_string(instance, snd_pcm_info_get_id(&info)));
771d5ac70f0Sopenharmony_ci	p1 = add_cons(instance, p1, 1, "name", new_string(instance, snd_pcm_info_get_name(&info)));
772d5ac70f0Sopenharmony_ci	p1 = add_cons(instance, p1, 1, "subdevice_name", new_string(instance, snd_pcm_info_get_subdevice_name(&info)));
773d5ac70f0Sopenharmony_ci	p1 = add_cons(instance, p1, 1, "class", new_integer(instance, snd_pcm_info_get_class(&info)));
774d5ac70f0Sopenharmony_ci	p1 = add_cons(instance, p1, 1, "subclass", new_integer(instance, snd_pcm_info_get_subclass(&info)));
775d5ac70f0Sopenharmony_ci	p1 = add_cons(instance, p1, 1, "subdevices_count", new_integer(instance, snd_pcm_info_get_subdevices_count(&info)));
776d5ac70f0Sopenharmony_ci	p1 = add_cons(instance, p1, 1, "subdevices_avail", new_integer(instance, snd_pcm_info_get_subdevices_avail(&info)));
777d5ac70f0Sopenharmony_ci	//p1 = add_cons(instance, p1, 1, "sync", new_string(instance, snd_pcm_info_get_sync(&info)));
778d5ac70f0Sopenharmony_ci	return lexpr;
779d5ac70f0Sopenharmony_ci}
780d5ac70f0Sopenharmony_ci
781d5ac70f0Sopenharmony_ci/*
782d5ac70f0Sopenharmony_ci *  main code
783d5ac70f0Sopenharmony_ci */
784d5ac70f0Sopenharmony_ci
785d5ac70f0Sopenharmony_cistatic const struct acall_table acall_table[] = {
786d5ac70f0Sopenharmony_ci	{ "card_get_index", &FA_int_str, (void *)snd_card_get_index, NULL },
787d5ac70f0Sopenharmony_ci	{ "card_get_longname", &FA_int_int_strp, (void *)snd_card_get_longname, NULL },
788d5ac70f0Sopenharmony_ci	{ "card_get_name", &FA_int_int_strp, (void *)snd_card_get_name, NULL },
789d5ac70f0Sopenharmony_ci	{ "card_next", &FA_int_intp, (void *)&snd_card_next, NULL },
790d5ac70f0Sopenharmony_ci	{ "ctl_card_info", &FA_card_info, NULL, "ctl" },
791d5ac70f0Sopenharmony_ci	{ "ctl_close", &FA_int_p, (void *)&snd_ctl_close, "ctl" },
792d5ac70f0Sopenharmony_ci	{ "ctl_open", &FA_int_pp_strp_int, (void *)&snd_ctl_open, "ctl" },
793d5ac70f0Sopenharmony_ci	{ "hctl_close", &FA_int_p, (void *)&snd_hctl_close, "hctl" },
794d5ac70f0Sopenharmony_ci	{ "hctl_ctl", &FA_p_p, (void *)&snd_hctl_ctl, "hctl" },
795d5ac70f0Sopenharmony_ci	{ "hctl_elem_info", &FA_hctl_elem_info, (void *)&snd_hctl_elem_info, "hctl_elem" },
796d5ac70f0Sopenharmony_ci	{ "hctl_elem_next", &FA_p_p, (void *)&snd_hctl_elem_next, "hctl_elem" },
797d5ac70f0Sopenharmony_ci	{ "hctl_elem_prev", &FA_p_p, (void *)&snd_hctl_elem_prev, "hctl_elem" },
798d5ac70f0Sopenharmony_ci	{ "hctl_elem_read", &FA_hctl_elem_read, (void *)&snd_hctl_elem_read, "hctl_elem" },
799d5ac70f0Sopenharmony_ci	{ "hctl_elem_write", &FA_hctl_elem_write, (void *)&snd_hctl_elem_write, "hctl_elem" },
800d5ac70f0Sopenharmony_ci	{ "hctl_find_elem", &FA_hctl_find_elem, (void *)&snd_hctl_find_elem, "hctl" },
801d5ac70f0Sopenharmony_ci	{ "hctl_first_elem", &FA_p_p, (void *)&snd_hctl_first_elem, "hctl" },
802d5ac70f0Sopenharmony_ci	{ "hctl_free", &FA_int_p, (void *)&snd_hctl_free, "hctl" },
803d5ac70f0Sopenharmony_ci	{ "hctl_last_elem", &FA_p_p, (void *)&snd_hctl_last_elem, "hctl" },
804d5ac70f0Sopenharmony_ci	{ "hctl_load", &FA_int_p, (void *)&snd_hctl_load, "hctl" },
805d5ac70f0Sopenharmony_ci	{ "hctl_open", &FA_int_pp_strp_int, (void *)&snd_hctl_open, "hctl" },
806d5ac70f0Sopenharmony_ci	{ "hctl_open_ctl", &FA_int_pp_p, (void *)&snd_hctl_open_ctl, "hctl" },
807d5ac70f0Sopenharmony_ci	{ "pcm_info", &FA_pcm_info, NULL, "pcm" },
808d5ac70f0Sopenharmony_ci	{ "pcm_name", &FA_str_p, (void *)&snd_pcm_name, "pcm" },
809d5ac70f0Sopenharmony_ci};
810d5ac70f0Sopenharmony_ci
811d5ac70f0Sopenharmony_cistatic int acall_compar(const void *p1, const void *p2)
812d5ac70f0Sopenharmony_ci{
813d5ac70f0Sopenharmony_ci	return strcmp(((struct acall_table *)p1)->name,
814d5ac70f0Sopenharmony_ci        	      ((struct acall_table *)p2)->name);
815d5ac70f0Sopenharmony_ci}
816d5ac70f0Sopenharmony_ci
817d5ac70f0Sopenharmony_cistatic struct alisp_object * F_acall(struct alisp_instance *instance, struct alisp_object * args)
818d5ac70f0Sopenharmony_ci{
819d5ac70f0Sopenharmony_ci	struct alisp_object * p1, *p2;
820d5ac70f0Sopenharmony_ci	struct acall_table key, *item;
821d5ac70f0Sopenharmony_ci
822d5ac70f0Sopenharmony_ci	p1 = eval(instance, car(args));
823d5ac70f0Sopenharmony_ci	p2 = cdr(args);
824d5ac70f0Sopenharmony_ci	delete_object(instance, args);
825d5ac70f0Sopenharmony_ci	if (!alisp_compare_type(p1, ALISP_OBJ_IDENTIFIER) &&
826d5ac70f0Sopenharmony_ci	    !alisp_compare_type(p1, ALISP_OBJ_STRING)) {
827d5ac70f0Sopenharmony_ci	    	delete_tree(instance, p2);
828d5ac70f0Sopenharmony_ci		return &alsa_lisp_nil;
829d5ac70f0Sopenharmony_ci	}
830d5ac70f0Sopenharmony_ci	key.name = p1->value.s;
831d5ac70f0Sopenharmony_ci	if ((item = bsearch(&key, acall_table,
832d5ac70f0Sopenharmony_ci			    sizeof acall_table / sizeof acall_table[0],
833d5ac70f0Sopenharmony_ci			    sizeof acall_table[0], acall_compar)) != NULL) {
834d5ac70f0Sopenharmony_ci		delete_tree(instance, p1);
835d5ac70f0Sopenharmony_ci		return item->func(instance, item, p2);
836d5ac70f0Sopenharmony_ci	}
837d5ac70f0Sopenharmony_ci	delete_tree(instance, p1);
838d5ac70f0Sopenharmony_ci	delete_tree(instance, p2);
839d5ac70f0Sopenharmony_ci	lisp_warn(instance, "acall function %s' is undefined", p1->value.s);
840d5ac70f0Sopenharmony_ci	return &alsa_lisp_nil;
841d5ac70f0Sopenharmony_ci}
842d5ac70f0Sopenharmony_ci
843d5ac70f0Sopenharmony_cistatic struct alisp_object * F_ahandle(struct alisp_instance *instance, struct alisp_object * args)
844d5ac70f0Sopenharmony_ci{
845d5ac70f0Sopenharmony_ci	struct alisp_object *p1;
846d5ac70f0Sopenharmony_ci
847d5ac70f0Sopenharmony_ci	p1 = eval(instance, car(args));
848d5ac70f0Sopenharmony_ci	delete_tree(instance, cdr(args));
849d5ac70f0Sopenharmony_ci	delete_object(instance, args);
850d5ac70f0Sopenharmony_ci	args = car(cdr(p1));
851d5ac70f0Sopenharmony_ci	delete_tree(instance, cdr(cdr(p1)));
852d5ac70f0Sopenharmony_ci	delete_object(instance, cdr(p1));
853d5ac70f0Sopenharmony_ci	delete_tree(instance, car(p1));
854d5ac70f0Sopenharmony_ci	delete_object(instance, p1);
855d5ac70f0Sopenharmony_ci	return args;
856d5ac70f0Sopenharmony_ci}
857d5ac70f0Sopenharmony_ci
858d5ac70f0Sopenharmony_cistatic struct alisp_object * F_aerror(struct alisp_instance *instance, struct alisp_object * args)
859d5ac70f0Sopenharmony_ci{
860d5ac70f0Sopenharmony_ci	struct alisp_object *p1;
861d5ac70f0Sopenharmony_ci
862d5ac70f0Sopenharmony_ci	p1 = eval(instance, car(args));
863d5ac70f0Sopenharmony_ci	delete_tree(instance, cdr(args));
864d5ac70f0Sopenharmony_ci	delete_object(instance, args);
865d5ac70f0Sopenharmony_ci	args = car(p1);
866d5ac70f0Sopenharmony_ci	if (args == &alsa_lisp_nil) {
867d5ac70f0Sopenharmony_ci		delete_tree(instance, p1);
868d5ac70f0Sopenharmony_ci		return new_integer(instance, SND_ERROR_ALISP_NIL);
869d5ac70f0Sopenharmony_ci	} else {
870d5ac70f0Sopenharmony_ci		delete_tree(instance, cdr(p1));
871d5ac70f0Sopenharmony_ci		delete_object(instance, p1);
872d5ac70f0Sopenharmony_ci	}
873d5ac70f0Sopenharmony_ci	return args;
874d5ac70f0Sopenharmony_ci}
875d5ac70f0Sopenharmony_ci
876d5ac70f0Sopenharmony_cistatic int common_error(snd_output_t **rout, struct alisp_instance *instance, struct alisp_object * args)
877d5ac70f0Sopenharmony_ci{
878d5ac70f0Sopenharmony_ci	struct alisp_object * p = args, * p1;
879d5ac70f0Sopenharmony_ci	snd_output_t *out;
880d5ac70f0Sopenharmony_ci	int err;
881d5ac70f0Sopenharmony_ci
882d5ac70f0Sopenharmony_ci	err = snd_output_buffer_open(&out);
883d5ac70f0Sopenharmony_ci	if (err < 0) {
884d5ac70f0Sopenharmony_ci		delete_tree(instance, args);
885d5ac70f0Sopenharmony_ci		return err;
886d5ac70f0Sopenharmony_ci	}
887d5ac70f0Sopenharmony_ci
888d5ac70f0Sopenharmony_ci	do {
889d5ac70f0Sopenharmony_ci		p1 = eval(instance, car(p));
890d5ac70f0Sopenharmony_ci		if (alisp_compare_type(p1, ALISP_OBJ_STRING))
891d5ac70f0Sopenharmony_ci			snd_output_printf(out, "%s", p1->value.s);
892d5ac70f0Sopenharmony_ci		else
893d5ac70f0Sopenharmony_ci			princ_object(out, p1);
894d5ac70f0Sopenharmony_ci		delete_tree(instance, p1);
895d5ac70f0Sopenharmony_ci		p = cdr(p1 = p);
896d5ac70f0Sopenharmony_ci		delete_object(instance, p1);
897d5ac70f0Sopenharmony_ci	} while (p != &alsa_lisp_nil);
898d5ac70f0Sopenharmony_ci
899d5ac70f0Sopenharmony_ci	*rout = out;
900d5ac70f0Sopenharmony_ci	return 0;
901d5ac70f0Sopenharmony_ci}
902d5ac70f0Sopenharmony_ci
903d5ac70f0Sopenharmony_cistatic struct alisp_object * F_snderr(struct alisp_instance *instance, struct alisp_object * args)
904d5ac70f0Sopenharmony_ci{
905d5ac70f0Sopenharmony_ci	snd_output_t *out;
906d5ac70f0Sopenharmony_ci	char *str;
907d5ac70f0Sopenharmony_ci
908d5ac70f0Sopenharmony_ci	if (common_error(&out, instance, args) < 0)
909d5ac70f0Sopenharmony_ci		return &alsa_lisp_nil;
910d5ac70f0Sopenharmony_ci	snd_output_buffer_string(out, &str);
911d5ac70f0Sopenharmony_ci	SNDERR(str);
912d5ac70f0Sopenharmony_ci	snd_output_close(out);
913d5ac70f0Sopenharmony_ci	return &alsa_lisp_t;
914d5ac70f0Sopenharmony_ci}
915d5ac70f0Sopenharmony_ci
916d5ac70f0Sopenharmony_cistatic struct alisp_object * F_syserr(struct alisp_instance *instance, struct alisp_object * args)
917d5ac70f0Sopenharmony_ci{
918d5ac70f0Sopenharmony_ci	snd_output_t *out;
919d5ac70f0Sopenharmony_ci	char *str;
920d5ac70f0Sopenharmony_ci
921d5ac70f0Sopenharmony_ci	if (common_error(&out, instance, args) < 0)
922d5ac70f0Sopenharmony_ci		return &alsa_lisp_nil;
923d5ac70f0Sopenharmony_ci	snd_output_buffer_string(out, &str);
924d5ac70f0Sopenharmony_ci	SYSERR(str);
925d5ac70f0Sopenharmony_ci	snd_output_close(out);
926d5ac70f0Sopenharmony_ci	return &alsa_lisp_t;
927d5ac70f0Sopenharmony_ci}
928d5ac70f0Sopenharmony_ci
929d5ac70f0Sopenharmony_cistatic const struct intrinsic snd_intrinsics[] = {
930d5ac70f0Sopenharmony_ci	{ "Acall", F_acall },
931d5ac70f0Sopenharmony_ci	{ "Aerror", F_aerror },
932d5ac70f0Sopenharmony_ci	{ "Ahandle", F_ahandle },
933d5ac70f0Sopenharmony_ci	{ "Aresult", F_ahandle },
934d5ac70f0Sopenharmony_ci	{ "Asnderr", F_snderr },
935d5ac70f0Sopenharmony_ci	{ "Asyserr", F_syserr }
936d5ac70f0Sopenharmony_ci};
937