aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaroslav Kysela <perex@perex.cz>2003-12-23 16:42:55 +0000
committerJaroslav Kysela <perex@perex.cz>2003-12-23 16:42:55 +0000
commitd0facfde2b1ef8a55fd277f99e64ff7c6c8e7a90 (patch)
tree4c94cec07fe32a799385fd49a6b0bff3e35cbd77
parentbeb837bcf77c949313b0dbb2cf54b4e9701f3339 (diff)
ALISP update
- function names are more emacs-like - implemented (format) function - fixed numerous memory-leaks (valgrind is now happy) Ordinary mixer - added the global view (using hdsp names only)
-rw-r--r--alsalisp/test.lisp84
-rw-r--r--include/alisp.h2
-rw-r--r--include/mixer_ordinary.h3
-rw-r--r--src/alisp/alisp.c583
-rw-r--r--src/conf/cards/SI7018/sndoc-mixer.alisp11
-rw-r--r--src/conf/cards/SI7018/sndop-mixer.alisp11
-rw-r--r--src/conf/cards/aliases.alisp30
-rw-r--r--src/conf/sndo-mixer.alisp67
-rw-r--r--src/ordinary_mixer/ordinary_mixer.c56
-rw-r--r--test/omixer.c25
10 files changed, 625 insertions, 247 deletions
diff --git a/alsalisp/test.lisp b/alsalisp/test.lisp
index eebb7b7f..99a9340b 100644
--- a/alsalisp/test.lisp
+++ b/alsalisp/test.lisp
@@ -3,7 +3,7 @@
; The test is indended to find memory leaks.
;
; Copyright (c) 2003 Jaroslav Kysela <perex@suse.cz>
-; License: GPL
+; License: GPL v2 (http://www.gnu.org/licenses/gpl.html)
;
;
@@ -120,7 +120,7 @@
(atom "one") (&check-memory)
(atom "one" 'two) (&check-memory)
-(call) (&check-memory)
+(funcall) (&check-memory)
(car) (&check-memory)
(car '(one . two)) (&check-memory)
@@ -128,6 +128,13 @@
(cdr) (&check-memory)
(cdr '(one . two)) (&check-memory)
+(concat) (&check-memory)
+(concat 'aaaa) (&check-memory)
+(concat 'aaaa 'bbbb) (&check-memory)
+(concat "aaaa") (&check-memory)
+(concat "aaaa" "bbbb") (&check-memory)
+(concat "aaaa" "bbbb" "cccc") (&check-memory)
+
(cond) (&check-memory)
(cond 0) (&check-memory)
(cond 0 1) (&check-memory)
@@ -160,11 +167,17 @@
(exfun 'abcd) (&check-memory)
(exfun 'abcd 'ijkl) (&check-memory)
-(float) (&check-memory)
-(float 1) (&check-memory)
-(float 'a) (&check-memory)
-(float "a" "b" "c") (&check-memory)
-(float "1.2") (&check-memory)
+(format) (&check-memory)
+(format 1) (&check-memory)
+(format 'a) (&check-memory)
+(format "a" "b" "c") (&check-memory)
+(format "1.2") (&check-memory)
+(format "%c" 43) (&check-memory)
+(format "%d" 12) (&check-memory)
+(format "%i" 12) (&check-memory)
+(format "%f" 12.1) (&check-memory)
+(format "%s" "abcd") (&check-memory)
+(format "%s %i %i" "abcd" 1 2) (&check-memory)
(garbage-collect) (&check-memory)
(gc) (&check-memory)
@@ -179,12 +192,6 @@
(include "itest.lisp") (&check-memory)
-(int) (&check-memory)
-(int 1) (&check-memory)
-(int 'a) (&check-memory)
-(int "a" "b" "c") (&check-memory)
-(int "1.2") (&check-memory)
-
(list) (&check-memory)
(list "a") (&check-memory)
(list "a" "b") (&check-memory)
@@ -267,10 +274,28 @@
(setq a 1) (unsetq a) (&check-memory)
(setq a 1 2) (unsetq a) (&check-memory)
-(str) (&check-memory)
-(str 1) (&check-memory)
-(str 1 2 3) (&check-memory)
-(str 1.2 1.3) (&check-memory)
+(string-equal) (&check-memory)
+(string-equal 1) (&check-memory)
+(string-equal "a") (&check-memory)
+(string-equal "a" "a") (&check-memory)
+(string-equal "a" "b") (&check-memory)
+(string-equal "a" "b" "c") (&check-memory)
+
+(string-to-integer) (&check-memory)
+(string-to-integer 1) (&check-memory)
+(string-to-integer 1.5) (&check-memory)
+(string-to-integer "a") (&check-memory)
+(string-to-integer "a" "a") (&check-memory)
+(string-to-integer "a" "b") (&check-memory)
+(string-to-integer "a" "b" "c") (&check-memory)
+
+(string-to-float) (&check-memory)
+(string-to-float 1) (&check-memory)
+(string-to-float 1.5) (&check-memory)
+(string-to-float "a") (&check-memory)
+(string-to-float "a" "a") (&check-memory)
+(string-to-float "a" "b") (&check-memory)
+(string-to-float "a" "b" "c") (&check-memory)
(string=) (&check-memory)
(string= 1) (&check-memory)
@@ -279,13 +304,6 @@
(string= "a" "b") (&check-memory)
(string= "a" "b" "c") (&check-memory)
-(string-equal) (&check-memory)
-(string-equal 1) (&check-memory)
-(string-equal "a") (&check-memory)
-(string-equal "a" "a") (&check-memory)
-(string-equal "a" "b") (&check-memory)
-(string-equal "a" "b" "c") (&check-memory)
-
(unless) (&check-memory)
(unless 1) (&check-memory)
(unless 0 1 2) (&check-memory)
@@ -322,27 +340,31 @@
(unsetq abcd)
(&check-memory)
+(setq abcd (("abcd" . "efgh") ("1234" . "5678")))
+(unsetq abcd)
+(&check-memory)
+
(defun myfun () (princ "a\n"))
(exfun 'myfun)
(unsetq myfun)
(&check-memory)
(defun myfun () (princ "a\n"))
-(call 'myfun)
-(call 'myfun 'aaaaa)
+(funcall 'myfun)
+(funcall 'myfun 'aaaaa)
(unsetq myfun)
(&check-memory)
(defun myfun (o) (princ o "a\n"))
-(call 'myfun)
-(call 'myfun 'aaaaa)
+(funcall 'myfun)
+(funcall 'myfun 'aaaaa)
(unsetq myfun)
(&check-memory)
(defun myfun (o p) (princ o p "\n"))
-(call 'myfun)
-(call 'myfun 'aaaaa)
-(call 'myfun 'aaaaa 'bbbbb)
+(funcall 'myfun)
+(funcall 'myfun 'aaaaa)
+(funcall 'myfun 'aaaaa 'bbbbb)
(unsetq myfun)
(&check-memory)
diff --git a/include/alisp.h b/include/alisp.h
index f8423d34..4deb4d23 100644
--- a/include/alisp.h
+++ b/include/alisp.h
@@ -45,6 +45,8 @@ int alsa_lisp_function(struct alisp_instance *instance, struct alisp_seq_iterato
__attribute__ ((format (printf, 4, 5)))
#endif
;
+void alsa_lisp_result_free(struct alisp_instance *instance,
+ struct alisp_seq_iterator *result);
int alsa_lisp_seq_first(struct alisp_instance *instance, const char *id,
struct alisp_seq_iterator **seq);
int alsa_lisp_seq_next(struct alisp_seq_iterator **seq);
diff --git a/include/mixer_ordinary.h b/include/mixer_ordinary.h
index 0c25dc20..db362a50 100644
--- a/include/mixer_ordinary.h
+++ b/include/mixer_ordinary.h
@@ -195,7 +195,8 @@ extern "C" {
* \{
*/
-int sndo_mixer_open(sndo_mixer_t **pmixer, snd_pcm_t *playback_pcm, snd_pcm_t *capture_pcm, struct alisp_cfg *lconf);
+int sndo_mixer_open(sndo_mixer_t **pmixer, const char *playback_name, const char *capture_name, struct alisp_cfg *lconf);
+int sndo_mixer_open_pcm(sndo_mixer_t **pmixer, snd_pcm_t *playback_pcm, snd_pcm_t *capture_pcm, struct alisp_cfg *lconf);
int sndo_mixer_close(sndo_mixer_t *mixer);
int sndo_mixer_poll_descriptors_count(sndo_mixer_t *mixer);
int sndo_mixer_poll_descriptors(sndo_mixer_t *mixer, struct pollfd *pfds, unsigned int space);
diff --git a/src/alisp/alisp.c b/src/alisp/alisp.c
index e70b6d21..987e2712 100644
--- a/src/alisp/alisp.c
+++ b/src/alisp/alisp.c
@@ -46,11 +46,11 @@ static struct alisp_object * parse_object(struct alisp_instance *instance, int h
static void princ_cons(snd_output_t *out, struct alisp_object * p);
static void princ_object(snd_output_t *out, struct alisp_object * p);
static struct alisp_object * eval(struct alisp_instance *instance, struct alisp_object * p);
-static struct alisp_object * eval_cons1(struct alisp_instance *instance, struct alisp_object * p1, struct alisp_object * p2);
/* functions */
static struct alisp_object *F_eval(struct alisp_instance *instance, struct alisp_object *);
static struct alisp_object *F_progn(struct alisp_instance *instance, struct alisp_object *);
+static struct alisp_object *F_funcall(struct alisp_instance *instance, struct alisp_object *);
/* others */
static int alisp_include_file(struct alisp_instance *instance, const char *filename);
@@ -176,9 +176,7 @@ static void free_object(struct alisp_object * p)
static void delete_object(struct alisp_instance *instance, struct alisp_object * p)
{
- if (p == NULL)
- return;
- if (p == &alsa_lisp_nil || p == &alsa_lisp_t)
+ if (p == NULL || p == &alsa_lisp_nil || p == &alsa_lisp_t)
return;
if (alisp_compare_type(p, ALISP_OBJ_NIL) ||
alisp_compare_type(p, ALISP_OBJ_T))
@@ -215,8 +213,8 @@ static void delete_tree(struct alisp_instance *instance, struct alisp_object * p
static struct alisp_object * incref_object(struct alisp_instance *instance ATTRIBUTE_UNUSED, struct alisp_object * p)
{
- if (p == NULL)
- return NULL;
+ if (p == NULL || p == &alsa_lisp_nil || p == &alsa_lisp_t)
+ return p;
if (alisp_get_refs(p) == ALISP_MAX_REFS) {
assert(0);
fprintf(stderr, "OOPS: alsa lisp: incref fatal error\n");
@@ -259,12 +257,30 @@ static void free_objects(struct alisp_instance *instance)
{
struct list_head *pos, *pos1;
struct alisp_object * p;
+ struct alisp_object_pair * pair;
int i, j;
+ for (i = 0; i < ALISP_OBJ_PAIR_HASH_SIZE; i++) {
+ list_for_each_safe(pos, pos1, &instance->setobjs_list[i]) {
+ pair = list_entry(pos, struct alisp_object_pair, list);
+ lisp_debug(instance, "freeing pair: '%s' -> %p", pair->name, pair->value);
+ delete_tree(instance, pair->value);
+ free((void *)pair->name);
+ free(pair);
+ }
+ }
for (i = 0; i < ALISP_OBJ_PAIR_HASH_SIZE; i++)
for (j = 0; j <= ALISP_OBJ_LAST_SEARCH; j++) {
list_for_each_safe(pos, pos1, &instance->used_objs_list[i][j]) {
p = list_entry(pos, struct alisp_object, list);
+ lisp_warn(instance, "object %p is still referenced %i times!", p, alisp_get_refs(p));
+#if 0
+ snd_output_printf(instance->wout, ">>>> ");
+ princ_object(instance->wout, p);
+ snd_output_printf(instance->wout, " <<<<\n");
+#endif
+ if (alisp_get_refs(p) > 0)
+ alisp_set_refs(p, 1);
delete_object(instance, p);
}
}
@@ -575,7 +591,7 @@ static int gettoken(struct alisp_instance *instance)
instance->thistoken = ALISP_INTEGER;
do {
__ok:
- if (p - instance->token_buffer >= instance->token_buffer_max) {
+ if (p - instance->token_buffer >= instance->token_buffer_max - 1) {
p = extend_buf(instance, p);
if (p == NULL)
return instance->thistoken = EOF;
@@ -620,7 +636,7 @@ static int gettoken(struct alisp_instance *instance)
/* Identifier: [!-/+*%<>=&a-zA-Z_][-/+*%<>=&a-zA-Z_0-9]* */
p = instance->token_buffer;
do {
- if (p - instance->token_buffer >= instance->token_buffer_max) {
+ if (p - instance->token_buffer >= instance->token_buffer_max - 1) {
p = extend_buf(instance, p);
if (p == NULL)
return instance->thistoken = EOF;
@@ -636,7 +652,7 @@ static int gettoken(struct alisp_instance *instance)
/* String: "\""([^"]|"\\".)*"\"" */
p = instance->token_buffer;
while ((c = xgetc(instance)) != '"' && c != EOF) {
- if (p - instance->token_buffer >= instance->token_buffer_max) {
+ if (p - instance->token_buffer >= instance->token_buffer_max - 1) {
p = extend_buf(instance, p);
if (p == NULL)
return instance->thistoken = EOF;
@@ -683,24 +699,26 @@ static struct alisp_object * parse_form(struct alisp_instance *instance)
* Parse a dotted pair notation.
*/
if (thistoken == '.') {
- thistoken = gettoken(instance);
+ gettoken(instance);
if (prev == NULL) {
- lisp_error(instance, "unexpected `.'");
+ lisp_error(instance, "unexpected '.'");
+ __err:
+ delete_tree(instance, first);
return NULL;
}
prev->value.c.cdr = parse_object(instance, 1);
if (prev->value.c.cdr == NULL)
- return NULL;
+ goto __err;
if ((thistoken = gettoken(instance)) != ')') {
- lisp_error(instance, "expected `)'");
- return NULL;
+ lisp_error(instance, "expected ')'");
+ goto __err;
}
break;
}
p = new_object(instance, ALISP_OBJ_CONS);
if (p == NULL)
- return NULL;
+ goto __err;
if (first == NULL)
first = p;
@@ -709,7 +727,8 @@ static struct alisp_object * parse_form(struct alisp_instance *instance)
p->value.c.car = parse_object(instance, 1);
if (p->value.c.car == NULL)
- return NULL;
+ goto __err;
+
prev = p;
}
@@ -724,11 +743,11 @@ static struct alisp_object * quote_object(struct alisp_instance *instance, struc
struct alisp_object * p;
if (obj == NULL)
- return NULL;
+ goto __end1;
p = new_object(instance, ALISP_OBJ_CONS);
if (p == NULL)
- return NULL;
+ goto __end1;
p->value.c.car = new_identifier(instance, "quote");
if (p->value.c.car == NULL)
@@ -737,8 +756,9 @@ static struct alisp_object * quote_object(struct alisp_instance *instance, struc
if (p->value.c.cdr == NULL) {
delete_object(instance, p->value.c.car);
__end:
- delete_object(instance, obj);
delete_object(instance, p);
+ __end1:
+ delete_tree(instance, obj);
return NULL;
}
@@ -898,6 +918,7 @@ static struct alisp_object * unset_object(struct alisp_instance *instance, struc
if (!strcmp(p->name, id)) {
list_del(&p->list);
res = p->value;
+ free((void *)p->name);
free(p);
return res;
}
@@ -1117,74 +1138,78 @@ static struct alisp_object * F_cdr(struct alisp_instance *instance, struct alisp
static struct alisp_object * F_add(struct alisp_instance *instance, struct alisp_object * args)
{
struct alisp_object * p = args, * p1, * n;
+ long v = 0;
+ double f = 0;
+ int type = ALISP_OBJ_INTEGER;
p1 = eval(instance, car(p));
- if (alisp_compare_type(p1, ALISP_OBJ_INTEGER) ||
- alisp_compare_type(p1, ALISP_OBJ_FLOAT)) {
- long v = 0;
- double f = 0;
- int type = ALISP_OBJ_INTEGER;
- for (;;) {
- if (alisp_compare_type(p1, ALISP_OBJ_INTEGER)) {
- if (type == ALISP_OBJ_FLOAT)
- f += p1->value.i;
- else
- v += p1->value.i;
- } else if (alisp_compare_type(p1, ALISP_OBJ_FLOAT)) {
- f += p1->value.f + v;
- v = 0;
- type = ALISP_OBJ_FLOAT;
- } else {
- lisp_warn(instance, "sum with a non integer or float operand");
- }
- delete_tree(instance, p1);
- p = cdr(n = p);
- delete_object(instance, n);
- if (p == &alsa_lisp_nil)
- break;
- p1 = eval(instance, car(p));
- }
- if (type == ALISP_OBJ_INTEGER) {
- return new_integer(instance, v);
+ for (;;) {
+ if (alisp_compare_type(p1, ALISP_OBJ_INTEGER)) {
+ if (type == ALISP_OBJ_FLOAT)
+ f += p1->value.i;
+ else
+ v += p1->value.i;
+ } else if (alisp_compare_type(p1, ALISP_OBJ_FLOAT)) {
+ f += p1->value.f + v;
+ v = 0;
+ type = ALISP_OBJ_FLOAT;
} else {
- return new_float(instance, f);
+ lisp_warn(instance, "sum with a non integer or float operand");
}
- } else if (alisp_compare_type(p1, ALISP_OBJ_STRING)) {
- char *str = NULL, *str1;
- for (;;) {
- if (alisp_compare_type(p1, ALISP_OBJ_STRING)) {
- str1 = realloc(str, (str ? strlen(str) : 0) + strlen(p1->value.s) + 1);
- if (str1 == NULL) {
- nomem();
- if (str)
- free(str);
- return NULL;
- }
- if (str == NULL)
- strcpy(str1, p1->value.s);
- else
- strcat(str1, p1->value.s);
- str = str1;
- } else {
- lisp_warn(instance, "concat with a non string or identifier operand");
+ delete_tree(instance, p1);
+ p = cdr(n = p);
+ delete_object(instance, n);
+ if (p == &alsa_lisp_nil)
+ break;
+ p1 = eval(instance, car(p));
+ }
+ if (type == ALISP_OBJ_INTEGER) {
+ return new_integer(instance, v);
+ } else {
+ return new_float(instance, f);
+ }
+}
+
+/*
+ * Syntax: (concat expr...)
+ */
+static struct alisp_object * F_concat(struct alisp_instance *instance, struct alisp_object * args)
+{
+ struct alisp_object * p = args, * p1, * n;
+ char *str = NULL, *str1;
+
+ p1 = eval(instance, car(p));
+ for (;;) {
+ if (alisp_compare_type(p1, ALISP_OBJ_STRING)) {
+ str1 = realloc(str, (str ? strlen(str) : 0) + strlen(p1->value.s) + 1);
+ if (str1 == NULL) {
+ nomem();
+ if (str)
+ free(str);
+ return NULL;
}
- delete_tree(instance, p1);
- p = cdr(n = p);
- delete_object(instance, n);
- if (p == &alsa_lisp_nil)
- break;
- p1 = eval(instance, car(p));
+ if (str == NULL)
+ strcpy(str1, p1->value.s);
+ else
+ strcat(str1, p1->value.s);
+ str = str1;
+ } else {
+ lisp_warn(instance, "concat with a non string or identifier operand");
}
+ delete_tree(instance, p1);
+ p = cdr(n = p);
+ delete_object(instance, n);
+ if (p == &alsa_lisp_nil)
+ break;
+ p1 = eval(instance, car(p));
+ }
+ if (str) {
p = new_string(instance, str);
free(str);
- return p;
} else {
- lisp_warn(instance, "sum/concat with non-integer or string operand");
- delete_tree(instance, cdr(p));
- delete_object(instance, p);
- delete_tree(instance, p1);
+ p = &alsa_lisp_nil;
}
- return &alsa_lisp_nil;
+ return p;
}
/*
@@ -2218,6 +2243,7 @@ static struct alisp_object * F_unsetq(struct alisp_instance *instance, struct al
if (p1)
delete_tree(instance, p1);
p1 = unset_object(instance, car(p));
+ delete_tree(instance, car(p));
p = cdr(n = p);
delete_object(instance, n);
} while (p != &alsa_lisp_nil);
@@ -2269,7 +2295,7 @@ static struct alisp_object * F_defun(struct alisp_instance *instance, struct ali
static struct alisp_object * eval_func(struct alisp_instance *instance, struct alisp_object * p, struct alisp_object * args)
{
- struct alisp_object * p1, * p2, * p3, * p4, * p5;
+ struct alisp_object * p1, * p2, * p3, * p4;
struct alisp_object ** eval_objs, ** save_objs;
int i;
@@ -2297,9 +2323,8 @@ static struct alisp_object * eval_func(struct alisp_instance *instance, struct a
i = 0;
while (p3 != &alsa_lisp_nil) {
eval_objs[i++] = eval(instance, car(p3));
- p4 = cdr(p3);
- delete_object(instance, p3);
- p3 = p4;
+ p3 = cdr(p4 = p3);
+ delete_object(instance, p4);
}
/*
@@ -2307,48 +2332,49 @@ static struct alisp_object * eval_func(struct alisp_instance *instance, struct a
*/
i = 0;
while (p2 != &alsa_lisp_nil) {
- p4 = car(p2);
- save_objs[i] = replace_object(instance, p4, eval_objs[i]);
+ p3 = car(p2);
+ save_objs[i] = replace_object(instance, p3, eval_objs[i]);
if (save_objs[i] == NULL &&
- set_object_direct(instance, p4, eval_objs[i]) == NULL)
+ set_object_direct(instance, p3, eval_objs[i]) == NULL) {
+ p4 = NULL;
goto _end;
+ }
p2 = cdr(p2);
++i;
}
- p5 = F_progn(instance, incref_tree(instance, cdr(cdr(p))));
+ p4 = F_progn(instance, cdr(incref_tree(instance, p3 = cdr(p))));
/*
* Restore the old variable values.
*/
- p2 = car(cdr(p));
+ p2 = car(p3);
+ delete_object(instance, p3);
i = 0;
while (p2 != &alsa_lisp_nil) {
- p4 = car(p2);
+ p3 = car(p2);
if (save_objs[i] == NULL) {
- p4 = unset_object(instance, p4);
+ p3 = unset_object(instance, p3);
} else {
- p4 = replace_object(instance, p4, save_objs[i]);
+ p3 = replace_object(instance, p3, save_objs[i]);
}
i++;
- delete_tree(instance, p4);
- p2 = cdr(p2);
+ delete_tree(instance, p3);
+ delete_tree(instance, car(p2));
+ p2 = cdr(p3 = p2);
+ delete_object(instance, p3);
}
+ _end:
if (eval_objs)
free(eval_objs);
- return p5;
+ return p4;
} else {
_delete:
delete_tree(instance, args);
}
return &alsa_lisp_nil;
-
- _end:
- if (eval_objs)
- free(eval_objs);
- return NULL;
}
struct alisp_object * F_gc(struct alisp_instance *instance ATTRIBUTE_UNUSED, struct alisp_object * args ATTRIBUTE_UNUSED)
@@ -2401,30 +2427,10 @@ struct alisp_object * F_include(struct alisp_instance *instance, struct alisp_ob
}
/*
- * Syntax: (call function args...)
- */
-struct alisp_object * F_call(struct alisp_instance *instance, struct alisp_object * args)
-{
- struct alisp_object * p = eval(instance, car(args)), * p1;
-
- if (!alisp_compare_type(p, ALISP_OBJ_IDENTIFIER) &&
- !alisp_compare_type(p, ALISP_OBJ_STRING)) {
- lisp_warn(instance, "expected an function name");
- delete_tree(instance, p);
- delete_tree(instance, cdr(args));
- delete_object(instance, args);
- return &alsa_lisp_nil;
- }
- p1 = cdr(args);
- delete_object(instance, args);
- return eval_cons1(instance, p, p1);
-}
-
-/*
- * Syntax: (int value)
+ * Syntax: (string-to-integer value)
* 'value' can be integer or float type
*/
-struct alisp_object * F_int(struct alisp_instance *instance, struct alisp_object * args)
+struct alisp_object * F_string_to_integer(struct alisp_instance *instance, struct alisp_object * args)
{
struct alisp_object * p = eval(instance, car(args)), * p1;
@@ -2443,10 +2449,10 @@ struct alisp_object * F_int(struct alisp_instance *instance, struct alisp_object
}
/*
- * Syntax: (float value)
+ * Syntax: (string-to-float value)
* 'value' can be integer or float type
*/
-struct alisp_object * F_float(struct alisp_instance *instance, struct alisp_object * args)
+struct alisp_object * F_string_to_float(struct alisp_instance *instance, struct alisp_object * args)
{
struct alisp_object * p = eval(instance, car(args)), * p1;
@@ -2464,42 +2470,282 @@ struct alisp_object * F_float(struct alisp_instance *instance, struct alisp_obje
return p1;
}
+static int append_to_string(char **s, int *len, char *from, int size)
+{
+ if (*len == 0) {
+ *s = malloc(*len = size + 1);
+ if (*s == NULL) {
+ nomem();
+ return -ENOMEM;
+ }
+ memcpy(*s, from, size);
+ } else {
+ *len += size;
+ *s = realloc(*s, *len);
+ if (*s == NULL) {
+ nomem();
+ return -ENOMEM;
+ }
+ memcpy(*s + strlen(*s), from, size);
+ }
+ (*s)[*len - 1] = '\0';
+ return 0;
+}
+
+static int format_parse_char(struct alisp_instance *instance, char **s, int *len, struct alisp_object *p)
+{
+ char b;
+
+ if (!alisp_compare_type(p, ALISP_OBJ_INTEGER)) {
+ lisp_warn(instance, "format: expected integer\n");
+ return 0;
+ }
+ b = p->value.i;
+ return append_to_string(s, len, &b, 1);
+}
+
+static int format_parse_integer(struct alisp_instance *instance, char **s, int *len, struct alisp_object *p)
+{
+ int res;
+ char *s1;
+
+ if (!alisp_compare_type(p, ALISP_OBJ_INTEGER) &&
+ !alisp_compare_type(p, ALISP_OBJ_FLOAT)) {
+ lisp_warn(instance, "format: expected integer or float\n");
+ return 0;
+ }
+ s1 = malloc(64);
+ if (s1 == NULL) {
+ nomem();
+ return -ENOMEM;
+ }
+ sprintf(s1, "%li", alisp_compare_type(p, ALISP_OBJ_FLOAT) ? (long)floor(p->value.f) : p->value.i);
+ res = append_to_string(s, len, s1, strlen(s1));
+ free(s1);
+ return res;
+}
+
+static int format_parse_float(struct alisp_instance *instance, char **s, int *len, struct alisp_object *p)
+{
+ int res;
+ char *s1;
+
+ if (!alisp_compare_type(p, ALISP_OBJ_INTEGER) &&
+ !alisp_compare_type(p, ALISP_OBJ_FLOAT)) {
+ lisp_warn(instance, "format: expected integer or float\n");
+ return 0;
+ }
+ s1 = malloc(64);
+ if (s1 == NULL) {
+ nomem();
+ return -ENOMEM;
+ }
+ sprintf(s1, "%f", alisp_compare_type(p, ALISP_OBJ_FLOAT) ? p->value.f : (double)p->value.i);
+ res = append_to_string(s, len, s1, strlen(s1));
+ free(s1);
+ return res;
+}
+
+static int format_parse_string(struct alisp_instance *instance, char **s, int *len, struct alisp_object *p)
+{
+ if (!alisp_compare_type(p, ALISP_OBJ_STRING)) {
+ lisp_warn(instance, "format: expected string\n");
+ return 0;
+ }
+ return append_to_string(s, len, p->value.s, strlen(p->value.s));
+}
+
/*
- * Syntax: (str value)
- * 'value' can be integer, float or string type
+ * Syntax: (format format value...)
+ * 'format' is C-like format string
*/
-struct alisp_object * F_str(struct alisp_instance *instance, struct alisp_object * args)
+struct alisp_object * F_format(struct alisp_instance *instance, struct alisp_object * args)
{
- struct alisp_object * p = eval(instance, car(args)), * p1;
+ struct alisp_object * p = eval(instance, car(args)), * p1 = cdr(args), * n;
+ char *s, *s1, *s2;
+ int len;
- delete_tree(instance, cdr(args));
delete_object(instance, args);
- if (alisp_compare_type(p, ALISP_OBJ_STRING))
- return p;
- if (alisp_compare_type(p, ALISP_OBJ_INTEGER) ||
- alisp_compare_type(p, ALISP_OBJ_FLOAT)) {
- char *buf = malloc(64);
- if (buf == NULL) {
- delete_tree(instance, p);
- nomem();
- return NULL;
- }
- if (alisp_compare_type(p, ALISP_OBJ_INTEGER)) {
- snprintf(buf, sizeof(buf), "%ld", p->value.i);
- } else {
- snprintf(buf, sizeof(buf), "%.f", p->value.f);
+ if (!alisp_compare_type(p, ALISP_OBJ_STRING)) {
+ delete_tree(instance, p1);
+ delete_tree(instance, p);
+ lisp_warn(instance, "format: expected an format string");
+ return &alsa_lisp_nil;
+ }
+ s = p->value.s;
+ s1 = NULL;
+ len = 0;
+ n = eval(instance, car(p1));
+ do {
+ while (1) {
+ s2 = s;
+ while (*s2 && *s2 != '%')
+ s2++;
+ if (s2 != s) {
+ if (append_to_string(&s1, &len, s, s2 - s) < 0) {
+ __error:
+ delete_tree(instance, n);
+ delete_tree(instance, cdr(p1));
+ delete_object(instance, p1);
+ delete_tree(instance, p);
+ return NULL;
+ }
+ }
+ if (*s2 == '%')
+ s2++;
+ switch (*s2) {
+ case '%':
+ if (append_to_string(&s1, &len, s2, 1) < 0)
+ goto __error;
+ s = s2 + 1;
+ break;
+ case 'c':
+ if (format_parse_char(instance, &s1, &len, n) < 0)
+ goto __error;
+ s = s2 + 1;
+ goto __next;
+ case 'd':
+ case 'i':
+ if (format_parse_integer(instance, &s1, &len, n) < 0)
+ goto __error;
+ s = s2 + 1;
+ goto __next;
+ case 'f':
+ if (format_parse_float(instance, &s1, &len, n) < 0)
+ goto __error;
+ s = s2 + 1;
+ goto __next;
+ case 's':
+ if (format_parse_string(instance, &s1, &len, n) < 0)
+ goto __error;
+ s = s2 + 1;
+ goto __next;
+ case '\0':
+ goto __end;
+ default:
+ lisp_warn(instance, "unknown format char '%c'", *s2);
+ s = s2 + 1;
+ goto __next;
+ }
}
- p1 = new_string(instance, buf);
- free(buf);
+ __next:
+ delete_tree(instance, n);
+ p1 = cdr(n = p1);
+ delete_object(instance, n);
+ n = eval(instance, car(p1));
+ } while (*s);
+ __end:
+ delete_tree(instance, n);
+ delete_tree(instance, cdr(p1));
+ delete_object(instance, p1);
+ delete_tree(instance, p);
+ if (len > 0) {
+ p1 = new_string(instance, s1);
+ free(s1);
} else {
- lisp_warn(instance, "expected an integer or float for integer conversion");
p1 = &alsa_lisp_nil;
}
- delete_tree(instance, p);
return p1;
}
/*
+ * Syntax: (compare-strings str1 start1 end1 str2 start2 end2 /opt-case-insensitive)
+ * 'str1' is first compared string
+ * 'start1' is first char (0..)
+ * 'end1' is last char (0..)
+ * 'str2' is second compared string
+ * 'start2' is first char (0..)
+ * 'end2' is last char (0..)
+ * /opt-case-insensitive true - case insensitive match
+ */
+struct alisp_object * F_compare_strings(struct alisp_instance *instance, struct alisp_object * args)
+{
+ struct alisp_object * p1 = args, * n, * p[7];
+ char *s1, *s2;
+ int start1, end1, start2, end2;
+
+ for (start1 = 0; start1 < 7; start1++) {
+ p[start1] = eval(instance, car(p1));
+ p1 = cdr(n = p1);
+ delete_object(instance, n);
+ }
+ delete_tree(instance, p1);
+ if (alisp_compare_type(p[0], ALISP_OBJ_STRING)) {
+ lisp_warn(instance, "compare-strings: first argument must be string\n");
+ p1 = &alsa_lisp_nil;
+ goto __err;
+ }
+ if (alisp_compare_type(p[1], ALISP_OBJ_INTEGER)) {
+ lisp_warn(instance, "compare-strings: second argument must be integer\n");
+ p1 = &alsa_lisp_nil;
+ goto __err;
+ }
+ if (alisp_compare_type(p[2], ALISP_OBJ_INTEGER)) {
+ lisp_warn(instance, "compare-strings: third argument must be integer\n");
+ p1 = &alsa_lisp_nil;
+ goto __err;
+ }
+ if (alisp_compare_type(p[3], ALISP_OBJ_STRING)) {
+ lisp_warn(instance, "compare-strings: fifth argument must be string\n");
+ p1 = &alsa_lisp_nil;
+ goto __err;
+ }
+ if (!alisp_compare_type(p[4], ALISP_OBJ_NIL) &&
+ !alisp_compare_type(p[4], ALISP_OBJ_INTEGER)) {
+ lisp_warn(instance, "compare-strings: fourth argument must be integer\n");
+ p1 = &alsa_lisp_nil;
+ goto __err;
+ }
+ if (!alisp_compare_type(p[5], ALISP_OBJ_NIL) &&
+ !alisp_compare_type(p[5], ALISP_OBJ_INTEGER)) {
+ lisp_warn(instance, "compare-strings: sixth argument must be integer\n");
+ p1 = &alsa_lisp_nil;
+ goto __err;
+ }
+ s1 = p[0]->value.s;
+ start1 = p[1]->value.i;
+ end1 = p[2]->value.i;
+ s2 = p[3]->value.s;
+ start2 = alisp_compare_type(p[4], ALISP_OBJ_NIL) ? 0 : p[4]->value.i;
+ end2 = alisp_compare_type(p[5], ALISP_OBJ_NIL) ? start2 + (end1 - start1) : p[5]->value.i;
+ if (start1 < 0 || start2 < 0 || end1 < 0 || end2 < 0 ||
+ start1 >= (int)strlen(s1) || start2 >= (int)strlen(s2) ||
+ (end1 - start1) != (end2 - start2)) {
+ p1 = &alsa_lisp_nil;
+ goto __err;
+ }
+ if (p[6] != &alsa_lisp_nil) {
+ while (start1 < end1) {
+ if (s1[start1] == '\0' ||
+ s2[start2] == '\0' ||
+ tolower(s1[start1]) != tolower(s2[start2])) {
+ p1 = &alsa_lisp_nil;
+ goto __err;
+ }
+ start1++;
+ start2++;
+ }
+ } else {
+ while (start1 < end1) {
+ if (s1[start1] == '\0' ||
+ s2[start2] == '\0' ||
+ s1[start1] != s2[start2]) {
+ p1 = &alsa_lisp_nil;
+ goto __err;
+ }
+ start1++;
+ start2++;
+ }
+ }
+ p1 = &alsa_lisp_t;
+
+ __err:
+ for (start1 = 0; start1 < 7; start1++)
+ delete_tree(instance, p[start1]);
+ return p1;
+}
+
+/*
* Syntax: (assoc key alist)
*/
struct alisp_object * F_assoc(struct alisp_instance *instance, struct alisp_object * args)
@@ -2744,9 +2990,10 @@ static struct intrinsic intrinsics[] = {
{ "assoc", F_assoc },
{ "assq", F_assq },
{ "atom", F_atom },
- { "call", F_call },
{ "car", F_car },
{ "cdr", F_cdr },
+ { "compare-strings", F_compare_strings },
+ { "concat", F_concat },
{ "cond", F_cond },
{ "cons", F_cons },
{ "defun", F_defun },
@@ -2754,12 +3001,12 @@ static struct intrinsic intrinsics[] = {
{ "equal", F_equal },
{ "eval", F_eval },
{ "exfun", F_exfun },
- { "float", F_float },
+ { "format", F_format },
+ { "funcall", F_funcall },
{ "garbage-collect", F_gc },
{ "gc", F_gc },
{ "if", F_if },
{ "include", F_include },
- { "int", F_int },
{ "list", F_list },
{ "not", F_not },
{ "nth", F_nth },
@@ -2776,9 +3023,11 @@ static struct intrinsic intrinsics[] = {
{ "set", F_set },
{ "setf", F_setq },
{ "setq", F_setq },
- { "str", F_str },
- { "string=", F_equal },
{ "string-equal", F_equal },
+ { "string-to-float", F_string_to_float },
+ { "string-to-integer", F_string_to_integer },
+ { "string-to-number", F_string_to_float },
+ { "string=", F_equal },
{ "unless", F_unless },
{ "unset", F_unset },
{ "unsetf", F_unsetq },
@@ -2795,7 +3044,7 @@ static int compar(const void *p1, const void *p2)
((struct intrinsic *)p2)->name);
}
-static struct alisp_object * eval_cons1(struct alisp_instance *instance, struct alisp_object * p1, struct alisp_object * p2)
+static inline struct alisp_object * eval_cons1(struct alisp_instance *instance, struct alisp_object * p1, struct alisp_object * p2)
{
struct alisp_object * p3;
struct intrinsic key, *item;
@@ -2828,6 +3077,26 @@ static struct alisp_object * eval_cons1(struct alisp_instance *instance, struct
return &alsa_lisp_nil;
}
+/*
+ * Syntax: (funcall function args...)
+ */
+static struct alisp_object * F_funcall(struct alisp_instance *instance, struct alisp_object * args)
+{
+ struct alisp_object * p = eval(instance, car(args)), * p1;
+
+ if (!alisp_compare_type(p, ALISP_OBJ_IDENTIFIER) &&
+ !alisp_compare_type(p, ALISP_OBJ_STRING)) {
+ lisp_warn(instance, "expected an function name");
+ delete_tree(instance, p);
+ delete_tree(instance, cdr(args));
+ delete_object(instance, args);
+ return &alsa_lisp_nil;
+ }
+ p1 = cdr(args);
+ delete_object(instance, args);
+ return eval_cons1(instance, p, p1);
+}
+
static inline struct alisp_object * eval_cons(struct alisp_instance *instance, struct alisp_object * p)
{
struct alisp_object * p1 = car(p), * p2;
@@ -2839,6 +3108,8 @@ static inline struct alisp_object * eval_cons(struct alisp_instance *instance, s
p2 = cdr(p);
delete_object(instance, p);
return eval_cons1(instance, p1, p2);
+ } else {
+ delete_tree(instance, p);
}
return &alsa_lisp_nil;
@@ -2919,6 +3190,7 @@ static int alisp_include_file(struct alisp_instance *instance, const char *filen
}
}
+ snd_input_close(instance->in);
_err:
free(name);
instance->in = old_in;
@@ -3141,12 +3413,21 @@ int alsa_lisp_function(struct alisp_instance *instance, struct alisp_seq_iterato
}
if (res == NULL)
err = -ENOMEM;
- if (err == 0 && result)
+ if (err == 0 && result) {
*result = res;
+ } else {
+ delete_tree(instance, res);
+ }
return 0;
}
+void alsa_lisp_result_free(struct alisp_instance *instance,
+ struct alisp_seq_iterator *result)
+{
+ delete_tree(instance, result);
+}
+
int alsa_lisp_seq_first(struct alisp_instance *instance, const char *id,
struct alisp_seq_iterator **seq)
{
diff --git a/src/conf/cards/SI7018/sndoc-mixer.alisp b/src/conf/cards/SI7018/sndoc-mixer.alisp
index 2bea45c0..5f6047ae 100644
--- a/src/conf/cards/SI7018/sndoc-mixer.alisp
+++ b/src/conf/cards/SI7018/sndoc-mixer.alisp
@@ -1,4 +1,11 @@
-(defun sndoc_mixer_open (hctl)
- (princ "sndoc_mixer_open\n")
+;
+; SiS SI7018 mixer abstract layer
+;
+; Copyright (c) 2003 Jaroslav Kysela <perex@suse.cz>
+; License: GPL v2 (http://www.gnu.org/licenses/gpl.html)
+;
+
+(defun sndoc_mixer_open (hctl pcm)
+ (princ "sndoc_mixer_open: hctl=" hctl " pcm=" pcm "\n")
0
)
diff --git a/src/conf/cards/SI7018/sndop-mixer.alisp b/src/conf/cards/SI7018/sndop-mixer.alisp
index 26dc9ad9..4c5b65c6 100644
--- a/src/conf/cards/SI7018/sndop-mixer.alisp
+++ b/src/conf/cards/SI7018/sndop-mixer.alisp
@@ -1,4 +1,11 @@
-(defun sndop_mixer_open (hctl)
- (princ "sndop_mixer_open\n")
+;
+; SiS SI7018 mixer abstract layer
+;
+; Copyright (c) 2003 Jaroslav Kysela <perex@suse.cz>
+; License: GPL v2 (http://www.gnu.org/licenses/gpl.html)
+;
+
+(defun sndop_mixer_open (hctl pcm)
+ (princ "sndop_mixer_open: hctl=" hctl " pcm=" pcm "\n")
0
)
diff --git a/src/conf/cards/aliases.alisp b/src/conf/cards/aliases.alisp
index 3ab21e76..cff78f7a 100644
--- a/src/conf/cards/aliases.alisp
+++ b/src/conf/cards/aliases.alisp
@@ -1,20 +1,20 @@
(setq snd_card_aliases_array
(
- ("YMF724" . "YMF744")
- ("YMF724F" . "YMF744")
- ("YMF740" . "YMF744")
- ("YMF740C" . "YMF744")
- ("YMF754" . "YMF744")
- ("CMIPCI" . "CMI8338")
- ("CMI8738" . "CMI8338")
- ("CMI8738-MC4" . "CMI8738-MC6")
- ("E-mu APS" . "EMU10K1")
- ("GUS Max" . "GUS")
- ("GUS ACE" . "GUS")
- ("GUS Extreme" . "GUS")
- ("AMD InterWave" . "GUS")
- ("Dynasonic 3-D" . "GUS")
- ("InterWave STB" . "GUS")
+ ("YMF724" . "YMF744")
+ ("YMF724F" . "YMF744")
+ ("YMF740" . "YMF744")
+ ("YMF740C" . "YMF744")
+ ("YMF754" . "YMF744")
+ ("CMIPCI" . "CMI8338")
+ ("CMI8738" . "CMI8338")
+ ("CMI8738-MC4" . "CMI8738-MC6")
+ ("E-mu APS" . "EMU10K1")
+ ("GUS Max" . "GUS")
+ ("GUS ACE" . "GUS")
+ ("GUS Extreme" . "GUS")
+ ("AMD InterWave" . "GUS")
+ ("Dynasonic 3-D" . "GUS")
+ ("InterWave STB" . "GUS")
)
)
diff --git a/src/conf/sndo-mixer.alisp b/src/conf/sndo-mixer.alisp
index b125b6e7..adf7c977 100644
--- a/src/conf/sndo-mixer.alisp
+++ b/src/conf/sndo-mixer.alisp
@@ -1,6 +1,9 @@
;
; Toplevel configuration for the ALSA Ordinary Mixer Interface
;
+; Copyright (c) 2003 Jaroslav Kysela <perex@suse.cz>
+; License: GPL v2 (http://www.gnu.org/licenses/gpl.html)
+;
(defun sndo_include (hctl stream)
(setq info (Acall "ctl_card_info" (Acall "hctl_ctl" hctl)))
@@ -8,7 +11,7 @@
(progn
(setq info (Aresult info))
(setq driver (cdr (assq "driver" (unsetq info))))
- (setq file (+ (path "data") "/alsa/cards/" (snd_card_alias driver) "/sndo" stream "-mixer.alisp"))
+ (setq file (concat (path "data") "/alsa/cards/" (snd_card_alias driver) "/sndo" stream "-mixer.alisp"))
(setq r (include file))
(when (= r -2) (Asyserr "unable to find file " file))
)
@@ -17,36 +20,55 @@
(unsetq info driver file r)
)
-(defun sndo_mixer_open_fcn (stream)
- (setq fcn (+ "sndo" stream "_mixer_open"))
- (setq r (if (exfun fcn) (call fcn hctl) 0))
+(defun sndo_mixer_open_fcn (hctl stream pcm)
+ (setq fcn (concat "sndo" stream "_mixer_open"))
+ (setq r (if (exfun fcn) (funcall fcn hctl pcm) 0))
(when (= r 0)
(setq hctls (if hctls (cons hctls (cons hctl)) hctl))
)
(unsetq fcn r)
)
-(defun sndo_mixer_open_hctl (card stream)
- (setq hctl (Acall "hctl_open" (+ "hw:" (str card)) nil))
+(defun sndo_mixer_open_hctl (name stream pcm)
+ (setq hctl (Acall "hctl_open" name nil))
(setq r (Aerror hctl))
(when (= r 0)
(setq hctl (Aresult hctl))
(setq r (sndo_include hctl stream))
- (when (= r 0) (setq r (sndo_mixer_open_fcn stream)))
+ (if (= r 0)
+ (setq r (sndo_mixer_open_fcn hctl stream pcm))
+ (Acall "hctl_close" hctl)
+ )
)
(unsetq hctl r)
)
-(defun sndo_mixer_open_virtual (pcm stream)
- (setq name (Acall "pcm_name" pcm))
- (setq file (+ (path "data") "/alsa/virtual/" name "/sndo" stream "-mixer.alisp"))
+(defun sndo_mixer_open_virtual (name stream pcm)
+ (setq file (concat (path "data") "/alsa/virtual/" name "/sndo" stream "-mixer.alisp"))
(setq r (include file))
(when (= r -2) (Asyserr "unable to find file " file))
- (when (= r 0) (setq r (sndo_mixer_open_fcn stream)))
- (unsetq name file r)
+ (when (= r 0) (setq r (sndo_mixer_open_fcn nil stream pcm)))
+ (unsetq file r)
+)
+
+(defun sndo_mixer_open1 (name stream)
+ (if (compare-strings name 0 2 "hw:" 0 2)
+ (sndo_mixer_open_hctl name stream nil)
+ (sndo_mixer_open_virtual name stream nil)
+ )
+)
+
+(defun sndo_mixer_open (pname cname)
+ (setq r (sndo_mixer_open1 pname "p"))
+ (when (= r 0) (setq r (sndo_mixer_open1 cname "c")))
+ (when (!= r 0) (sndo_mixer_close))
+ (unsetq sndo_mixer_open
+ sndo_mixer_open_pcm sndo_mixer_open_pcm1
+ sndo_mixer_open_virtual sndo_mixer_open_fcn
+ sndo_include r)
)
-(defun sndo_mixer_open1 (pcm stream)
+(defun sndo_mixer_open_pcm1 (pcm stream)
(setq info (Acall "pcm_info" pcm))
(setq r (Aerror info))
(when (= r 0)
@@ -54,19 +76,20 @@
(setq card (cdr (assq "card" info)))
(setq r
(if (< card 0)
- (sndo_mixer_open_virtual pcm stream)
- (sndo_mixer_open_hctl card stream)
+ (sndo_mixer_open_virtual (Acall "pcm_name" pcm) stream pcm)
+ (sndo_mixer_open_hctl (format "hw:%i" card) stream pcm)
)
)
)
(unsetq info card r)
)
-(defun sndo_mixer_open (ppcm cpcm)
- (setq r (sndo_mixer_open1 ppcm "p"))
- (when (= r 0) (setq r (sndo_mixer_open1 cpcm "c")))
+(defun sndo_mixer_open_pcm (ppcm cpcm)
+ (setq r (sndo_mixer_open_pcm1 ppcm "p"))
+ (when (= r 0) (setq r (sndo_mixer_open_pcm1 cpcm "c")))
(when (!= r 0) (sndo_mixer_close))
- (unsetq sndo_mixer_open sndo_mixer_open1
+ (unsetq sndo_mixer_open
+ sndo_mixer_open_pcm sndo_mixer_open_pcm1
sndo_mixer_open_virtual sndo_mixer_open_fcn
sndo_include r)
)
@@ -74,8 +97,8 @@
(defun sndo_mixer_close1 (hctl stream)
(when hctl
(progn
- (setq fcn (+ "sndo" stream "_mixer_close"))
- (when (exfun fcn) (call fcn hctl))
+ (setq fcn (concat "sndo" stream "_mixer_close"))
+ (when (exfun fcn) (funcall fcn hctl))
(unsetq fcn)
(Acall "hctl_close" hctl)
)
@@ -88,4 +111,4 @@
(unsetq hctls)
)
-(include (+ (path "data") "/alsa/cards/aliases.alisp"))
+(include (concat (path "data") "/alsa/cards/aliases.alisp"))
diff --git a/src/ordinary_mixer/ordinary_mixer.c b/src/ordinary_mixer/ordinary_mixer.c
index fe9eb4d5..d5d3c266 100644
--- a/src/ordinary_mixer/ordinary_mixer.c
+++ b/src/ordinary_mixer/ordinary_mixer.c
@@ -67,18 +67,12 @@ struct sndo_mixer {
int _free_cfg;
};
-/**
- * \brief Opens a ordinary mixer instance
- * \param pmixer Returned ordinary mixer handle
- * \param playback_pcm handle of the playback PCM
- * \param capture_pcm handle of the capture PCM
- * \param lconf Local configuration (might be NULL - use global configuration)
- * \return 0 on success otherwise a negative error code
- */
-int sndo_mixer_open(sndo_mixer_t **pmixer,
- snd_pcm_t *playback_pcm,
- snd_pcm_t *capture_pcm,
- struct alisp_cfg *lconf)
+int sndo_mixer_open1(sndo_mixer_t **pmixer,
+ const char *lisp_fcn,
+ const char *lisp_fmt,
+ const void *parg,
+ const void *carg,
+ struct alisp_cfg *lconf)
{
struct alisp_cfg *cfg = lconf;
struct alisp_instance *alisp;
@@ -101,16 +95,16 @@ int sndo_mixer_open(sndo_mixer_t **pmixer,
cfg = alsa_lisp_default_cfg(input);
if (cfg == NULL)
return -ENOMEM;
+ cfg->warning = 1;
#if 0
cfg->debug = 1;
cfg->verbose = 1;
- cfg->warning = 1;
#endif
}
err = alsa_lisp(cfg, &alisp);
if (err < 0)
goto __error;
- err = alsa_lisp_function(alisp, &iterator, "sndo_mixer_open", "%ppcm%ppcm", playback_pcm, capture_pcm);
+ err = alsa_lisp_function(alisp, &iterator, lisp_fcn, lisp_fmt, parg, carg);
if (err < 0) {
alsa_lisp_free(alisp);
goto __error;
@@ -118,6 +112,7 @@ int sndo_mixer_open(sndo_mixer_t **pmixer,
err = alsa_lisp_seq_integer(iterator, &val);
if (err == 0 && val < 0)
err = val;
+ alsa_lisp_result_free(alisp, iterator);
if (err < 0) {
alsa_lisp_free(alisp);
goto __error;
@@ -158,6 +153,39 @@ int sndo_mixer_open(sndo_mixer_t **pmixer,
}
/**
+ * \brief Opens a ordinary mixer instance
+ * \param pmixer Returned ordinary mixer handle
+ * \param playback_name name for playback HCTL communication
+ * \param capture_name name for capture HCTL communication
+ * \param lconf Local configuration (might be NULL - use global configuration)
+ * \return 0 on success otherwise a negative error code
+ */
+int sndo_mixer_open(sndo_mixer_t **pmixer,
+ const char *playback_name,
+ const char *capture_name,
+ struct alisp_cfg *lconf)
+{
+ return sndo_mixer_open1(pmixer, "sndo_mixer_open", "%s%s", playback_name, capture_name, lconf);
+}
+
+
+/**
+ * \brief Opens a ordinary mixer instance
+ * \param pmixer Returned ordinary mixer handle
+ * \param playback_pcm handle of the playback PCM
+ * \param capture_pcm handle of the capture PCM
+ * \param lconf Local configuration (might be NULL - use global configuration)
+ * \return 0 on success otherwise a negative error code
+ */
+int sndo_mixer_open_pcm(sndo_mixer_t **pmixer,
+ snd_pcm_t *playback_pcm,
+ snd_pcm_t *capture_pcm,
+ struct alisp_cfg *lconf)
+{
+ return sndo_mixer_open1(pmixer, "sndo_mixer_open_pcm", "%ppcm%ppcm", playback_pcm, capture_pcm, lconf);
+}
+
+/**
* \brief Closes a ordinary mixer instance
* \param mixer Ordinary mixer handle to close
* \return 0 on success otherwise a negative error code
diff --git a/test/omixer.c b/test/omixer.c
index 1f4b2e1c..119fa331 100644
--- a/test/omixer.c
+++ b/test/omixer.c
@@ -27,7 +27,7 @@ int main(int argc, char *argv[])
{"cname", 1, NULL, 'C'},
{NULL, 0, NULL, 0},
};
- int err, morehelp;
+ int err, morehelp, result = EXIT_SUCCESS;
char *pname = "default", *cname = "default";
snd_pcm_t *phandle = NULL, *chandle = NULL;
sndo_mixer_t *handle;
@@ -59,7 +59,8 @@ int main(int argc, char *argv[])
err = snd_pcm_open(&phandle, pname, SND_PCM_STREAM_PLAYBACK, 0);
if (err < 0) {
fprintf(stderr, "Playback PCM open error: %s\n", snd_strerror(err));
- return EXIT_FAILURE;
+ result = EXIT_FAILURE;
+ goto __end;
}
}
@@ -69,17 +70,23 @@ int main(int argc, char *argv[])
if (phandle)
snd_pcm_close(phandle);
fprintf(stderr, "Capture PCM open error: %s\n", snd_strerror(err));
- return EXIT_FAILURE;
+ result = EXIT_FAILURE;
+ goto __end;
}
}
- err = sndo_mixer_open(&handle, phandle, chandle, NULL);
+ err = sndo_mixer_open_pcm(&handle, phandle, chandle, NULL);
if (err < 0) {
fprintf(stderr, "mixer open error: %s\n", snd_strerror(err));
- return EXIT_FAILURE;
+ result = EXIT_FAILURE;
+ } else {
+ sndo_mixer_close(handle);
}
- sndo_mixer_close(handle);
- snd_pcm_close(chandle);
- snd_pcm_close(phandle);
- return EXIT_SUCCESS;
+ __end:
+ if (chandle)
+ snd_pcm_close(chandle);
+ if (phandle)
+ snd_pcm_close(phandle);
+ snd_config_update_free_global(); /* to keep valgrind happy */
+ return result;
}