mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-10-29 05:40:25 -04:00
Improved .asoundrc changes
This commit is contained in:
parent
0300bbbbb3
commit
a275d66356
25 changed files with 888 additions and 612 deletions
|
|
@ -968,11 +968,15 @@ int main(int argc, char **argv)
|
|||
return 1;
|
||||
}
|
||||
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) {
|
||||
ERROR("Missing definition for server %s", srvname);
|
||||
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_t *n = snd_config_iterator_entry(i);
|
||||
const char *id = snd_config_get_id(n);
|
||||
|
|
|
|||
422
doc/asoundrc.doc
422
doc/asoundrc.doc
|
|
@ -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:
|
||||
type PCM type
|
||||
[comment] Saved comments
|
||||
# PCM type definition
|
||||
pcm_type.NAME {
|
||||
[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
|
||||
Fields:
|
||||
card Card name or number
|
||||
[device] Device number (default 0)
|
||||
[subdevice] Subdevice number, -1 first available (default -1)
|
||||
# Slave PCM definition
|
||||
pcm_slave.NAME {
|
||||
pcm STR # PCM name
|
||||
format STR # Format
|
||||
channels INT # Channels
|
||||
rate INT # Rate
|
||||
period_time INT # Period time
|
||||
buffer_time INT # Buffer time
|
||||
etc.
|
||||
}
|
||||
|
||||
- plug Format adjusted PCM
|
||||
Fields:
|
||||
sname Slave PCM name
|
||||
ttable Transfer table (bidimensional compound of
|
||||
cchannels * schannels numbers)
|
||||
.C
|
||||
.S route value
|
||||
# PCM definition
|
||||
pcm.NAME {
|
||||
type STR # Type
|
||||
[comment ANY] # Saved comments
|
||||
|
||||
- linear Linear format conversion PCM
|
||||
- adpcm IMA-ADPCM format conversion PCM
|
||||
- alaw A-Law format conversion PCM
|
||||
- mulaw Mu-Law format conversion PCM
|
||||
Fields:
|
||||
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)
|
||||
# PCM types:
|
||||
type hw # Kernel PCM
|
||||
card INT/STR # Card name or number
|
||||
[device] INT # Device number (default 0)
|
||||
[subdevice] INT # Subdevice number, -1 first available (default -1)
|
||||
|
||||
|
||||
- null Null endpoint plugin (NYI)
|
||||
Fields:
|
||||
time Time related or not
|
||||
|
||||
- shm Shared memory client PCM
|
||||
Fields:
|
||||
server Server name
|
||||
sname Slave PCM name on server
|
||||
|
||||
- share Share PCM
|
||||
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
|
||||
type plug # Format adjusted PCM
|
||||
slave STR # Slave name
|
||||
# or
|
||||
slave { # Slave definition or name
|
||||
pcm STR # Slave PCM name
|
||||
}
|
||||
ttable { # Transfer table (bidimensional compound of
|
||||
# cchannels * schannels numbers)
|
||||
CCHANNEL {
|
||||
SCHANNEL REAL # route value (0.0 ... 1.0)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CTL common fields:
|
||||
type CTL type
|
||||
[comment] Saved comments
|
||||
type linear # Linear format conversion PCM
|
||||
type adpcm # IMA-ADPCM format conversion PCM
|
||||
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
|
||||
Fields:
|
||||
server Server name
|
||||
sname Slave CTL name on server
|
||||
type rate # Rate conversion PCM
|
||||
slave STR # Slave name
|
||||
# or
|
||||
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
|
||||
Fields:
|
||||
[lib] Library file
|
||||
open Open function
|
||||
type route # Attenuated static route PCM
|
||||
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)
|
||||
}
|
||||
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
|
||||
Fields:
|
||||
[lib] Library file
|
||||
open Open function
|
||||
type multi # Linked PCMs (exclusive access to selected channels)
|
||||
slaves { # Slaves definitions
|
||||
N STR # Slave name for slave N
|
||||
# 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:
|
||||
host host where the server is located (if map to local address
|
||||
server is local, and then it may be started automatically)
|
||||
[socket] PF_LOCAL socket name to listen/connect
|
||||
[port] PF_INET port number to listen/connect
|
||||
|
||||
type file # File plugin
|
||||
slave STR # Slave name
|
||||
# or
|
||||
slave { # Slave definition or name
|
||||
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:
|
||||
|
||||
pcmtype.hw {
|
||||
open _snd_pcm_hw_open
|
||||
}
|
||||
|
||||
pcmtype.plug {
|
||||
open _snd_pcm_plug_open
|
||||
}
|
||||
|
||||
pcm.trident {
|
||||
type hw
|
||||
card 0
|
||||
|
|
@ -180,31 +272,41 @@ pcm.ice1712_spdif {
|
|||
type plug
|
||||
ttable.0.8 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 {
|
||||
type meter
|
||||
sname plug:trident
|
||||
slave.pcm plug:trident
|
||||
frequency 50
|
||||
scope.0 {
|
||||
scopes.0 {
|
||||
type level
|
||||
}
|
||||
}
|
||||
|
||||
scopetype.level {
|
||||
scope_type.level {
|
||||
lib /home/abramo/scopes/liblevel.so
|
||||
}
|
||||
|
||||
Special PCM names:
|
||||
hw:#card,#dev,#subdev
|
||||
hw:#card,#dev
|
||||
plug:#card,#dev,#subdev
|
||||
plug:#card,#dev
|
||||
plug:sname
|
||||
shm:socket,sname
|
||||
file:fname,fmt,sname
|
||||
file:fname,fmt
|
||||
file:fname
|
||||
hw:CARD,DEV,SUBDEV
|
||||
hw:CARD,DEV
|
||||
plug:CARD,DEV,SUBDEV
|
||||
plug:CARD,DEV
|
||||
plug:SLAVE_PCM
|
||||
shm:SOCKET,PCM
|
||||
file:FNAME,FMT,SLAVE_PCM
|
||||
file:FNAME,FMT
|
||||
file:FNAME
|
||||
null
|
||||
|
||||
|
|
|
|||
|
|
@ -36,6 +36,9 @@ int snd_config_search(snd_config_t *config, const char *key,
|
|||
snd_config_t **result);
|
||||
int snd_config_searchv(snd_config_t *config,
|
||||
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_delete(snd_config_t *config);
|
||||
|
|
|
|||
15
src/conf.c
15
src/conf.c
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
160
src/pcm/pcm.c
160
src/pcm/pcm.c
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue