mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-10-29 05:40:25 -04:00
added snd_user_file() function
alisp extensions - added nth, include, path commands - added auto-exec functionality - added helpers for C<->lisp interoperability
This commit is contained in:
parent
95418afc67
commit
6ad93ac892
13 changed files with 668 additions and 93 deletions
|
|
@ -88,3 +88,8 @@
|
||||||
|
|
||||||
(&stat-memory)
|
(&stat-memory)
|
||||||
(&dump-memory "memory.dump")
|
(&dump-memory "memory.dump")
|
||||||
|
|
||||||
|
(defun autotest () (princ "abcd\n"))
|
||||||
|
(setq auto-exec 'autotest)
|
||||||
|
|
||||||
|
(princ (path 'data) "\n")
|
||||||
|
|
|
||||||
|
|
@ -32,9 +32,22 @@ struct alisp_cfg {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct alisp_instance;
|
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);
|
int alsa_lisp(struct alisp_cfg *cfg, struct alisp_instance **instance);
|
||||||
void alsa_lisp_free(struct alisp_instance *instance);
|
void alsa_lisp_free(struct alisp_instance *instance);
|
||||||
|
int alsa_lisp_function(struct alisp_instance *instance, struct alisp_seq_iterator **result,
|
||||||
extern struct alisp_object alsa_lisp_nil;
|
const char *id, const char *args, ...)
|
||||||
extern struct alisp_object alsa_lisp_t;
|
#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);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
int snd_async_handler_get_signo(snd_async_handler_t *handler);
|
||||||
void *snd_async_handler_get_callback_private(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_create(int shmid, void *ptr);
|
||||||
struct snd_shm_area *snd_shm_area_share(struct snd_shm_area *area);
|
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_shm_area_destroy(struct snd_shm_area *area);
|
||||||
|
|
||||||
|
int snd_user_file(const char *file, char **result);
|
||||||
|
|
||||||
/** Timestamp */
|
/** Timestamp */
|
||||||
typedef struct timeval snd_timestamp_t;
|
typedef struct timeval snd_timestamp_t;
|
||||||
/** Hi-res timestamp */
|
/** Hi-res timestamp */
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,7 @@ enum sndo_mixer_io_type {
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct sndo_mixer sndo_mixer_t;
|
typedef struct sndo_mixer sndo_mixer_t;
|
||||||
|
struct alisp_cfg;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
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_close(sndo_mixer_t *mixer);
|
||||||
int sndo_mixer_poll_descriptors_count(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);
|
int sndo_mixer_poll_descriptors(sndo_mixer_t *mixer, struct pollfd *pfds, unsigned int space);
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ VSYMS =
|
||||||
endif
|
endif
|
||||||
|
|
||||||
lib_LTLIBRARIES = libasound.la
|
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 \
|
libasound_la_LIBADD = control/libcontrol.la \
|
||||||
mixer/libmixer.la ordinary_mixer/libordinarymixer.la \
|
mixer/libmixer.la ordinary_mixer/libordinarymixer.la \
|
||||||
pcm/libpcm.la ordinary_pcm/libordinarypcm.la \
|
pcm/libpcm.la ordinary_pcm/libordinarypcm.la \
|
||||||
|
|
|
||||||
|
|
@ -126,3 +126,11 @@ ALSA_0.9.6 {
|
||||||
snd_seq_port_info_set_timestamp_real;
|
snd_seq_port_info_set_timestamp_real;
|
||||||
snd_seq_port_info_set_timestamp_queue;
|
snd_seq_port_info_set_timestamp_queue;
|
||||||
} ALSA_0.9.5;
|
} ALSA_0.9.5;
|
||||||
|
|
||||||
|
ALSA_0.9.7 {
|
||||||
|
global:
|
||||||
|
|
||||||
|
snd_user_file;
|
||||||
|
sndo_*;
|
||||||
|
alsa_lisp_*;
|
||||||
|
} ALSA_0.9.6;
|
||||||
|
|
|
||||||
|
|
@ -30,11 +30,15 @@
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
|
#include <wordexp.h>
|
||||||
|
|
||||||
|
#define alisp_seq_iterator alisp_object
|
||||||
|
|
||||||
#include "local.h"
|
#include "local.h"
|
||||||
#include "alisp.h"
|
#include "alisp.h"
|
||||||
#include "alisp_local.h"
|
#include "alisp_local.h"
|
||||||
|
|
||||||
|
|
||||||
#define ALISP_FREE_OBJ_POOL 500 /* free objects above this pool */
|
#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_AUTO_GC_THRESHOLD 200 /* run automagically garbage-collect when this threshold is reached */
|
||||||
#define ALISP_MAIN_ID "---alisp---main---"
|
#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_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_progn(struct alisp_instance *instance, struct alisp_object *);
|
||||||
|
|
||||||
|
/* others */
|
||||||
|
static int alisp_include_file(struct alisp_instance *instance, const char *filename);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* object handling
|
* object handling
|
||||||
*/
|
*/
|
||||||
|
|
@ -655,13 +662,13 @@ static struct alisp_object_pair * set_object(struct alisp_instance *instance, st
|
||||||
return p;
|
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;
|
struct alisp_object_pair *p, *p1;
|
||||||
|
|
||||||
for (p = instance->setobjs_list, p1 = NULL; p != NULL; p1 = p, p = p->next) {
|
for (p = instance->setobjs_list, p1 = NULL; p != NULL; p1 = p, p = p->next) {
|
||||||
if (p->name->value.id != NULL &&
|
if (p->name->value.id != NULL &&
|
||||||
!strcmp(name->value.id, p->name->value.id)) {
|
!strcmp(id, p->name->value.id)) {
|
||||||
if (p1)
|
if (p1)
|
||||||
p1->next = p->next;
|
p1->next = p->next;
|
||||||
else
|
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;
|
struct alisp_object_pair *p;
|
||||||
|
|
||||||
for (p = instance->setobjs_list; p != NULL; p = p->next)
|
for (p = instance->setobjs_list; p != NULL; p = p->next)
|
||||||
if (p->name->value.id != NULL &&
|
if (p->name->value.id != NULL &&
|
||||||
!strcmp(name->value.id, p->name->value.id))
|
!strcmp(id, p->name->value.id))
|
||||||
return p->value;
|
return p->value;
|
||||||
|
|
||||||
return &alsa_lisp_nil;
|
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)
|
static void dump_objects(struct alisp_instance *instance, const char *fname)
|
||||||
{
|
{
|
||||||
struct alisp_object_pair *p;
|
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)
|
static struct alisp_object * F_add(struct alisp_instance *instance, struct alisp_object * args)
|
||||||
{
|
{
|
||||||
struct alisp_object * p = args, * p1;
|
struct alisp_object * p = args, * p1;
|
||||||
long v = 0;
|
|
||||||
double f = 0;
|
|
||||||
int type = ALISP_OBJ_INTEGER;
|
|
||||||
|
|
||||||
do {
|
p1 = eval(instance, car(p));
|
||||||
p1 = eval(instance, car(p));
|
if (p1->type == ALISP_OBJ_INTEGER || p1->type == ALISP_OBJ_FLOAT) {
|
||||||
if (p1->type == ALISP_OBJ_INTEGER) {
|
long v = 0;
|
||||||
if (type == ALISP_OBJ_FLOAT)
|
double f = 0;
|
||||||
f += p1->value.i;
|
int type = ALISP_OBJ_INTEGER;
|
||||||
else
|
for (;;) {
|
||||||
v += p1->value.i;
|
if (p1->type == ALISP_OBJ_INTEGER) {
|
||||||
} else if (p1->type == ALISP_OBJ_FLOAT) {
|
if (type == ALISP_OBJ_FLOAT)
|
||||||
f += p1->value.f + v;
|
f += p1->value.i;
|
||||||
v = 0;
|
else
|
||||||
type = ALISP_OBJ_FLOAT;
|
v += p1->value.i;
|
||||||
} else {
|
} else if (p1->type == ALISP_OBJ_FLOAT) {
|
||||||
lisp_warn(instance, "sum with a non integer or float operand");
|
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));
|
||||||
}
|
}
|
||||||
p = cdr(p);
|
if (type == ALISP_OBJ_INTEGER) {
|
||||||
} while (p != &alsa_lisp_nil);
|
return new_integer(instance, v);
|
||||||
|
} else {
|
||||||
if (type == ALISP_OBJ_INTEGER) {
|
return new_float(instance, f);
|
||||||
return new_integer(instance, v);
|
}
|
||||||
} else {
|
} else if (p1->type == ALISP_OBJ_STRING || p1->type == ALISP_OBJ_IDENTIFIER) {
|
||||||
return new_float(instance, f);
|
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)
|
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, * p5;
|
||||||
struct alisp_object * eval_objs[64], * save_objs[64];
|
struct alisp_object ** eval_objs, ** save_objs;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
p1 = car(p);
|
p1 = car(p);
|
||||||
|
|
@ -1761,33 +1806,40 @@ static struct alisp_object * eval_func(struct alisp_instance *instance, struct a
|
||||||
p2 = car(cdr(p));
|
p2 = car(cdr(p));
|
||||||
p3 = args;
|
p3 = args;
|
||||||
|
|
||||||
if (count_list(p2) != count_list(p3)) {
|
if ((i = count_list(p2)) != count_list(p3)) {
|
||||||
lisp_warn(instance, "wrong number of parameters");
|
lisp_warn(instance, "wrong number of parameters");
|
||||||
return &alsa_lisp_nil;
|
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.
|
* Save the new variable values.
|
||||||
*/
|
*/
|
||||||
i = 0;
|
i = 0;
|
||||||
do {
|
while (p3 != &alsa_lisp_nil) {
|
||||||
p5 = eval(instance, car(p3));
|
p5 = eval(instance, car(p3));
|
||||||
eval_objs[i++] = p5;
|
eval_objs[i++] = p5;
|
||||||
p3 = cdr(p3);
|
p3 = cdr(p3);
|
||||||
} while (p3 != &alsa_lisp_nil);
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Save the old variable values and set the new ones.
|
* Save the old variable values and set the new ones.
|
||||||
*/
|
*/
|
||||||
i = 0;
|
i = 0;
|
||||||
do {
|
while (p2 != &alsa_lisp_nil) {
|
||||||
p4 = car(p2);
|
p4 = car(p2);
|
||||||
save_objs[i] = get_object(instance, p4);
|
save_objs[i] = get_object(instance, p4);
|
||||||
if (set_object(instance, p4, eval_objs[i]) == NULL)
|
if (set_object(instance, p4, eval_objs[i]) == NULL)
|
||||||
return NULL;
|
goto _err;
|
||||||
p2 = cdr(p2);
|
p2 = cdr(p2);
|
||||||
++i;
|
++i;
|
||||||
} while (p2 != &alsa_lisp_nil);
|
}
|
||||||
|
|
||||||
p5 = F_progn(instance, cdr(cdr(p)));
|
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));
|
p2 = car(cdr(p));
|
||||||
i = 0;
|
i = 0;
|
||||||
do {
|
while (p2 != &alsa_lisp_nil) {
|
||||||
p4 = car(p2);
|
p4 = car(p2);
|
||||||
if (set_object(instance, p4, save_objs[i++]) == NULL)
|
if (set_object(instance, p4, save_objs[i++]) == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
p2 = cdr(p2);
|
p2 = cdr(p2);
|
||||||
} while (p2 != &alsa_lisp_nil);
|
}
|
||||||
|
|
||||||
|
if (eval_objs)
|
||||||
|
free(eval_objs);
|
||||||
|
|
||||||
return p5;
|
return p5;
|
||||||
}
|
}
|
||||||
|
|
||||||
return &alsa_lisp_nil;
|
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)
|
struct alisp_object * F_gc(struct alisp_instance *instance, struct alisp_object * args ATTRIBUTE_UNUSED)
|
||||||
|
|
@ -1816,6 +1876,39 @@ struct alisp_object * F_gc(struct alisp_instance *instance, struct alisp_object
|
||||||
return &alsa_lisp_t;
|
return &alsa_lisp_t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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)
|
* Syntax: (int value)
|
||||||
* 'value' can be integer or float type
|
* 'value' can be integer or float type
|
||||||
|
|
@ -1931,6 +2024,27 @@ struct alisp_object * F_assq(struct alisp_instance *instance, struct alisp_objec
|
||||||
return &alsa_lisp_nil;
|
return &alsa_lisp_nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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)
|
* Syntax: (rassq value alist)
|
||||||
*/
|
*/
|
||||||
|
|
@ -2031,10 +2145,13 @@ static struct intrinsic intrinsics[] = {
|
||||||
{ "gc", F_gc },
|
{ "gc", F_gc },
|
||||||
{ "if", F_if },
|
{ "if", F_if },
|
||||||
{ "int", F_int },
|
{ "int", F_int },
|
||||||
|
{ "include", F_include },
|
||||||
{ "list", F_list },
|
{ "list", F_list },
|
||||||
{ "not", F_not },
|
{ "not", F_not },
|
||||||
|
{ "nth", F_nth },
|
||||||
{ "null", F_not },
|
{ "null", F_not },
|
||||||
{ "or", F_or },
|
{ "or", F_or },
|
||||||
|
{ "path", F_path },
|
||||||
{ "princ", F_princ },
|
{ "princ", F_princ },
|
||||||
{ "prog1", F_prog1 },
|
{ "prog1", F_prog1 },
|
||||||
{ "prog2", F_prog2 },
|
{ "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)
|
sizeof snd_intrinsics[0], compar)) != NULL)
|
||||||
return item->func(instance, p2);
|
return item->func(instance, p2);
|
||||||
|
|
||||||
|
|
||||||
if ((p3 = get_object(instance, p1)) != &alsa_lisp_nil)
|
if ((p3 = get_object(instance, p1)) != &alsa_lisp_nil)
|
||||||
return eval_func(instance, p3, p2);
|
return eval_func(instance, p3, p2);
|
||||||
else
|
else
|
||||||
|
|
@ -2120,12 +2236,91 @@ static struct alisp_object * F_eval(struct alisp_instance *instance, struct alis
|
||||||
/*
|
/*
|
||||||
* main routine
|
* 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)
|
int alsa_lisp(struct alisp_cfg *cfg, struct alisp_instance **_instance)
|
||||||
{
|
{
|
||||||
struct alisp_instance *instance;
|
struct alisp_instance *instance;
|
||||||
struct alisp_object *p, *p1, *omain;
|
struct alisp_object *p, *p1, *omain;
|
||||||
struct alisp_object_pair *pmain;
|
struct alisp_object_pair *pmain;
|
||||||
|
int retval = 0;
|
||||||
|
|
||||||
instance = (struct alisp_instance *)malloc(sizeof(struct alisp_instance));
|
instance = (struct alisp_instance *)malloc(sizeof(struct alisp_instance));
|
||||||
if (instance == NULL) {
|
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 */
|
pmain->value = p; /* protect the code tree from garbage-collect */
|
||||||
p1 = eval(instance, p);
|
p1 = eval(instance, p);
|
||||||
pmain->value = &alsa_lisp_t; /* let garbage-collect working */
|
if (p1 == NULL) {
|
||||||
|
retval = -ENOMEM;
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (instance->verbose) {
|
if (instance->verbose) {
|
||||||
lisp_verbose(instance, "** result");
|
lisp_verbose(instance, "** result");
|
||||||
princ_object(instance->vout, p1);
|
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");
|
lisp_debug(instance, "** objects before collection");
|
||||||
print_obj_lists(instance, instance->dout);
|
print_obj_lists(instance, instance->dout);
|
||||||
}
|
}
|
||||||
|
pmain->value = &alsa_lisp_t; /* let garbage-collect working */
|
||||||
garbage_collect(instance);
|
garbage_collect(instance);
|
||||||
if (instance->debug) {
|
if (instance->debug) {
|
||||||
lisp_debug(instance, "** objects after collection");
|
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);
|
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);
|
done_lex(instance);
|
||||||
if (_instance)
|
if (_instance)
|
||||||
*_instance = instance;
|
*_instance = instance;
|
||||||
|
|
@ -2202,3 +2417,205 @@ void alsa_lisp_free(struct alisp_instance *instance)
|
||||||
free_objects(instance);
|
free_objects(instance);
|
||||||
free(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;
|
||||||
|
}
|
||||||
|
|
|
||||||
41
src/conf.c
41
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;
|
goto _err;
|
||||||
}
|
}
|
||||||
if (i == idx) {
|
if (i == idx) {
|
||||||
wordexp_t we;
|
|
||||||
char *name;
|
char *name;
|
||||||
if ((err = snd_config_get_ascii(n, &name)) < 0)
|
if ((err = snd_config_get_ascii(n, &name)) < 0)
|
||||||
goto _err;
|
goto _err;
|
||||||
err = wordexp(name, &we, WRDE_NOCMD);
|
if ((err = snd_user_file(name, &fi[idx].name)) < 0)
|
||||||
switch (err) {
|
|
||||||
case WRDE_NOSPACE:
|
|
||||||
err = -ENOMEM;
|
|
||||||
goto _err;
|
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);
|
free(name);
|
||||||
if (fi[idx].name == NULL) {
|
|
||||||
err = -ENOMEM;
|
|
||||||
goto _err;
|
|
||||||
}
|
|
||||||
idx++;
|
idx++;
|
||||||
hit = 1;
|
hit = 1;
|
||||||
}
|
}
|
||||||
|
|
@ -2924,7 +2906,6 @@ int snd_config_update_r(snd_config_t **_top, snd_config_update_t **_update, cons
|
||||||
int err;
|
int err;
|
||||||
const char *configs, *c;
|
const char *configs, *c;
|
||||||
unsigned int k;
|
unsigned int k;
|
||||||
wordexp_t we;
|
|
||||||
size_t l;
|
size_t l;
|
||||||
snd_config_update_t *local;
|
snd_config_update_t *local;
|
||||||
snd_config_update_t *update;
|
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];
|
char name[l + 1];
|
||||||
memcpy(name, c, l);
|
memcpy(name, c, l);
|
||||||
name[l] = 0;
|
name[l] = 0;
|
||||||
err = wordexp(name, &we, WRDE_NOCMD);
|
err = snd_user_file(name, &local->finfo[k].name);
|
||||||
switch (err) {
|
if (err < 0)
|
||||||
case WRDE_NOSPACE:
|
|
||||||
err = -ENOMEM;
|
|
||||||
goto _end;
|
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;
|
|
||||||
goto _end;
|
|
||||||
}
|
|
||||||
c += l;
|
c += l;
|
||||||
k++;
|
k++;
|
||||||
if (!*c)
|
if (!*c)
|
||||||
|
|
|
||||||
|
|
@ -56,10 +56,15 @@ Write something here
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include "local.h"
|
#include "local.h"
|
||||||
|
#include "alisp.h"
|
||||||
#include "mixer_ordinary.h"
|
#include "mixer_ordinary.h"
|
||||||
|
|
||||||
struct sndo_mixer {
|
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,
|
int sndo_mixer_open(sndo_mixer_t **pmixer,
|
||||||
const char *playback_name,
|
const char *playback_name,
|
||||||
const char *capture_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;
|
*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)
|
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)
|
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)
|
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)
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
check_PROGRAMS=control pcm latency seq \
|
check_PROGRAMS=control pcm latency seq \
|
||||||
playmidi1 timer rawmidi midiloop \
|
playmidi1 timer rawmidi midiloop \
|
||||||
code
|
omixer code
|
||||||
|
|
||||||
control_LDADD=../src/libasound.la
|
control_LDADD=../src/libasound.la
|
||||||
pcm_LDADD=../src/libasound.la
|
pcm_LDADD=../src/libasound.la
|
||||||
|
|
@ -10,6 +10,7 @@ playmidi1_LDADD=../src/libasound.la
|
||||||
timer_LDADD=../src/libasound.la
|
timer_LDADD=../src/libasound.la
|
||||||
rawmidi_LDADD=../src/libasound.la
|
rawmidi_LDADD=../src/libasound.la
|
||||||
midiloop_LDADD=../src/libasound.la
|
midiloop_LDADD=../src/libasound.la
|
||||||
|
omixer_LDADD=../src/libasound.la
|
||||||
code_CFLAGS=-Wall -pipe -g -O2
|
code_CFLAGS=-Wall -pipe -g -O2
|
||||||
|
|
||||||
INCLUDES=-I$(top_srcdir)/include
|
INCLUDES=-I$(top_srcdir)/include
|
||||||
|
|
|
||||||
|
|
@ -100,5 +100,7 @@ int main(void)
|
||||||
}
|
}
|
||||||
snd_ctl_close(handle);
|
snd_ctl_close(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
snd_config_update_free_global();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
64
test/omixer.c
Normal file
64
test/omixer.c
Normal file
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
@ -691,7 +691,7 @@ static void help(void)
|
||||||
{
|
{
|
||||||
int k;
|
int k;
|
||||||
printf(
|
printf(
|
||||||
"Usage: latency [OPTION]... [FILE]...\n"
|
"Usage: pcm [OPTION]... [FILE]...\n"
|
||||||
"-h,--help help\n"
|
"-h,--help help\n"
|
||||||
"-D,--device playback device\n"
|
"-D,--device playback device\n"
|
||||||
"-r,--rate stream rate in Hz\n"
|
"-r,--rate stream rate in Hz\n"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue