Continued config implementation. Added incomplete support for pcm

This commit is contained in:
Abramo Bagnara 2000-08-24 17:07:44 +00:00
parent c709eb8140
commit 244653df61
8 changed files with 329 additions and 19 deletions

View file

@ -24,11 +24,14 @@ struct snd_config {
snd_config_t *father;
};
int snd_config_top(snd_config_t **config);
int snd_config_load(snd_config_t **config, FILE *fp);
int snd_config_load(snd_config_t *config, FILE *fp);
int snd_config_save(snd_config_t *config, FILE *fp);
int snd_config_search(snd_config_t *config, char *key, snd_config_t **result);
int snd_config_searchv(snd_config_t *config,
snd_config_t **result, ...);
int snd_config_add(snd_config_t *config, snd_config_t *leaf);
int snd_config_delete(snd_config_t *config);
@ -55,3 +58,15 @@ typedef struct list_head *snd_config_iterator_t;
#define snd_config_entry(iterator) list_entry(iterator, snd_config_t, list)
static inline snd_config_type_t snd_config_type(snd_config_t *config)
{
return config->type;
}
static inline char *snd_config_id(snd_config_t *config)
{
return config->id;
}
snd_config_t *snd_config;
int snd_config_update();

View file

@ -122,6 +122,9 @@ int snd_pcm_synchro(snd_pcm_synchro_cmd_t cmd,
#endif
int snd_pcm_open(snd_pcm_t **handle, char *name,
int stream, int mode);
int snd_pcm_hw_open_subdevice(snd_pcm_t **handle, int card, int device, int subdevice, int stream, int mode);
int snd_pcm_hw_open(snd_pcm_t **handle, int card, int device, int stream, int mode);

View file

@ -6,7 +6,7 @@ libasound_la_SOURCES = error.c
libasound_la_LIBADD = control/libcontrol.la mixer/libmixer.la pcm/libpcm.la \
rawmidi/librawmidi.la timer/libtimer.la \
hwdep/libhwdep.la seq/libseq.la instr/libinstr.la \
compat/libcompat.la
compat/libcompat.la conf/libconf.la
libasound_la_LDFLAGS = -version-info $(COMPATNUM)
@ -37,4 +37,7 @@ instr/libinstr.la:
compat/libcompat.la:
$(MAKE) -C compat libcompat.la
conf/libconf.la:
$(MAKE) -C conf libconf.la
INCLUDES=-I$(top_srcdir)/include

View file

@ -22,9 +22,13 @@
#include <assert.h>
#include <errno.h>
#include <stdarg.h>
#include <sys/stat.h>
#include "asoundlib.h"
#include "list.h"
#define SYS_ASOUNDRC "/etc/asound.conf"
#define USR_ASOUNDRC ".asoundrc"
typedef struct {
FILE *fp;
unsigned int line, column;
@ -183,7 +187,7 @@ static int get_freestring(char **string, input_t *input)
}
if (idx >= alloc) {
size_t old_alloc = alloc;
alloc *= 2;
alloc += bufsize;
if (old_alloc == bufsize) {
buf = malloc(alloc);
memcpy(buf, _buf, old_alloc);
@ -227,7 +231,7 @@ static int get_delimstring(char **string, int delim, input_t *input)
}
if (idx >= alloc) {
size_t old_alloc = alloc;
alloc *= 2;
alloc += bufsize;
if (old_alloc == bufsize) {
buf = malloc(alloc);
memcpy(buf, _buf, old_alloc);
@ -507,30 +511,30 @@ static int parse_defs(snd_config_t *father, input_t *input)
return 0;
}
int snd_config_top(snd_config_t **config)
{
assert(config);
return _snd_config_make(config, 0, SND_CONFIG_TYPE_COMPOUND);
}
int snd_config_load(snd_config_t **config, FILE *fp)
int snd_config_load(snd_config_t *config, FILE *fp)
{
int err;
input_t input;
snd_config_t *c;
assert(config && fp);
err = _snd_config_make(&c, 0, SND_CONFIG_TYPE_COMPOUND);
if (err < 0)
return err;
input.fp = fp;
input.line = 1;
input.column = 0;
input.unget = 0;
err = parse_defs(c, &input);
err = parse_defs(config, &input);
if (err < 0) {
snd_config_delete(c);
snd_config_delete(config);
return err;
}
if (get_char(&input) != EOF) {
snd_config_delete(c);
snd_config_delete(config);
return -1;
}
*config = c;
return 0;
}
@ -595,14 +599,18 @@ int snd_config_make(snd_config_t **config, char *id,
int snd_config_integer_set(snd_config_t *config, long value)
{
assert(config->type == SND_CONFIG_TYPE_INTEGER);
assert(config);
if (config->type != SND_CONFIG_TYPE_INTEGER)
return -EINVAL;
config->u.integer = value;
return 0;
}
int snd_config_real_set(snd_config_t *config, double value)
{
assert(config->type == SND_CONFIG_TYPE_REAL);
assert(config);
if (config->type != SND_CONFIG_TYPE_REAL)
return -EINVAL;
config->u.real = value;
return 0;
}
@ -610,7 +618,8 @@ int snd_config_real_set(snd_config_t *config, double value)
int snd_config_string_set(snd_config_t *config, char *value)
{
assert(config);
assert(config->type == SND_CONFIG_TYPE_INTEGER);
if (config->type != SND_CONFIG_TYPE_STRING)
return -EINVAL;
if (config->u.string)
free(config->u.string);
config->u.string = strdup(value);
@ -645,7 +654,8 @@ int snd_config_set(snd_config_t *config, ...)
int snd_config_integer_get(snd_config_t *config, long *ptr)
{
assert(config && ptr);
assert(config->type == SND_CONFIG_TYPE_INTEGER);
if (config->type != SND_CONFIG_TYPE_INTEGER)
return -EINVAL;
*ptr = config->u.integer;
return 0;
}
@ -653,7 +663,8 @@ int snd_config_integer_get(snd_config_t *config, long *ptr)
int snd_config_real_get(snd_config_t *config, double *ptr)
{
assert(config && ptr);
assert(config->type == SND_CONFIG_TYPE_REAL);
if (config->type != SND_CONFIG_TYPE_REAL)
return -EINVAL;
*ptr = config->u.real;
return 0;
}
@ -661,7 +672,8 @@ int snd_config_real_get(snd_config_t *config, double *ptr)
int snd_config_string_get(snd_config_t *config, char **ptr)
{
assert(config && ptr);
assert(config->type == SND_CONFIG_TYPE_INTEGER);
if (config->type != SND_CONFIG_TYPE_STRING)
return -EINVAL;
*ptr = config->u.string;
return 0;
}
@ -860,4 +872,110 @@ int snd_config_search(snd_config_t *config, char *key, snd_config_t **result)
return _snd_config_search(config, key, -1, result);
}
}
int snd_config_searchv(snd_config_t *config,
snd_config_t **result, ...)
{
va_list arg;
const size_t bufsize = 256;
char _buf[bufsize];
char *buf = _buf;
size_t alloc = bufsize;
size_t idx = 0;
size_t dot = 0;
assert(config && result);
va_start(arg, result);
while (1) {
char *k = va_arg(arg, char *);
size_t len;
if (!k)
break;
len = strlen(k);
if (idx + len + dot>= alloc) {
size_t old_alloc = alloc;
alloc = idx + len + dot;
alloc += bufsize - alloc % bufsize;
if (old_alloc == bufsize) {
buf = malloc(alloc);
memcpy(buf, _buf, old_alloc);
} else
buf = realloc(buf, alloc);
}
if (dot)
buf[idx] = '.';
memcpy(buf + idx + dot, k, len);
idx += len + dot;
if (dot == 0)
dot = 1;
}
buf[idx] = '\0';
return snd_config_search(config, buf, result);
}
snd_config_t *snd_config = 0;
static dev_t sys_asoundrc_device;
static ino_t sys_asoundrc_inode;
static time_t sys_asoundrc_mtime;
static dev_t usr_asoundrc_device;
static ino_t usr_asoundrc_inode;
static time_t usr_asoundrc_mtime;
int snd_config_update()
{
int err;
char *usr_asoundrc = NULL;
char *home = getenv("HOME");
struct stat st;
int reload;
FILE *fp;
if (home) {
size_t len = strlen(home);
size_t len1 = strlen(USR_ASOUNDRC);
usr_asoundrc = alloca(len + len1 + 2);
memcpy(usr_asoundrc, home, len);
usr_asoundrc[len] = '/';
memcpy(usr_asoundrc + len + 1, USR_ASOUNDRC, len1);
usr_asoundrc[len + 1 + len1] = '\0';
}
reload = (snd_config == NULL);
if (!reload &&
stat(usr_asoundrc, &st) == 0 &&
(st.st_dev != usr_asoundrc_device ||
st.st_ino != usr_asoundrc_inode ||
st.st_mtime != usr_asoundrc_mtime))
reload = 1;
if (!reload &&
stat(SYS_ASOUNDRC, &st) == 0 &&
(st.st_dev != sys_asoundrc_device ||
st.st_ino != sys_asoundrc_inode ||
st.st_mtime != sys_asoundrc_mtime))
reload = 1;
if (!reload)
return 0;
if (snd_config == NULL) {
err = snd_config_top(&snd_config);
if (err < 0)
return err;
}
fp = fopen(SYS_ASOUNDRC, "r");
if (fp) {
err = snd_config_load(snd_config, fp);
if (err < 0) {
snd_config = NULL;
fclose(fp);
return err;
}
fclose(fp);
}
fp = fopen(usr_asoundrc, "r");
if (fp) {
err = snd_config_load(snd_config, fp);
if (err < 0) {
snd_config = NULL;
fclose(fp);
return err;
}
fclose(fp);
}
return 0;
}

View file

@ -27,6 +27,7 @@
#include <sys/poll.h>
#include <sys/uio.h>
#include "pcm_local.h"
#include "list.h"
snd_pcm_type_t snd_pcm_type(snd_pcm_t *handle)
{
@ -501,3 +502,170 @@ ssize_t snd_pcm_samples_to_bytes(snd_pcm_t *handle, ssize_t samples)
return samples * handle->bits_per_sample / 8;
}
static int _snd_pcm_open_hw(snd_pcm_t **handlep, snd_config_t *conf,
int stream, int mode)
{
snd_config_iterator_t i;
long card = -1, device = -1, subdevice = -1;
char *str;
int err;
snd_config_foreach(i, conf) {
snd_config_t *n = snd_config_entry(i);
if (strcmp(n->id, "comment") == 0)
continue;
if (strcmp(n->id, "type") == 0)
continue;
if (strcmp(n->id, "stream") == 0)
continue;
if (strcmp(n->id, "card") == 0) {
err = snd_config_integer_get(n, &card);
if (err < 0) {
err = snd_config_string_get(n, &str);
if (err < 0)
return -EINVAL;
card = snd_card_name(str);
if (card < 0)
return card;
}
continue;
}
if (strcmp(n->id, "device") == 0) {
err = snd_config_integer_get(n, &device);
if (err < 0)
return err;
continue;
}
if (strcmp(n->id, "subdevice") == 0) {
err = snd_config_integer_get(n, &subdevice);
if (err < 0)
return err;
continue;
}
return -EINVAL;
}
if (card < 0 || device < 0)
return -EINVAL;
return snd_pcm_hw_open_subdevice(handlep, card, device, subdevice, stream, mode);
}
static int _snd_pcm_open_plug(snd_pcm_t **handlep, snd_config_t *conf,
int stream, int mode)
{
snd_config_iterator_t i;
long card = -1, device = -1, subdevice = -1;
char *str;
int err;
snd_config_foreach(i, conf) {
snd_config_t *n = snd_config_entry(i);
if (strcmp(n->id, "comment") == 0)
continue;
if (strcmp(n->id, "type") == 0)
continue;
if (strcmp(n->id, "stream") == 0)
continue;
if (strcmp(n->id, "card") == 0) {
err = snd_config_integer_get(n, &card);
if (err < 0) {
err = snd_config_string_get(n, &str);
if (err < 0)
return -EINVAL;
card = snd_card_name(str);
if (card < 0)
return card;
}
continue;
}
if (strcmp(n->id, "device") == 0) {
err = snd_config_integer_get(n, &device);
if (err < 0)
return err;
continue;
}
if (strcmp(n->id, "subdevice") == 0) {
err = snd_config_integer_get(n, &subdevice);
if (err < 0)
return err;
continue;
}
return -EINVAL;
}
if (card < 0 || device < 0)
return -EINVAL;
return snd_pcm_plug_open_subdevice(handlep, card, device, subdevice, stream, mode);
}
static int _snd_pcm_open_multi(snd_pcm_t **handle, snd_config_t *conf,
int stream, int mode)
{
snd_config_iterator_t i;
char *str;
int err;
snd_config_foreach(i, conf) {
snd_config_t *n = snd_config_entry(i);
if (strcmp(n->id, "comment") == 0)
continue;
if (strcmp(n->id, "type") == 0)
continue;
if (strcmp(n->id, "stream") == 0)
continue;
if (strcmp(n->id, "slave") == 0) {
if (snd_config_type(n) != SND_CONFIG_TYPE_COMPOUND)
return -EINVAL;
/* Not yet implemented */
continue;
}
if (strcmp(n->id, "binding") == 0) {
if (snd_config_type(n) != SND_CONFIG_TYPE_COMPOUND)
return -EINVAL;
/* Not yet implemented */
continue;
}
return -EINVAL;
}
return -ENOSYS;
}
int snd_pcm_open(snd_pcm_t **handlep, char *name,
int stream, int mode)
{
char *str;
int err;
snd_config_t *pcm_conf, *conf;
assert(handlep && name);
err = snd_config_update();
if (err < 0)
return err;
err = snd_config_searchv(snd_config, &pcm_conf, "pcm", name, 0);
if (err < 0)
return err;
if (snd_config_type(pcm_conf) != SND_CONFIG_TYPE_COMPOUND)
return -EINVAL;
err = snd_config_search(pcm_conf, "stream", &conf);
if (err >= 0) {
err = snd_config_string_get(conf, &str);
if (err < 0)
return err;
if (strcmp(str, "playback") == 0) {
if (stream != SND_PCM_STREAM_PLAYBACK)
return -EINVAL;
} else if (strcmp(str, "capture") == 0) {
if (stream != SND_PCM_STREAM_CAPTURE)
return -EINVAL;
} else
return -EINVAL;
}
err = snd_config_search(pcm_conf, "type", &conf);
if (err < 0)
return err;
err = snd_config_string_get(conf, &str);
if (err < 0)
return err;
if (strcmp(str, "hw") == 0)
return _snd_pcm_open_hw(handlep, pcm_conf, stream, mode);
else if (strcmp(str, "plug") == 0)
return _snd_pcm_open_plug(handlep, pcm_conf, stream, mode);
else if (strcmp(str, "multi") == 0)
return _snd_pcm_open_multi(handlep, pcm_conf, stream, mode);
else
return -EINVAL;
}

View file

@ -406,6 +406,7 @@ int snd_pcm_hw_open_subdevice(snd_pcm_t **handlep, int card, int device, int sub
snd_pcm_t *handle;
snd_pcm_hw_t *hw;
assert(handlep);
*handlep = 0;
if ((ret = snd_ctl_open(&ctl, card)) < 0)

View file

@ -737,6 +737,7 @@ int snd_pcm_multi_create(snd_pcm_t **handlep, size_t slaves_count,
char client_map[32] = { 0 };
char slave_map[32][32] = { { 0 } };
assert(handlep);
assert(slaves_count > 0 && slaves_handle && slaves_channels_count);
assert(binds_count > 0 && binds_slave && binds_client_channel && binds_slave_channel);

View file

@ -789,6 +789,7 @@ int snd_pcm_plug_create(snd_pcm_t **handlep, snd_pcm_t *slave, int close_slave)
{
snd_pcm_t *handle;
snd_pcm_plug_t *plug;
assert(handlep && slave);
handle = calloc(1, sizeof(snd_pcm_t));
if (!handle)
return -ENOMEM;