aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--alsalisp/hctl.lisp5
-rw-r--r--include/alisp.h19
-rw-r--r--include/global.h5
-rw-r--r--include/mixer_ordinary.h3
-rw-r--r--src/Makefile.am2
-rw-r--r--src/Versions8
-rw-r--r--src/alisp/alisp.c491
-rw-r--r--src/conf.c41
-rw-r--r--src/ordinary_mixer/ordinary_mixer.c114
-rw-r--r--test/Makefile.am3
-rw-r--r--test/control.c2
-rw-r--r--test/omixer.c64
-rw-r--r--test/pcm.c2
13 files changed, 667 insertions, 92 deletions
diff --git a/alsalisp/hctl.lisp b/alsalisp/hctl.lisp
index 2d040411..6348d7bb 100644
--- a/alsalisp/hctl.lisp
+++ b/alsalisp/hctl.lisp
@@ -88,3 +88,8 @@
(&stat-memory)
(&dump-memory "memory.dump")
+
+(defun autotest () (princ "abcd\n"))
+(setq auto-exec 'autotest)
+
+(princ (path 'data) "\n")
diff --git a/include/alisp.h b/include/alisp.h
index 1bc88a77..f8423d34 100644
--- a/include/alisp.h
+++ b/include/alisp.h
@@ -32,9 +32,22 @@ struct alisp_cfg {
};
struct alisp_instance;
+struct alisp_object;
+struct alisp_seq_iterator;
+struct alisp_cfg *alsa_lisp_default_cfg(snd_input_t *input);
+void alsa_lisp_default_cfg_free(struct alisp_cfg *cfg);
int alsa_lisp(struct alisp_cfg *cfg, struct alisp_instance **instance);
void alsa_lisp_free(struct alisp_instance *instance);
-
-extern struct alisp_object alsa_lisp_nil;
-extern struct alisp_object alsa_lisp_t;
+int alsa_lisp_function(struct alisp_instance *instance, struct alisp_seq_iterator **result,
+ const char *id, const char *args, ...)
+#ifndef DOC_HIDDEN
+ __attribute__ ((format (printf, 4, 5)))
+#endif
+ ;
+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);
+int alsa_lisp_seq_count(struct alisp_seq_iterator *seq);
+int alsa_lisp_seq_integer(struct alisp_seq_iterator *seq, long *val);
+int alsa_lisp_seq_pointer(struct alisp_seq_iterator *seq, const char *ptr_id, void **ptr);
diff --git a/include/global.h b/include/global.h
index 60a6737d..f6b5fc3e 100644
--- a/include/global.h
+++ b/include/global.h
@@ -119,13 +119,12 @@ int snd_async_handler_get_fd(snd_async_handler_t *handler);
int snd_async_handler_get_signo(snd_async_handler_t *handler);
void *snd_async_handler_get_callback_private(snd_async_handler_t *handler);
-/**
- * \brief Internal structure for an IPC shm area manager.
- */
struct snd_shm_area *snd_shm_area_create(int shmid, void *ptr);
struct snd_shm_area *snd_shm_area_share(struct snd_shm_area *area);
int snd_shm_area_destroy(struct snd_shm_area *area);
+int snd_user_file(const char *file, char **result);
+
/** Timestamp */
typedef struct timeval snd_timestamp_t;
/** Hi-res timestamp */
diff --git a/include/mixer_ordinary.h b/include/mixer_ordinary.h
index e8dd0db2..940d7ac9 100644
--- a/include/mixer_ordinary.h
+++ b/include/mixer_ordinary.h
@@ -95,6 +95,7 @@ enum sndo_mixer_io_type {
};
typedef struct sndo_mixer sndo_mixer_t;
+struct alisp_cfg;
#ifdef __cplusplus
extern "C" {
@@ -106,7 +107,7 @@ extern "C" {
* \{
*/
-int sndo_mixer_open(sndo_mixer_t **pmixer, const char *playback_name, const char *capture_name, snd_config_t *lconf);
+int sndo_mixer_open(sndo_mixer_t **pmixer, const char *playback_name, const char *capture_name, 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/Makefile.am b/src/Makefile.am
index 2851d222..da73e6ca 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -9,7 +9,7 @@ VSYMS =
endif
lib_LTLIBRARIES = libasound.la
-libasound_la_SOURCES = conf.c confmisc.c input.c output.c async.c error.c dlmisc.c socket.c shmarea.c
+libasound_la_SOURCES = conf.c confmisc.c input.c output.c async.c error.c dlmisc.c socket.c shmarea.c userfile.c
libasound_la_LIBADD = control/libcontrol.la \
mixer/libmixer.la ordinary_mixer/libordinarymixer.la \
pcm/libpcm.la ordinary_pcm/libordinarypcm.la \
diff --git a/src/Versions b/src/Versions
index 62a20bc8..4e6a7eab 100644
--- a/src/Versions
+++ b/src/Versions
@@ -126,3 +126,11 @@ ALSA_0.9.6 {
snd_seq_port_info_set_timestamp_real;
snd_seq_port_info_set_timestamp_queue;
} ALSA_0.9.5;
+
+ALSA_0.9.7 {
+ global:
+
+ snd_user_file;
+ sndo_*;
+ alsa_lisp_*;
+} ALSA_0.9.6;
diff --git a/src/alisp/alisp.c b/src/alisp/alisp.c
index e13ff53d..2321c7f3 100644
--- a/src/alisp/alisp.c
+++ b/src/alisp/alisp.c
@@ -30,11 +30,15 @@
#include <ctype.h>
#include <math.h>
#include <err.h>
+#include <wordexp.h>
+
+#define alisp_seq_iterator alisp_object
#include "local.h"
#include "alisp.h"
#include "alisp_local.h"
+
#define ALISP_FREE_OBJ_POOL 500 /* free objects above this pool */
#define ALISP_AUTO_GC_THRESHOLD 200 /* run automagically garbage-collect when this threshold is reached */
#define ALISP_MAIN_ID "---alisp---main---"
@@ -52,6 +56,9 @@ static struct alisp_object * eval(struct alisp_instance *instance, struct alisp_
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 *);
+/* others */
+static int alisp_include_file(struct alisp_instance *instance, const char *filename);
+
/*
* object handling
*/
@@ -655,13 +662,13 @@ static struct alisp_object_pair * set_object(struct alisp_instance *instance, st
return p;
}
-static void unset_object(struct alisp_instance *instance, struct alisp_object * name)
+static void unset_object1(struct alisp_instance *instance, const char *id)
{
struct alisp_object_pair *p, *p1;
for (p = instance->setobjs_list, p1 = NULL; p != NULL; p1 = p, p = p->next) {
if (p->name->value.id != NULL &&
- !strcmp(name->value.id, p->name->value.id)) {
+ !strcmp(id, p->name->value.id)) {
if (p1)
p1->next = p->next;
else
@@ -672,18 +679,28 @@ static void unset_object(struct alisp_instance *instance, struct alisp_object *
}
}
-static struct alisp_object * get_object(struct alisp_instance *instance, struct alisp_object * name)
+static inline void unset_object(struct alisp_instance *instance, struct alisp_object * name)
+{
+ return unset_object1(instance, name->value.id);
+}
+
+static struct alisp_object * get_object1(struct alisp_instance *instance, const char *id)
{
struct alisp_object_pair *p;
for (p = instance->setobjs_list; p != NULL; p = p->next)
if (p->name->value.id != NULL &&
- !strcmp(name->value.id, p->name->value.id))
+ !strcmp(id, p->name->value.id))
return p->value;
return &alsa_lisp_nil;
}
+static inline struct alisp_object * get_object(struct alisp_instance *instance, struct alisp_object * name)
+{
+ return get_object1(instance, name->value.id);
+}
+
static void dump_objects(struct alisp_instance *instance, const char *fname)
{
struct alisp_object_pair *p;
@@ -910,32 +927,60 @@ 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;
- long v = 0;
- double f = 0;
- int type = ALISP_OBJ_INTEGER;
- do {
- p1 = eval(instance, car(p));
- if (p1->type == ALISP_OBJ_INTEGER) {
- if (type == ALISP_OBJ_FLOAT)
- f += p1->value.i;
- else
- v += p1->value.i;
- } else if (p1->type == ALISP_OBJ_FLOAT) {
- f += p1->value.f + v;
- v = 0;
- type = ALISP_OBJ_FLOAT;
+ p1 = eval(instance, car(p));
+ if (p1->type == ALISP_OBJ_INTEGER || p1->type == ALISP_OBJ_FLOAT) {
+ long v = 0;
+ double f = 0;
+ int type = ALISP_OBJ_INTEGER;
+ for (;;) {
+ if (p1->type == ALISP_OBJ_INTEGER) {
+ if (type == ALISP_OBJ_FLOAT)
+ f += p1->value.i;
+ else
+ v += p1->value.i;
+ } else if (p1->type == 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");
+ }
+ p = cdr(p);
+ if (p == &alsa_lisp_nil)
+ break;
+ p1 = eval(instance, car(p));
+ }
+ if (type == ALISP_OBJ_INTEGER) {
+ return new_integer(instance, v);
} else {
- lisp_warn(instance, "sum with a non integer or float operand");
+ return new_float(instance, f);
}
- p = cdr(p);
- } while (p != &alsa_lisp_nil);
-
- if (type == ALISP_OBJ_INTEGER) {
- return new_integer(instance, v);
- } else {
- return new_float(instance, f);
+ } else if (p1->type == ALISP_OBJ_STRING || p1->type == ALISP_OBJ_IDENTIFIER) {
+ char *str = NULL, *str1;
+ for (;;) {
+ if (p1->type == ALISP_OBJ_STRING || p1->type == ALISP_OBJ_IDENTIFIER) {
+ str1 = realloc(str, strlen(str) + strlen(p1->value.s) + 1);
+ if (str1 == NULL) {
+ nomem();
+ if (str)
+ free(str);
+ return NULL;
+ }
+ strcat(str, p1->value.s);
+ } else {
+ lisp_warn(instance, "concat with a non string or identifier operand");
+ }
+ p = cdr(p);
+ if (p == &alsa_lisp_nil)
+ break;
+ p1 = eval(instance, car(p));
+ }
+ p = new_string(instance, str);
+ free(str);
+ return p;
}
+ return &alsa_lisp_nil;
}
/*
@@ -1753,7 +1798,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 * eval_objs[64], * save_objs[64];
+ struct alisp_object ** eval_objs, ** save_objs;
int i;
p1 = car(p);
@@ -1761,33 +1806,40 @@ static struct alisp_object * eval_func(struct alisp_instance *instance, struct a
p2 = car(cdr(p));
p3 = args;
- if (count_list(p2) != count_list(p3)) {
+ if ((i = count_list(p2)) != count_list(p3)) {
lisp_warn(instance, "wrong number of parameters");
return &alsa_lisp_nil;
}
+ eval_objs = malloc(2 * i * sizeof(struct alisp_object *));
+ if (eval_objs == NULL) {
+ nomem();
+ goto _err;
+ }
+ save_objs = eval_objs + i;
+
/*
* Save the new variable values.
*/
i = 0;
- do {
+ while (p3 != &alsa_lisp_nil) {
p5 = eval(instance, car(p3));
eval_objs[i++] = p5;
p3 = cdr(p3);
- } while (p3 != &alsa_lisp_nil);
+ }
/*
* Save the old variable values and set the new ones.
*/
i = 0;
- do {
+ while (p2 != &alsa_lisp_nil) {
p4 = car(p2);
save_objs[i] = get_object(instance, p4);
if (set_object(instance, p4, eval_objs[i]) == NULL)
- return NULL;
+ goto _err;
p2 = cdr(p2);
++i;
- } while (p2 != &alsa_lisp_nil);
+ }
p5 = F_progn(instance, cdr(cdr(p)));
@@ -1796,17 +1848,25 @@ static struct alisp_object * eval_func(struct alisp_instance *instance, struct a
*/
p2 = car(cdr(p));
i = 0;
- do {
+ while (p2 != &alsa_lisp_nil) {
p4 = car(p2);
if (set_object(instance, p4, save_objs[i++]) == NULL)
return NULL;
p2 = cdr(p2);
- } while (p2 != &alsa_lisp_nil);
+ }
+
+ if (eval_objs)
+ free(eval_objs);
return p5;
}
return &alsa_lisp_nil;
+
+ _err:
+ if (eval_objs)
+ free(eval_objs);
+ return NULL;
}
struct alisp_object * F_gc(struct alisp_instance *instance, struct alisp_object * args ATTRIBUTE_UNUSED)
@@ -1817,6 +1877,39 @@ struct alisp_object * F_gc(struct alisp_instance *instance, struct alisp_object
}
/*
+ * Syntax: (path what)
+ * what is string ('data')
+ */
+struct alisp_object * F_path(struct alisp_instance *instance, struct alisp_object * args)
+{
+ struct alisp_object * p = args, * p1;
+
+ p1 = eval(instance, car(p));
+ if (p1->type != ALISP_STRING && p1->type != ALISP_IDENTIFIER)
+ return &alsa_lisp_nil;
+ if (!strcmp(p1->value.s, "data"))
+ return new_string(instance, DATADIR);
+ return &alsa_lisp_nil;
+}
+
+/*
+ * Syntax: (include filename...)
+ */
+struct alisp_object * F_include(struct alisp_instance *instance, struct alisp_object * args)
+{
+ struct alisp_object * p = args, * p1;
+
+ do {
+ p1 = eval(instance, car(p));
+ if (p1->type == ALISP_STRING && p1->type == ALISP_IDENTIFIER)
+ alisp_include_file(instance, p1->value.s);
+ p = cdr(p);
+ } while (p != &alsa_lisp_nil);
+
+ return p1;
+}
+
+/*
* Syntax: (int value)
* 'value' can be integer or float type
*/
@@ -1932,6 +2025,27 @@ struct alisp_object * F_assq(struct alisp_instance *instance, struct alisp_objec
}
/*
+ * Syntax: (nth index alist)
+ */
+struct alisp_object * F_nth(struct alisp_instance *instance, struct alisp_object * args)
+{
+ struct alisp_object * p1, * p2;
+ long idx;
+
+ p1 = eval(instance, car(args));
+ p2 = eval(instance, car(cdr(args)));
+
+ if (p1->type != ALISP_OBJ_INTEGER)
+ return &alsa_lisp_nil;
+ if (p2->type != ALISP_OBJ_CONS)
+ return &alsa_lisp_nil;
+ idx = p1->value.i;
+ while (idx-- > 0)
+ p2 = cdr(p2);
+ return car(p2);
+}
+
+/*
* Syntax: (rassq value alist)
*/
struct alisp_object * F_rassq(struct alisp_instance *instance, struct alisp_object * args)
@@ -2031,10 +2145,13 @@ static struct intrinsic intrinsics[] = {
{ "gc", F_gc },
{ "if", F_if },
{ "int", F_int },
+ { "include", F_include },
{ "list", F_list },
{ "not", F_not },
+ { "nth", F_nth },
{ "null", F_not },
{ "or", F_or },
+ { "path", F_path },
{ "princ", F_princ },
{ "prog1", F_prog1 },
{ "prog2", F_prog2 },
@@ -2087,7 +2204,6 @@ static struct alisp_object * eval_cons(struct alisp_instance *instance, struct a
sizeof snd_intrinsics[0], compar)) != NULL)
return item->func(instance, p2);
-
if ((p3 = get_object(instance, p1)) != &alsa_lisp_nil)
return eval_func(instance, p3, p2);
else
@@ -2120,12 +2236,91 @@ static struct alisp_object * F_eval(struct alisp_instance *instance, struct alis
/*
* main routine
*/
+
+static int alisp_include_file(struct alisp_instance *instance, const char *filename)
+{
+ snd_input_t *old_in;
+ struct alisp_object *p, *p1, *omain;
+ struct alisp_object_pair *pmain;
+ char *name, *uname;
+ int retval = 0, err;
+
+ err = snd_user_file(filename, &name);
+ if (err < 0)
+ return err;
+ old_in = instance->in;
+ err = snd_input_stdio_open(&instance->in, name, "r");
+ if (err < 0) {
+ retval = err;
+ goto _err;
+ }
+ if (instance->verbose)
+ lisp_verbose(instance, "** include filename '%s'", name);
+ uname = malloc(sizeof(ALISP_MAIN_ID) + strlen(name) + 2);
+ if (uname == NULL) {
+ retval = -ENOMEM;
+ goto _err;
+ }
+ strcpy(uname, ALISP_MAIN_ID);
+ strcat(uname, "-");
+ strcat(uname, name);
+ omain = new_identifier(instance, uname);
+ free(uname);
+ if (omain == NULL) {
+ retval = -ENOMEM;
+ goto _err;
+ }
+ pmain = set_object(instance, omain, &alsa_lisp_t);
+ if (pmain == NULL) {
+ retval = -ENOMEM;
+ goto _err;
+ }
+
+ for (;;) {
+ if ((p = parse_object(instance, 0)) == NULL)
+ break;
+ if (instance->verbose) {
+ lisp_verbose(instance, "** code");
+ princ_object(instance->vout, p);
+ snd_output_putc(instance->vout, '\n');
+ }
+ pmain->value = p; /* protect the code tree from garbage-collect */
+ p1 = eval(instance, p);
+ if (p1 == NULL) {
+ retval = -ENOMEM;
+ break;
+ }
+ if (instance->verbose) {
+ lisp_verbose(instance, "** result");
+ princ_object(instance->vout, p1);
+ snd_output_putc(instance->vout, '\n');
+ }
+ if (instance->debug) {
+ lisp_debug(instance, "** objects before collection");
+ print_obj_lists(instance, instance->dout);
+ }
+ pmain->value = &alsa_lisp_t; /* let garbage-collect working */
+ garbage_collect(instance);
+ if (instance->debug) {
+ lisp_debug(instance, "** objects after collection");
+ print_obj_lists(instance, instance->dout);
+ }
+ }
+
+ unset_object(instance, omain);
+
+ _err:
+ free(name);
+ instance->in = old_in;
+ return retval;
+}
int alsa_lisp(struct alisp_cfg *cfg, struct alisp_instance **_instance)
{
struct alisp_instance *instance;
struct alisp_object *p, *p1, *omain;
struct alisp_object_pair *pmain;
+ int retval = 0;
instance = (struct alisp_instance *)malloc(sizeof(struct alisp_instance));
if (instance == NULL) {
@@ -2167,7 +2362,10 @@ int alsa_lisp(struct alisp_cfg *cfg, struct alisp_instance **_instance)
}
pmain->value = p; /* protect the code tree from garbage-collect */
p1 = eval(instance, p);
- pmain->value = &alsa_lisp_t; /* let garbage-collect working */
+ if (p1 == NULL) {
+ retval = -ENOMEM;
+ break;
+ }
if (instance->verbose) {
lisp_verbose(instance, "** result");
princ_object(instance->vout, p1);
@@ -2177,6 +2375,7 @@ int alsa_lisp(struct alisp_cfg *cfg, struct alisp_instance **_instance)
lisp_debug(instance, "** objects before collection");
print_obj_lists(instance, instance->dout);
}
+ pmain->value = &alsa_lisp_t; /* let garbage-collect working */
garbage_collect(instance);
if (instance->debug) {
lisp_debug(instance, "** objects after collection");
@@ -2186,6 +2385,22 @@ int alsa_lisp(struct alisp_cfg *cfg, struct alisp_instance **_instance)
unset_object(instance, omain);
+ for (;;) {
+ p = get_object1(instance, "auto-exec");
+ if (p == &alsa_lisp_nil)
+ break;
+ p = get_object(instance, p);
+ if (p == &alsa_lisp_nil)
+ break;
+ unset_object1(instance, "auto-exec");
+ p1 = eval_func(instance, p, &alsa_lisp_nil);
+ if (p1 == NULL) {
+ retval = -ENOMEM;
+ break;
+ }
+ garbage_collect(instance);
+ }
+
done_lex(instance);
if (_instance)
*_instance = instance;
@@ -2202,3 +2417,205 @@ void alsa_lisp_free(struct alisp_instance *instance)
free_objects(instance);
free(instance);
}
+
+struct alisp_cfg *alsa_lisp_default_cfg(snd_input_t *input)
+{
+ snd_output_t *output, *eoutput;
+ struct alisp_cfg *cfg;
+ int err;
+
+ err = snd_output_stdio_attach(&output, stdout, 0);
+ if (err < 0)
+ return NULL;
+ err = snd_output_stdio_attach(&eoutput, stderr, 0);
+ if (err < 0) {
+ snd_output_close(output);
+ return NULL;
+ }
+ cfg = calloc(1, sizeof(struct alisp_cfg));
+ if (cfg == NULL) {
+ snd_output_close(eoutput);
+ snd_output_close(output);
+ return NULL;
+ }
+ cfg->out = output;
+ cfg->wout = eoutput;
+ cfg->eout = eoutput;
+ cfg->dout = eoutput;
+ cfg->in = input;
+ return cfg;
+}
+
+void alsa_lisp_default_cfg_free(struct alisp_cfg *cfg)
+{
+ snd_input_close(cfg->in);
+ snd_output_close(cfg->out);
+ snd_output_close(cfg->dout);
+ free(cfg);
+}
+
+int alsa_lisp_function(struct alisp_instance *instance, struct alisp_seq_iterator **result,
+ const char *id, const char *args, ...)
+{
+ int err = 0;
+ struct alisp_object *aargs = NULL, *p3, *res;
+
+ if (args && *args != 'n') {
+ va_list ap;
+ struct alisp_object *p, *obj;
+ p = NULL;
+ va_start(ap, args);
+ while (*args) {
+ if (*args++ != '%') {
+ err = -EINVAL;
+ break;
+ }
+ if (*args == '\0') {
+ err = -EINVAL;
+ break;
+ }
+ obj = NULL;
+ err = 0;
+ switch (*args++) {
+ case 's':
+ obj = new_string(instance, va_arg(ap, char *));
+ break;
+ case 'i':
+ obj = new_integer(instance, va_arg(ap, int));
+ break;
+ case 'l':
+ obj = new_integer(instance, va_arg(ap, long));
+ break;
+ case 'f':
+ case 'd':
+ obj = new_integer(instance, va_arg(ap, double));
+ break;
+ default:
+ err = -EINVAL;
+ break;
+ }
+ if (err < 0)
+ goto __args_end;
+ if (obj == NULL) {
+ err = -ENOMEM;
+ goto __args_end;
+ }
+ if (p == NULL) {
+ p = aargs = new_object(instance, ALISP_OBJ_CONS);
+ } else {
+ p->value.c.cdr = new_object(instance, ALISP_OBJ_CONS);
+ p = p->value.c.cdr;
+ }
+ if (p == NULL) {
+ err = -ENOMEM;
+ goto __args_end;
+ }
+ p->value.c.car = obj;
+ }
+ __args_end:
+ va_end(ap);
+ if (err < 0)
+ return err;
+#if 0
+ snd_output_printf(instance->wout, ">>>");
+ princ_object(instance->wout, aargs);
+ snd_output_printf(instance->wout, "<<<\n");
+#endif
+ }
+
+ err = -ENOENT;
+ if (aargs == NULL)
+ aargs = &alsa_lisp_nil;
+ if ((p3 = get_object1(instance, id)) != &alsa_lisp_nil) {
+ res = eval_func(instance, p3, aargs);
+ err = 0;
+ } else {
+ struct intrinsic key, *item;
+ key.name = id;
+ if ((item = bsearch(&key, intrinsics,
+ sizeof intrinsics / sizeof intrinsics[0],
+ sizeof intrinsics[0], compar)) != NULL) {
+ res = item->func(instance, aargs);
+ err = 0;
+ } else if ((item = bsearch(&key, snd_intrinsics,
+ sizeof snd_intrinsics / sizeof snd_intrinsics[0],
+ sizeof snd_intrinsics[0], compar)) != NULL) {
+ res = item->func(instance, aargs);
+ err = 0;
+ } else {
+ res = &alsa_lisp_nil;
+ }
+ }
+ if (res == NULL)
+ err = -ENOMEM;
+ if (err == 0 && result)
+ *result = res;
+
+ return 0;
+}
+
+int alsa_lisp_seq_first(struct alisp_instance *instance, const char *id,
+ struct alisp_seq_iterator **seq)
+{
+ struct alisp_object * p1;
+
+ p1 = get_object1(instance, id);
+ if (p1 == NULL)
+ return -ENOMEM;
+ *seq = p1;
+ return 0;
+}
+
+int alsa_lisp_seq_next(struct alisp_seq_iterator **seq)
+{
+ struct alisp_object * p1 = *seq;
+
+ p1 = cdr(p1);
+ if (p1 == &alsa_lisp_nil)
+ return -ENOENT;
+ *seq = p1;
+ return 0;
+}
+
+int alsa_lisp_seq_count(struct alisp_seq_iterator *seq)
+{
+ int count = 0;
+
+ while (seq != &alsa_lisp_nil) {
+ count++;
+ seq = cdr(seq);
+ }
+ return count;
+}
+
+int alsa_lisp_seq_integer(struct alisp_seq_iterator *seq, long *val)
+{
+ if (seq->type == ALISP_OBJ_CONS)
+ seq = seq->value.c.cdr;
+ if (seq->type == ALISP_OBJ_INTEGER)
+ *val = seq->value.i;
+ else
+ return -EINVAL;
+ return 0;
+}
+
+int alsa_lisp_seq_pointer(struct alisp_seq_iterator *seq, const char *ptr_id, void **ptr)
+{
+ struct alisp_object * p2;
+
+ if (seq->type == ALISP_OBJ_CONS && seq->value.c.cdr->type == ALISP_OBJ_CONS)
+ seq = seq->value.c.cdr;
+ if (seq->type == ALISP_OBJ_CONS) {
+ p2 = seq->value.c.car;
+ if (p2->type != ALISP_OBJ_STRING && p2->type != ALISP_OBJ_IDENTIFIER)
+ return -EINVAL;
+ if (strcmp(p2->value.s, ptr_id))
+ return -EINVAL;
+ p2 = seq->value.c.cdr;
+ if (p2->type != ALISP_OBJ_POINTER)
+ return -EINVAL;
+ *ptr = (void *)seq->value.ptr;
+ } else
+ return -EINVAL;
+ return 0;
+}
diff --git a/src/conf.c b/src/conf.c
index 54798f0c..7c5f9935 100644
--- a/src/conf.c
+++ b/src/conf.c
@@ -2780,30 +2780,12 @@ int snd_config_hook_load(snd_config_t *root, snd_config_t *config, snd_config_t
goto _err;
}
if (i == idx) {
- wordexp_t we;
char *name;
if ((err = snd_config_get_ascii(n, &name)) < 0)
goto _err;
- err = wordexp(name, &we, WRDE_NOCMD);
- switch (err) {
- case WRDE_NOSPACE:
- err = -ENOMEM;
+ if ((err = snd_user_file(name, &fi[idx].name)) < 0)
goto _err;
- case 0:
- if (we.we_wordc == 1)
- break;
- /* Fall through */
- default:
- err = -EINVAL;
- goto _err;
- }
- fi[idx].name = strdup(we.we_wordv[0]);
- wordfree(&we);
free(name);
- if (fi[idx].name == NULL) {
- err = -ENOMEM;
- goto _err;
- }
idx++;
hit = 1;
}
@@ -2924,7 +2906,6 @@ int snd_config_update_r(snd_config_t **_top, snd_config_update_t **_update, cons
int err;
const char *configs, *c;
unsigned int k;
- wordexp_t we;
size_t l;
snd_config_update_t *local;
snd_config_update_t *update;
@@ -2963,25 +2944,9 @@ int snd_config_update_r(snd_config_t **_top, snd_config_update_t **_update, cons
char name[l + 1];
memcpy(name, c, l);
name[l] = 0;
- err = wordexp(name, &we, WRDE_NOCMD);
- switch (err) {
- case WRDE_NOSPACE:
- err = -ENOMEM;
- goto _end;
- case 0:
- if (we.we_wordc == 1)
- break;
- /* Fall through */
- default:
- err = -EINVAL;
- goto _end;
- }
- local->finfo[k].name = strdup(we.we_wordv[0]);
- wordfree(&we);
- if (!local->finfo[k].name) {
- err = -ENOMEM;
+ err = snd_user_file(name, &local->finfo[k].name);
+ if (err < 0)
goto _end;
- }
c += l;
k++;
if (!*c)
diff --git a/src/ordinary_mixer/ordinary_mixer.c b/src/ordinary_mixer/ordinary_mixer.c
index 0e8490bf..a005aac1 100644
--- a/src/ordinary_mixer/ordinary_mixer.c
+++ b/src/ordinary_mixer/ordinary_mixer.c
@@ -56,10 +56,15 @@ Write something here
#include <sys/mman.h>
#include <limits.h>
#include "local.h"
+#include "alisp.h"
#include "mixer_ordinary.h"
struct sndo_mixer {
- snd_mixer_t *mixer;
+ struct alisp_cfg *cfg;
+ struct alisp_instance *alisp;
+ int hctl_count;
+ snd_hctl_t **hctl;
+ int _free_cfg;
};
/**
@@ -73,10 +78,78 @@ struct sndo_mixer {
int sndo_mixer_open(sndo_mixer_t **pmixer,
const char *playback_name,
const char *capture_name,
- snd_config_t *lconf)
+ struct alisp_cfg *lconf)
{
+ struct alisp_cfg *cfg = lconf;
+ struct alisp_instance *alisp;
+ struct alisp_seq_iterator *iterator;
+ sndo_mixer_t *mixer;
+ int err, count;
+ long val;
+
*pmixer = NULL;
- return -ENODEV;
+ if (cfg == NULL) {
+ char *file;
+ snd_input_t *input;
+ file = getenv("ALSA_ORDINARY_MIXER");
+ if (!file)
+ file = DATADIR "/alsa/sndo-mixer.alisp";
+ if ((err = snd_input_stdio_open(&input, file, "r")) < 0) {
+ SNDERR("unable to open alisp file '%s'", file);
+ return err;
+ }
+ cfg = alsa_lisp_default_cfg(input);
+ if (cfg == NULL)
+ return -ENOMEM;
+ }
+ err = alsa_lisp(cfg, &alisp);
+ if (err < 0)
+ goto __error;
+ err = alsa_lisp_function(alisp, &iterator, "open", "%s%s", playback_name, capture_name);
+ if (err < 0) {
+ alsa_lisp_free(alisp);
+ goto __error;
+ }
+ err = alsa_lisp_seq_integer(iterator, &val);
+ if (err == 0 && val < 0)
+ err = val;
+ if (err < 0) {
+ alsa_lisp_free(alisp);
+ goto __error;
+ }
+ count = 0;
+ if (alsa_lisp_seq_first(alisp, "hctls", &iterator) == 0) {
+ count = alsa_lisp_seq_count(iterator);
+ if (count < 0)
+ count = 0;
+ }
+ mixer = malloc(sizeof(sndo_mixer_t) + count * sizeof(snd_hctl_t *));
+ if (mixer == NULL) {
+ alsa_lisp_free(alisp);
+ err = -ENOMEM;
+ goto __error;
+ }
+ memset(mixer, 0, sizeof(sndo_mixer_t));
+ if (count > 0) {
+ mixer->hctl = (snd_hctl_t **)(mixer + 1);
+ do {
+ if (alsa_lisp_seq_pointer(iterator, "hctl", (void **)&mixer->hctl[mixer->hctl_count++]))
+ break;
+ } while (mixer->hctl_count < count && alsa_lisp_seq_next(&iterator) == 0);
+ if (mixer->hctl_count < count) {
+ mixer->hctl = NULL;
+ mixer->hctl_count = 0;
+ }
+ }
+ mixer->alisp = alisp;
+ mixer->cfg = cfg;
+ mixer->_free_cfg = cfg != lconf;
+ *pmixer = mixer;
+ return 0;
+ __error:
+ if (cfg != lconf)
+ alsa_lisp_default_cfg_free(cfg);
+ return err;
}
/**
@@ -86,7 +159,14 @@ int sndo_mixer_open(sndo_mixer_t **pmixer,
*/
int sndo_mixer_close(sndo_mixer_t *mixer)
{
- return -ENODEV;
+ int res;
+
+ res = alsa_lisp_function(mixer->alisp, NULL, "close", "n");
+ alsa_lisp_free(mixer->alisp);
+ if (mixer->_free_cfg)
+ alsa_lisp_default_cfg_free(mixer->cfg);
+ free(mixer);
+ return res;
}
/**
@@ -96,7 +176,25 @@ int sndo_mixer_close(sndo_mixer_t *mixer)
*/
int sndo_mixer_poll_descriptors_count(sndo_mixer_t *mixer)
{
- return snd_mixer_poll_descriptors_count(mixer->mixer);
+ int idx, err, res = -EIO;
+
+ if (mixer->hctl_count > 0) {
+ for (idx = 0; idx < mixer->hctl_count; idx++) {
+ err = snd_hctl_poll_descriptors_count(mixer->hctl[idx]);
+ if (err < 0)
+ return err;
+ res += err;
+ }
+ } else {
+ struct alisp_seq_iterator *result;
+ long val;
+ err = alsa_lisp_function(mixer->alisp, &result, "poll_descriptors_count", "n");
+ if (err < 0)
+ return err;
+ err = alsa_lisp_seq_integer(result, &val);
+ return err < 0 ? err : val;
+ }
+ return res;
}
/**
@@ -108,7 +206,8 @@ 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)
{
- return snd_mixer_poll_descriptors(mixer->mixer, pfds, space);
+ //return snd_mixer_poll_descriptors(mixer->mixer, pfds, space);
+ return -ENODEV;
}
/**
@@ -121,7 +220,8 @@ int sndo_mixer_poll_descriptors(sndo_mixer_t *mixer, struct pollfd *pfds, unsign
*/
int sndo_mixer_poll_descriptors_revents(sndo_mixer_t *mixer, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
{
- return snd_mixer_poll_descriptors_revents(mixer->mixer, pfds, nfds, revents);
+ //return snd_mixer_poll_descriptors_revents(mixer->mixer, pfds, nfds, revents);
+ return -ENODEV;
}
/**
diff --git a/test/Makefile.am b/test/Makefile.am
index ac354c07..3ce04041 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -1,6 +1,6 @@
check_PROGRAMS=control pcm latency seq \
playmidi1 timer rawmidi midiloop \
- code
+ omixer code
control_LDADD=../src/libasound.la
pcm_LDADD=../src/libasound.la
@@ -10,6 +10,7 @@ playmidi1_LDADD=../src/libasound.la
timer_LDADD=../src/libasound.la
rawmidi_LDADD=../src/libasound.la
midiloop_LDADD=../src/libasound.la
+omixer_LDADD=../src/libasound.la
code_CFLAGS=-Wall -pipe -g -O2
INCLUDES=-I$(top_srcdir)/include
diff --git a/test/control.c b/test/control.c
index 9fec0ea7..f4b437ee 100644
--- a/test/control.c
+++ b/test/control.c
@@ -100,5 +100,7 @@ int main(void)
}
snd_ctl_close(handle);
}
+
+ snd_config_update_free_global();
return 0;
}
diff --git a/test/omixer.c b/test/omixer.c
new file mode 100644
index 00000000..f4ffabf4
--- /dev/null
+++ b/test/omixer.c
@@ -0,0 +1,64 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sched.h>
+#include <errno.h>
+#include <getopt.h>
+#include "../include/mixer_ordinary.h"
+#include <sys/time.h>
+#include <math.h>
+
+static void help(void)
+{
+ printf(
+"Usage: omixer [OPTION]...\n"
+"-h,--help help\n"
+"-P,--pname playback device\n"
+"-C,--cname capture device\n"
+"\n");
+}
+
+int main(int argc, char *argv[])
+{
+ struct option long_option[] =
+ {
+ {"help", 0, NULL, 'h'},
+ {"pname", 1, NULL, 'P'},
+ {"cname", 1, NULL, 'C'},
+ {NULL, 0, NULL, 0},
+ };
+ int err, morehelp;
+ char *pname = "default", *cname = "default";
+ sndo_mixer_t *handle;
+
+ morehelp = 0;
+ while (1) {
+ int c;
+ if ((c = getopt_long(argc, argv, "hP:C:", long_option, NULL)) < 0)
+ break;
+ switch (c) {
+ case 'h':
+ morehelp++;
+ break;
+ case 'P':
+ pname = strdup(optarg);
+ break;
+ case 'C':
+ cname = strdup(optarg);
+ break;
+ }
+ }
+
+ if (morehelp) {
+ help();
+ return 0;
+ }
+
+ err = sndo_mixer_open(&handle, pname, cname, NULL);
+ if (err < 0) {
+ fprintf(stderr, "mixer open error: %s\n", snd_strerror(err));
+ return EXIT_FAILURE;
+ }
+ sndo_mixer_close(handle);
+ return EXIT_SUCCESS;
+}
diff --git a/test/pcm.c b/test/pcm.c
index c9185ffa..2c8e1b97 100644
--- a/test/pcm.c
+++ b/test/pcm.c
@@ -691,7 +691,7 @@ static void help(void)
{
int k;
printf(
-"Usage: latency [OPTION]... [FILE]...\n"
+"Usage: pcm [OPTION]... [FILE]...\n"
"-h,--help help\n"
"-D,--device playback device\n"
"-r,--rate stream rate in Hz\n"