Improved .asoundrc changes

This commit is contained in:
Abramo Bagnara 2001-03-17 16:34:43 +00:00
parent 0300bbbbb3
commit a275d66356
25 changed files with 888 additions and 612 deletions

View file

@ -1014,6 +1014,21 @@ int snd_config_searchv(snd_config_t *config,
return 0;
}
int snd_config_search_alias(snd_config_t *config,
const char *base, const char *key,
snd_config_t **result)
{
int err;
assert(config && base && key && result);
err = snd_config_searchv(config, result, base, key, 0);
if (err < 0)
return err;
while (snd_config_get_string(*result, &key) >= 0 &&
snd_config_searchv(config, result, base, key, 0) >= 0)
;
return 0;
}
snd_config_t *snd_config = 0;
static dev_t sys_asoundrc_device;
static ino_t sys_asoundrc_inode;

View file

@ -204,33 +204,42 @@ int snd_ctl_open(snd_ctl_t **ctlp, const char *name)
const char *lib = NULL, *open = NULL;
int (*open_func)(snd_ctl_t **ctlp, const char *name, snd_config_t *conf);
void *h;
const char *name1;
assert(ctlp && name);
err = snd_config_update();
if (err < 0)
return err;
err = snd_config_searchv(snd_config, &ctl_conf, "ctl", name, 0);
if (err < 0) {
err = snd_config_search_alias(snd_config, "ctl", name, &ctl_conf);
name1 = name;
if (err < 0 || snd_config_get_string(ctl_conf, &name1) >= 0) {
int card;
char socket[256], sname[256];
err = sscanf(name, "hw:%d", &card);
err = sscanf(name1, "hw:%d", &card);
if (err == 1)
return snd_ctl_hw_open(ctlp, name, card);
err = sscanf(name, "shm:%256[^,],%256[^,]", socket, sname);
err = sscanf(name1, "shm:%256[^,],%256[^,]", socket, sname);
if (err == 2)
return snd_ctl_shm_open(ctlp, name, socket, sname);
SNDERR("Unknown control %s", name);
SNDERR("Unknown ctl %s", name1);
return -ENOENT;
}
if (snd_config_get_type(ctl_conf) != SND_CONFIG_TYPE_COMPOUND)
if (snd_config_get_type(ctl_conf) != SND_CONFIG_TYPE_COMPOUND) {
SNDERR("Invalid type for %s", snd_config_get_id(ctl_conf));
return -EINVAL;
}
err = snd_config_search(ctl_conf, "type", &conf);
if (err < 0)
return err;
err = snd_config_get_string(conf, &str);
if (err < 0)
return err;
err = snd_config_searchv(snd_config, &type_conf, "ctltype", str, 0);
err = snd_config_search_alias(snd_config, "ctl_type", str, &type_conf);
if (err >= 0) {
if (snd_config_get_type(type_conf) != SND_CONFIG_TYPE_COMPOUND) {
SNDERR("Invalid type for ctl type %s definition", str);
return -EINVAL;
}
snd_config_for_each(i, next, type_conf) {
snd_config_t *n = snd_config_iterator_entry(i);
const char *id = snd_config_get_id(n);

View file

@ -544,11 +544,15 @@ int _snd_ctl_shm_open(snd_ctl_t **handlep, char *name, snd_config_t *conf)
SNDERR("server is not defined");
return -EINVAL;
}
err = snd_config_searchv(snd_config, &sconfig, "server", server, 0);
err = snd_config_search_alias(snd_config, "server", server, &sconfig);
if (err < 0) {
SNDERR("Unknown server %s", server);
return -EINVAL;
}
if (snd_config_get_type(sconfig) != SND_CONFIG_TYPE_COMPOUND) {
SNDERR("Invalid type for server %s definition", server);
return -EINVAL;
}
snd_config_for_each(i, next, conf) {
snd_config_t *n = snd_config_iterator_entry(i);
const char *id = snd_config_get_id(n);

View file

@ -5,8 +5,8 @@ libpcm_la_SOURCES = atomic.c mask.c interval.c \
pcm.c pcm_m4.c pcm_hw.c pcm_plugin.c pcm_copy.c pcm_linear.c \
pcm_route.c pcm_mulaw.c pcm_alaw.c pcm_adpcm.c \
pcm_rate.c pcm_plug.c pcm_misc.c pcm_mmap.c pcm_multi.c \
pcm_shm.c pcm_file.c pcm_share.c pcm_null.c pcm_meter.c \
pcm_params.c
pcm_shm.c pcm_file.c pcm_null.c pcm_share.c \
pcm_meter.c pcm_params.c
noinst_HEADERS = atomic.h pcm_local.h pcm_plugin.h mask.h mask_inline.h \
interval.h interval_inline.h plugin_ops.h

View file

@ -23,6 +23,7 @@
#include <string.h>
#include <malloc.h>
#include <stdarg.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <sys/poll.h>
#include <sys/shm.h>
@ -89,8 +90,20 @@ int snd_pcm_nonblock(snd_pcm_t *pcm, int nonblock)
int snd_pcm_async(snd_pcm_t *pcm, int sig, pid_t pid)
{
int err;
assert(pcm);
return pcm->ops->async(pcm->op_arg, sig, pid);
err = pcm->ops->async(pcm->op_arg, sig, pid);
if (err < 0)
return err;
if (sig)
pcm->async_sig = sig;
else
pcm->async_sig = SIGIO;
if (pid)
pcm->async_pid = pid;
else
pcm->async_pid = getpid();
return 0;
}
int snd_pcm_info(snd_pcm_t *pcm, snd_pcm_info_t *info)
@ -564,28 +577,31 @@ int snd_pcm_open(snd_pcm_t **pcmp, const char *name,
int (*open_func)(snd_pcm_t **pcmp, const char *name, snd_config_t *conf,
snd_pcm_stream_t stream, int mode);
void *h;
const char *name1;
assert(pcmp && name);
err = snd_config_update();
if (err < 0)
return err;
err = snd_config_searchv(snd_config, &pcm_conf, "pcm", name, 0);
if (err < 0) {
err = snd_config_search_alias(snd_config, "pcm", name, &pcm_conf);
name1 = name;
if (err < 0 || snd_config_get_string(pcm_conf, &name1) >= 0) {
int card, dev, subdev;
char socket[256], sname[256];
char format[16], file[256];
err = sscanf(name, "hw:%d,%d,%d", &card, &dev, &subdev);
err = sscanf(name1, "hw:%d,%d,%d", &card, &dev, &subdev);
if (err == 3)
return snd_pcm_hw_open(pcmp, name, card, dev, subdev, stream, mode);
err = sscanf(name, "hw:%d,%d", &card, &dev);
err = sscanf(name1, "hw:%d,%d", &card, &dev);
if (err == 2)
return snd_pcm_hw_open(pcmp, name, card, dev, -1, stream, mode);
err = sscanf(name, "plug:%d,%d,%d", &card, &dev, &subdev);
err = sscanf(name1, "plug:%d,%d,%d", &card, &dev, &subdev);
if (err == 3)
return snd_pcm_plug_open_hw(pcmp, name, card, dev, subdev, stream, mode);
err = sscanf(name, "plug:%d,%d", &card, &dev);
err = sscanf(name1, "plug:%d,%d", &card, &dev);
if (err == 2)
return snd_pcm_plug_open_hw(pcmp, name, card, dev, -1, stream, mode);
err = sscanf(name, "plug:%256[^,]", sname);
err = sscanf(name1, "plug:%256[^,]", sname);
if (err == 1) {
snd_pcm_t *slave;
err = snd_pcm_open(&slave, sname, stream, mode);
@ -593,18 +609,18 @@ int snd_pcm_open(snd_pcm_t **pcmp, const char *name,
return err;
return snd_pcm_plug_open(pcmp, name, NULL, 0, 0, 0, slave, 1);
}
err = sscanf(name, "shm:%256[^,],%256[^,]", socket, sname);
err = sscanf(name1, "shm:%256[^,],%256[^,]", socket, sname);
if (err == 2)
return snd_pcm_shm_open(pcmp, name, socket, sname, stream, mode);
err = sscanf(name, "file:%256[^,],%16[^,],%256[^,]", file, format, sname);
err = sscanf(name1, "file:%256[^,],%16[^,],%256[^,]", file, format, sname);
if (err == 3) {
snd_pcm_t *slave;
err = snd_pcm_open(&slave, sname, stream, mode);
if (err < 0)
return err;
return snd_pcm_file_open(pcmp, name, file, -1, format, slave, 1);
return snd_pcm_file_open(pcmp, name1, file, -1, format, slave, 1);
}
err = sscanf(name, "file:%256[^,],%16[^,]", file, format);
err = sscanf(name1, "file:%256[^,],%16[^,]", file, format);
if (err == 2) {
snd_pcm_t *slave;
err = snd_pcm_null_open(&slave, name, stream, mode);
@ -612,7 +628,7 @@ int snd_pcm_open(snd_pcm_t **pcmp, const char *name,
return err;
return snd_pcm_file_open(pcmp, name, file, -1, format, slave, 1);
}
err = sscanf(name, "file:%256[^,]", file);
err = sscanf(name1, "file:%256[^,]", file);
if (err == 1) {
snd_pcm_t *slave;
err = snd_pcm_null_open(&slave, name, stream, mode);
@ -620,13 +636,13 @@ int snd_pcm_open(snd_pcm_t **pcmp, const char *name,
return err;
return snd_pcm_file_open(pcmp, name, file, -1, "raw", slave, 1);
}
if (strcmp(name, "null") == 0)
if (strcmp(name1, "null") == 0)
return snd_pcm_null_open(pcmp, name, stream, mode);
SNDERR("Unknown PCM %s", name);
SNDERR("Unknown PCM %s", name1);
return -ENOENT;
}
if (snd_config_get_type(pcm_conf) != SND_CONFIG_TYPE_COMPOUND) {
SNDERR("Invalid type for PCM %s definition", name);
SNDERR("Invalid type for PCM %s definition", name1);
return -EINVAL;
}
err = snd_config_search(pcm_conf, "type", &conf);
@ -639,8 +655,12 @@ int snd_pcm_open(snd_pcm_t **pcmp, const char *name,
SNDERR("Invalid type for %s", snd_config_get_id(conf));
return err;
}
err = snd_config_searchv(snd_config, &type_conf, "pcmtype", str, 0);
err = snd_config_search_alias(snd_config, "pcm_type", str, &type_conf);
if (err >= 0) {
if (snd_config_get_type(type_conf) != SND_CONFIG_TYPE_COMPOUND) {
SNDERR("Invalid type for PCM type %s definition", str);
return -EINVAL;
}
snd_config_for_each(i, next, type_conf) {
snd_config_t *n = snd_config_iterator_entry(i);
const char *id = snd_config_get_id(n);
@ -1181,3 +1201,109 @@ snd_pcm_uframes_t _snd_pcm_boundary(snd_pcm_t *pcm)
return pcm->boundary;
}
static const char *names[SND_PCM_HW_PARAM_LAST + 1] = {
[SND_PCM_HW_PARAM_FORMAT] = "format",
[SND_PCM_HW_PARAM_CHANNELS] = "channels",
[SND_PCM_HW_PARAM_RATE] = "rate",
[SND_PCM_HW_PARAM_PERIOD_TIME] = "period_time",
[SND_PCM_HW_PARAM_BUFFER_TIME] = "buffer_time"
};
int snd_pcm_slave_conf(snd_config_t *conf, const char **namep,
unsigned int count, ...)
{
snd_config_iterator_t i, next;
const char *str;
struct {
unsigned int index;
int mandatory;
void *ptr;
int valid;
} fields[count];
unsigned int k;
int pcm_valid = 0;
int err;
va_list args;
if (snd_config_get_string(conf, &str) >= 0) {
err = snd_config_search_alias(snd_config, "pcm_slave", str, &conf);
if (err < 0) {
SNDERR("unkown pcm_slave %s", str);
return err;
}
}
va_start(args, count);
for (k = 0; k < count; ++k) {
fields[k].index = va_arg(args, int);
fields[k].mandatory = va_arg(args, int);
fields[k].ptr = va_arg(args, void *);
fields[k].valid = 0;
}
va_end(args);
snd_config_for_each(i, next, conf) {
snd_config_t *n = snd_config_iterator_entry(i);
const char *id = snd_config_get_id(n);
if (strcmp(id, "comment") == 0)
continue;
if (strcmp(id, "pcm") == 0) {
if (pcm_valid) {
_duplicated:
SNDERR("duplicated %s", id);
return -EINVAL;
}
err = snd_config_get_string(n, namep);
if (err < 0) {
_invalid:
SNDERR("invalid type for %s", id);
return err;
}
pcm_valid = 1;
continue;
}
for (k = 0; k < count; ++k) {
unsigned int idx = fields[k].index;
long v;
assert(idx < SND_PCM_HW_PARAM_LAST);
assert(names[idx]);
if (strcmp(id, names[idx]) != 0)
continue;
if (fields[k].valid)
goto _duplicated;
switch (idx) {
case SND_PCM_HW_PARAM_FORMAT:
{
snd_pcm_format_t f;
err = snd_config_get_string(n, &str);
if (err < 0)
goto _invalid;
f = snd_pcm_format_value(str);
if (f == SND_PCM_FORMAT_UNKNOWN) {
SNDERR("unknown format");
return -EINVAL;
}
*(snd_pcm_format_t*)fields[k].ptr = f;
break;
}
default:
err = snd_config_get_integer(n, &v);
if (err < 0)
goto _invalid;
*(int*)fields[k].ptr = v;
break;
}
fields[k].valid = 1;
break;
}
if (k < count)
continue;
SNDERR("Unknown field %s", id);
return -EINVAL;
}
for (k = 0; k < count; ++k) {
if (fields[k].mandatory && !fields[k].valid) {
SNDERR("missing field %s", names[fields[k].index]);
return -EINVAL;
}
}
return 0;
}

View file

@ -552,7 +552,8 @@ int _snd_pcm_adpcm_open(snd_pcm_t **pcmp, const char *name,
const char *sname = NULL;
int err;
snd_pcm_t *spcm;
snd_pcm_format_t sformat = SND_PCM_FORMAT_UNKNOWN;
snd_config_t *slave = NULL;
snd_pcm_format_t sformat;
snd_config_for_each(i, next, conf) {
snd_config_t *n = snd_config_iterator_entry(i);
const char *id = snd_config_get_id(n);
@ -560,42 +561,24 @@ int _snd_pcm_adpcm_open(snd_pcm_t **pcmp, const char *name,
continue;
if (strcmp(id, "type") == 0)
continue;
if (strcmp(id, "sname") == 0) {
err = snd_config_get_string(n, &sname);
if (err < 0) {
SNDERR("Invalid type for %s", id);
return -EINVAL;
}
continue;
}
if (strcmp(id, "sformat") == 0) {
const char *f;
err = snd_config_get_string(n, &f);
if (err < 0) {
SNDERR("Invalid type for %s", id);
return -EINVAL;
}
sformat = snd_pcm_format_value(f);
if (sformat == SND_PCM_FORMAT_UNKNOWN) {
SNDERR("Unknown sformat");
return -EINVAL;
}
if (snd_pcm_format_linear(sformat) != 1 &&
sformat != SND_PCM_FORMAT_IMA_ADPCM) {
SNDERR("Invalid sformat");
return -EINVAL;
}
if (strcmp(id, "slave") == 0) {
slave = n;
continue;
}
SNDERR("Unknown field %s", id);
return -EINVAL;
}
if (!sname) {
SNDERR("sname is not defined");
if (!slave) {
SNDERR("slave is not defined");
return -EINVAL;
}
if (sformat == SND_PCM_FORMAT_UNKNOWN) {
SNDERR("sformat is not defined");
err = snd_pcm_slave_conf(slave, &sname, 1,
SND_PCM_HW_PARAM_FORMAT, 1, &sformat);
if (err < 0)
return err;
if (snd_pcm_format_linear(sformat) != 1 &&
sformat != SND_PCM_FORMAT_IMA_ADPCM) {
SNDERR("invalid slave format");
return -EINVAL;
}
/* This is needed cause snd_config_update may destroy config */

View file

@ -425,7 +425,8 @@ int _snd_pcm_alaw_open(snd_pcm_t **pcmp, const char *name,
const char *sname = NULL;
int err;
snd_pcm_t *spcm;
snd_pcm_format_t sformat = SND_PCM_FORMAT_UNKNOWN;
snd_config_t *slave = NULL;
snd_pcm_format_t sformat;
snd_config_for_each(i, next, conf) {
snd_config_t *n = snd_config_iterator_entry(i);
const char *id = snd_config_get_id(n);
@ -433,42 +434,24 @@ int _snd_pcm_alaw_open(snd_pcm_t **pcmp, const char *name,
continue;
if (strcmp(id, "type") == 0)
continue;
if (strcmp(id, "sname") == 0) {
err = snd_config_get_string(n, &sname);
if (err < 0) {
SNDERR("Invalid type for %s", id);
return -EINVAL;
}
continue;
}
if (strcmp(id, "sformat") == 0) {
const char *f;
err = snd_config_get_string(n, &f);
if (err < 0) {
SNDERR("Invalid type for %s", id);
return -EINVAL;
}
sformat = snd_pcm_format_value(f);
if (sformat == SND_PCM_FORMAT_UNKNOWN) {
SNDERR("Unknown sformat");
return -EINVAL;
}
if (snd_pcm_format_linear(sformat) != 1 &&
sformat != SND_PCM_FORMAT_A_LAW) {
SNDERR("Invalid sformat");
return -EINVAL;
}
if (strcmp(id, "slave") == 0) {
slave = n;
continue;
}
SNDERR("Unknown field %s", id);
return -EINVAL;
}
if (!sname) {
SNDERR("sname is not defined");
if (!slave) {
SNDERR("slave is not defined");
return -EINVAL;
}
if (sformat == SND_PCM_FORMAT_UNKNOWN) {
SNDERR("sformat is not defined");
err = snd_pcm_slave_conf(slave, &sname, 1,
SND_PCM_HW_PARAM_FORMAT, 1, &sformat);
if (err < 0)
return err;
if (snd_pcm_format_linear(sformat) != 1 &&
sformat != SND_PCM_FORMAT_A_LAW) {
SNDERR("invalid slave format");
return -EINVAL;
}
/* This is needed cause snd_config_update may destroy config */

View file

@ -198,6 +198,7 @@ int _snd_pcm_copy_open(snd_pcm_t **pcmp, const char *name,
const char *sname = NULL;
int err;
snd_pcm_t *spcm;
snd_config_t *slave = NULL;
snd_config_for_each(i, next, conf) {
snd_config_t *n = snd_config_iterator_entry(i);
const char *id = snd_config_get_id(n);
@ -205,21 +206,20 @@ int _snd_pcm_copy_open(snd_pcm_t **pcmp, const char *name,
continue;
if (strcmp(id, "type") == 0)
continue;
if (strcmp(id, "sname") == 0) {
err = snd_config_get_string(n, &sname);
if (err < 0) {
SNDERR("Invalid type for %s", id);
return -EINVAL;
}
if (strcmp(id, "slave") == 0) {
slave = n;
continue;
}
SNDERR("Unknown field %s", id);
return -EINVAL;
}
if (!sname) {
SNDERR("sname is not defined");
if (!slave) {
SNDERR("slave is not defined");
return -EINVAL;
}
err = snd_pcm_slave_conf(slave, &sname, 0);
if (err < 0)
return err;
/* This is needed cause snd_config_update may destroy config */
sname = strdup(sname);
if (!sname)

View file

@ -467,6 +467,7 @@ int _snd_pcm_file_open(snd_pcm_t **pcmp, const char *name,
const char *sname = NULL;
int err;
snd_pcm_t *spcm;
snd_config_t *slave = NULL;
const char *fname = NULL;
const char *format = NULL;
long fd = -1;
@ -477,12 +478,8 @@ int _snd_pcm_file_open(snd_pcm_t **pcmp, const char *name,
continue;
if (strcmp(id, "type") == 0)
continue;
if (strcmp(id, "sname") == 0) {
err = snd_config_get_string(n, &sname);
if (err < 0) {
SNDERR("Invalid type for %s", id);
return -EINVAL;
}
if (strcmp(id, "slave") == 0) {
slave = n;
continue;
}
if (strcmp(id, "format") == 0) {
@ -507,10 +504,13 @@ int _snd_pcm_file_open(snd_pcm_t **pcmp, const char *name,
SNDERR("Unknown field %s", id);
return -EINVAL;
}
if (!sname) {
SNDERR("sname is not defined");
if (!slave) {
SNDERR("slave is not defined");
return -EINVAL;
}
err = snd_pcm_slave_conf(slave, &sname, 0);
if (err < 0)
return err;
if (!fname && fd < 0) {
SNDERR("file is not defined");
return -EINVAL;

View file

@ -329,10 +329,11 @@ int _snd_pcm_linear_open(snd_pcm_t **pcmp, const char *name,
snd_pcm_stream_t stream, int mode)
{
snd_config_iterator_t i, next;
const char *sname = NULL;
const char *sname;
int err;
snd_pcm_t *spcm;
snd_pcm_format_t sformat = SND_PCM_FORMAT_UNKNOWN;
snd_config_t *slave = NULL;
snd_pcm_format_t sformat;
snd_config_for_each(i, next, conf) {
snd_config_t *n = snd_config_iterator_entry(i);
const char *id = snd_config_get_id(n);
@ -340,41 +341,23 @@ int _snd_pcm_linear_open(snd_pcm_t **pcmp, const char *name,
continue;
if (strcmp(id, "type") == 0)
continue;
if (strcmp(id, "sname") == 0) {
err = snd_config_get_string(n, &sname);
if (err < 0) {
SNDERR("Invalid type for %s", id);
return -EINVAL;
}
continue;
}
if (strcmp(id, "sformat") == 0) {
const char *f;
err = snd_config_get_string(n, &f);
if (err < 0) {
SNDERR("Invalid type for %s", id);
return -EINVAL;
}
sformat = snd_pcm_format_value(f);
if (sformat == SND_PCM_FORMAT_UNKNOWN) {
SNDERR("Unknown sformat %s", f);
return err;
}
if (snd_pcm_format_linear(sformat) != 1) {
SNDERR("sformat is not linear");
return -EINVAL;
}
if (strcmp(id, "slave") == 0) {
slave = n;
continue;
}
SNDERR("Unknown field %s", id);
return -EINVAL;
}
if (!sname) {
SNDERR("sname is not defined");
if (!slave) {
SNDERR("slave is not defined");
return -EINVAL;
}
if (sformat == SND_PCM_FORMAT_UNKNOWN) {
SNDERR("sformat is not defined");
err = snd_pcm_slave_conf(slave, &sname, 1,
SND_PCM_HW_PARAM_FORMAT, 1, &sformat);
if (err < 0)
return err;
if (snd_pcm_format_linear(sformat) != 1) {
SNDERR("slave format is not linear");
return -EINVAL;
}
/* This is needed cause snd_config_update may destroy config */

View file

@ -143,6 +143,8 @@ struct _snd_pcm {
snd_pcm_uframes_t silence_size; /* Silence filling size */
snd_pcm_uframes_t xfer_align; /* xfer size need to be a multiple */
snd_pcm_uframes_t boundary; /* pointers wrap point */
int async_sig;
pid_t async_pid;
unsigned int info; /* Info for returned setup */
unsigned int msbits; /* used most significant bits */
unsigned int rate_num; /* rate numerator */
@ -486,6 +488,9 @@ int snd_pcm_hw_strategy_simple_choices(snd_pcm_hw_strategy_t *strategy, int orde
unsigned int count,
snd_pcm_hw_strategy_simple_choices_list_t *choices);
int snd_pcm_slave_conf(snd_config_t *conf, const char **namep,
unsigned int count, ...);
#define SND_PCM_HW_PARBIT_ACCESS (1 << SND_PCM_HW_PARAM_ACCESS)
#define SND_PCM_HW_PARBIT_FORMAT (1 << SND_PCM_HW_PARAM_FORMAT)
#define SND_PCM_HW_PARBIT_SUBFORMAT (1 << SND_PCM_HW_PARAM_SUBFORMAT)

View file

@ -658,7 +658,7 @@ int snd_pcm_meter_add_scope_conf(snd_pcm_t *pcm, const char *name,
SNDERR("Invalid type for %s", snd_config_get_id(c));
return err;
}
err = snd_config_searchv(snd_config, &type_conf, "scopetype", str, 0);
err = snd_config_search_alias(snd_config, "pcm_scope_type", str, &type_conf);
if (err >= 0) {
snd_config_for_each(i, next, type_conf) {
snd_config_t *n = snd_config_iterator_entry(i);
@ -714,6 +714,7 @@ int _snd_pcm_meter_open(snd_pcm_t **pcmp, const char *name,
const char *sname = NULL;
int err;
snd_pcm_t *spcm;
snd_config_t *slave = NULL;
long frequency = -1;
snd_config_t *scopes = NULL;
snd_config_for_each(i, next, conf) {
@ -723,12 +724,8 @@ int _snd_pcm_meter_open(snd_pcm_t **pcmp, const char *name,
continue;
if (strcmp(id, "type") == 0)
continue;
if (strcmp(id, "sname") == 0) {
err = snd_config_get_string(n, &sname);
if (err < 0) {
SNDERR("Invalid type for %s", id);
return -EINVAL;
}
if (strcmp(id, "slave") == 0) {
slave = n;
continue;
}
if (strcmp(id, "frequency") == 0) {
@ -739,7 +736,7 @@ int _snd_pcm_meter_open(snd_pcm_t **pcmp, const char *name,
}
continue;
}
if (strcmp(id, "scope") == 0) {
if (strcmp(id, "scopes") == 0) {
if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) {
SNDERR("Invalid type for %s", id);
return -EINVAL;
@ -750,11 +747,13 @@ int _snd_pcm_meter_open(snd_pcm_t **pcmp, const char *name,
SNDERR("Unknown field %s", id);
return -EINVAL;
}
if (!sname) {
SNDERR("sname is not defined");
if (!slave) {
SNDERR("slave is not defined");
return -EINVAL;
}
err = snd_pcm_slave_conf(slave, &sname, 0);
if (err < 0)
return err;
/* This is needed cause snd_config_update may destroy config */
sname = strdup(sname);
if (!sname)

View file

@ -440,7 +440,8 @@ int _snd_pcm_mulaw_open(snd_pcm_t **pcmp, const char *name,
const char *sname = NULL;
int err;
snd_pcm_t *spcm;
snd_pcm_format_t sformat = SND_PCM_FORMAT_UNKNOWN;
snd_config_t *slave = NULL;
snd_pcm_format_t sformat;
snd_config_for_each(i, next, conf) {
snd_config_t *n = snd_config_iterator_entry(i);
const char *id = snd_config_get_id(n);
@ -448,42 +449,24 @@ int _snd_pcm_mulaw_open(snd_pcm_t **pcmp, const char *name,
continue;
if (strcmp(id, "type") == 0)
continue;
if (strcmp(id, "sname") == 0) {
err = snd_config_get_string(n, &sname);
if (err < 0) {
SNDERR("Invalid type for %s", id);
return -EINVAL;
}
continue;
}
if (strcmp(id, "sformat") == 0) {
const char *f;
err = snd_config_get_string(n, &f);
if (err < 0) {
SNDERR("Invalid type for %s", id);
return -EINVAL;
}
sformat = snd_pcm_format_value(f);
if (sformat == SND_PCM_FORMAT_UNKNOWN) {
SNDERR("Unknown sformat");
return -EINVAL;
}
if (snd_pcm_format_linear(sformat) != 1 &&
sformat != SND_PCM_FORMAT_MU_LAW) {
SNDERR("Invalid sformat");
return -EINVAL;
}
if (strcmp(id, "slave") == 0) {
slave = n;
continue;
}
SNDERR("Unknown field %s", id);
return -EINVAL;
}
if (!sname) {
SNDERR("sname is not defined");
if (!slave) {
SNDERR("slave is not defined");
return -EINVAL;
}
if (sformat == SND_PCM_FORMAT_UNKNOWN) {
SNDERR("sformat is not defined");
err = snd_pcm_slave_conf(slave, &sname, 1,
SND_PCM_HW_PARAM_FORMAT, 1, &sformat);
if (err < 0)
return err;
if (snd_pcm_format_linear(sformat) != 1 &&
sformat != SND_PCM_FORMAT_MU_LAW) {
SNDERR("invalid slave format");
return -EINVAL;
}
/* This is needed cause snd_config_update may destroy config */

View file

@ -584,8 +584,8 @@ int _snd_pcm_multi_open(snd_pcm_t **pcmp, const char *name, snd_config_t *conf,
snd_pcm_stream_t stream, int mode)
{
snd_config_iterator_t i, inext, j, jnext;
snd_config_t *slave = NULL;
snd_config_t *binding = NULL;
snd_config_t *slaves = NULL;
snd_config_t *bindings = NULL;
int err;
unsigned int idx;
const char **slaves_id = NULL;
@ -603,37 +603,37 @@ int _snd_pcm_multi_open(snd_pcm_t **pcmp, const char *name, snd_config_t *conf,
continue;
if (strcmp(id, "type") == 0)
continue;
if (strcmp(id, "slave") == 0) {
if (strcmp(id, "slaves") == 0) {
if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) {
SNDERR("Invalid type for %s", id);
return -EINVAL;
}
slave = n;
slaves = n;
continue;
}
if (strcmp(id, "binding") == 0) {
if (strcmp(id, "bindings") == 0) {
if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) {
SNDERR("Invalid type for %s", id);
return -EINVAL;
}
binding = n;
bindings = n;
continue;
}
SNDERR("Unknown field %s", id);
return -EINVAL;
}
if (!slave) {
SNDERR("slave is not defined");
if (!slaves) {
SNDERR("slaves is not defined");
return -EINVAL;
}
if (!binding) {
SNDERR("binding is not defined");
if (!bindings) {
SNDERR("bindings is not defined");
return -EINVAL;
}
snd_config_for_each(i, inext, slave) {
snd_config_for_each(i, inext, slaves) {
++slaves_count;
}
snd_config_for_each(i, inext, binding) {
snd_config_for_each(i, inext, bindings) {
int cchannel = -1;
char *p;
snd_config_t *m = snd_config_iterator_entry(i);
@ -661,52 +661,21 @@ int _snd_pcm_multi_open(snd_pcm_t **pcmp, const char *name, snd_config_t *conf,
for (idx = 0; idx < channels_count; ++idx)
channels_sidx[idx] = -1;
idx = 0;
snd_config_for_each(i, inext, slave) {
snd_config_for_each(i, inext, slaves) {
snd_config_t *m = snd_config_iterator_entry(i);
const char *name = NULL;
long channels = -1;
const char *name;
int channels;
slaves_id[idx] = snd_config_get_id(m);
snd_config_for_each(j, jnext, m) {
snd_config_t *n = snd_config_iterator_entry(j);
const char *id = snd_config_get_id(n);
if (strcmp(id, "comment") == 0)
continue;
if (strcmp(id, "name") == 0) {
err = snd_config_get_string(n, &name);
if (err < 0) {
SNDERR("Invalid type for %s", id);
goto _free;
}
continue;
}
if (strcmp(id, "channels") == 0) {
err = snd_config_get_integer(n, &channels);
if (err < 0) {
SNDERR("Invalid type for %s", id);
goto _free;
}
continue;
}
SNDERR("Unknown field %s", id);
err = -EINVAL;
err = snd_pcm_slave_conf(m, &name, 1,
SND_PCM_HW_PARAM_CHANNELS, 1, &channels);
if (err < 0)
goto _free;
}
if (!name) {
SNDERR("name is not defined");
err = -EINVAL;
goto _free;
}
if (channels < 0) {
SNDERR("channels is not defined");
err = -EINVAL;
goto _free;
}
slaves_name[idx] = strdup(name);
slaves_channels[idx] = channels;
++idx;
}
snd_config_for_each(i, inext, binding) {
snd_config_for_each(i, inext, bindings) {
snd_config_t *m = snd_config_iterator_entry(i);
long cchannel = -1;
long schannel = -1;
@ -725,7 +694,7 @@ int _snd_pcm_multi_open(snd_pcm_t **pcmp, const char *name, snd_config_t *conf,
const char *id = snd_config_get_id(n);
if (strcmp(id, "comment") == 0)
continue;
if (strcmp(id, "sidx") == 0) {
if (strcmp(id, "slave") == 0) {
char buf[32];
unsigned int k;
err = snd_config_get_string(n, &str);
@ -744,7 +713,7 @@ int _snd_pcm_multi_open(snd_pcm_t **pcmp, const char *name, snd_config_t *conf,
}
continue;
}
if (strcmp(id, "schannel") == 0) {
if (strcmp(id, "channel") == 0) {
err = snd_config_get_integer(n, &schannel);
if (err < 0) {
SNDERR("Invalid type for %s", id);

View file

@ -718,6 +718,7 @@ int _snd_pcm_plug_open(snd_pcm_t **pcmp, const char *name,
const char *sname = NULL;
int err;
snd_pcm_t *spcm;
snd_config_t *slave = NULL;
snd_config_t *tt = NULL;
snd_pcm_route_ttable_entry_t *ttable = NULL;
unsigned int cused, sused;
@ -728,12 +729,8 @@ int _snd_pcm_plug_open(snd_pcm_t **pcmp, const char *name,
continue;
if (strcmp(id, "type") == 0)
continue;
if (strcmp(id, "sname") == 0) {
err = snd_config_get_string(n, &sname);
if (err < 0) {
SNDERR("Invalid type for %s", id);
return -EINVAL;
}
if (strcmp(id, "slave") == 0) {
slave = n;
continue;
}
if (strcmp(id, "ttable") == 0) {
@ -747,10 +744,13 @@ int _snd_pcm_plug_open(snd_pcm_t **pcmp, const char *name,
SNDERR("Unknown field %s", id);
return -EINVAL;
}
if (!sname) {
SNDERR("sname is not defined");
if (!slave) {
SNDERR("slave is not defined");
return -EINVAL;
}
err = snd_pcm_slave_conf(slave, &sname, 0);
if (err < 0)
return err;
if (tt) {
ttable = malloc(MAX_CHANNELS * MAX_CHANNELS * sizeof(*ttable));
err = snd_pcm_route_load_ttable(tt, ttable, MAX_CHANNELS, MAX_CHANNELS,

View file

@ -542,8 +542,9 @@ int _snd_pcm_rate_open(snd_pcm_t **pcmp, const char *name,
const char *sname = NULL;
int err;
snd_pcm_t *spcm;
snd_config_t *slave = NULL;
snd_pcm_format_t sformat = SND_PCM_FORMAT_UNKNOWN;
long srate = -1;
int srate = -1;
snd_config_for_each(i, next, conf) {
snd_config_t *n = snd_config_iterator_entry(i);
const char *id = snd_config_get_id(n);
@ -551,49 +552,25 @@ int _snd_pcm_rate_open(snd_pcm_t **pcmp, const char *name,
continue;
if (strcmp(id, "type") == 0)
continue;
if (strcmp(id, "sname") == 0) {
err = snd_config_get_string(n, &sname);
if (err < 0) {
SNDERR("Invalid type for %s", id);
return -EINVAL;
}
continue;
}
if (strcmp(id, "sformat") == 0) {
const char *f;
err = snd_config_get_string(n, &f);
if (err < 0) {
SNDERR("Invalid type for %s", id);
return -EINVAL;
}
sformat = snd_pcm_format_value(f);
if (sformat == SND_PCM_FORMAT_UNKNOWN) {
SNDERR("Unknown sformat");
return -EINVAL;
}
if (snd_pcm_format_linear(sformat) != 1) {
SNDERR("sformat is not linear");
return -EINVAL;
}
continue;
}
if (strcmp(id, "srate") == 0) {
err = snd_config_get_integer(n, &srate);
if (err < 0) {
SNDERR("Invalid type for %s", id);
return -EINVAL;
}
if (strcmp(id, "slave") == 0) {
slave = n;
continue;
}
SNDERR("Unknown field %s", id);
return -EINVAL;
}
if (!sname) {
SNDERR("sname is not defined");
if (!slave) {
SNDERR("slave is not defined");
return -EINVAL;
}
if (srate < 0) {
SNDERR("srate is not defined");
err = snd_pcm_slave_conf(slave, &sname, 2,
SND_PCM_HW_PARAM_FORMAT, 0, &sformat,
SND_PCM_HW_PARAM_RATE, 1, &srate);
if (err < 0)
return err;
if (sformat != SND_PCM_FORMAT_UNKNOWN &&
snd_pcm_format_linear(sformat) != 1) {
SNDERR("slave format is not linear");
return -EINVAL;
}
/* This is needed cause snd_config_update may destroy config */

View file

@ -156,44 +156,47 @@ void snd_pcm_route_convert1_many(const snd_pcm_channel_area_t *dst_area,
#include "plugin_ops.h"
#undef GETU_LABELS
#undef PUT32_LABELS
static void *zero_labels[3] = { &&zero_int32, &&zero_int64,
static void *zero_labels[3] = {
&&zero_int32, &&zero_int64,
#if ROUTE_PLUGIN_FLOAT
&&zero_float
&&zero_float
#endif
};
/* sum_type att */
static void *add_labels[3 * 2] = { &&add_int32_noatt, &&add_int32_att,
&&add_int64_noatt, &&add_int64_att,
static void *add_labels[3 * 2] = {
&&add_int32_noatt, &&add_int32_att,
&&add_int64_noatt, &&add_int64_att,
#if ROUTE_PLUGIN_FLOAT
&&add_float_noatt, &&add_float_att
&&add_float_noatt, &&add_float_att
#endif
};
/* sum_type att shift */
static void *norm_labels[3 * 2 * 4] = { 0,
&&norm_int32_8_noatt,
&&norm_int32_16_noatt,
&&norm_int32_24_noatt,
0,
&&norm_int32_8_att,
&&norm_int32_16_att,
&&norm_int32_24_att,
&&norm_int64_0_noatt,
&&norm_int64_8_noatt,
&&norm_int64_16_noatt,
&&norm_int64_24_noatt,
&&norm_int64_0_att,
&&norm_int64_8_att,
&&norm_int64_16_att,
&&norm_int64_24_att,
static void *norm_labels[3 * 2 * 4] = {
0,
&&norm_int32_8_noatt,
&&norm_int32_16_noatt,
&&norm_int32_24_noatt,
0,
&&norm_int32_8_att,
&&norm_int32_16_att,
&&norm_int32_24_att,
&&norm_int64_0_noatt,
&&norm_int64_8_noatt,
&&norm_int64_16_noatt,
&&norm_int64_24_noatt,
&&norm_int64_0_att,
&&norm_int64_8_att,
&&norm_int64_16_att,
&&norm_int64_24_att,
#if ROUTE_PLUGIN_FLOAT
&&norm_float_0,
&&norm_float_8,
&&norm_float_16,
&&norm_float_24,
&&norm_float_0,
&&norm_float_8,
&&norm_float_16,
&&norm_float_24,
&&norm_float_0,
&&norm_float_8,
&&norm_float_16,
&&norm_float_24,
&&norm_float_0,
&&norm_float_8,
&&norm_float_16,
&&norm_float_24,
#endif
};
void *zero, *get, *add, *norm, *put32;
@ -843,8 +846,9 @@ int _snd_pcm_route_open(snd_pcm_t **pcmp, const char *name,
const char *sname = NULL;
int err;
snd_pcm_t *spcm;
snd_config_t *slave = NULL;
snd_pcm_format_t sformat = SND_PCM_FORMAT_UNKNOWN;
long schannels = -1;
int schannels = -1;
snd_config_t *tt = NULL;
snd_pcm_route_ttable_entry_t ttable[MAX_CHANNELS*MAX_CHANNELS];
unsigned int cused, sused;
@ -855,38 +859,8 @@ int _snd_pcm_route_open(snd_pcm_t **pcmp, const char *name,
continue;
if (strcmp(id, "type") == 0)
continue;
if (strcmp(id, "sname") == 0) {
err = snd_config_get_string(n, &sname);
if (err < 0) {
SNDERR("Invalid type for %s", id);
return -EINVAL;
}
continue;
}
if (strcmp(id, "sformat") == 0) {
const char *f;
err = snd_config_get_string(n, &f);
if (err < 0) {
SNDERR("Invalid type for %s", id);
return -EINVAL;
}
sformat = snd_pcm_format_value(f);
if (sformat == SND_PCM_FORMAT_UNKNOWN) {
SNDERR("Unknown sformat");
return -EINVAL;
}
if (snd_pcm_format_linear(sformat) != 1) {
SNDERR("sformat is not linear");
return -EINVAL;
}
continue;
}
if (strcmp(id, "schannels") == 0) {
err = snd_config_get_integer(n, &schannels);
if (err < 0) {
SNDERR("Invalid type for %s", id);
return -EINVAL;
}
if (strcmp(id, "slave") == 0) {
slave = n;
continue;
}
if (strcmp(id, "ttable") == 0) {
@ -900,14 +874,24 @@ int _snd_pcm_route_open(snd_pcm_t **pcmp, const char *name,
SNDERR("Unknown field %s", id);
return -EINVAL;
}
if (!sname) {
SNDERR("sname is not defined");
if (!slave) {
SNDERR("slave is not defined");
return -EINVAL;
}
if (!tt) {
SNDERR("ttable is not defined");
return -EINVAL;
}
err = snd_pcm_slave_conf(slave, &sname, 2,
SND_PCM_HW_PARAM_FORMAT, 0, &sformat,
SND_PCM_HW_PARAM_CHANNELS, 0, &schannels);
if (err < 0)
return err;
if (sformat != SND_PCM_FORMAT_UNKNOWN &&
snd_pcm_format_linear(sformat) != 1) {
SNDERR("slave format is not linear");
return -EINVAL;
}
err = snd_pcm_route_load_ttable(tt, ttable, MAX_CHANNELS, MAX_CHANNELS,
&cused, &sused, schannels);

View file

@ -33,33 +33,31 @@
#include "pcm_local.h"
#include "list.h"
static LIST_HEAD(slaves);
static pthread_mutex_t slaves_mutex = PTHREAD_MUTEX_INITIALIZER;
char *slaves_mutex_holder;
#define _S(x) #x
#define S(x) _S(x)
static LIST_HEAD(snd_pcm_share_slaves);
static pthread_mutex_t snd_pcm_share_slaves_mutex = PTHREAD_MUTEX_INITIALIZER;
#if 1
#define Pthread_mutex_lock(mutex) pthread_mutex_lock(mutex)
#define Pthread_mutex_unlock(mutex) pthread_mutex_unlock(mutex)
#else
#ifdef MUTEX_DEBUG
#define Pthread_mutex_lock(mutex) \
char *snd_pcm_share_slaves_mutex_holder;
do { \
int err = pthread_mutex_trylock(mutex); \
if (err == EBUSY) { \
fprintf(stderr, "lock " #mutex " is busy (%s): waiting in " __FUNCTION__ "\n", *(mutex##_holder)); \
pthread_mutex_lock(mutex); \
fprintf(stderr, "... got\n"); \
} \
*(mutex##_holder) = __FUNCTION__; \
int err = pthread_mutex_trylock(mutex); \
if (err < 0) { \
fprintf(stderr, "lock " #mutex " is busy (%s): waiting in " __FUNCTION__ "\n", *(mutex##_holder)); \
pthread_mutex_lock(mutex); \
fprintf(stderr, "... got\n"); \
} \
*(mutex##_holder) = __FUNCTION__; \
} while (0)
#define Pthread_mutex_unlock(mutex) \
do { \
*(mutex##_holder) = 0; \
pthread_mutex_unlock(mutex); \
*(mutex##_holder) = 0; \
pthread_mutex_unlock(mutex); \
} while (0)
#else
#define Pthread_mutex_lock(mutex) pthread_mutex_lock(mutex)
#define Pthread_mutex_unlock(mutex) pthread_mutex_unlock(mutex)
#endif
typedef struct {
@ -68,7 +66,9 @@ typedef struct {
snd_pcm_t *pcm;
snd_pcm_format_t format;
int rate;
unsigned int channels_count;
unsigned int channels;
int period_time;
int buffer_time;
unsigned int open_count;
unsigned int setup_count;
unsigned int mmap_count;
@ -82,7 +82,9 @@ typedef struct {
int polling;
pthread_t thread;
pthread_mutex_t mutex;
#ifdef MUTEX_DEBUG
char *mutex_holder;
#endif
pthread_cond_t poll_cond;
} snd_pcm_share_slave_t;
@ -92,11 +94,6 @@ typedef struct {
snd_pcm_share_slave_t *slave;
unsigned int channels_count;
int *slave_channels;
int xfer_mode;
int xrun_mode;
snd_pcm_uframes_t avail_min;
int async_sig;
pid_t async_pid;
int drain_silenced;
struct timeval trigger_tstamp;
snd_pcm_state_t state;
@ -138,7 +135,7 @@ static snd_pcm_uframes_t _snd_pcm_share_slave_forward(snd_pcm_share_slave_t *sla
min_frames = slave_avail;
max_frames = 0;
slave_appl_ptr = *slave->pcm->appl_ptr;
for (i = slave->clients.next; i != &slave->clients; i = i->next) {
list_for_each(i, &slave->clients) {
snd_pcm_share_t *share = list_entry(i, snd_pcm_share_t, list);
snd_pcm_t *pcm = share->pcm;
switch (snd_enum_to_int(share->state)) {
@ -259,7 +256,7 @@ static snd_pcm_uframes_t _snd_pcm_share_missing(snd_pcm_t *pcm, int slave_xrun)
if ((snd_pcm_uframes_t)hw_avail < missing)
missing = hw_avail;
}
ready_missing = share->avail_min - avail;
ready_missing = pcm->avail_min - avail;
if (ready_missing > 0) {
ready = 0;
if ((snd_pcm_uframes_t)ready_missing < missing)
@ -328,7 +325,7 @@ static snd_pcm_uframes_t _snd_pcm_share_slave_missing(snd_pcm_share_slave_t *sla
snd_pcm_sframes_t avail = snd_pcm_avail_update(slave->pcm);
int slave_xrun = (avail == -EPIPE);
slave->hw_ptr = *slave->pcm->hw_ptr;
for (i = slave->clients.next; i != &slave->clients; i = i->next) {
list_for_each(i, &slave->clients) {
snd_pcm_share_t *share = list_entry(i, snd_pcm_share_t, list);
snd_pcm_t *pcm = share->pcm;
snd_pcm_uframes_t m = _snd_pcm_share_missing(pcm, slave_xrun);
@ -432,17 +429,8 @@ static int snd_pcm_share_nonblock(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int nonblock
return 0;
}
static int snd_pcm_share_async(snd_pcm_t *pcm, int sig, pid_t pid)
static int snd_pcm_share_async(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int sig ATTRIBUTE_UNUSED, pid_t pid ATTRIBUTE_UNUSED)
{
snd_pcm_share_t *share = pcm->private_data;
if (sig)
share->async_sig = sig;
else
share->async_sig = SIGIO;
if (pid)
share->async_pid = pid;
else
share->async_pid = getpid();
return -ENOSYS;
}
@ -480,6 +468,18 @@ static int snd_pcm_share_hw_refine_cprepare(snd_pcm_t *pcm, snd_pcm_hw_params_t
if (err < 0)
return err;
}
if (slave->period_time >= 0) {
err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_PERIOD_TIME,
slave->period_time, 0);
if (err < 0)
return err;
}
if (slave->buffer_time >= 0) {
err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_BUFFER_TIME,
slave->buffer_time, 0);
if (err < 0)
return err;
}
params->info |= SND_PCM_INFO_DOUBLE;
return 0;
}
@ -493,7 +493,7 @@ static int snd_pcm_share_hw_refine_sprepare(snd_pcm_t *pcm, snd_pcm_hw_params_t
_snd_pcm_hw_param_set_mask(sparams, SND_PCM_HW_PARAM_ACCESS,
&saccess_mask);
_snd_pcm_hw_param_set(sparams, SND_PCM_HW_PARAM_CHANNELS,
slave->channels_count, 0);
slave->channels, 0);
return 0;
}
@ -1093,7 +1093,7 @@ static int snd_pcm_share_close(snd_pcm_t *pcm)
snd_pcm_share_t *share = pcm->private_data;
snd_pcm_share_slave_t *slave = share->slave;
int err = 0;
Pthread_mutex_lock(&slaves_mutex);
Pthread_mutex_lock(&snd_pcm_share_slaves_mutex);
Pthread_mutex_lock(&slave->mutex);
slave->open_count--;
if (slave->open_count == 0) {
@ -1111,7 +1111,7 @@ static int snd_pcm_share_close(snd_pcm_t *pcm)
list_del(&share->list);
Pthread_mutex_unlock(&slave->mutex);
}
Pthread_mutex_unlock(&slaves_mutex);
Pthread_mutex_unlock(&snd_pcm_share_slaves_mutex);
close(share->client_socket);
close(share->slave_socket);
free(share->slave_channels);
@ -1183,6 +1183,7 @@ snd_pcm_fast_ops_t snd_pcm_share_fast_ops = {
int snd_pcm_share_open(snd_pcm_t **pcmp, const char *name, const char *sname,
snd_pcm_format_t sformat, int srate,
unsigned int schannels_count,
int speriod_time, int sbuffer_time,
unsigned int channels_count, int *channels_map,
snd_pcm_stream_t stream, int mode)
{
@ -1263,8 +1264,8 @@ int snd_pcm_share_open(snd_pcm_t **pcmp, const char *name, const char *sname,
return err;
}
Pthread_mutex_lock(&slaves_mutex);
for (i = slaves.next; i != &slaves; i = i->next) {
Pthread_mutex_lock(&snd_pcm_share_slaves_mutex);
list_for_each(i, &snd_pcm_share_slaves) {
snd_pcm_share_slave_t *s = list_entry(i, snd_pcm_share_slave_t, list);
if (s->pcm->name && strcmp(s->pcm->name, sname) == 0) {
slave = s;
@ -1275,7 +1276,7 @@ int snd_pcm_share_open(snd_pcm_t **pcmp, const char *name, const char *sname,
snd_pcm_t *spcm;
err = snd_pcm_open(&spcm, sname, stream, mode);
if (err < 0) {
Pthread_mutex_unlock(&slaves_mutex);
Pthread_mutex_unlock(&snd_pcm_share_slaves_mutex);
close(sd[0]);
close(sd[1]);
free(pcm);
@ -1285,7 +1286,7 @@ int snd_pcm_share_open(snd_pcm_t **pcmp, const char *name, const char *sname,
}
slave = calloc(1, sizeof(*slave));
if (!slave) {
Pthread_mutex_unlock(&slaves_mutex);
Pthread_mutex_unlock(&snd_pcm_share_slaves_mutex);
snd_pcm_close(spcm);
close(sd[0]);
close(sd[1]);
@ -1296,20 +1297,22 @@ int snd_pcm_share_open(snd_pcm_t **pcmp, const char *name, const char *sname,
}
INIT_LIST_HEAD(&slave->clients);
slave->pcm = spcm;
slave->channels_count = schannels_count;
slave->channels = schannels_count;
slave->format = sformat;
slave->rate = srate;
slave->period_time = speriod_time;
slave->buffer_time = sbuffer_time;
pthread_mutex_init(&slave->mutex, NULL);
pthread_cond_init(&slave->poll_cond, NULL);
list_add_tail(&slave->list, &slaves);
list_add_tail(&slave->list, &snd_pcm_share_slaves);
Pthread_mutex_lock(&slave->mutex);
err = pthread_create(&slave->thread, NULL, snd_pcm_share_thread, slave);
assert(err == 0);
Pthread_mutex_unlock(&slaves_mutex);
Pthread_mutex_unlock(&snd_pcm_share_slaves_mutex);
} else {
Pthread_mutex_lock(&slave->mutex);
Pthread_mutex_unlock(&slaves_mutex);
for (i = slave->clients.next; i != &slave->clients; i = i->next) {
Pthread_mutex_unlock(&snd_pcm_share_slaves_mutex);
list_for_each(i, &slave->clients) {
snd_pcm_share_t *sh = list_entry(i, snd_pcm_share_t, list);
unsigned int k;
for (k = 0; k < sh->channels_count; ++k) {
@ -1331,8 +1334,6 @@ int snd_pcm_share_open(snd_pcm_t **pcmp, const char *name, const char *sname,
share->pcm = pcm;
share->client_socket = sd[0];
share->slave_socket = sd[1];
share->async_sig = SIGIO;
share->async_pid = getpid();
if (name)
pcm->name = strdup(name);
@ -1363,15 +1364,17 @@ int _snd_pcm_share_open(snd_pcm_t **pcmp, const char *name, snd_config_t *conf,
{
snd_config_iterator_t i, next;
const char *sname = NULL;
snd_config_t *binding = NULL;
snd_config_t *bindings = NULL;
int err;
snd_config_t *slave = NULL;
unsigned int idx;
int *channels_map;
unsigned int channels_count = 0;
long schannels_count = -1;
unsigned int schannel_max = 0;
snd_pcm_format_t sformat = SND_PCM_FORMAT_UNKNOWN;
long srate = -1;
int schannels = -1;
int srate = -1;
int speriod_time= -1, sbuffer_time = -1;
unsigned int schannel_max = 0;
snd_config_for_each(i, next, conf) {
snd_config_t *n = snd_config_iterator_entry(i);
@ -1380,64 +1383,43 @@ int _snd_pcm_share_open(snd_pcm_t **pcmp, const char *name, snd_config_t *conf,
continue;
if (strcmp(id, "type") == 0)
continue;
if (strcmp(id, "sname") == 0) {
if (strcmp(id, "slave") == 0) {
err = snd_config_get_string(n, &sname);
if (err < 0) {
SNDERR("Invalid type for %s", id);
return -EINVAL;
}
slave = n;
continue;
}
if (strcmp(id, "sformat") == 0) {
const char *f;
err = snd_config_get_string(n, &f);
if (err < 0) {
SNDERR("Invalid type for %s", id);
return -EINVAL;
}
sformat = snd_pcm_format_value(f);
if (sformat == SND_PCM_FORMAT_UNKNOWN) {
SNDERR("Unknown format %s", f);
return -EINVAL;
}
continue;
}
if (strcmp(id, "schannels") == 0) {
err = snd_config_get_integer(n, &schannels_count);
if (err < 0) {
SNDERR("Invalid type for %s", id);
return -EINVAL;
}
continue;
}
if (strcmp(id, "srate") == 0) {
err = snd_config_get_integer(n, &srate);
if (err < 0) {
SNDERR("Invalid type for %s", id);
return -EINVAL;
}
continue;
}
if (strcmp(id, "binding") == 0) {
if (strcmp(id, "bindings") == 0) {
if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) {
SNDERR("Invalid type for %s", id);
return -EINVAL;
}
binding = n;
bindings = n;
continue;
}
SNDERR("Unknown field %s", id);
return -EINVAL;
}
if (!sname) {
SNDERR("sname is not defined");
if (!slave) {
SNDERR("slave is not defined");
return -EINVAL;
}
if (!binding) {
SNDERR("binding is not defined");
err = snd_pcm_slave_conf(slave, &sname, 5,
SND_PCM_HW_PARAM_FORMAT, 0, &sformat,
SND_PCM_HW_PARAM_CHANNELS, 0, &schannels,
SND_PCM_HW_PARAM_RATE, 0, &srate,
SND_PCM_HW_PARAM_PERIOD_TIME, 0, &speriod_time,
SND_PCM_HW_PARAM_BUFFER_TIME, 0, &sbuffer_time);
if (err < 0)
return err;
if (!bindings) {
SNDERR("bindings is not defined");
return -EINVAL;
}
snd_config_for_each(i, next, binding) {
snd_config_for_each(i, next, bindings) {
int cchannel = -1;
char *p;
snd_config_t *n = snd_config_iterator_entry(i);
@ -1459,7 +1441,7 @@ int _snd_pcm_share_open(snd_pcm_t **pcmp, const char *name, snd_config_t *conf,
for (idx = 0; idx < channels_count; ++idx)
channels_map[idx] = -1;
snd_config_for_each(i, next, binding) {
snd_config_for_each(i, next, bindings) {
snd_config_t *n = snd_config_iterator_entry(i);
const char *id = snd_config_get_id(n);
long cchannel;
@ -1468,15 +1450,15 @@ int _snd_pcm_share_open(snd_pcm_t **pcmp, const char *name, snd_config_t *conf,
err = snd_config_get_integer(n, &schannel);
if (err < 0)
goto _free;
assert(schannels_count <= 0 || schannel < schannels_count);
assert(schannels <= 0 || schannel < schannels);
channels_map[cchannel] = schannel;
if ((unsigned)schannel > schannel_max)
schannel_max = schannel;
}
if (schannels_count <= 0)
schannels_count = schannel_max + 1;
if (schannels <= 0)
schannels = schannel_max + 1;
err = snd_pcm_share_open(pcmp, name, sname, sformat, srate,
schannels_count,
schannels, speriod_time, sbuffer_time,
channels_count, channels_map, stream, mode);
_free:
free(channels_map);

View file

@ -721,7 +721,7 @@ int _snd_pcm_shm_open(snd_pcm_t **pcmp, const char *name, snd_config_t *conf,
{
snd_config_iterator_t i, next;
const char *server = NULL;
const char *sname = NULL;
const char *pcm_name = NULL;
snd_config_t *sconfig;
const char *host = NULL;
const char *socket = NULL;
@ -744,8 +744,8 @@ int _snd_pcm_shm_open(snd_pcm_t **pcmp, const char *name, snd_config_t *conf,
}
continue;
}
if (strcmp(id, "sname") == 0) {
err = snd_config_get_string(n, &sname);
if (strcmp(id, "pcm") == 0) {
err = snd_config_get_string(n, &pcm_name);
if (err < 0) {
SNDERR("Invalid type for %s", id);
return -EINVAL;
@ -755,19 +755,23 @@ int _snd_pcm_shm_open(snd_pcm_t **pcmp, const char *name, snd_config_t *conf,
SNDERR("Unknown field %s", id);
return -EINVAL;
}
if (!sname) {
SNDERR("sname is not defined");
if (!pcm_name) {
SNDERR("pcm is not defined");
return -EINVAL;
}
if (!server) {
SNDERR("server is not defined");
return -EINVAL;
}
err = snd_config_searchv(snd_config, &sconfig, "server", server, 0);
err = snd_config_search_alias(snd_config, "server", server, &sconfig);
if (err < 0) {
SNDERR("Unknown server %s", server);
return -EINVAL;
}
if (snd_config_get_type(sconfig) != SND_CONFIG_TYPE_COMPOUND) {
SNDERR("Invalid type for server %s definition", server);
return -EINVAL;
}
snd_config_for_each(i, next, sconfig) {
snd_config_t *n = snd_config_iterator_entry(i);
const char *id = snd_config_get_id(n);
@ -819,6 +823,6 @@ int _snd_pcm_shm_open(snd_pcm_t **pcmp, const char *name, snd_config_t *conf,
SNDERR("%s is not the local host", host);
return -EINVAL;
}
return snd_pcm_shm_open(pcmp, name, socket, sname, stream, mode);
return snd_pcm_shm_open(pcmp, name, socket, pcm_name, stream, mode);
}

View file

@ -524,6 +524,163 @@ put_1234_4321: as_s32(dst) = bswap_32(sample); goto PUT_END;
put_1234_4329: as_u32(dst) = bswap_32(sample) ^ 0x80; goto PUT_END;
#endif
#ifdef GETS_LABELS
static inline int32_t getS(const void *src, int src_sign, int src_wid, int src_end,
int dst_wid)
{
int32_t s;
switch (src_wid) {
case 8:
s = *(u_int8_t*)src;
break;
case 16:
s = *(u_int16_t*)src;
if (src_end)
s = bswap_16(s);
break;
case 24:
case 32:
s = *(u_int32_t*)src;
if (src_end)
s = bswap_32(s);
break;
}
if (!src_sign)
s -= 1U << (src_wid - 1);
if (src_wid < dst_wid)
return s * (1 << (dst_wid - src_wid));
else
return s / (1 << (src_wid - dst_wid));
}
/* src_sign src_wid src_end dst_wid */
static void *gets_labels[2 * 4 * 2 * 4] = {
&&gets_u8_8, /* u8h -> s8 */
&&gets_u8_16, /* u8h -> s16 */
&&gets_u8_24, /* u8h -> s24 */
&&gets_u8_32, /* u8h -> s32 */
&&gets_u8_8, /* u8s -> s8 */
&&gets_u8_16, /* u8s -> s16 */
&&gets_u8_24, /* u8s -> s24 */
&&gets_u8_32, /* u8s -> s32 */
&&gets_u16h_8, /* u16h -> s8 */
&&gets_u16h_16, /* u16h -> s16 */
&&gets_u16h_24, /* u16h -> s24 */
&&gets_u16h_32, /* u16h -> s32 */
&&gets_u16s_8, /* u16s -> s8 */
&&gets_u16s_16, /* u16s -> s16 */
&&gets_u16s_24, /* u16s -> s24 */
&&gets_u16s_32, /* u16s -> s32 */
&&gets_u24h_8, /* u24h -> s8 */
&&gets_u24h_16, /* u24h -> s16 */
&&gets_u24h_24, /* u24h -> s24 */
&&gets_u24h_32, /* u24h -> s32 */
&&gets_u24s_8, /* u24s -> s8 */
&&gets_u24s_16, /* u24s -> s16 */
&&gets_u24s_24, /* u24s -> s24 */
&&gets_u24s_32, /* u24s -> s32 */
&&gets_u32h_8, /* u32h -> s8 */
&&gets_u32h_16, /* u32h -> s16 */
&&gets_u32h_24, /* u32h -> s24 */
&&gets_u32h_32, /* u32h -> s32 */
&&gets_u32s_8, /* u32s -> s8 */
&&gets_u32s_16, /* u32s -> s16 */
&&gets_u32s_24, /* u32s -> s24 */
&&gets_u32s_32, /* u32s -> s32 */
&&gets_s8_8, /* s8h -> s8 */
&&gets_s8_16, /* s8h -> s16 */
&&gets_s8_24, /* s8h -> s24 */
&&gets_s8_32, /* s8h -> s32 */
&&gets_s8_8, /* s8s -> s8 */
&&gets_s8_16, /* s8s -> s16 */
&&gets_s8_24, /* s8s -> s24 */
&&gets_s8_32, /* s8s -> s32 */
&&gets_s16h_8, /* s16h -> s8 */
&&gets_s16h_16, /* s16h -> s16 */
&&gets_s16h_24, /* s16h -> s24 */
&&gets_s16h_32, /* s16h -> s32 */
&&gets_s16s_8, /* s16s -> s8 */
&&gets_s16s_16, /* s16s -> s16 */
&&gets_s16s_24, /* s16s -> s24 */
&&gets_s16s_32, /* s16s -> s32 */
&&gets_s24h_8, /* s24h -> s8 */
&&gets_s24h_16, /* s24h -> s16 */
&&gets_s24h_24, /* s24h -> s24 */
&&gets_s24h_32, /* s24h -> s32 */
&&gets_s24s_8, /* s24s -> s8 */
&&gets_s24s_16, /* s24s -> s16 */
&&gets_s24s_24, /* s24s -> s24 */
&&gets_s24s_32, /* s24s -> s32 */
&&gets_s32h_8, /* s32h -> s8 */
&&gets_s32h_16, /* s32h -> s16 */
&&gets_s32h_24, /* s32h -> s24 */
&&gets_s32h_32, /* s32h -> s32 */
&&gets_s32s_8, /* s32s -> s8 */
&&gets_s32s_16, /* s32s -> s16 */
&&gets_s32s_24, /* s32s -> s24 */
&&gets_s32s_32, /* s32s -> s32 */
};
#endif
#ifdef GETS_END
gets_u8_8: sample = getS(src, 0, 8, 0, 8); goto GETS_END;
gets_u8_16: sample = getS(src, 0, 8, 0, 16); goto GETS_END;
gets_u8_24: sample = getS(src, 0, 8, 0, 24); goto GETS_END;
gets_u8_32: sample = getS(src, 0, 8, 0, 32); goto GETS_END;
gets_u16h_8: sample = getS(src, 0, 16, 0, 8); goto GETS_END;
gets_u16h_16: sample = getS(src, 0, 16, 0, 16); goto GETS_END;
gets_u16h_24: sample = getS(src, 0, 16, 0, 24); goto GETS_END;
gets_u16h_32: sample = getS(src, 0, 16, 0, 32); goto GETS_END;
gets_u16s_8: sample = getS(src, 0, 16, 1, 8); goto GETS_END;
gets_u16s_16: sample = getS(src, 0, 16, 1, 16); goto GETS_END;
gets_u16s_24: sample = getS(src, 0, 16, 1, 24); goto GETS_END;
gets_u16s_32: sample = getS(src, 0, 16, 1, 32); goto GETS_END;
gets_u24h_8: sample = getS(src, 0, 24, 0, 8); goto GETS_END;
gets_u24h_16: sample = getS(src, 0, 24, 0, 16); goto GETS_END;
gets_u24h_24: sample = getS(src, 0, 24, 0, 24); goto GETS_END;
gets_u24h_32: sample = getS(src, 0, 24, 0, 32); goto GETS_END;
gets_u24s_8: sample = getS(src, 0, 24, 1, 8); goto GETS_END;
gets_u24s_16: sample = getS(src, 0, 24, 1, 16); goto GETS_END;
gets_u24s_24: sample = getS(src, 0, 24, 1, 24); goto GETS_END;
gets_u24s_32: sample = getS(src, 0, 24, 1, 32); goto GETS_END;
gets_u32h_8: sample = getS(src, 0, 32, 0, 8); goto GETS_END;
gets_u32h_16: sample = getS(src, 0, 32, 0, 16); goto GETS_END;
gets_u32h_24: sample = getS(src, 0, 32, 0, 24); goto GETS_END;
gets_u32h_32: sample = getS(src, 0, 32, 0, 32); goto GETS_END;
gets_u32s_8: sample = getS(src, 0, 32, 1, 8); goto GETS_END;
gets_u32s_16: sample = getS(src, 0, 32, 1, 16); goto GETS_END;
gets_u32s_24: sample = getS(src, 0, 32, 1, 24); goto GETS_END;
gets_u32s_32: sample = getS(src, 0, 32, 1, 32); goto GETS_END;
gets_s8_8: sample = getS(src, 1, 8, 0, 8); goto GETS_END;
gets_s8_16: sample = getS(src, 1, 8, 0, 16); goto GETS_END;
gets_s8_24: sample = getS(src, 1, 8, 0, 24); goto GETS_END;
gets_s8_32: sample = getS(src, 1, 8, 0, 32); goto GETS_END;
gets_s16h_8: sample = getS(src, 1, 16, 0, 8); goto GETS_END;
gets_s16h_16: sample = getS(src, 1, 16, 0, 16); goto GETS_END;
gets_s16h_24: sample = getS(src, 1, 16, 0, 24); goto GETS_END;
gets_s16h_32: sample = getS(src, 1, 16, 0, 32); goto GETS_END;
gets_s16s_8: sample = getS(src, 1, 16, 1, 8); goto GETS_END;
gets_s16s_16: sample = getS(src, 1, 16, 1, 16); goto GETS_END;
gets_s16s_24: sample = getS(src, 1, 16, 1, 24); goto GETS_END;
gets_s16s_32: sample = getS(src, 1, 16, 1, 32); goto GETS_END;
gets_s24h_8: sample = getS(src, 1, 24, 0, 8); goto GETS_END;
gets_s24h_16: sample = getS(src, 1, 24, 0, 16); goto GETS_END;
gets_s24h_24: sample = getS(src, 1, 24, 0, 24); goto GETS_END;
gets_s24h_32: sample = getS(src, 1, 24, 0, 32); goto GETS_END;
gets_s24s_8: sample = getS(src, 1, 24, 1, 8); goto GETS_END;
gets_s24s_16: sample = getS(src, 1, 24, 1, 16); goto GETS_END;
gets_s24s_24: sample = getS(src, 1, 24, 1, 24); goto GETS_END;
gets_s24s_32: sample = getS(src, 1, 24, 1, 32); goto GETS_END;
gets_s32h_8: sample = getS(src, 1, 32, 0, 8); goto GETS_END;
gets_s32h_16: sample = getS(src, 1, 32, 0, 16); goto GETS_END;
gets_s32h_24: sample = getS(src, 1, 32, 0, 24); goto GETS_END;
gets_s32h_32: sample = getS(src, 1, 32, 0, 32); goto GETS_END;
gets_s32s_8: sample = getS(src, 1, 32, 1, 8); goto GETS_END;
gets_s32s_16: sample = getS(src, 1, 32, 1, 16); goto GETS_END;
gets_s32s_24: sample = getS(src, 1, 32, 1, 24); goto GETS_END;
gets_s32s_32: sample = getS(src, 1, 32, 1, 32); goto GETS_END;
#endif
#undef as_u8
#undef as_u16
#undef as_u32

View file

@ -178,20 +178,22 @@ int snd_rawmidi_open(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp,
int (*open_func)(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp,
const char *name, snd_config_t *conf, int mode);
void *h;
const char *name1;
assert((inputp || outputp) && name);
err = snd_config_update();
if (err < 0)
return err;
err = snd_config_searchv(snd_config, &rawmidi_conf, "rawmidi", name, 0);
if (err < 0) {
err = snd_config_search_alias(snd_config, "rawmidi", name, &rawmidi_conf);
name1 = name;
if (err < 0 || snd_config_get_string(rawmidi_conf, &name1) >= 0) {
int card, dev, subdev;
err = sscanf(name, "hw:%d,%d,%d", &card, &dev, &subdev);
err = sscanf(name1, "hw:%d,%d,%d", &card, &dev, &subdev);
if (err == 3)
return snd_rawmidi_hw_open(inputp, outputp, name, card, dev, subdev, mode);
err = sscanf(name, "hw:%d,%d", &card, &dev);
err = sscanf(name1, "hw:%d,%d", &card, &dev);
if (err == 2)
return snd_rawmidi_hw_open(inputp, outputp, name, card, dev, -1, mode);
SNDERR("Unknown RAWMIDI %s", name);
SNDERR("Unknown RAWMIDI %s", name1);
return -ENOENT;
}
if (snd_config_get_type(rawmidi_conf) != SND_CONFIG_TYPE_COMPOUND) {
@ -208,7 +210,7 @@ int snd_rawmidi_open(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp,
SNDERR("Invalid type for %s", snd_config_get_id(conf));
return err;
}
err = snd_config_searchv(snd_config, &type_conf, "rawmiditype", str, 0);
err = snd_config_search_alias(snd_config, "rawmidi_type", str, &type_conf);
if (err >= 0) {
snd_config_for_each(i, next, type_conf) {
snd_config_t *n = snd_config_iterator_entry(i);

View file

@ -48,15 +48,17 @@ int snd_seq_open(snd_seq_t **seqp, const char *name,
int (*open_func)(snd_seq_t **seqp, const char *name, snd_config_t *conf,
int streams, int mode);
void *h;
const char *name1;
assert(seqp && name);
err = snd_config_update();
if (err < 0)
return err;
err = snd_config_searchv(snd_config, &seq_conf, "seq", name, 0);
if (err < 0) {
if (strcmp(name, "hw") == 0)
err = snd_config_search_alias(snd_config, "seq", name, &seq_conf);
name1 = name;
if (err < 0 || snd_config_get_string(seq_conf, &name1) >= 0) {
if (strcmp(name1, "hw") == 0)
return snd_seq_hw_open(seqp, name, streams, mode);
SNDERR("Unknown SEQ %s", name);
SNDERR("Unknown SEQ %s", name1);
return -ENOENT;
}
if (snd_config_get_type(seq_conf) != SND_CONFIG_TYPE_COMPOUND) {
@ -73,7 +75,7 @@ int snd_seq_open(snd_seq_t **seqp, const char *name,
SNDERR("Invalid type for %s", snd_config_get_id(conf));
return err;
}
err = snd_config_searchv(snd_config, &type_conf, "seqtype", str, 0);
err = snd_config_search_alias(snd_config, "seq_type", str, &type_conf);
if (err >= 0) {
snd_config_for_each(i, next, type_conf) {
snd_config_t *n = snd_config_iterator_entry(i);