From a275d663565ce41c97867750eab96f1dd6cba357 Mon Sep 17 00:00:00 2001 From: Abramo Bagnara Date: Sat, 17 Mar 2001 16:34:43 +0000 Subject: [PATCH] Improved .asoundrc changes --- aserver/aserver.c | 6 +- doc/asoundrc.doc | 446 ++++++++++++++++++++++++++++------------------ include/conf.h | 3 + src/conf.c | 15 ++ src/control/control.c | 23 ++- src/control/control_shm.c | 6 +- src/pcm/Makefile.am | 4 +- src/pcm/pcm.c | 160 +++++++++++++++-- src/pcm/pcm_adpcm.c | 43 ++--- src/pcm/pcm_alaw.c | 43 ++--- src/pcm/pcm_copy.c | 16 +- src/pcm/pcm_file.c | 16 +- src/pcm/pcm_linear.c | 43 ++--- src/pcm/pcm_local.h | 5 + src/pcm/pcm_meter.c | 21 ++- src/pcm/pcm_mulaw.c | 43 ++--- src/pcm/pcm_multi.c | 73 +++----- src/pcm/pcm_plug.c | 16 +- src/pcm/pcm_rate.c | 51 ++---- src/pcm/pcm_route.c | 112 +++++------- src/pcm/pcm_share.c | 178 +++++++++--------- src/pcm/pcm_shm.c | 18 +- src/pcm/plugin_ops.h | 157 ++++++++++++++++ src/rawmidi/rawmidi.c | 14 +- src/seq/seq.c | 12 +- 25 files changed, 900 insertions(+), 624 deletions(-) diff --git a/aserver/aserver.c b/aserver/aserver.c index c3f209fa..d3281f9e 100644 --- a/aserver/aserver.c +++ b/aserver/aserver.c @@ -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); diff --git a/doc/asoundrc.doc b/doc/asoundrc.doc index 8a70458c..249eb166 100644 --- a/doc/asoundrc.doc +++ b/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 types: - -- hw Kernel PCM -Fields: -card Card name or number -[device] Device number (default 0) -[subdevice] Subdevice number, -1 first available (default -1) - -- plug Format adjusted PCM -Fields: -sname Slave PCM name -ttable Transfer table (bidimensional compound of - cchannels * schannels numbers) - .C - .S route value - -- 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) - - -- 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 - - -CTL common fields: -type CTL type -[comment] Saved comments - -- hw Kernel CTL -Fields: -card Card name or number - -- shm Shared memory client CTL -Fields: -server Server name -sname Slave CTL name on server - -Other related definitions: - -- pcmtype PCM type -Fields: -[lib] Library file -open Open function - -- ctltype Control type -Fields: -[lib] Library file -open Open function - -- scopetype PCM scope type -Fields: -[lib] Library file -open Open function - -- 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 +# PCM type definition +pcm_type.NAME { + [lib STR] # Library file (default libasound.so) + [open STR] # Open function (default _snd_pcm_NAME_open) +} + +# 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) +} + +# 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. +} + +# PCM definition +pcm.NAME { + type STR # Type + [comment ANY] # Saved comments + +# 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) + + + 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) + } + } + + + 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 + } + + + 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 + } + + + 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) + } + } + + + 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 + } + } + + + 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 + } -Some examples: -pcmtype.hw { - open _snd_pcm_hw_open } -pcmtype.plug { - open _snd_pcm_plug_open +# 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: + 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 diff --git a/include/conf.h b/include/conf.h index 139ebfef..55499e0a 100644 --- a/include/conf.h +++ b/include/conf.h @@ -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); diff --git a/src/conf.c b/src/conf.c index 080769fe..d3abd20d 100644 --- a/src/conf.c +++ b/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; diff --git a/src/control/control.c b/src/control/control.c index 292563e3..194771ff 100644 --- a/src/control/control.c +++ b/src/control/control.c @@ -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); diff --git a/src/control/control_shm.c b/src/control/control_shm.c index 10cb3447..7bec2fe2 100644 --- a/src/control/control_shm.c +++ b/src/control/control_shm.c @@ -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); diff --git a/src/pcm/Makefile.am b/src/pcm/Makefile.am index 47fccb76..7b3b6c27 100644 --- a/src/pcm/Makefile.am +++ b/src/pcm/Makefile.am @@ -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 diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c index 51b3e458..fc7fa2d6 100644 --- a/src/pcm/pcm.c +++ b/src/pcm/pcm.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -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; +} + diff --git a/src/pcm/pcm_adpcm.c b/src/pcm/pcm_adpcm.c index 70d25e09..1d1b8313 100644 --- a/src/pcm/pcm_adpcm.c +++ b/src/pcm/pcm_adpcm.c @@ -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 */ diff --git a/src/pcm/pcm_alaw.c b/src/pcm/pcm_alaw.c index 6c1a799b..714a987b 100644 --- a/src/pcm/pcm_alaw.c +++ b/src/pcm/pcm_alaw.c @@ -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 */ diff --git a/src/pcm/pcm_copy.c b/src/pcm/pcm_copy.c index e52adfa4..e0b2d896 100644 --- a/src/pcm/pcm_copy.c +++ b/src/pcm/pcm_copy.c @@ -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) diff --git a/src/pcm/pcm_file.c b/src/pcm/pcm_file.c index 87b3c0a7..1447c024 100644 --- a/src/pcm/pcm_file.c +++ b/src/pcm/pcm_file.c @@ -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; diff --git a/src/pcm/pcm_linear.c b/src/pcm/pcm_linear.c index 21224bdf..b10dc0eb 100644 --- a/src/pcm/pcm_linear.c +++ b/src/pcm/pcm_linear.c @@ -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 */ diff --git a/src/pcm/pcm_local.h b/src/pcm/pcm_local.h index 4234fbf8..4b6e86f7 100644 --- a/src/pcm/pcm_local.h +++ b/src/pcm/pcm_local.h @@ -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) diff --git a/src/pcm/pcm_meter.c b/src/pcm/pcm_meter.c index ef8ea0d1..88dd825e 100644 --- a/src/pcm/pcm_meter.c +++ b/src/pcm/pcm_meter.c @@ -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) diff --git a/src/pcm/pcm_mulaw.c b/src/pcm/pcm_mulaw.c index ff9a2e8b..79a35e11 100644 --- a/src/pcm/pcm_mulaw.c +++ b/src/pcm/pcm_mulaw.c @@ -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 */ diff --git a/src/pcm/pcm_multi.c b/src/pcm/pcm_multi.c index e84682c5..b3622284 100644 --- a/src/pcm/pcm_multi.c +++ b/src/pcm/pcm_multi.c @@ -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; - goto _free; - } - if (!name) { - SNDERR("name is not defined"); - err = -EINVAL; - goto _free; - } - if (channels < 0) { - SNDERR("channels is not defined"); - err = -EINVAL; + err = snd_pcm_slave_conf(m, &name, 1, + SND_PCM_HW_PARAM_CHANNELS, 1, &channels); + if (err < 0) 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); diff --git a/src/pcm/pcm_plug.c b/src/pcm/pcm_plug.c index 647c9271..175ac097 100644 --- a/src/pcm/pcm_plug.c +++ b/src/pcm/pcm_plug.c @@ -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, diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c index 29a4a48a..6d3251ac 100644 --- a/src/pcm/pcm_rate.c +++ b/src/pcm/pcm_rate.c @@ -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 */ diff --git a/src/pcm/pcm_route.c b/src/pcm/pcm_route.c index 6b997da9..cbe9f558 100644 --- a/src/pcm/pcm_route.c +++ b/src/pcm/pcm_route.c @@ -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); diff --git a/src/pcm/pcm_share.c b/src/pcm/pcm_share.c index 416f7b16..242796f1 100644 --- a/src/pcm/pcm_share.c +++ b/src/pcm/pcm_share.c @@ -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); diff --git a/src/pcm/pcm_shm.c b/src/pcm/pcm_shm.c index ffcf8c04..42a6b70d 100644 --- a/src/pcm/pcm_shm.c +++ b/src/pcm/pcm_shm.c @@ -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); } diff --git a/src/pcm/plugin_ops.h b/src/pcm/plugin_ops.h index de75fbaf..a9f68549 100644 --- a/src/pcm/plugin_ops.h +++ b/src/pcm/plugin_ops.h @@ -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 diff --git a/src/rawmidi/rawmidi.c b/src/rawmidi/rawmidi.c index 8223755a..698fdc5c 100644 --- a/src/rawmidi/rawmidi.c +++ b/src/rawmidi/rawmidi.c @@ -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); diff --git a/src/seq/seq.c b/src/seq/seq.c index f281b4a7..0a0c8ab6 100644 --- a/src/seq/seq.c +++ b/src/seq/seq.c @@ -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); -- 2.11.0