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

@ -968,11 +968,15 @@ int main(int argc, char **argv)
return 1; return 1;
} }
srvname = argv[optind]; srvname = argv[optind];
err = snd_config_searchv(snd_config, &conf, "server", srvname, 0); err = snd_config_search_alias(snd_config, "server", srvname, &conf);
if (err < 0) { if (err < 0) {
ERROR("Missing definition for server %s", srvname); ERROR("Missing definition for server %s", srvname);
return 1; return 1;
} }
if (snd_config_get_type(conf) != SND_CONFIG_TYPE_COMPOUND) {
SNDERR("Invalid type for server %s definition", srvname);
return -EINVAL;
}
snd_config_for_each(i, next, conf) { snd_config_for_each(i, next, conf) {
snd_config_t *n = snd_config_iterator_entry(i); snd_config_t *n = snd_config_iterator_entry(i);
const char *id = snd_config_get_id(n); const char *id = snd_config_get_id(n);

View file

@ -1,169 +1,261 @@
# Server definition
server.NAME {
host STR # host where the server is located (if map to local address
# server is local, and then it may be started automatically)
[socket STR] # PF_LOCAL socket name to listen/connect
[port INT] # PF_INET port number to listen/connect
}
PCM common fields: # PCM type definition
type PCM type pcm_type.NAME {
[comment] Saved comments [lib STR] # Library file (default libasound.so)
[open STR] # Open function (default _snd_pcm_NAME_open)
}
PCM types: # PCM scope type definition
pcm_scope_type.NAME {
[lib STR] # Library file (default libasound.so)
[open STR] # Open function (default _snd_pcm_scope_NAME_open)
}
- hw Kernel PCM # Slave PCM definition
Fields: pcm_slave.NAME {
card Card name or number pcm STR # PCM name
[device] Device number (default 0) format STR # Format
[subdevice] Subdevice number, -1 first available (default -1) channels INT # Channels
rate INT # Rate
period_time INT # Period time
buffer_time INT # Buffer time
etc.
}
- plug Format adjusted PCM # PCM definition
Fields: pcm.NAME {
sname Slave PCM name type STR # Type
ttable Transfer table (bidimensional compound of [comment ANY] # Saved comments
cchannels * schannels numbers)
.C
.S route value
- linear Linear format conversion PCM # PCM types:
- adpcm IMA-ADPCM format conversion PCM type hw # Kernel PCM
- alaw A-Law format conversion PCM card INT/STR # Card name or number
- mulaw Mu-Law format conversion PCM [device] INT # Device number (default 0)
Fields: [subdevice] INT # Subdevice number, -1 first available (default -1)
sformat Slave format
sname Slave PCM name
- rate Rate conversion PCM
Fields:
[sformat] Slave format (default client format)
srate Slave rate
sname Slave PCM name
- route Attenuated static route PCM
Fields:
[sformat] Slave format (default client format)
[schannels] Slave channels (default client channels)
sname Slave PCM name
ttable Transfer table (bidimensional compound of
cchannels * schannels numbers)
.C
.S route value
- multi Linked PCMs (exclusive access to selected channels)
Fields:
slave Slaves definitions
.N Slave definition
.name Slave PCM name
.channels Slave channels
binding Bindings table
.N Binding for client channel N
.sidx Slave key for slave definition
.schannel Slave channel
- file File plugin
Fields:
sname Slave PCM name
file File name (or fd)
[format] File format (NYI)
- null Null endpoint plugin (NYI) type plug # Format adjusted PCM
Fields: slave STR # Slave name
time Time related or not # or
slave { # Slave definition or name
- shm Shared memory client PCM pcm STR # Slave PCM name
Fields: }
server Server name ttable { # Transfer table (bidimensional compound of
sname Slave PCM name on server # cchannels * schannels numbers)
CCHANNEL {
- share Share PCM SCHANNEL REAL # route value (0.0 ... 1.0)
Fields: }
sname Slave name }
[schannels] Slave channels
[sformat] Slave format
[srate] Slave rate
binding Bindings table
.N Slave channel for client channel N
- meter Meter PCM
Fields:
sname Slave name
[frequency] Updates per second
scope Scopes
.N Scope #N
.type Scope type
[.PARAMS] Scope params
- mix Mix PCM (NYI)
Fields:
sname Server name
binding Bindings table
.N Binding for client channel N
.schannel Slave channel
- droute Attenuated dynamic route PCM (NYI)
Fields:
[sformat] Slave format (default client format)
[schannels] Slave channels (default client channels)
sname Slave PCM name
binding Bindings table
.N Binding entry
.cchannel Client channels
.C Client channel
.schannel Slave channels
.S Slave channel
.control Control name of C * S values or C values (only if C == S)
- lbserver Loopback server (NYI)
Fields:
name Loopback PCM ID (useful for multiple loopback served by the
same server)
[socket] PF_LOCAL socket name to listen
[port] PF_INET port number to listen
sname Slave name
CTL common fields: type linear # Linear format conversion PCM
type CTL type type adpcm # IMA-ADPCM format conversion PCM
[comment] Saved comments type alaw # A-Law format conversion PCM
type mulaw # Mu-Law format conversion PCM
slave STR # Slave name
# or
slave { # Slave definition or name
pcm STR # Slave PCM name
format STR # Slave format
}
- hw Kernel CTL
Fields:
card Card name or number
- shm Shared memory client CTL type rate # Rate conversion PCM
Fields: slave STR # Slave name
server Server name # or
sname Slave CTL name on server slave { # Slave definition or name
pcm STR # Slave PCM name
[format STR] # Slave format (default client format)
rate INT # Slave rate
}
Other related definitions:
- pcmtype PCM type type route # Attenuated static route PCM
Fields: slave STR # Slave name
[lib] Library file # or
open Open function slave { # Slave definition or name
pcm STR # Slave PCM name
[format STR] # Slave format (default client format)
[channels INT] # Slave channels (default client channels)
}
ttable { # Transfer table (bidimensional compound of
# cchannels * schannels numbers)
CCHANNEL {
SCHANNEL REAL # route value (0.0 ... 1.0)
}
}
- ctltype Control type
Fields:
[lib] Library file
open Open function
- scopetype PCM scope type type multi # Linked PCMs (exclusive access to selected channels)
Fields: slaves { # Slaves definitions
[lib] Library file N STR # Slave name for slave N
open Open function # or
N { # Slave definition for slave N
pcm STR # Slave PCM name
channels INT # Slave channels
}
}
bindings { # Bindings table
N { # Binding for client channel N
slave STR # Slave key
channel INT # Slave channel
}
}
- server Server
Fields: type file # File plugin
host host where the server is located (if map to local address slave STR # Slave name
server is local, and then it may be started automatically) # or
[socket] PF_LOCAL socket name to listen/connect slave { # Slave definition or name
[port] PF_INET port number to listen/connect pcm STR # Slave PCM name
}
[format STR] # File format (NYI)
type meter # Meter PCM
slave STR # Slave name
# or
slave { # Slave definition or name
pcm STR # Slave PCM name
}
[frequency INT] # Updates per second
scopes { # Scopes
N { # Scope definition
type STR # Scope type
[PARAMS] # Scope params
}
}
type droute # Attenuated dynamic route PCM (NYI)
slave STR # Slave name
# or
slave { # Slave definition or name
pcm STR # Slave PCM name
[format STR] # Slave format (default client format)
[channels INT] # Slave channels (default client channels)
}
ctl STR # Ctl name
bindings { # Bindings table
N { # Binding entry
cchannels { # Client channels
C INT # Client channel
}
schannel { # Slave channels
S INT # Slave channel
}
control STR # Control name of C * S (or C values: only if C == S)
}
}
type loopback # Loopback server (NYI)
server STR # Server name
slave STR # Slave name
# or
slave { # Slave definition or name
pcm STR # Slave PCM name
}
type null # Null endpoint plugin
[time INT] # Time related or not (NYI)
type shm # Shared memory client PCM
server STR # Server name
pcm STR # PCM name on server
type share # Share PCM
slave STR # Slave name
bindings { # Bindings table
N INT # Slave channel for client channel N
}
type mix # Mix PCM
slave STR # Slave name
bindings { # Bindings table
N INT # Slave channel for client channel N
}
}
# CTL type definition
ctl_type.NAME {
[lib STR] # Library file (default libasound.so)
[open STR] # Open function (default _snd_ctl_NAME_open)
}
# CTL definition
ctl.NAME {
type STR # Type
[comment ANY] # Saved comments
# CTL types
type hw
card STR/INT # Card name or number
type shm # Shared memory client CTL
server STR # Server name
ctl STR # CTL name on server
}
# RAWMIDI type definition
rawmidi_type.NAME {
[lib STR] # Library file (default libasound.so)
[open STR] # Open function (default _snd_rawmidi_NAME_open)
}
# RAWMIDI definition
rawmidi.NAME {
type STR # Type
[comment ANY] # Saved comments
# RAWMIDI types:
type hw # Kernel RAWMIDI
card INT/STR # Card name or number
[device] INT # Device number (default 0)
[subdevice] INT # Subdevice number, -1 first available (default -1)
}
# SEQ type definition
seq_type.NAME {
[lib STR] # Library file (default libasound.so)
[open STR] # Open function (default _snd_seq_NAME_open)
}
# SEQ definition
seq.NAME {
type STR # Type
[comment ANY] # Saved comments
# SEQ types:
type hw # Kernel SEQ
}
# Aliases
DEF.NAME1 NAME2 # DEF.NAME1 is an alias for DEF.NAME2
Some examples: Some examples:
pcmtype.hw {
open _snd_pcm_hw_open
}
pcmtype.plug {
open _snd_pcm_plug_open
}
pcm.trident { pcm.trident {
type hw type hw
card 0 card 0
@ -180,31 +272,41 @@ pcm.ice1712_spdif {
type plug type plug
ttable.0.8 1 ttable.0.8 1
ttable.1.9 1 ttable.1.9 1
sname ice1712 slave.pcm ice1712
}
pcm_slave.rs {
pcm trident
rate 44100
}
pcm.r {
type rate
slave rs
} }
pcm.m { pcm.m {
type meter type meter
sname plug:trident slave.pcm plug:trident
frequency 50 frequency 50
scope.0 { scopes.0 {
type level type level
} }
} }
scopetype.level { scope_type.level {
lib /home/abramo/scopes/liblevel.so lib /home/abramo/scopes/liblevel.so
} }
Special PCM names: Special PCM names:
hw:#card,#dev,#subdev hw:CARD,DEV,SUBDEV
hw:#card,#dev hw:CARD,DEV
plug:#card,#dev,#subdev plug:CARD,DEV,SUBDEV
plug:#card,#dev plug:CARD,DEV
plug:sname plug:SLAVE_PCM
shm:socket,sname shm:SOCKET,PCM
file:fname,fmt,sname file:FNAME,FMT,SLAVE_PCM
file:fname,fmt file:FNAME,FMT
file:fname file:FNAME
null null

View file

@ -36,6 +36,9 @@ int snd_config_search(snd_config_t *config, const char *key,
snd_config_t **result); snd_config_t **result);
int snd_config_searchv(snd_config_t *config, int snd_config_searchv(snd_config_t *config,
snd_config_t **result, ...); snd_config_t **result, ...);
int snd_config_search_alias(snd_config_t *config,
const char *base, const char *key,
snd_config_t **result);
int snd_config_add(snd_config_t *config, snd_config_t *leaf); int snd_config_add(snd_config_t *config, snd_config_t *leaf);
int snd_config_delete(snd_config_t *config); int snd_config_delete(snd_config_t *config);

View file

@ -1014,6 +1014,21 @@ int snd_config_searchv(snd_config_t *config,
return 0; 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; snd_config_t *snd_config = 0;
static dev_t sys_asoundrc_device; static dev_t sys_asoundrc_device;
static ino_t sys_asoundrc_inode; 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; const char *lib = NULL, *open = NULL;
int (*open_func)(snd_ctl_t **ctlp, const char *name, snd_config_t *conf); int (*open_func)(snd_ctl_t **ctlp, const char *name, snd_config_t *conf);
void *h; void *h;
const char *name1;
assert(ctlp && name); assert(ctlp && name);
err = snd_config_update(); err = snd_config_update();
if (err < 0) if (err < 0)
return err; 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; int card;
char socket[256], sname[256]; char socket[256], sname[256];
err = sscanf(name, "hw:%d", &card); err = sscanf(name1, "hw:%d", &card);
if (err == 1) if (err == 1)
return snd_ctl_hw_open(ctlp, name, card); 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) if (err == 2)
return snd_ctl_shm_open(ctlp, name, socket, sname); return snd_ctl_shm_open(ctlp, name, socket, sname);
SNDERR("Unknown control %s", name); SNDERR("Unknown ctl %s", name1);
return -ENOENT; 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; return -EINVAL;
}
err = snd_config_search(ctl_conf, "type", &conf); err = snd_config_search(ctl_conf, "type", &conf);
if (err < 0) if (err < 0)
return err; return err;
err = snd_config_get_string(conf, &str); err = snd_config_get_string(conf, &str);
if (err < 0) if (err < 0)
return err; 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 (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_for_each(i, next, type_conf) {
snd_config_t *n = snd_config_iterator_entry(i); snd_config_t *n = snd_config_iterator_entry(i);
const char *id = snd_config_get_id(n); 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"); SNDERR("server is not defined");
return -EINVAL; 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) { if (err < 0) {
SNDERR("Unknown server %s", server); SNDERR("Unknown server %s", server);
return -EINVAL; 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_for_each(i, next, conf) {
snd_config_t *n = snd_config_iterator_entry(i); snd_config_t *n = snd_config_iterator_entry(i);
const char *id = snd_config_get_id(n); 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.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_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_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_shm.c pcm_file.c pcm_null.c pcm_share.c \
pcm_params.c pcm_meter.c pcm_params.c
noinst_HEADERS = atomic.h pcm_local.h pcm_plugin.h mask.h mask_inline.h \ noinst_HEADERS = atomic.h pcm_local.h pcm_plugin.h mask.h mask_inline.h \
interval.h interval_inline.h plugin_ops.h interval.h interval_inline.h plugin_ops.h

View file

@ -23,6 +23,7 @@
#include <string.h> #include <string.h>
#include <malloc.h> #include <malloc.h>
#include <stdarg.h> #include <stdarg.h>
#include <signal.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/poll.h> #include <sys/poll.h>
#include <sys/shm.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 snd_pcm_async(snd_pcm_t *pcm, int sig, pid_t pid)
{ {
int err;
assert(pcm); 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) 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, int (*open_func)(snd_pcm_t **pcmp, const char *name, snd_config_t *conf,
snd_pcm_stream_t stream, int mode); snd_pcm_stream_t stream, int mode);
void *h; void *h;
const char *name1;
assert(pcmp && name); assert(pcmp && name);
err = snd_config_update(); err = snd_config_update();
if (err < 0) if (err < 0)
return err; 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; int card, dev, subdev;
char socket[256], sname[256]; char socket[256], sname[256];
char format[16], file[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) if (err == 3)
return snd_pcm_hw_open(pcmp, name, card, dev, subdev, stream, mode); 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) if (err == 2)
return snd_pcm_hw_open(pcmp, name, card, dev, -1, stream, mode); 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) if (err == 3)
return snd_pcm_plug_open_hw(pcmp, name, card, dev, subdev, stream, mode); 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) if (err == 2)
return snd_pcm_plug_open_hw(pcmp, name, card, dev, -1, stream, mode); 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) { if (err == 1) {
snd_pcm_t *slave; snd_pcm_t *slave;
err = snd_pcm_open(&slave, sname, stream, mode); 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 err;
return snd_pcm_plug_open(pcmp, name, NULL, 0, 0, 0, slave, 1); 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) if (err == 2)
return snd_pcm_shm_open(pcmp, name, socket, sname, stream, mode); 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) { if (err == 3) {
snd_pcm_t *slave; snd_pcm_t *slave;
err = snd_pcm_open(&slave, sname, stream, mode); err = snd_pcm_open(&slave, sname, stream, mode);
if (err < 0) if (err < 0)
return err; 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) { if (err == 2) {
snd_pcm_t *slave; snd_pcm_t *slave;
err = snd_pcm_null_open(&slave, name, stream, mode); 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 err;
return snd_pcm_file_open(pcmp, name, file, -1, format, slave, 1); 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) { if (err == 1) {
snd_pcm_t *slave; snd_pcm_t *slave;
err = snd_pcm_null_open(&slave, name, stream, mode); 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 err;
return snd_pcm_file_open(pcmp, name, file, -1, "raw", slave, 1); 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); return snd_pcm_null_open(pcmp, name, stream, mode);
SNDERR("Unknown PCM %s", name); SNDERR("Unknown PCM %s", name1);
return -ENOENT; return -ENOENT;
} }
if (snd_config_get_type(pcm_conf) != SND_CONFIG_TYPE_COMPOUND) { 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; return -EINVAL;
} }
err = snd_config_search(pcm_conf, "type", &conf); 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)); SNDERR("Invalid type for %s", snd_config_get_id(conf));
return err; 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 (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_for_each(i, next, type_conf) {
snd_config_t *n = snd_config_iterator_entry(i); snd_config_t *n = snd_config_iterator_entry(i);
const char *id = snd_config_get_id(n); 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; 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; const char *sname = NULL;
int err; int err;
snd_pcm_t *spcm; 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_for_each(i, next, conf) {
snd_config_t *n = snd_config_iterator_entry(i); snd_config_t *n = snd_config_iterator_entry(i);
const char *id = snd_config_get_id(n); 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; continue;
if (strcmp(id, "type") == 0) if (strcmp(id, "type") == 0)
continue; continue;
if (strcmp(id, "sname") == 0) { if (strcmp(id, "slave") == 0) {
err = snd_config_get_string(n, &sname); slave = n;
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;
}
continue; continue;
} }
SNDERR("Unknown field %s", id); SNDERR("Unknown field %s", id);
return -EINVAL; return -EINVAL;
} }
if (!sname) { if (!slave) {
SNDERR("sname is not defined"); SNDERR("slave is not defined");
return -EINVAL; return -EINVAL;
} }
if (sformat == SND_PCM_FORMAT_UNKNOWN) { err = snd_pcm_slave_conf(slave, &sname, 1,
SNDERR("sformat is not defined"); 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; return -EINVAL;
} }
/* This is needed cause snd_config_update may destroy config */ /* 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; const char *sname = NULL;
int err; int err;
snd_pcm_t *spcm; 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_for_each(i, next, conf) {
snd_config_t *n = snd_config_iterator_entry(i); snd_config_t *n = snd_config_iterator_entry(i);
const char *id = snd_config_get_id(n); 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; continue;
if (strcmp(id, "type") == 0) if (strcmp(id, "type") == 0)
continue; continue;
if (strcmp(id, "sname") == 0) { if (strcmp(id, "slave") == 0) {
err = snd_config_get_string(n, &sname); slave = n;
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;
}
continue; continue;
} }
SNDERR("Unknown field %s", id); SNDERR("Unknown field %s", id);
return -EINVAL; return -EINVAL;
} }
if (!sname) { if (!slave) {
SNDERR("sname is not defined"); SNDERR("slave is not defined");
return -EINVAL; return -EINVAL;
} }
if (sformat == SND_PCM_FORMAT_UNKNOWN) { err = snd_pcm_slave_conf(slave, &sname, 1,
SNDERR("sformat is not defined"); 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; return -EINVAL;
} }
/* This is needed cause snd_config_update may destroy config */ /* 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; const char *sname = NULL;
int err; int err;
snd_pcm_t *spcm; snd_pcm_t *spcm;
snd_config_t *slave = NULL;
snd_config_for_each(i, next, conf) { snd_config_for_each(i, next, conf) {
snd_config_t *n = snd_config_iterator_entry(i); snd_config_t *n = snd_config_iterator_entry(i);
const char *id = snd_config_get_id(n); 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; continue;
if (strcmp(id, "type") == 0) if (strcmp(id, "type") == 0)
continue; continue;
if (strcmp(id, "sname") == 0) { if (strcmp(id, "slave") == 0) {
err = snd_config_get_string(n, &sname); slave = n;
if (err < 0) {
SNDERR("Invalid type for %s", id);
return -EINVAL;
}
continue; continue;
} }
SNDERR("Unknown field %s", id); SNDERR("Unknown field %s", id);
return -EINVAL; return -EINVAL;
} }
if (!sname) { if (!slave) {
SNDERR("sname is not defined"); SNDERR("slave is not defined");
return -EINVAL; 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 */ /* This is needed cause snd_config_update may destroy config */
sname = strdup(sname); sname = strdup(sname);
if (!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; const char *sname = NULL;
int err; int err;
snd_pcm_t *spcm; snd_pcm_t *spcm;
snd_config_t *slave = NULL;
const char *fname = NULL; const char *fname = NULL;
const char *format = NULL; const char *format = NULL;
long fd = -1; long fd = -1;
@ -477,12 +478,8 @@ int _snd_pcm_file_open(snd_pcm_t **pcmp, const char *name,
continue; continue;
if (strcmp(id, "type") == 0) if (strcmp(id, "type") == 0)
continue; continue;
if (strcmp(id, "sname") == 0) { if (strcmp(id, "slave") == 0) {
err = snd_config_get_string(n, &sname); slave = n;
if (err < 0) {
SNDERR("Invalid type for %s", id);
return -EINVAL;
}
continue; continue;
} }
if (strcmp(id, "format") == 0) { 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); SNDERR("Unknown field %s", id);
return -EINVAL; return -EINVAL;
} }
if (!sname) { if (!slave) {
SNDERR("sname is not defined"); SNDERR("slave is not defined");
return -EINVAL; return -EINVAL;
} }
err = snd_pcm_slave_conf(slave, &sname, 0);
if (err < 0)
return err;
if (!fname && fd < 0) { if (!fname && fd < 0) {
SNDERR("file is not defined"); SNDERR("file is not defined");
return -EINVAL; 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_pcm_stream_t stream, int mode)
{ {
snd_config_iterator_t i, next; snd_config_iterator_t i, next;
const char *sname = NULL; const char *sname;
int err; int err;
snd_pcm_t *spcm; 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_for_each(i, next, conf) {
snd_config_t *n = snd_config_iterator_entry(i); snd_config_t *n = snd_config_iterator_entry(i);
const char *id = snd_config_get_id(n); 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; continue;
if (strcmp(id, "type") == 0) if (strcmp(id, "type") == 0)
continue; continue;
if (strcmp(id, "sname") == 0) { if (strcmp(id, "slave") == 0) {
err = snd_config_get_string(n, &sname); slave = n;
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;
}
continue; continue;
} }
SNDERR("Unknown field %s", id); SNDERR("Unknown field %s", id);
return -EINVAL; return -EINVAL;
} }
if (!sname) { if (!slave) {
SNDERR("sname is not defined"); SNDERR("slave is not defined");
return -EINVAL; return -EINVAL;
} }
if (sformat == SND_PCM_FORMAT_UNKNOWN) { err = snd_pcm_slave_conf(slave, &sname, 1,
SNDERR("sformat is not defined"); 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; return -EINVAL;
} }
/* This is needed cause snd_config_update may destroy config */ /* 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 silence_size; /* Silence filling size */
snd_pcm_uframes_t xfer_align; /* xfer size need to be a multiple */ snd_pcm_uframes_t xfer_align; /* xfer size need to be a multiple */
snd_pcm_uframes_t boundary; /* pointers wrap point */ snd_pcm_uframes_t boundary; /* pointers wrap point */
int async_sig;
pid_t async_pid;
unsigned int info; /* Info for returned setup */ unsigned int info; /* Info for returned setup */
unsigned int msbits; /* used most significant bits */ unsigned int msbits; /* used most significant bits */
unsigned int rate_num; /* rate numerator */ 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, unsigned int count,
snd_pcm_hw_strategy_simple_choices_list_t *choices); 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_ACCESS (1 << SND_PCM_HW_PARAM_ACCESS)
#define SND_PCM_HW_PARBIT_FORMAT (1 << SND_PCM_HW_PARAM_FORMAT) #define SND_PCM_HW_PARBIT_FORMAT (1 << SND_PCM_HW_PARAM_FORMAT)
#define SND_PCM_HW_PARBIT_SUBFORMAT (1 << SND_PCM_HW_PARAM_SUBFORMAT) #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)); SNDERR("Invalid type for %s", snd_config_get_id(c));
return err; 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) { if (err >= 0) {
snd_config_for_each(i, next, type_conf) { snd_config_for_each(i, next, type_conf) {
snd_config_t *n = snd_config_iterator_entry(i); 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; const char *sname = NULL;
int err; int err;
snd_pcm_t *spcm; snd_pcm_t *spcm;
snd_config_t *slave = NULL;
long frequency = -1; long frequency = -1;
snd_config_t *scopes = NULL; snd_config_t *scopes = NULL;
snd_config_for_each(i, next, conf) { snd_config_for_each(i, next, conf) {
@ -723,12 +724,8 @@ int _snd_pcm_meter_open(snd_pcm_t **pcmp, const char *name,
continue; continue;
if (strcmp(id, "type") == 0) if (strcmp(id, "type") == 0)
continue; continue;
if (strcmp(id, "sname") == 0) { if (strcmp(id, "slave") == 0) {
err = snd_config_get_string(n, &sname); slave = n;
if (err < 0) {
SNDERR("Invalid type for %s", id);
return -EINVAL;
}
continue; continue;
} }
if (strcmp(id, "frequency") == 0) { if (strcmp(id, "frequency") == 0) {
@ -739,7 +736,7 @@ int _snd_pcm_meter_open(snd_pcm_t **pcmp, const char *name,
} }
continue; continue;
} }
if (strcmp(id, "scope") == 0) { if (strcmp(id, "scopes") == 0) {
if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) { if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) {
SNDERR("Invalid type for %s", id); SNDERR("Invalid type for %s", id);
return -EINVAL; return -EINVAL;
@ -750,11 +747,13 @@ int _snd_pcm_meter_open(snd_pcm_t **pcmp, const char *name,
SNDERR("Unknown field %s", id); SNDERR("Unknown field %s", id);
return -EINVAL; return -EINVAL;
} }
if (!sname) { if (!slave) {
SNDERR("sname is not defined"); SNDERR("slave is not defined");
return -EINVAL; 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 */ /* This is needed cause snd_config_update may destroy config */
sname = strdup(sname); sname = strdup(sname);
if (!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; const char *sname = NULL;
int err; int err;
snd_pcm_t *spcm; 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_for_each(i, next, conf) {
snd_config_t *n = snd_config_iterator_entry(i); snd_config_t *n = snd_config_iterator_entry(i);
const char *id = snd_config_get_id(n); 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; continue;
if (strcmp(id, "type") == 0) if (strcmp(id, "type") == 0)
continue; continue;
if (strcmp(id, "sname") == 0) { if (strcmp(id, "slave") == 0) {
err = snd_config_get_string(n, &sname); slave = n;
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;
}
continue; continue;
} }
SNDERR("Unknown field %s", id); SNDERR("Unknown field %s", id);
return -EINVAL; return -EINVAL;
} }
if (!sname) { if (!slave) {
SNDERR("sname is not defined"); SNDERR("slave is not defined");
return -EINVAL; return -EINVAL;
} }
if (sformat == SND_PCM_FORMAT_UNKNOWN) { err = snd_pcm_slave_conf(slave, &sname, 1,
SNDERR("sformat is not defined"); 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; return -EINVAL;
} }
/* This is needed cause snd_config_update may destroy config */ /* 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_pcm_stream_t stream, int mode)
{ {
snd_config_iterator_t i, inext, j, jnext; snd_config_iterator_t i, inext, j, jnext;
snd_config_t *slave = NULL; snd_config_t *slaves = NULL;
snd_config_t *binding = NULL; snd_config_t *bindings = NULL;
int err; int err;
unsigned int idx; unsigned int idx;
const char **slaves_id = NULL; 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; continue;
if (strcmp(id, "type") == 0) if (strcmp(id, "type") == 0)
continue; continue;
if (strcmp(id, "slave") == 0) { if (strcmp(id, "slaves") == 0) {
if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) { if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) {
SNDERR("Invalid type for %s", id); SNDERR("Invalid type for %s", id);
return -EINVAL; return -EINVAL;
} }
slave = n; slaves = n;
continue; continue;
} }
if (strcmp(id, "binding") == 0) { if (strcmp(id, "bindings") == 0) {
if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) { if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) {
SNDERR("Invalid type for %s", id); SNDERR("Invalid type for %s", id);
return -EINVAL; return -EINVAL;
} }
binding = n; bindings = n;
continue; continue;
} }
SNDERR("Unknown field %s", id); SNDERR("Unknown field %s", id);
return -EINVAL; return -EINVAL;
} }
if (!slave) { if (!slaves) {
SNDERR("slave is not defined"); SNDERR("slaves is not defined");
return -EINVAL; return -EINVAL;
} }
if (!binding) { if (!bindings) {
SNDERR("binding is not defined"); SNDERR("bindings is not defined");
return -EINVAL; return -EINVAL;
} }
snd_config_for_each(i, inext, slave) { snd_config_for_each(i, inext, slaves) {
++slaves_count; ++slaves_count;
} }
snd_config_for_each(i, inext, binding) { snd_config_for_each(i, inext, bindings) {
int cchannel = -1; int cchannel = -1;
char *p; char *p;
snd_config_t *m = snd_config_iterator_entry(i); 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) for (idx = 0; idx < channels_count; ++idx)
channels_sidx[idx] = -1; channels_sidx[idx] = -1;
idx = 0; 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); snd_config_t *m = snd_config_iterator_entry(i);
const char *name = NULL; const char *name;
long channels = -1; int channels;
slaves_id[idx] = snd_config_get_id(m); slaves_id[idx] = snd_config_get_id(m);
snd_config_for_each(j, jnext, m) { err = snd_pcm_slave_conf(m, &name, 1,
snd_config_t *n = snd_config_iterator_entry(j); SND_PCM_HW_PARAM_CHANNELS, 1, &channels);
const char *id = snd_config_get_id(n); if (err < 0)
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;
goto _free; 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_name[idx] = strdup(name);
slaves_channels[idx] = channels; slaves_channels[idx] = channels;
++idx; ++idx;
} }
snd_config_for_each(i, inext, binding) { snd_config_for_each(i, inext, bindings) {
snd_config_t *m = snd_config_iterator_entry(i); snd_config_t *m = snd_config_iterator_entry(i);
long cchannel = -1; long cchannel = -1;
long schannel = -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); const char *id = snd_config_get_id(n);
if (strcmp(id, "comment") == 0) if (strcmp(id, "comment") == 0)
continue; continue;
if (strcmp(id, "sidx") == 0) { if (strcmp(id, "slave") == 0) {
char buf[32]; char buf[32];
unsigned int k; unsigned int k;
err = snd_config_get_string(n, &str); 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; continue;
} }
if (strcmp(id, "schannel") == 0) { if (strcmp(id, "channel") == 0) {
err = snd_config_get_integer(n, &schannel); err = snd_config_get_integer(n, &schannel);
if (err < 0) { if (err < 0) {
SNDERR("Invalid type for %s", id); 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; const char *sname = NULL;
int err; int err;
snd_pcm_t *spcm; snd_pcm_t *spcm;
snd_config_t *slave = NULL;
snd_config_t *tt = NULL; snd_config_t *tt = NULL;
snd_pcm_route_ttable_entry_t *ttable = NULL; snd_pcm_route_ttable_entry_t *ttable = NULL;
unsigned int cused, sused; unsigned int cused, sused;
@ -728,12 +729,8 @@ int _snd_pcm_plug_open(snd_pcm_t **pcmp, const char *name,
continue; continue;
if (strcmp(id, "type") == 0) if (strcmp(id, "type") == 0)
continue; continue;
if (strcmp(id, "sname") == 0) { if (strcmp(id, "slave") == 0) {
err = snd_config_get_string(n, &sname); slave = n;
if (err < 0) {
SNDERR("Invalid type for %s", id);
return -EINVAL;
}
continue; continue;
} }
if (strcmp(id, "ttable") == 0) { 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); SNDERR("Unknown field %s", id);
return -EINVAL; return -EINVAL;
} }
if (!sname) { if (!slave) {
SNDERR("sname is not defined"); SNDERR("slave is not defined");
return -EINVAL; return -EINVAL;
} }
err = snd_pcm_slave_conf(slave, &sname, 0);
if (err < 0)
return err;
if (tt) { if (tt) {
ttable = malloc(MAX_CHANNELS * MAX_CHANNELS * sizeof(*ttable)); ttable = malloc(MAX_CHANNELS * MAX_CHANNELS * sizeof(*ttable));
err = snd_pcm_route_load_ttable(tt, ttable, MAX_CHANNELS, MAX_CHANNELS, 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; const char *sname = NULL;
int err; int err;
snd_pcm_t *spcm; snd_pcm_t *spcm;
snd_config_t *slave = NULL;
snd_pcm_format_t sformat = SND_PCM_FORMAT_UNKNOWN; snd_pcm_format_t sformat = SND_PCM_FORMAT_UNKNOWN;
long srate = -1; int srate = -1;
snd_config_for_each(i, next, conf) { snd_config_for_each(i, next, conf) {
snd_config_t *n = snd_config_iterator_entry(i); snd_config_t *n = snd_config_iterator_entry(i);
const char *id = snd_config_get_id(n); 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; continue;
if (strcmp(id, "type") == 0) if (strcmp(id, "type") == 0)
continue; continue;
if (strcmp(id, "sname") == 0) { if (strcmp(id, "slave") == 0) {
err = snd_config_get_string(n, &sname); slave = n;
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;
}
continue; continue;
} }
SNDERR("Unknown field %s", id); SNDERR("Unknown field %s", id);
return -EINVAL; return -EINVAL;
} }
if (!sname) { if (!slave) {
SNDERR("sname is not defined"); SNDERR("slave is not defined");
return -EINVAL; return -EINVAL;
} }
if (srate < 0) { err = snd_pcm_slave_conf(slave, &sname, 2,
SNDERR("srate is not defined"); 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; return -EINVAL;
} }
/* This is needed cause snd_config_update may destroy config */ /* 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" #include "plugin_ops.h"
#undef GETU_LABELS #undef GETU_LABELS
#undef PUT32_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 #if ROUTE_PLUGIN_FLOAT
&&zero_float &&zero_float
#endif #endif
}; };
/* sum_type att */ /* sum_type att */
static void *add_labels[3 * 2] = { &&add_int32_noatt, &&add_int32_att, static void *add_labels[3 * 2] = {
&&add_int64_noatt, &&add_int64_att, &&add_int32_noatt, &&add_int32_att,
&&add_int64_noatt, &&add_int64_att,
#if ROUTE_PLUGIN_FLOAT #if ROUTE_PLUGIN_FLOAT
&&add_float_noatt, &&add_float_att &&add_float_noatt, &&add_float_att
#endif #endif
}; };
/* sum_type att shift */ /* sum_type att shift */
static void *norm_labels[3 * 2 * 4] = { 0, static void *norm_labels[3 * 2 * 4] = {
&&norm_int32_8_noatt, 0,
&&norm_int32_16_noatt, &&norm_int32_8_noatt,
&&norm_int32_24_noatt, &&norm_int32_16_noatt,
0, &&norm_int32_24_noatt,
&&norm_int32_8_att, 0,
&&norm_int32_16_att, &&norm_int32_8_att,
&&norm_int32_24_att, &&norm_int32_16_att,
&&norm_int64_0_noatt, &&norm_int32_24_att,
&&norm_int64_8_noatt, &&norm_int64_0_noatt,
&&norm_int64_16_noatt, &&norm_int64_8_noatt,
&&norm_int64_24_noatt, &&norm_int64_16_noatt,
&&norm_int64_0_att, &&norm_int64_24_noatt,
&&norm_int64_8_att, &&norm_int64_0_att,
&&norm_int64_16_att, &&norm_int64_8_att,
&&norm_int64_24_att, &&norm_int64_16_att,
&&norm_int64_24_att,
#if ROUTE_PLUGIN_FLOAT #if ROUTE_PLUGIN_FLOAT
&&norm_float_0, &&norm_float_0,
&&norm_float_8, &&norm_float_8,
&&norm_float_16, &&norm_float_16,
&&norm_float_24, &&norm_float_24,
&&norm_float_0, &&norm_float_0,
&&norm_float_8, &&norm_float_8,
&&norm_float_16, &&norm_float_16,
&&norm_float_24, &&norm_float_24,
#endif #endif
}; };
void *zero, *get, *add, *norm, *put32; 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; const char *sname = NULL;
int err; int err;
snd_pcm_t *spcm; snd_pcm_t *spcm;
snd_config_t *slave = NULL;
snd_pcm_format_t sformat = SND_PCM_FORMAT_UNKNOWN; snd_pcm_format_t sformat = SND_PCM_FORMAT_UNKNOWN;
long schannels = -1; int schannels = -1;
snd_config_t *tt = NULL; snd_config_t *tt = NULL;
snd_pcm_route_ttable_entry_t ttable[MAX_CHANNELS*MAX_CHANNELS]; snd_pcm_route_ttable_entry_t ttable[MAX_CHANNELS*MAX_CHANNELS];
unsigned int cused, sused; unsigned int cused, sused;
@ -855,38 +859,8 @@ int _snd_pcm_route_open(snd_pcm_t **pcmp, const char *name,
continue; continue;
if (strcmp(id, "type") == 0) if (strcmp(id, "type") == 0)
continue; continue;
if (strcmp(id, "sname") == 0) { if (strcmp(id, "slave") == 0) {
err = snd_config_get_string(n, &sname); slave = n;
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;
}
continue; continue;
} }
if (strcmp(id, "ttable") == 0) { 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); SNDERR("Unknown field %s", id);
return -EINVAL; return -EINVAL;
} }
if (!sname) { if (!slave) {
SNDERR("sname is not defined"); SNDERR("slave is not defined");
return -EINVAL; return -EINVAL;
} }
if (!tt) { if (!tt) {
SNDERR("ttable is not defined"); SNDERR("ttable is not defined");
return -EINVAL; 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, err = snd_pcm_route_load_ttable(tt, ttable, MAX_CHANNELS, MAX_CHANNELS,
&cused, &sused, schannels); &cused, &sused, schannels);

View file

@ -33,33 +33,31 @@
#include "pcm_local.h" #include "pcm_local.h"
#include "list.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 static LIST_HEAD(snd_pcm_share_slaves);
#define S(x) _S(x) static pthread_mutex_t snd_pcm_share_slaves_mutex = PTHREAD_MUTEX_INITIALIZER;
#if 1 #ifdef MUTEX_DEBUG
#define Pthread_mutex_lock(mutex) pthread_mutex_lock(mutex)
#define Pthread_mutex_unlock(mutex) pthread_mutex_unlock(mutex)
#else
#define Pthread_mutex_lock(mutex) \ #define Pthread_mutex_lock(mutex) \
char *snd_pcm_share_slaves_mutex_holder;
do { \ do { \
int err = pthread_mutex_trylock(mutex); \ int err = pthread_mutex_trylock(mutex); \
if (err == EBUSY) { \ if (err < 0) { \
fprintf(stderr, "lock " #mutex " is busy (%s): waiting in " __FUNCTION__ "\n", *(mutex##_holder)); \ fprintf(stderr, "lock " #mutex " is busy (%s): waiting in " __FUNCTION__ "\n", *(mutex##_holder)); \
pthread_mutex_lock(mutex); \ pthread_mutex_lock(mutex); \
fprintf(stderr, "... got\n"); \ fprintf(stderr, "... got\n"); \
} \ } \
*(mutex##_holder) = __FUNCTION__; \ *(mutex##_holder) = __FUNCTION__; \
} while (0) } while (0)
#define Pthread_mutex_unlock(mutex) \ #define Pthread_mutex_unlock(mutex) \
do { \ do { \
*(mutex##_holder) = 0; \ *(mutex##_holder) = 0; \
pthread_mutex_unlock(mutex); \ pthread_mutex_unlock(mutex); \
} while (0) } while (0)
#else
#define Pthread_mutex_lock(mutex) pthread_mutex_lock(mutex)
#define Pthread_mutex_unlock(mutex) pthread_mutex_unlock(mutex)
#endif #endif
typedef struct { typedef struct {
@ -68,7 +66,9 @@ typedef struct {
snd_pcm_t *pcm; snd_pcm_t *pcm;
snd_pcm_format_t format; snd_pcm_format_t format;
int rate; int rate;
unsigned int channels_count; unsigned int channels;
int period_time;
int buffer_time;
unsigned int open_count; unsigned int open_count;
unsigned int setup_count; unsigned int setup_count;
unsigned int mmap_count; unsigned int mmap_count;
@ -82,7 +82,9 @@ typedef struct {
int polling; int polling;
pthread_t thread; pthread_t thread;
pthread_mutex_t mutex; pthread_mutex_t mutex;
#ifdef MUTEX_DEBUG
char *mutex_holder; char *mutex_holder;
#endif
pthread_cond_t poll_cond; pthread_cond_t poll_cond;
} snd_pcm_share_slave_t; } snd_pcm_share_slave_t;
@ -92,11 +94,6 @@ typedef struct {
snd_pcm_share_slave_t *slave; snd_pcm_share_slave_t *slave;
unsigned int channels_count; unsigned int channels_count;
int *slave_channels; 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; int drain_silenced;
struct timeval trigger_tstamp; struct timeval trigger_tstamp;
snd_pcm_state_t state; 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; min_frames = slave_avail;
max_frames = 0; max_frames = 0;
slave_appl_ptr = *slave->pcm->appl_ptr; 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_share_t *share = list_entry(i, snd_pcm_share_t, list);
snd_pcm_t *pcm = share->pcm; snd_pcm_t *pcm = share->pcm;
switch (snd_enum_to_int(share->state)) { 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) if ((snd_pcm_uframes_t)hw_avail < missing)
missing = hw_avail; missing = hw_avail;
} }
ready_missing = share->avail_min - avail; ready_missing = pcm->avail_min - avail;
if (ready_missing > 0) { if (ready_missing > 0) {
ready = 0; ready = 0;
if ((snd_pcm_uframes_t)ready_missing < missing) 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); snd_pcm_sframes_t avail = snd_pcm_avail_update(slave->pcm);
int slave_xrun = (avail == -EPIPE); int slave_xrun = (avail == -EPIPE);
slave->hw_ptr = *slave->pcm->hw_ptr; 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_share_t *share = list_entry(i, snd_pcm_share_t, list);
snd_pcm_t *pcm = share->pcm; snd_pcm_t *pcm = share->pcm;
snd_pcm_uframes_t m = _snd_pcm_share_missing(pcm, slave_xrun); 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; 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; 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) if (err < 0)
return err; 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; params->info |= SND_PCM_INFO_DOUBLE;
return 0; 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, _snd_pcm_hw_param_set_mask(sparams, SND_PCM_HW_PARAM_ACCESS,
&saccess_mask); &saccess_mask);
_snd_pcm_hw_param_set(sparams, SND_PCM_HW_PARAM_CHANNELS, _snd_pcm_hw_param_set(sparams, SND_PCM_HW_PARAM_CHANNELS,
slave->channels_count, 0); slave->channels, 0);
return 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_t *share = pcm->private_data;
snd_pcm_share_slave_t *slave = share->slave; snd_pcm_share_slave_t *slave = share->slave;
int err = 0; int err = 0;
Pthread_mutex_lock(&slaves_mutex); Pthread_mutex_lock(&snd_pcm_share_slaves_mutex);
Pthread_mutex_lock(&slave->mutex); Pthread_mutex_lock(&slave->mutex);
slave->open_count--; slave->open_count--;
if (slave->open_count == 0) { if (slave->open_count == 0) {
@ -1111,7 +1111,7 @@ static int snd_pcm_share_close(snd_pcm_t *pcm)
list_del(&share->list); list_del(&share->list);
Pthread_mutex_unlock(&slave->mutex); Pthread_mutex_unlock(&slave->mutex);
} }
Pthread_mutex_unlock(&slaves_mutex); Pthread_mutex_unlock(&snd_pcm_share_slaves_mutex);
close(share->client_socket); close(share->client_socket);
close(share->slave_socket); close(share->slave_socket);
free(share->slave_channels); 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, int snd_pcm_share_open(snd_pcm_t **pcmp, const char *name, const char *sname,
snd_pcm_format_t sformat, int srate, snd_pcm_format_t sformat, int srate,
unsigned int schannels_count, unsigned int schannels_count,
int speriod_time, int sbuffer_time,
unsigned int channels_count, int *channels_map, unsigned int channels_count, int *channels_map,
snd_pcm_stream_t stream, int mode) 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; return err;
} }
Pthread_mutex_lock(&slaves_mutex); Pthread_mutex_lock(&snd_pcm_share_slaves_mutex);
for (i = slaves.next; i != &slaves; i = i->next) { list_for_each(i, &snd_pcm_share_slaves) {
snd_pcm_share_slave_t *s = list_entry(i, snd_pcm_share_slave_t, list); 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) { if (s->pcm->name && strcmp(s->pcm->name, sname) == 0) {
slave = s; 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; snd_pcm_t *spcm;
err = snd_pcm_open(&spcm, sname, stream, mode); err = snd_pcm_open(&spcm, sname, stream, mode);
if (err < 0) { if (err < 0) {
Pthread_mutex_unlock(&slaves_mutex); Pthread_mutex_unlock(&snd_pcm_share_slaves_mutex);
close(sd[0]); close(sd[0]);
close(sd[1]); close(sd[1]);
free(pcm); 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)); slave = calloc(1, sizeof(*slave));
if (!slave) { if (!slave) {
Pthread_mutex_unlock(&slaves_mutex); Pthread_mutex_unlock(&snd_pcm_share_slaves_mutex);
snd_pcm_close(spcm); snd_pcm_close(spcm);
close(sd[0]); close(sd[0]);
close(sd[1]); 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); INIT_LIST_HEAD(&slave->clients);
slave->pcm = spcm; slave->pcm = spcm;
slave->channels_count = schannels_count; slave->channels = schannels_count;
slave->format = sformat; slave->format = sformat;
slave->rate = srate; slave->rate = srate;
slave->period_time = speriod_time;
slave->buffer_time = sbuffer_time;
pthread_mutex_init(&slave->mutex, NULL); pthread_mutex_init(&slave->mutex, NULL);
pthread_cond_init(&slave->poll_cond, 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); Pthread_mutex_lock(&slave->mutex);
err = pthread_create(&slave->thread, NULL, snd_pcm_share_thread, slave); err = pthread_create(&slave->thread, NULL, snd_pcm_share_thread, slave);
assert(err == 0); assert(err == 0);
Pthread_mutex_unlock(&slaves_mutex); Pthread_mutex_unlock(&snd_pcm_share_slaves_mutex);
} else { } else {
Pthread_mutex_lock(&slave->mutex); Pthread_mutex_lock(&slave->mutex);
Pthread_mutex_unlock(&slaves_mutex); Pthread_mutex_unlock(&snd_pcm_share_slaves_mutex);
for (i = slave->clients.next; i != &slave->clients; i = i->next) { list_for_each(i, &slave->clients) {
snd_pcm_share_t *sh = list_entry(i, snd_pcm_share_t, list); snd_pcm_share_t *sh = list_entry(i, snd_pcm_share_t, list);
unsigned int k; unsigned int k;
for (k = 0; k < sh->channels_count; ++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->pcm = pcm;
share->client_socket = sd[0]; share->client_socket = sd[0];
share->slave_socket = sd[1]; share->slave_socket = sd[1];
share->async_sig = SIGIO;
share->async_pid = getpid();
if (name) if (name)
pcm->name = strdup(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; snd_config_iterator_t i, next;
const char *sname = NULL; const char *sname = NULL;
snd_config_t *binding = NULL; snd_config_t *bindings = NULL;
int err; int err;
snd_config_t *slave = NULL;
unsigned int idx; unsigned int idx;
int *channels_map; int *channels_map;
unsigned int channels_count = 0; unsigned int channels_count = 0;
long schannels_count = -1;
unsigned int schannel_max = 0;
snd_pcm_format_t sformat = SND_PCM_FORMAT_UNKNOWN; 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_for_each(i, next, conf) {
snd_config_t *n = snd_config_iterator_entry(i); 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; continue;
if (strcmp(id, "type") == 0) if (strcmp(id, "type") == 0)
continue; continue;
if (strcmp(id, "sname") == 0) { if (strcmp(id, "slave") == 0) {
err = snd_config_get_string(n, &sname); err = snd_config_get_string(n, &sname);
if (err < 0) { if (err < 0) {
SNDERR("Invalid type for %s", id); SNDERR("Invalid type for %s", id);
return -EINVAL; return -EINVAL;
} }
slave = n;
continue; continue;
} }
if (strcmp(id, "sformat") == 0) { if (strcmp(id, "bindings") == 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 (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) { if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) {
SNDERR("Invalid type for %s", id); SNDERR("Invalid type for %s", id);
return -EINVAL; return -EINVAL;
} }
binding = n; bindings = n;
continue; continue;
} }
SNDERR("Unknown field %s", id); SNDERR("Unknown field %s", id);
return -EINVAL; return -EINVAL;
} }
if (!sname) { if (!slave) {
SNDERR("sname is not defined"); SNDERR("slave is not defined");
return -EINVAL; return -EINVAL;
} }
if (!binding) { err = snd_pcm_slave_conf(slave, &sname, 5,
SNDERR("binding is not defined"); 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; return -EINVAL;
} }
snd_config_for_each(i, next, binding) { snd_config_for_each(i, next, bindings) {
int cchannel = -1; int cchannel = -1;
char *p; char *p;
snd_config_t *n = snd_config_iterator_entry(i); 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) for (idx = 0; idx < channels_count; ++idx)
channels_map[idx] = -1; 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); snd_config_t *n = snd_config_iterator_entry(i);
const char *id = snd_config_get_id(n); const char *id = snd_config_get_id(n);
long cchannel; 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); err = snd_config_get_integer(n, &schannel);
if (err < 0) if (err < 0)
goto _free; goto _free;
assert(schannels_count <= 0 || schannel < schannels_count); assert(schannels <= 0 || schannel < schannels);
channels_map[cchannel] = schannel; channels_map[cchannel] = schannel;
if ((unsigned)schannel > schannel_max) if ((unsigned)schannel > schannel_max)
schannel_max = schannel; schannel_max = schannel;
} }
if (schannels_count <= 0) if (schannels <= 0)
schannels_count = schannel_max + 1; schannels = schannel_max + 1;
err = snd_pcm_share_open(pcmp, name, sname, sformat, srate, err = snd_pcm_share_open(pcmp, name, sname, sformat, srate,
schannels_count, schannels, speriod_time, sbuffer_time,
channels_count, channels_map, stream, mode); channels_count, channels_map, stream, mode);
_free: _free:
free(channels_map); 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; snd_config_iterator_t i, next;
const char *server = NULL; const char *server = NULL;
const char *sname = NULL; const char *pcm_name = NULL;
snd_config_t *sconfig; snd_config_t *sconfig;
const char *host = NULL; const char *host = NULL;
const char *socket = 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; continue;
} }
if (strcmp(id, "sname") == 0) { if (strcmp(id, "pcm") == 0) {
err = snd_config_get_string(n, &sname); err = snd_config_get_string(n, &pcm_name);
if (err < 0) { if (err < 0) {
SNDERR("Invalid type for %s", id); SNDERR("Invalid type for %s", id);
return -EINVAL; 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); SNDERR("Unknown field %s", id);
return -EINVAL; return -EINVAL;
} }
if (!sname) { if (!pcm_name) {
SNDERR("sname is not defined"); SNDERR("pcm is not defined");
return -EINVAL; return -EINVAL;
} }
if (!server) { if (!server) {
SNDERR("server is not defined"); SNDERR("server is not defined");
return -EINVAL; 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) { if (err < 0) {
SNDERR("Unknown server %s", server); SNDERR("Unknown server %s", server);
return -EINVAL; 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_for_each(i, next, sconfig) {
snd_config_t *n = snd_config_iterator_entry(i); snd_config_t *n = snd_config_iterator_entry(i);
const char *id = snd_config_get_id(n); 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); SNDERR("%s is not the local host", host);
return -EINVAL; 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; put_1234_4329: as_u32(dst) = bswap_32(sample) ^ 0x80; goto PUT_END;
#endif #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_u8
#undef as_u16 #undef as_u16
#undef as_u32 #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, int (*open_func)(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp,
const char *name, snd_config_t *conf, int mode); const char *name, snd_config_t *conf, int mode);
void *h; void *h;
const char *name1;
assert((inputp || outputp) && name); assert((inputp || outputp) && name);
err = snd_config_update(); err = snd_config_update();
if (err < 0) if (err < 0)
return err; return err;
err = snd_config_searchv(snd_config, &rawmidi_conf, "rawmidi", name, 0); err = snd_config_search_alias(snd_config, "rawmidi", name, &rawmidi_conf);
if (err < 0) { name1 = name;
if (err < 0 || snd_config_get_string(rawmidi_conf, &name1) >= 0) {
int card, dev, subdev; 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) if (err == 3)
return snd_rawmidi_hw_open(inputp, outputp, name, card, dev, subdev, mode); 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) if (err == 2)
return snd_rawmidi_hw_open(inputp, outputp, name, card, dev, -1, mode); return snd_rawmidi_hw_open(inputp, outputp, name, card, dev, -1, mode);
SNDERR("Unknown RAWMIDI %s", name); SNDERR("Unknown RAWMIDI %s", name1);
return -ENOENT; return -ENOENT;
} }
if (snd_config_get_type(rawmidi_conf) != SND_CONFIG_TYPE_COMPOUND) { 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)); SNDERR("Invalid type for %s", snd_config_get_id(conf));
return err; 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) { if (err >= 0) {
snd_config_for_each(i, next, type_conf) { snd_config_for_each(i, next, type_conf) {
snd_config_t *n = snd_config_iterator_entry(i); 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 (*open_func)(snd_seq_t **seqp, const char *name, snd_config_t *conf,
int streams, int mode); int streams, int mode);
void *h; void *h;
const char *name1;
assert(seqp && name); assert(seqp && name);
err = snd_config_update(); err = snd_config_update();
if (err < 0) if (err < 0)
return err; return err;
err = snd_config_searchv(snd_config, &seq_conf, "seq", name, 0); err = snd_config_search_alias(snd_config, "seq", name, &seq_conf);
if (err < 0) { name1 = name;
if (strcmp(name, "hw") == 0) 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); return snd_seq_hw_open(seqp, name, streams, mode);
SNDERR("Unknown SEQ %s", name); SNDERR("Unknown SEQ %s", name1);
return -ENOENT; return -ENOENT;
} }
if (snd_config_get_type(seq_conf) != SND_CONFIG_TYPE_COMPOUND) { 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)); SNDERR("Invalid type for %s", snd_config_get_id(conf));
return err; 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) { if (err >= 0) {
snd_config_for_each(i, next, type_conf) { snd_config_for_each(i, next, type_conf) {
snd_config_t *n = snd_config_iterator_entry(i); snd_config_t *n = snd_config_iterator_entry(i);