OSDN Git Service

Improved .asoundrc changes
authorAbramo Bagnara <abramo@alsa-project.org>
Sat, 17 Mar 2001 16:34:43 +0000 (16:34 +0000)
committerAbramo Bagnara <abramo@alsa-project.org>
Sat, 17 Mar 2001 16:34:43 +0000 (16:34 +0000)
25 files changed:
aserver/aserver.c
doc/asoundrc.doc
include/conf.h
src/conf.c
src/control/control.c
src/control/control_shm.c
src/pcm/Makefile.am
src/pcm/pcm.c
src/pcm/pcm_adpcm.c
src/pcm/pcm_alaw.c
src/pcm/pcm_copy.c
src/pcm/pcm_file.c
src/pcm/pcm_linear.c
src/pcm/pcm_local.h
src/pcm/pcm_meter.c
src/pcm/pcm_mulaw.c
src/pcm/pcm_multi.c
src/pcm/pcm_plug.c
src/pcm/pcm_rate.c
src/pcm/pcm_route.c
src/pcm/pcm_share.c
src/pcm/pcm_shm.c
src/pcm/plugin_ops.h
src/rawmidi/rawmidi.c
src/seq/seq.c

index c3f209f..d3281f9 100644 (file)
@@ -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);
index 8a70458..249eb16 100644 (file)
+# 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
 
index 139ebfe..55499e0 100644 (file)
@@ -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);
index 080769f..d3abd20 100644 (file)
@@ -1014,6 +1014,21 @@ int snd_config_searchv(snd_config_t *config,
        return 0;
 }
 
+int snd_config_search_alias(snd_config_t *config,
+                           const char *base, const char *key,
+                           snd_config_t **result)
+{
+       int err;
+       assert(config && base && key && result);
+       err = snd_config_searchv(config, result, base, key, 0);
+       if (err < 0)
+               return err;
+       while (snd_config_get_string(*result, &key) >= 0 &&
+              snd_config_searchv(config, result, base, key, 0) >= 0)
+               ;
+       return 0;
+}
+
 snd_config_t *snd_config = 0;
 static dev_t sys_asoundrc_device;
 static ino_t sys_asoundrc_inode;
index 292563e..194771f 100644 (file)
@@ -204,33 +204,42 @@ int snd_ctl_open(snd_ctl_t **ctlp, const char *name)
        const char *lib = NULL, *open = NULL;
        int (*open_func)(snd_ctl_t **ctlp, const char *name, snd_config_t *conf);
        void *h;
+       const char *name1;
        assert(ctlp && name);
        err = snd_config_update();
        if (err < 0)
                return err;
-       err = snd_config_searchv(snd_config, &ctl_conf, "ctl", name, 0);
-       if (err < 0) {
+
+       err = snd_config_search_alias(snd_config, "ctl", name, &ctl_conf);
+       name1 = name;
+       if (err < 0 || snd_config_get_string(ctl_conf, &name1) >= 0) {
                int card;
                char socket[256], sname[256];
-               err = sscanf(name, "hw:%d", &card);
+               err = sscanf(name1, "hw:%d", &card);
                if (err == 1)
                        return snd_ctl_hw_open(ctlp, name, card);
-               err = sscanf(name, "shm:%256[^,],%256[^,]", socket, sname);
+               err = sscanf(name1, "shm:%256[^,],%256[^,]", socket, sname);
                if (err == 2)
                        return snd_ctl_shm_open(ctlp, name, socket, sname);
-               SNDERR("Unknown control %s", name);
+               SNDERR("Unknown ctl %s", name1);
                return -ENOENT;
        }
-       if (snd_config_get_type(ctl_conf) != SND_CONFIG_TYPE_COMPOUND)
+       if (snd_config_get_type(ctl_conf) != SND_CONFIG_TYPE_COMPOUND) {
+               SNDERR("Invalid type for %s", snd_config_get_id(ctl_conf));
                return -EINVAL;
+       }
        err = snd_config_search(ctl_conf, "type", &conf);
        if (err < 0)
                return err;
        err = snd_config_get_string(conf, &str);
        if (err < 0)
                return err;
-       err = snd_config_searchv(snd_config, &type_conf, "ctltype", str, 0);
+       err = snd_config_search_alias(snd_config, "ctl_type", str, &type_conf);
        if (err >= 0) {
+               if (snd_config_get_type(type_conf) != SND_CONFIG_TYPE_COMPOUND) {
+                       SNDERR("Invalid type for ctl type %s definition", str);
+                       return -EINVAL;
+               }
                snd_config_for_each(i, next, type_conf) {
                        snd_config_t *n = snd_config_iterator_entry(i);
                        const char *id = snd_config_get_id(n);
index 10cb344..7bec2fe 100644 (file)
@@ -544,11 +544,15 @@ int _snd_ctl_shm_open(snd_ctl_t **handlep, char *name, snd_config_t *conf)
                SNDERR("server is not defined");
                return -EINVAL;
        }
-       err = snd_config_searchv(snd_config, &sconfig, "server", server, 0);
+       err = snd_config_search_alias(snd_config, "server", server, &sconfig);
        if (err < 0) {
                SNDERR("Unknown server %s", server);
                return -EINVAL;
        }
+       if (snd_config_get_type(sconfig) != SND_CONFIG_TYPE_COMPOUND) {
+               SNDERR("Invalid type for server %s definition", server);
+               return -EINVAL;
+       }
        snd_config_for_each(i, next, conf) {
                snd_config_t *n = snd_config_iterator_entry(i);
                const char *id = snd_config_get_id(n);
index 47fccb7..7b3b6c2 100644 (file)
@@ -5,8 +5,8 @@ libpcm_la_SOURCES = atomic.c mask.c interval.c \
                    pcm.c pcm_m4.c pcm_hw.c pcm_plugin.c pcm_copy.c pcm_linear.c \
                    pcm_route.c pcm_mulaw.c pcm_alaw.c pcm_adpcm.c \
                    pcm_rate.c pcm_plug.c pcm_misc.c pcm_mmap.c pcm_multi.c \
-                   pcm_shm.c pcm_file.c pcm_share.c pcm_null.c pcm_meter.c \
-                   pcm_params.c
+                   pcm_shm.c pcm_file.c pcm_null.c pcm_share.c \
+                   pcm_meter.c pcm_params.c
 noinst_HEADERS = atomic.h pcm_local.h pcm_plugin.h mask.h mask_inline.h \
                 interval.h interval_inline.h plugin_ops.h
 
index 51b3e45..fc7fa2d 100644 (file)
@@ -23,6 +23,7 @@
 #include <string.h>
 #include <malloc.h>
 #include <stdarg.h>
+#include <signal.h>
 #include <sys/ioctl.h>
 #include <sys/poll.h>
 #include <sys/shm.h>
@@ -89,8 +90,20 @@ int snd_pcm_nonblock(snd_pcm_t *pcm, int nonblock)
 
 int snd_pcm_async(snd_pcm_t *pcm, int sig, pid_t pid)
 {
+       int err;
        assert(pcm);
-       return pcm->ops->async(pcm->op_arg, sig, pid);
+       err = pcm->ops->async(pcm->op_arg, sig, pid);
+       if (err < 0)
+               return err;
+       if (sig)
+               pcm->async_sig = sig;
+       else
+               pcm->async_sig = SIGIO;
+       if (pid)
+               pcm->async_pid = pid;
+       else
+               pcm->async_pid = getpid();
+       return 0;
 }
 
 int snd_pcm_info(snd_pcm_t *pcm, snd_pcm_info_t *info)
@@ -564,28 +577,31 @@ int snd_pcm_open(snd_pcm_t **pcmp, const char *name,
        int (*open_func)(snd_pcm_t **pcmp, const char *name, snd_config_t *conf, 
                         snd_pcm_stream_t stream, int mode);
        void *h;
+       const char *name1;
        assert(pcmp && name);
        err = snd_config_update();
        if (err < 0)
                return err;
-       err = snd_config_searchv(snd_config, &pcm_conf, "pcm", name, 0);
-       if (err < 0) {
+
+       err = snd_config_search_alias(snd_config, "pcm", name, &pcm_conf);
+       name1 = name;
+       if (err < 0 || snd_config_get_string(pcm_conf, &name1) >= 0) {
                int card, dev, subdev;
                char socket[256], sname[256];
                char format[16], file[256];
-               err = sscanf(name, "hw:%d,%d,%d", &card, &dev, &subdev);
+               err = sscanf(name1, "hw:%d,%d,%d", &card, &dev, &subdev);
                if (err == 3)
                        return snd_pcm_hw_open(pcmp, name, card, dev, subdev, stream, mode);
-               err = sscanf(name, "hw:%d,%d", &card, &dev);
+               err = sscanf(name1, "hw:%d,%d", &card, &dev);
                if (err == 2)
                        return snd_pcm_hw_open(pcmp, name, card, dev, -1, stream, mode);
-               err = sscanf(name, "plug:%d,%d,%d", &card, &dev, &subdev);
+               err = sscanf(name1, "plug:%d,%d,%d", &card, &dev, &subdev);
                if (err == 3)
                        return snd_pcm_plug_open_hw(pcmp, name, card, dev, subdev, stream, mode);
-               err = sscanf(name, "plug:%d,%d", &card, &dev);
+               err = sscanf(name1, "plug:%d,%d", &card, &dev);
                if (err == 2)
                        return snd_pcm_plug_open_hw(pcmp, name, card, dev, -1, stream, mode);
-               err = sscanf(name, "plug:%256[^,]", sname);
+               err = sscanf(name1, "plug:%256[^,]", sname);
                if (err == 1) {
                        snd_pcm_t *slave;
                        err = snd_pcm_open(&slave, sname, stream, mode);
@@ -593,18 +609,18 @@ int snd_pcm_open(snd_pcm_t **pcmp, const char *name,
                                return err;
                        return snd_pcm_plug_open(pcmp, name, NULL, 0, 0, 0, slave, 1);
                }
-               err = sscanf(name, "shm:%256[^,],%256[^,]", socket, sname);
+               err = sscanf(name1, "shm:%256[^,],%256[^,]", socket, sname);
                if (err == 2)
                        return snd_pcm_shm_open(pcmp, name, socket, sname, stream, mode);
-               err = sscanf(name, "file:%256[^,],%16[^,],%256[^,]", file, format, sname);
+               err = sscanf(name1, "file:%256[^,],%16[^,],%256[^,]", file, format, sname);
                if (err == 3) {
                        snd_pcm_t *slave;
                        err = snd_pcm_open(&slave, sname, stream, mode);
                        if (err < 0)
                                return err;
-                       return snd_pcm_file_open(pcmp, name, file, -1, format, slave, 1);
+                       return snd_pcm_file_open(pcmp, name1, file, -1, format, slave, 1);
                }
-               err = sscanf(name, "file:%256[^,],%16[^,]", file, format);
+               err = sscanf(name1, "file:%256[^,],%16[^,]", file, format);
                if (err == 2) {
                        snd_pcm_t *slave;
                        err = snd_pcm_null_open(&slave, name, stream, mode);
@@ -612,7 +628,7 @@ int snd_pcm_open(snd_pcm_t **pcmp, const char *name,
                                return err;
                        return snd_pcm_file_open(pcmp, name, file, -1, format, slave, 1);
                }
-               err = sscanf(name, "file:%256[^,]", file);
+               err = sscanf(name1, "file:%256[^,]", file);
                if (err == 1) {
                        snd_pcm_t *slave;
                        err = snd_pcm_null_open(&slave, name, stream, mode);
@@ -620,13 +636,13 @@ int snd_pcm_open(snd_pcm_t **pcmp, const char *name,
                                return err;
                        return snd_pcm_file_open(pcmp, name, file, -1, "raw", slave, 1);
                }
-               if (strcmp(name, "null") == 0)
+               if (strcmp(name1, "null") == 0)
                        return snd_pcm_null_open(pcmp, name, stream, mode);
-               SNDERR("Unknown PCM %s", name);
+               SNDERR("Unknown PCM %s", name1);
                return -ENOENT;
        }
        if (snd_config_get_type(pcm_conf) != SND_CONFIG_TYPE_COMPOUND) {
-               SNDERR("Invalid type for PCM %s definition", name);
+               SNDERR("Invalid type for PCM %s definition", name1);
                return -EINVAL;
        }
        err = snd_config_search(pcm_conf, "type", &conf);
@@ -639,8 +655,12 @@ int snd_pcm_open(snd_pcm_t **pcmp, const char *name,
                SNDERR("Invalid type for %s", snd_config_get_id(conf));
                return err;
        }
-       err = snd_config_searchv(snd_config, &type_conf, "pcmtype", str, 0);
+       err = snd_config_search_alias(snd_config, "pcm_type", str, &type_conf);
        if (err >= 0) {
+               if (snd_config_get_type(type_conf) != SND_CONFIG_TYPE_COMPOUND) {
+                       SNDERR("Invalid type for PCM type %s definition", str);
+                       return -EINVAL;
+               }
                snd_config_for_each(i, next, type_conf) {
                        snd_config_t *n = snd_config_iterator_entry(i);
                        const char *id = snd_config_get_id(n);
@@ -1181,3 +1201,109 @@ snd_pcm_uframes_t _snd_pcm_boundary(snd_pcm_t *pcm)
        return pcm->boundary;
 }
 
+static const char *names[SND_PCM_HW_PARAM_LAST + 1] = {
+       [SND_PCM_HW_PARAM_FORMAT] = "format",
+       [SND_PCM_HW_PARAM_CHANNELS] = "channels",
+       [SND_PCM_HW_PARAM_RATE] = "rate",
+       [SND_PCM_HW_PARAM_PERIOD_TIME] = "period_time",
+       [SND_PCM_HW_PARAM_BUFFER_TIME] = "buffer_time"
+};
+
+int snd_pcm_slave_conf(snd_config_t *conf, const char **namep, 
+                      unsigned int count, ...)
+{
+       snd_config_iterator_t i, next;
+       const char *str;
+       struct {
+               unsigned int index;
+               int mandatory;
+               void *ptr;
+               int valid;
+       } fields[count];
+       unsigned int k;
+       int pcm_valid = 0;
+       int err;
+       va_list args;
+       if (snd_config_get_string(conf, &str) >= 0) {
+               err = snd_config_search_alias(snd_config, "pcm_slave", str, &conf);
+               if (err < 0) {
+                       SNDERR("unkown pcm_slave %s", str);
+                       return err;
+               }
+       }
+       va_start(args, count);
+       for (k = 0; k < count; ++k) {
+               fields[k].index = va_arg(args, int);
+               fields[k].mandatory = va_arg(args, int);
+               fields[k].ptr = va_arg(args, void *);
+               fields[k].valid = 0;
+       }
+       va_end(args);
+       snd_config_for_each(i, next, conf) {
+               snd_config_t *n = snd_config_iterator_entry(i);
+               const char *id = snd_config_get_id(n);
+               if (strcmp(id, "comment") == 0)
+                       continue;
+               if (strcmp(id, "pcm") == 0) {
+                       if (pcm_valid) {
+                       _duplicated:
+                               SNDERR("duplicated %s", id);
+                               return -EINVAL;
+                       }
+                       err = snd_config_get_string(n, namep);
+                       if (err < 0) {
+                       _invalid:
+                               SNDERR("invalid type for %s", id);
+                               return err;
+                       }
+                       pcm_valid = 1;
+                       continue;
+               }
+               for (k = 0; k < count; ++k) {
+                       unsigned int idx = fields[k].index;
+                       long v;
+                       assert(idx < SND_PCM_HW_PARAM_LAST);
+                       assert(names[idx]);
+                       if (strcmp(id, names[idx]) != 0)
+                               continue;
+                       if (fields[k].valid)
+                               goto _duplicated;
+                       switch (idx) {
+                       case SND_PCM_HW_PARAM_FORMAT:
+                       {
+                               snd_pcm_format_t f;
+                               err = snd_config_get_string(n, &str);
+                               if (err < 0)
+                                       goto _invalid;
+                               f = snd_pcm_format_value(str);
+                               if (f == SND_PCM_FORMAT_UNKNOWN) {
+                                       SNDERR("unknown format");
+                                       return -EINVAL;
+                               }
+                               *(snd_pcm_format_t*)fields[k].ptr = f;
+                                       break;
+                       }
+                       default:
+                               err = snd_config_get_integer(n, &v);
+                               if (err < 0)
+                                       goto _invalid;
+                               *(int*)fields[k].ptr = v;
+                               break;
+                       }
+                       fields[k].valid = 1;
+                       break;
+               }
+               if (k < count)
+                       continue;
+               SNDERR("Unknown field %s", id);
+               return -EINVAL;
+       }
+       for (k = 0; k < count; ++k) {
+               if (fields[k].mandatory && !fields[k].valid) {
+                       SNDERR("missing field %s", names[fields[k].index]);
+                       return -EINVAL;
+               }
+       }
+       return 0;
+}
+               
index 70d25e0..1d1b831 100644 (file)
@@ -552,7 +552,8 @@ int _snd_pcm_adpcm_open(snd_pcm_t **pcmp, const char *name,
        const char *sname = NULL;
        int err;
        snd_pcm_t *spcm;
-       snd_pcm_format_t sformat = SND_PCM_FORMAT_UNKNOWN;
+       snd_config_t *slave = NULL;
+       snd_pcm_format_t sformat;
        snd_config_for_each(i, next, conf) {
                snd_config_t *n = snd_config_iterator_entry(i);
                const char *id = snd_config_get_id(n);
@@ -560,42 +561,24 @@ int _snd_pcm_adpcm_open(snd_pcm_t **pcmp, const char *name,
                        continue;
                if (strcmp(id, "type") == 0)
                        continue;
-               if (strcmp(id, "sname") == 0) {
-                       err = snd_config_get_string(n, &sname);
-                       if (err < 0) {
-                               SNDERR("Invalid type for %s", id);
-                               return -EINVAL;
-                       }
-                       continue;
-               }
-               if (strcmp(id, "sformat") == 0) {
-                       const char *f;
-                       err = snd_config_get_string(n, &f);
-                       if (err < 0) {
-                               SNDERR("Invalid type for %s", id);
-                               return -EINVAL;
-                       }
-                       sformat = snd_pcm_format_value(f);
-                       if (sformat == SND_PCM_FORMAT_UNKNOWN) {
-                               SNDERR("Unknown sformat");
-                               return -EINVAL;
-                       }
-                       if (snd_pcm_format_linear(sformat) != 1 &&
-                           sformat != SND_PCM_FORMAT_IMA_ADPCM) {
-                               SNDERR("Invalid sformat");
-                               return -EINVAL;
-                       }
+               if (strcmp(id, "slave") == 0) {
+                       slave = n;
                        continue;
                }
                SNDERR("Unknown field %s", id);
                return -EINVAL;
        }
-       if (!sname) {
-               SNDERR("sname is not defined");
+       if (!slave) {
+               SNDERR("slave is not defined");
                return -EINVAL;
        }
-       if (sformat == SND_PCM_FORMAT_UNKNOWN) {
-               SNDERR("sformat is not defined");
+       err = snd_pcm_slave_conf(slave, &sname, 1,
+                                SND_PCM_HW_PARAM_FORMAT, 1, &sformat);
+       if (err < 0)
+               return err;
+       if (snd_pcm_format_linear(sformat) != 1 &&
+           sformat != SND_PCM_FORMAT_IMA_ADPCM) {
+               SNDERR("invalid slave format");
                return -EINVAL;
        }
        /* This is needed cause snd_config_update may destroy config */
index 6c1a799..714a987 100644 (file)
@@ -425,7 +425,8 @@ int _snd_pcm_alaw_open(snd_pcm_t **pcmp, const char *name,
        const char *sname = NULL;
        int err;
        snd_pcm_t *spcm;
-       snd_pcm_format_t sformat = SND_PCM_FORMAT_UNKNOWN;
+       snd_config_t *slave = NULL;
+       snd_pcm_format_t sformat;
        snd_config_for_each(i, next, conf) {
                snd_config_t *n = snd_config_iterator_entry(i);
                const char *id = snd_config_get_id(n);
@@ -433,42 +434,24 @@ int _snd_pcm_alaw_open(snd_pcm_t **pcmp, const char *name,
                        continue;
                if (strcmp(id, "type") == 0)
                        continue;
-               if (strcmp(id, "sname") == 0) {
-                       err = snd_config_get_string(n, &sname);
-                       if (err < 0) {
-                               SNDERR("Invalid type for %s", id);
-                               return -EINVAL;
-                       }
-                       continue;
-               }
-               if (strcmp(id, "sformat") == 0) {
-                       const char *f;
-                       err = snd_config_get_string(n, &f);
-                       if (err < 0) {
-                               SNDERR("Invalid type for %s", id);
-                               return -EINVAL;
-                       }
-                       sformat = snd_pcm_format_value(f);
-                       if (sformat == SND_PCM_FORMAT_UNKNOWN) {
-                               SNDERR("Unknown sformat");
-                               return -EINVAL;
-                       }
-                       if (snd_pcm_format_linear(sformat) != 1 &&
-                           sformat != SND_PCM_FORMAT_A_LAW) {
-                               SNDERR("Invalid sformat");
-                               return -EINVAL;
-                       }
+               if (strcmp(id, "slave") == 0) {
+                       slave = n;
                        continue;
                }
                SNDERR("Unknown field %s", id);
                return -EINVAL;
        }
-       if (!sname) {
-               SNDERR("sname is not defined");
+       if (!slave) {
+               SNDERR("slave is not defined");
                return -EINVAL;
        }
-       if (sformat == SND_PCM_FORMAT_UNKNOWN) {
-               SNDERR("sformat is not defined");
+       err = snd_pcm_slave_conf(slave, &sname, 1,
+                                SND_PCM_HW_PARAM_FORMAT, 1, &sformat);
+       if (err < 0)
+               return err;
+       if (snd_pcm_format_linear(sformat) != 1 &&
+           sformat != SND_PCM_FORMAT_A_LAW) {
+               SNDERR("invalid slave format");
                return -EINVAL;
        }
        /* This is needed cause snd_config_update may destroy config */
index e52adfa..e0b2d89 100644 (file)
@@ -198,6 +198,7 @@ int _snd_pcm_copy_open(snd_pcm_t **pcmp, const char *name,
        const char *sname = NULL;
        int err;
        snd_pcm_t *spcm;
+       snd_config_t *slave = NULL;
        snd_config_for_each(i, next, conf) {
                snd_config_t *n = snd_config_iterator_entry(i);
                const char *id = snd_config_get_id(n);
@@ -205,21 +206,20 @@ int _snd_pcm_copy_open(snd_pcm_t **pcmp, const char *name,
                        continue;
                if (strcmp(id, "type") == 0)
                        continue;
-               if (strcmp(id, "sname") == 0) {
-                       err = snd_config_get_string(n, &sname);
-                       if (err < 0) {
-                               SNDERR("Invalid type for %s", id);
-                               return -EINVAL;
-                       }
+               if (strcmp(id, "slave") == 0) {
+                       slave = n;
                        continue;
                }
                SNDERR("Unknown field %s", id);
                return -EINVAL;
        }
-       if (!sname) {
-               SNDERR("sname is not defined");
+       if (!slave) {
+               SNDERR("slave is not defined");
                return -EINVAL;
        }
+       err = snd_pcm_slave_conf(slave, &sname, 0);
+       if (err < 0)
+               return err;
        /* This is needed cause snd_config_update may destroy config */
        sname = strdup(sname);
        if (!sname)
index 87b3c0a..1447c02 100644 (file)
@@ -467,6 +467,7 @@ int _snd_pcm_file_open(snd_pcm_t **pcmp, const char *name,
        const char *sname = NULL;
        int err;
        snd_pcm_t *spcm;
+       snd_config_t *slave = NULL;
        const char *fname = NULL;
        const char *format = NULL;
        long fd = -1;
@@ -477,12 +478,8 @@ int _snd_pcm_file_open(snd_pcm_t **pcmp, const char *name,
                        continue;
                if (strcmp(id, "type") == 0)
                        continue;
-               if (strcmp(id, "sname") == 0) {
-                       err = snd_config_get_string(n, &sname);
-                       if (err < 0) {
-                               SNDERR("Invalid type for %s", id);
-                               return -EINVAL;
-                       }
+               if (strcmp(id, "slave") == 0) {
+                       slave = n;
                        continue;
                }
                if (strcmp(id, "format") == 0) {
@@ -507,10 +504,13 @@ int _snd_pcm_file_open(snd_pcm_t **pcmp, const char *name,
                SNDERR("Unknown field %s", id);
                return -EINVAL;
        }
-       if (!sname) {
-               SNDERR("sname is not defined");
+       if (!slave) {
+               SNDERR("slave is not defined");
                return -EINVAL;
        }
+       err = snd_pcm_slave_conf(slave, &sname, 0);
+       if (err < 0)
+               return err;
        if (!fname && fd < 0) {
                SNDERR("file is not defined");
                return -EINVAL;
index 21224bd..b10dc0e 100644 (file)
@@ -329,10 +329,11 @@ int _snd_pcm_linear_open(snd_pcm_t **pcmp, const char *name,
                         snd_pcm_stream_t stream, int mode)
 {
        snd_config_iterator_t i, next;
-       const char *sname = NULL;
+       const char *sname;
        int err;
        snd_pcm_t *spcm;
-       snd_pcm_format_t sformat = SND_PCM_FORMAT_UNKNOWN;
+       snd_config_t *slave = NULL;
+       snd_pcm_format_t sformat;
        snd_config_for_each(i, next, conf) {
                snd_config_t *n = snd_config_iterator_entry(i);
                const char *id = snd_config_get_id(n);
@@ -340,41 +341,23 @@ int _snd_pcm_linear_open(snd_pcm_t **pcmp, const char *name,
                        continue;
                if (strcmp(id, "type") == 0)
                        continue;
-               if (strcmp(id, "sname") == 0) {
-                       err = snd_config_get_string(n, &sname);
-                       if (err < 0) {
-                               SNDERR("Invalid type for %s", id);
-                               return -EINVAL;
-                       }
-                       continue;
-               }
-               if (strcmp(id, "sformat") == 0) {
-                       const char *f;
-                       err = snd_config_get_string(n, &f);
-                       if (err < 0) {
-                               SNDERR("Invalid type for %s", id);
-                               return -EINVAL;
-                       }
-                       sformat = snd_pcm_format_value(f);
-                       if (sformat == SND_PCM_FORMAT_UNKNOWN) {
-                               SNDERR("Unknown sformat %s", f);
-                               return err;
-                       }
-                       if (snd_pcm_format_linear(sformat) != 1) {
-                               SNDERR("sformat is not linear");
-                               return -EINVAL;
-                       }
+               if (strcmp(id, "slave") == 0) {
+                       slave = n;
                        continue;
                }
                SNDERR("Unknown field %s", id);
                return -EINVAL;
        }
-       if (!sname) {
-               SNDERR("sname is not defined");
+       if (!slave) {
+               SNDERR("slave is not defined");
                return -EINVAL;
        }
-       if (sformat == SND_PCM_FORMAT_UNKNOWN) {
-               SNDERR("sformat is not defined");
+       err = snd_pcm_slave_conf(slave, &sname, 1,
+                                SND_PCM_HW_PARAM_FORMAT, 1, &sformat);
+       if (err < 0)
+               return err;
+       if (snd_pcm_format_linear(sformat) != 1) {
+               SNDERR("slave format is not linear");
                return -EINVAL;
        }
        /* This is needed cause snd_config_update may destroy config */
index 4234fbf..4b6e86f 100644 (file)
@@ -143,6 +143,8 @@ struct _snd_pcm {
        snd_pcm_uframes_t silence_size; /* Silence filling size */
        snd_pcm_uframes_t xfer_align;   /* xfer size need to be a multiple */
        snd_pcm_uframes_t boundary;     /* pointers wrap point */
+       int async_sig;
+       pid_t async_pid;
        unsigned int info;              /* Info for returned setup */
        unsigned int msbits;            /* used most significant bits */
        unsigned int rate_num;          /* rate numerator */
@@ -486,6 +488,9 @@ int snd_pcm_hw_strategy_simple_choices(snd_pcm_hw_strategy_t *strategy, int orde
                                       unsigned int count,
                                       snd_pcm_hw_strategy_simple_choices_list_t *choices);
 
+int snd_pcm_slave_conf(snd_config_t *conf, const char **namep,
+                      unsigned int count, ...);
+
 #define SND_PCM_HW_PARBIT_ACCESS       (1 << SND_PCM_HW_PARAM_ACCESS)
 #define SND_PCM_HW_PARBIT_FORMAT       (1 << SND_PCM_HW_PARAM_FORMAT)
 #define SND_PCM_HW_PARBIT_SUBFORMAT    (1 << SND_PCM_HW_PARAM_SUBFORMAT)
index ef8ea0d..88dd825 100644 (file)
@@ -658,7 +658,7 @@ int snd_pcm_meter_add_scope_conf(snd_pcm_t *pcm, const char *name,
                SNDERR("Invalid type for %s", snd_config_get_id(c));
                return err;
        }
-       err = snd_config_searchv(snd_config, &type_conf, "scopetype", str, 0);
+       err = snd_config_search_alias(snd_config, "pcm_scope_type", str, &type_conf);
        if (err >= 0) {
                snd_config_for_each(i, next, type_conf) {
                        snd_config_t *n = snd_config_iterator_entry(i);
@@ -714,6 +714,7 @@ int _snd_pcm_meter_open(snd_pcm_t **pcmp, const char *name,
        const char *sname = NULL;
        int err;
        snd_pcm_t *spcm;
+       snd_config_t *slave = NULL;
        long frequency = -1;
        snd_config_t *scopes = NULL;
        snd_config_for_each(i, next, conf) {
@@ -723,12 +724,8 @@ int _snd_pcm_meter_open(snd_pcm_t **pcmp, const char *name,
                        continue;
                if (strcmp(id, "type") == 0)
                        continue;
-               if (strcmp(id, "sname") == 0) {
-                       err = snd_config_get_string(n, &sname);
-                       if (err < 0) {
-                               SNDERR("Invalid type for %s", id);
-                               return -EINVAL;
-                       }
+               if (strcmp(id, "slave") == 0) {
+                       slave = n;
                        continue;
                }
                if (strcmp(id, "frequency") == 0) {
@@ -739,7 +736,7 @@ int _snd_pcm_meter_open(snd_pcm_t **pcmp, const char *name,
                        }
                        continue;
                }
-               if (strcmp(id, "scope") == 0) {
+               if (strcmp(id, "scopes") == 0) {
                        if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) {
                                SNDERR("Invalid type for %s", id);
                                return -EINVAL;
@@ -750,11 +747,13 @@ int _snd_pcm_meter_open(snd_pcm_t **pcmp, const char *name,
                SNDERR("Unknown field %s", id);
                return -EINVAL;
        }
-       if (!sname) {
-               SNDERR("sname is not defined");
+       if (!slave) {
+               SNDERR("slave is not defined");
                return -EINVAL;
        }
-
+       err = snd_pcm_slave_conf(slave, &sname, 0);
+       if (err < 0)
+               return err;
        /* This is needed cause snd_config_update may destroy config */
        sname = strdup(sname);
        if (!sname)
index ff9a2e8..79a35e1 100644 (file)
@@ -440,7 +440,8 @@ int _snd_pcm_mulaw_open(snd_pcm_t **pcmp, const char *name,
        const char *sname = NULL;
        int err;
        snd_pcm_t *spcm;
-       snd_pcm_format_t sformat = SND_PCM_FORMAT_UNKNOWN;
+       snd_config_t *slave = NULL;
+       snd_pcm_format_t sformat;
        snd_config_for_each(i, next, conf) {
                snd_config_t *n = snd_config_iterator_entry(i);
                const char *id = snd_config_get_id(n);
@@ -448,42 +449,24 @@ int _snd_pcm_mulaw_open(snd_pcm_t **pcmp, const char *name,
                        continue;
                if (strcmp(id, "type") == 0)
                        continue;
-               if (strcmp(id, "sname") == 0) {
-                       err = snd_config_get_string(n, &sname);
-                       if (err < 0) {
-                               SNDERR("Invalid type for %s", id);
-                               return -EINVAL;
-                       }
-                       continue;
-               }
-               if (strcmp(id, "sformat") == 0) {
-                       const char *f;
-                       err = snd_config_get_string(n, &f);
-                       if (err < 0) {
-                               SNDERR("Invalid type for %s", id);
-                               return -EINVAL;
-                       }
-                       sformat = snd_pcm_format_value(f);
-                       if (sformat == SND_PCM_FORMAT_UNKNOWN) {
-                               SNDERR("Unknown sformat");
-                               return -EINVAL;
-                       }
-                       if (snd_pcm_format_linear(sformat) != 1 &&
-                           sformat != SND_PCM_FORMAT_MU_LAW) {
-                               SNDERR("Invalid sformat");
-                               return -EINVAL;
-                       }
+               if (strcmp(id, "slave") == 0) {
+                       slave = n;
                        continue;
                }
                SNDERR("Unknown field %s", id);
                return -EINVAL;
        }
-       if (!sname) {
-               SNDERR("sname is not defined");
+       if (!slave) {
+               SNDERR("slave is not defined");
                return -EINVAL;
        }
-       if (sformat == SND_PCM_FORMAT_UNKNOWN) {
-               SNDERR("sformat is not defined");
+       err = snd_pcm_slave_conf(slave, &sname, 1,
+                                SND_PCM_HW_PARAM_FORMAT, 1, &sformat);
+       if (err < 0)
+               return err;
+       if (snd_pcm_format_linear(sformat) != 1 &&
+           sformat != SND_PCM_FORMAT_MU_LAW) {
+               SNDERR("invalid slave format");
                return -EINVAL;
        }
        /* This is needed cause snd_config_update may destroy config */
index e84682c..b362228 100644 (file)
@@ -584,8 +584,8 @@ int _snd_pcm_multi_open(snd_pcm_t **pcmp, const char *name, snd_config_t *conf,
                        snd_pcm_stream_t stream, int mode)
 {
        snd_config_iterator_t i, inext, j, jnext;
-       snd_config_t *slave = NULL;
-       snd_config_t *binding = NULL;
+       snd_config_t *slaves = NULL;
+       snd_config_t *bindings = NULL;
        int err;
        unsigned int idx;
        const char **slaves_id = NULL;
@@ -603,37 +603,37 @@ int _snd_pcm_multi_open(snd_pcm_t **pcmp, const char *name, snd_config_t *conf,
                        continue;
                if (strcmp(id, "type") == 0)
                        continue;
-               if (strcmp(id, "slave") == 0) {
+               if (strcmp(id, "slaves") == 0) {
                        if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) {
                                SNDERR("Invalid type for %s", id);
                                return -EINVAL;
                        }
-                       slave = n;
+                       slaves = n;
                        continue;
                }
-               if (strcmp(id, "binding") == 0) {
+               if (strcmp(id, "bindings") == 0) {
                        if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) {
                                SNDERR("Invalid type for %s", id);
                                return -EINVAL;
                        }
-                       binding = n;
+                       bindings = n;
                        continue;
                }
                SNDERR("Unknown field %s", id);
                return -EINVAL;
        }
-       if (!slave) {
-               SNDERR("slave is not defined");
+       if (!slaves) {
+               SNDERR("slaves is not defined");
                return -EINVAL;
        }
-       if (!binding) {
-               SNDERR("binding is not defined");
+       if (!bindings) {
+               SNDERR("bindings is not defined");
                return -EINVAL;
        }
-       snd_config_for_each(i, inext, slave) {
+       snd_config_for_each(i, inext, slaves) {
                ++slaves_count;
        }
-       snd_config_for_each(i, inext, binding) {
+       snd_config_for_each(i, inext, bindings) {
                int cchannel = -1;
                char *p;
                snd_config_t *m = snd_config_iterator_entry(i);
@@ -661,52 +661,21 @@ int _snd_pcm_multi_open(snd_pcm_t **pcmp, const char *name, snd_config_t *conf,
        for (idx = 0; idx < channels_count; ++idx)
                channels_sidx[idx] = -1;
        idx = 0;
-       snd_config_for_each(i, inext, slave) {
+       snd_config_for_each(i, inext, slaves) {
                snd_config_t *m = snd_config_iterator_entry(i);
-               const char *name = NULL;
-               long channels = -1;
+               const char *name;
+               int channels;
                slaves_id[idx] = snd_config_get_id(m);
-               snd_config_for_each(j, jnext, m) {
-                       snd_config_t *n = snd_config_iterator_entry(j);
-                       const char *id = snd_config_get_id(n);
-                       if (strcmp(id, "comment") == 0)
-                               continue;
-                       if (strcmp(id, "name") == 0) {
-                               err = snd_config_get_string(n, &name);
-                               if (err < 0) {
-                                       SNDERR("Invalid type for %s", id);
-                                       goto _free;
-                               }
-                               continue;
-                       }
-                       if (strcmp(id, "channels") == 0) {
-                               err = snd_config_get_integer(n, &channels);
-                               if (err < 0) {
-                                       SNDERR("Invalid type for %s", id);
-                                       goto _free;
-                               }
-                               continue;
-                       }
-                       SNDERR("Unknown field %s", id);
-                       err = -EINVAL;
-                       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);
index 647c927..175ac09 100644 (file)
@@ -718,6 +718,7 @@ int _snd_pcm_plug_open(snd_pcm_t **pcmp, const char *name,
        const char *sname = NULL;
        int err;
        snd_pcm_t *spcm;
+       snd_config_t *slave = NULL;
        snd_config_t *tt = NULL;
        snd_pcm_route_ttable_entry_t *ttable = NULL;
        unsigned int cused, sused;
@@ -728,12 +729,8 @@ int _snd_pcm_plug_open(snd_pcm_t **pcmp, const char *name,
                        continue;
                if (strcmp(id, "type") == 0)
                        continue;
-               if (strcmp(id, "sname") == 0) {
-                       err = snd_config_get_string(n, &sname);
-                       if (err < 0) {
-                               SNDERR("Invalid type for %s", id);
-                               return -EINVAL;
-                       }
+               if (strcmp(id, "slave") == 0) {
+                       slave = n;
                        continue;
                }
                if (strcmp(id, "ttable") == 0) {
@@ -747,10 +744,13 @@ int _snd_pcm_plug_open(snd_pcm_t **pcmp, const char *name,
                SNDERR("Unknown field %s", id);
                return -EINVAL;
        }
-       if (!sname) {
-               SNDERR("sname is not defined");
+       if (!slave) {
+               SNDERR("slave is not defined");
                return -EINVAL;
        }
+       err = snd_pcm_slave_conf(slave, &sname, 0);
+       if (err < 0)
+               return err;
        if (tt) {
                ttable = malloc(MAX_CHANNELS * MAX_CHANNELS * sizeof(*ttable));
                err = snd_pcm_route_load_ttable(tt, ttable, MAX_CHANNELS, MAX_CHANNELS,
index 29a4a48..6d3251a 100644 (file)
@@ -542,8 +542,9 @@ int _snd_pcm_rate_open(snd_pcm_t **pcmp, const char *name,
        const char *sname = NULL;
        int err;
        snd_pcm_t *spcm;
+       snd_config_t *slave = NULL;
        snd_pcm_format_t sformat = SND_PCM_FORMAT_UNKNOWN;
-       long srate = -1;
+       int srate = -1;
        snd_config_for_each(i, next, conf) {
                snd_config_t *n = snd_config_iterator_entry(i);
                const char *id = snd_config_get_id(n);
@@ -551,49 +552,25 @@ int _snd_pcm_rate_open(snd_pcm_t **pcmp, const char *name,
                        continue;
                if (strcmp(id, "type") == 0)
                        continue;
-               if (strcmp(id, "sname") == 0) { 
-                       err = snd_config_get_string(n, &sname);
-                       if (err < 0) {
-                               SNDERR("Invalid type for %s", id);
-                               return -EINVAL;
-                       }
-                       continue;
-               }
-               if (strcmp(id, "sformat") == 0) {
-                       const char *f;
-                       err = snd_config_get_string(n, &f);
-                       if (err < 0) {
-                               SNDERR("Invalid type for %s", id);
-                               return -EINVAL;
-                       }
-                       sformat = snd_pcm_format_value(f);
-                       if (sformat == SND_PCM_FORMAT_UNKNOWN) {
-                               SNDERR("Unknown sformat");
-                               return -EINVAL;
-                       }
-                       if (snd_pcm_format_linear(sformat) != 1) {
-                               SNDERR("sformat is not linear");
-                               return -EINVAL;
-                       }
-                       continue;
-               }
-               if (strcmp(id, "srate") == 0) {
-                       err = snd_config_get_integer(n, &srate);
-                       if (err < 0) {
-                               SNDERR("Invalid type for %s", id);
-                               return -EINVAL;
-                       }
+               if (strcmp(id, "slave") == 0) {
+                       slave = n;
                        continue;
                }
                SNDERR("Unknown field %s", id);
                return -EINVAL;
        }
-       if (!sname) {
-               SNDERR("sname is not defined");
+       if (!slave) {
+               SNDERR("slave is not defined");
                return -EINVAL;
        }
-       if (srate < 0) {
-               SNDERR("srate is not defined");
+       err = snd_pcm_slave_conf(slave, &sname, 2,
+                                SND_PCM_HW_PARAM_FORMAT, 0, &sformat,
+                                SND_PCM_HW_PARAM_RATE, 1, &srate);
+       if (err < 0)
+               return err;
+       if (sformat != SND_PCM_FORMAT_UNKNOWN &&
+           snd_pcm_format_linear(sformat) != 1) {
+               SNDERR("slave format is not linear");
                return -EINVAL;
        }
        /* This is needed cause snd_config_update may destroy config */
index 6b997da..cbe9f55 100644 (file)
@@ -156,44 +156,47 @@ void snd_pcm_route_convert1_many(const snd_pcm_channel_area_t *dst_area,
 #include "plugin_ops.h"
 #undef GETU_LABELS
 #undef PUT32_LABELS
-       static void *zero_labels[3] = { &&zero_int32, &&zero_int64,
+       static void *zero_labels[3] = {
+               &&zero_int32, &&zero_int64,
 #if ROUTE_PLUGIN_FLOAT
-                                &&zero_float
+               &&zero_float
 #endif
        };
        /* sum_type att */
-       static void *add_labels[3 * 2] = { &&add_int32_noatt, &&add_int32_att,
-                                   &&add_int64_noatt, &&add_int64_att,
+       static void *add_labels[3 * 2] = {
+               &&add_int32_noatt, &&add_int32_att,
+               &&add_int64_noatt, &&add_int64_att,
 #if ROUTE_PLUGIN_FLOAT
-                                   &&add_float_noatt, &&add_float_att
+               &&add_float_noatt, &&add_float_att
 #endif
        };
        /* sum_type att shift */
-       static void *norm_labels[3 * 2 * 4] = { 0,
-                                        &&norm_int32_8_noatt,
-                                        &&norm_int32_16_noatt,
-                                        &&norm_int32_24_noatt,
-                                        0,
-                                        &&norm_int32_8_att,
-                                        &&norm_int32_16_att,
-                                        &&norm_int32_24_att,
-                                        &&norm_int64_0_noatt,
-                                        &&norm_int64_8_noatt,
-                                        &&norm_int64_16_noatt,
-                                        &&norm_int64_24_noatt,
-                                        &&norm_int64_0_att,
-                                        &&norm_int64_8_att,
-                                        &&norm_int64_16_att,
-                                        &&norm_int64_24_att,
+       static void *norm_labels[3 * 2 * 4] = {
+               0,
+               &&norm_int32_8_noatt,
+               &&norm_int32_16_noatt,
+               &&norm_int32_24_noatt,
+               0,
+               &&norm_int32_8_att,
+               &&norm_int32_16_att,
+               &&norm_int32_24_att,
+               &&norm_int64_0_noatt,
+               &&norm_int64_8_noatt,
+               &&norm_int64_16_noatt,
+               &&norm_int64_24_noatt,
+               &&norm_int64_0_att,
+               &&norm_int64_8_att,
+               &&norm_int64_16_att,
+               &&norm_int64_24_att,
 #if ROUTE_PLUGIN_FLOAT
-                                        &&norm_float_0,
-                                        &&norm_float_8,
-                                        &&norm_float_16,
-                                        &&norm_float_24,
-                                        &&norm_float_0,
-                                        &&norm_float_8,
-                                        &&norm_float_16,
-                                        &&norm_float_24,
+               &&norm_float_0,
+               &&norm_float_8,
+               &&norm_float_16,
+               &&norm_float_24,
+               &&norm_float_0,
+               &&norm_float_8,
+               &&norm_float_16,
+               &&norm_float_24,
 #endif
        };
        void *zero, *get, *add, *norm, *put32;
@@ -843,8 +846,9 @@ int _snd_pcm_route_open(snd_pcm_t **pcmp, const char *name,
        const char *sname = NULL;
        int err;
        snd_pcm_t *spcm;
+       snd_config_t *slave = NULL;
        snd_pcm_format_t sformat = SND_PCM_FORMAT_UNKNOWN;
-       long schannels = -1;
+       int schannels = -1;
        snd_config_t *tt = NULL;
        snd_pcm_route_ttable_entry_t ttable[MAX_CHANNELS*MAX_CHANNELS];
        unsigned int cused, sused;
@@ -855,38 +859,8 @@ int _snd_pcm_route_open(snd_pcm_t **pcmp, const char *name,
                        continue;
                if (strcmp(id, "type") == 0)
                        continue;
-               if (strcmp(id, "sname") == 0) {
-                       err = snd_config_get_string(n, &sname);
-                       if (err < 0) {
-                               SNDERR("Invalid type for %s", id);
-                               return -EINVAL;
-                       }
-                       continue;
-               }
-               if (strcmp(id, "sformat") == 0) {
-                       const char *f;
-                       err = snd_config_get_string(n, &f);
-                       if (err < 0) {
-                               SNDERR("Invalid type for %s", id);
-                               return -EINVAL;
-                       }
-                       sformat = snd_pcm_format_value(f);
-                       if (sformat == SND_PCM_FORMAT_UNKNOWN) {
-                               SNDERR("Unknown sformat");
-                               return -EINVAL;
-                       }
-                       if (snd_pcm_format_linear(sformat) != 1) {
-                               SNDERR("sformat is not linear");
-                               return -EINVAL;
-                       }
-                       continue;
-               }
-               if (strcmp(id, "schannels") == 0) {
-                       err = snd_config_get_integer(n, &schannels);
-                       if (err < 0) {
-                               SNDERR("Invalid type for %s", id);
-                               return -EINVAL;
-                       }
+               if (strcmp(id, "slave") == 0) {
+                       slave = n;
                        continue;
                }
                if (strcmp(id, "ttable") == 0) {
@@ -900,14 +874,24 @@ int _snd_pcm_route_open(snd_pcm_t **pcmp, const char *name,
                SNDERR("Unknown field %s", id);
                return -EINVAL;
        }
-       if (!sname) {
-               SNDERR("sname is not defined");
+       if (!slave) {
+               SNDERR("slave is not defined");
                return -EINVAL;
        }
        if (!tt) {
                SNDERR("ttable is not defined");
                return -EINVAL;
        }
+       err = snd_pcm_slave_conf(slave, &sname, 2,
+                                SND_PCM_HW_PARAM_FORMAT, 0, &sformat,
+                                SND_PCM_HW_PARAM_CHANNELS, 0, &schannels);
+       if (err < 0)
+               return err;
+       if (sformat != SND_PCM_FORMAT_UNKNOWN &&
+           snd_pcm_format_linear(sformat) != 1) {
+               SNDERR("slave format is not linear");
+               return -EINVAL;
+       }
 
        err = snd_pcm_route_load_ttable(tt, ttable, MAX_CHANNELS, MAX_CHANNELS,
                                        &cused, &sused, schannels);
index 416f7b1..242796f 100644 (file)
 #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);
index ffcf8c0..42a6b70 100644 (file)
@@ -721,7 +721,7 @@ int _snd_pcm_shm_open(snd_pcm_t **pcmp, const char *name, snd_config_t *conf,
 {
        snd_config_iterator_t i, next;
        const char *server = NULL;
-       const char *sname = NULL;
+       const char *pcm_name = NULL;
        snd_config_t *sconfig;
        const char *host = NULL;
        const char *socket = NULL;
@@ -744,8 +744,8 @@ int _snd_pcm_shm_open(snd_pcm_t **pcmp, const char *name, snd_config_t *conf,
                        }
                        continue;
                }
-               if (strcmp(id, "sname") == 0) {
-                       err = snd_config_get_string(n, &sname);
+               if (strcmp(id, "pcm") == 0) {
+                       err = snd_config_get_string(n, &pcm_name);
                        if (err < 0) {
                                SNDERR("Invalid type for %s", id);
                                return -EINVAL;
@@ -755,19 +755,23 @@ int _snd_pcm_shm_open(snd_pcm_t **pcmp, const char *name, snd_config_t *conf,
                SNDERR("Unknown field %s", id);
                return -EINVAL;
        }
-       if (!sname) {
-               SNDERR("sname is not defined");
+       if (!pcm_name) {
+               SNDERR("pcm is not defined");
                return -EINVAL;
        }
        if (!server) {
                SNDERR("server is not defined");
                return -EINVAL;
        }
-       err = snd_config_searchv(snd_config, &sconfig, "server", server, 0);
+       err = snd_config_search_alias(snd_config, "server", server, &sconfig);
        if (err < 0) {
                SNDERR("Unknown server %s", server);
                return -EINVAL;
        }
+       if (snd_config_get_type(sconfig) != SND_CONFIG_TYPE_COMPOUND) {
+               SNDERR("Invalid type for server %s definition", server);
+               return -EINVAL;
+       }
        snd_config_for_each(i, next, sconfig) {
                snd_config_t *n = snd_config_iterator_entry(i);
                const char *id = snd_config_get_id(n);
@@ -819,6 +823,6 @@ int _snd_pcm_shm_open(snd_pcm_t **pcmp, const char *name, snd_config_t *conf,
                SNDERR("%s is not the local host", host);
                return -EINVAL;
        }
-       return snd_pcm_shm_open(pcmp, name, socket, sname, stream, mode);
+       return snd_pcm_shm_open(pcmp, name, socket, pcm_name, stream, mode);
 }
                                
index de75fba..a9f6854 100644 (file)
@@ -524,6 +524,163 @@ put_1234_4321: as_s32(dst) = bswap_32(sample); goto PUT_END;
 put_1234_4329: as_u32(dst) = bswap_32(sample) ^ 0x80; goto PUT_END;
 #endif
 
+#ifdef GETS_LABELS
+static inline int32_t getS(const void *src, int src_sign, int src_wid, int src_end,
+                          int dst_wid)
+{
+       int32_t s;
+       switch (src_wid) {
+       case 8:
+               s = *(u_int8_t*)src;
+               break;
+       case 16:
+               s = *(u_int16_t*)src;
+               if (src_end)
+                       s = bswap_16(s);
+               break;
+       case 24:
+       case 32:
+               s = *(u_int32_t*)src;
+               if (src_end)
+                       s = bswap_32(s);
+               break;
+       }
+       if (!src_sign)
+               s -= 1U << (src_wid - 1);
+       if (src_wid < dst_wid)
+               return s * (1 << (dst_wid - src_wid));
+       else
+               return s / (1 << (src_wid - dst_wid)); 
+}
+
+/* src_sign src_wid src_end dst_wid */
+static void *gets_labels[2 * 4 * 2 * 4] = {
+       &&gets_u8_8,    /*  u8h -> s8 */
+       &&gets_u8_16,   /*  u8h -> s16 */
+       &&gets_u8_24,   /*  u8h -> s24 */
+       &&gets_u8_32,   /*  u8h -> s32 */
+       &&gets_u8_8,    /*  u8s -> s8 */
+       &&gets_u8_16,   /*  u8s -> s16 */
+       &&gets_u8_24,   /*  u8s -> s24 */
+       &&gets_u8_32,   /*  u8s -> s32 */
+       &&gets_u16h_8,  /* u16h -> s8 */
+       &&gets_u16h_16, /* u16h -> s16 */
+       &&gets_u16h_24, /* u16h -> s24 */
+       &&gets_u16h_32, /* u16h -> s32 */
+       &&gets_u16s_8,  /* u16s -> s8 */
+       &&gets_u16s_16, /* u16s -> s16 */
+       &&gets_u16s_24, /* u16s -> s24 */
+       &&gets_u16s_32, /* u16s -> s32 */
+       &&gets_u24h_8,  /* u24h -> s8 */
+       &&gets_u24h_16, /* u24h -> s16 */
+       &&gets_u24h_24, /* u24h -> s24 */
+       &&gets_u24h_32, /* u24h -> s32 */
+       &&gets_u24s_8,  /* u24s -> s8 */
+       &&gets_u24s_16, /* u24s -> s16 */
+       &&gets_u24s_24, /* u24s -> s24 */
+       &&gets_u24s_32, /* u24s -> s32 */
+       &&gets_u32h_8,  /* u32h -> s8 */
+       &&gets_u32h_16, /* u32h -> s16 */
+       &&gets_u32h_24, /* u32h -> s24 */
+       &&gets_u32h_32, /* u32h -> s32 */
+       &&gets_u32s_8,  /* u32s -> s8 */
+       &&gets_u32s_16, /* u32s -> s16 */
+       &&gets_u32s_24, /* u32s -> s24 */
+       &&gets_u32s_32, /* u32s -> s32 */
+       &&gets_s8_8,    /*  s8h -> s8 */
+       &&gets_s8_16,   /*  s8h -> s16 */
+       &&gets_s8_24,   /*  s8h -> s24 */
+       &&gets_s8_32,   /*  s8h -> s32 */
+       &&gets_s8_8,    /*  s8s -> s8 */
+       &&gets_s8_16,   /*  s8s -> s16 */
+       &&gets_s8_24,   /*  s8s -> s24 */
+       &&gets_s8_32,   /*  s8s -> s32 */
+       &&gets_s16h_8,  /* s16h -> s8 */
+       &&gets_s16h_16, /* s16h -> s16 */
+       &&gets_s16h_24, /* s16h -> s24 */
+       &&gets_s16h_32, /* s16h -> s32 */
+       &&gets_s16s_8,  /* s16s -> s8 */
+       &&gets_s16s_16, /* s16s -> s16 */
+       &&gets_s16s_24, /* s16s -> s24 */
+       &&gets_s16s_32, /* s16s -> s32 */
+       &&gets_s24h_8,  /* s24h -> s8 */
+       &&gets_s24h_16, /* s24h -> s16 */
+       &&gets_s24h_24, /* s24h -> s24 */
+       &&gets_s24h_32, /* s24h -> s32 */
+       &&gets_s24s_8,  /* s24s -> s8 */
+       &&gets_s24s_16, /* s24s -> s16 */
+       &&gets_s24s_24, /* s24s -> s24 */
+       &&gets_s24s_32, /* s24s -> s32 */
+       &&gets_s32h_8,  /* s32h -> s8 */
+       &&gets_s32h_16, /* s32h -> s16 */
+       &&gets_s32h_24, /* s32h -> s24 */
+       &&gets_s32h_32, /* s32h -> s32 */
+       &&gets_s32s_8,  /* s32s -> s8 */
+       &&gets_s32s_16, /* s32s -> s16 */
+       &&gets_s32s_24, /* s32s -> s24 */
+       &&gets_s32s_32, /* s32s -> s32 */
+};
+#endif
+
+#ifdef GETS_END
+gets_u8_8:    sample = getS(src, 0,  8, 0,  8); goto GETS_END;
+gets_u8_16:   sample = getS(src, 0,  8, 0, 16); goto GETS_END;
+gets_u8_24:   sample = getS(src, 0,  8, 0, 24); goto GETS_END;
+gets_u8_32:   sample = getS(src, 0,  8, 0, 32); goto GETS_END;
+gets_u16h_8:  sample = getS(src, 0, 16, 0,  8); goto GETS_END;
+gets_u16h_16: sample = getS(src, 0, 16, 0, 16); goto GETS_END;
+gets_u16h_24: sample = getS(src, 0, 16, 0, 24); goto GETS_END;
+gets_u16h_32: sample = getS(src, 0, 16, 0, 32); goto GETS_END;
+gets_u16s_8:  sample = getS(src, 0, 16, 1,  8); goto GETS_END;
+gets_u16s_16: sample = getS(src, 0, 16, 1, 16); goto GETS_END;
+gets_u16s_24: sample = getS(src, 0, 16, 1, 24); goto GETS_END;
+gets_u16s_32: sample = getS(src, 0, 16, 1, 32); goto GETS_END;
+gets_u24h_8:  sample = getS(src, 0, 24, 0,  8); goto GETS_END;
+gets_u24h_16: sample = getS(src, 0, 24, 0, 16); goto GETS_END;
+gets_u24h_24: sample = getS(src, 0, 24, 0, 24); goto GETS_END;
+gets_u24h_32: sample = getS(src, 0, 24, 0, 32); goto GETS_END;
+gets_u24s_8:  sample = getS(src, 0, 24, 1,  8); goto GETS_END;
+gets_u24s_16: sample = getS(src, 0, 24, 1, 16); goto GETS_END;
+gets_u24s_24: sample = getS(src, 0, 24, 1, 24); goto GETS_END;
+gets_u24s_32: sample = getS(src, 0, 24, 1, 32); goto GETS_END;
+gets_u32h_8:  sample = getS(src, 0, 32, 0,  8); goto GETS_END;
+gets_u32h_16: sample = getS(src, 0, 32, 0, 16); goto GETS_END;
+gets_u32h_24: sample = getS(src, 0, 32, 0, 24); goto GETS_END;
+gets_u32h_32: sample = getS(src, 0, 32, 0, 32); goto GETS_END;
+gets_u32s_8:  sample = getS(src, 0, 32, 1,  8); goto GETS_END;
+gets_u32s_16: sample = getS(src, 0, 32, 1, 16); goto GETS_END;
+gets_u32s_24: sample = getS(src, 0, 32, 1, 24); goto GETS_END;
+gets_u32s_32: sample = getS(src, 0, 32, 1, 32); goto GETS_END;
+gets_s8_8:    sample = getS(src, 1,  8, 0,  8); goto GETS_END;
+gets_s8_16:   sample = getS(src, 1,  8, 0, 16); goto GETS_END;
+gets_s8_24:   sample = getS(src, 1,  8, 0, 24); goto GETS_END;
+gets_s8_32:   sample = getS(src, 1,  8, 0, 32); goto GETS_END;
+gets_s16h_8:  sample = getS(src, 1, 16, 0,  8); goto GETS_END;
+gets_s16h_16: sample = getS(src, 1, 16, 0, 16); goto GETS_END;
+gets_s16h_24: sample = getS(src, 1, 16, 0, 24); goto GETS_END;
+gets_s16h_32: sample = getS(src, 1, 16, 0, 32); goto GETS_END;
+gets_s16s_8:  sample = getS(src, 1, 16, 1,  8); goto GETS_END;
+gets_s16s_16: sample = getS(src, 1, 16, 1, 16); goto GETS_END;
+gets_s16s_24: sample = getS(src, 1, 16, 1, 24); goto GETS_END;
+gets_s16s_32: sample = getS(src, 1, 16, 1, 32); goto GETS_END;
+gets_s24h_8:  sample = getS(src, 1, 24, 0,  8); goto GETS_END;
+gets_s24h_16: sample = getS(src, 1, 24, 0, 16); goto GETS_END;
+gets_s24h_24: sample = getS(src, 1, 24, 0, 24); goto GETS_END;
+gets_s24h_32: sample = getS(src, 1, 24, 0, 32); goto GETS_END;
+gets_s24s_8:  sample = getS(src, 1, 24, 1,  8); goto GETS_END;
+gets_s24s_16: sample = getS(src, 1, 24, 1, 16); goto GETS_END;
+gets_s24s_24: sample = getS(src, 1, 24, 1, 24); goto GETS_END;
+gets_s24s_32: sample = getS(src, 1, 24, 1, 32); goto GETS_END;
+gets_s32h_8:  sample = getS(src, 1, 32, 0,  8); goto GETS_END;
+gets_s32h_16: sample = getS(src, 1, 32, 0, 16); goto GETS_END;
+gets_s32h_24: sample = getS(src, 1, 32, 0, 24); goto GETS_END;
+gets_s32h_32: sample = getS(src, 1, 32, 0, 32); goto GETS_END;
+gets_s32s_8:  sample = getS(src, 1, 32, 1,  8); goto GETS_END;
+gets_s32s_16: sample = getS(src, 1, 32, 1, 16); goto GETS_END;
+gets_s32s_24: sample = getS(src, 1, 32, 1, 24); goto GETS_END;
+gets_s32s_32: sample = getS(src, 1, 32, 1, 32); goto GETS_END;
+#endif
+
 #undef as_u8
 #undef as_u16
 #undef as_u32
index 8223755..698fdc5 100644 (file)
@@ -178,20 +178,22 @@ int snd_rawmidi_open(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp,
        int (*open_func)(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp,
                         const char *name, snd_config_t *conf, int mode);
        void *h;
+       const char *name1;
        assert((inputp || outputp) && name);
        err = snd_config_update();
        if (err < 0)
                return err;
-       err = snd_config_searchv(snd_config, &rawmidi_conf, "rawmidi", name, 0);
-       if (err < 0) {
+       err = snd_config_search_alias(snd_config, "rawmidi", name, &rawmidi_conf);
+       name1 = name;
+       if (err < 0 || snd_config_get_string(rawmidi_conf, &name1) >= 0) {
                int card, dev, subdev;
-               err = sscanf(name, "hw:%d,%d,%d", &card, &dev, &subdev);
+               err = sscanf(name1, "hw:%d,%d,%d", &card, &dev, &subdev);
                if (err == 3)
                        return snd_rawmidi_hw_open(inputp, outputp, name, card, dev, subdev, mode);
-               err = sscanf(name, "hw:%d,%d", &card, &dev);
+               err = sscanf(name1, "hw:%d,%d", &card, &dev);
                if (err == 2)
                        return snd_rawmidi_hw_open(inputp, outputp, name, card, dev, -1, mode);
-               SNDERR("Unknown RAWMIDI %s", name);
+               SNDERR("Unknown RAWMIDI %s", name1);
                return -ENOENT;
        }
        if (snd_config_get_type(rawmidi_conf) != SND_CONFIG_TYPE_COMPOUND) {
@@ -208,7 +210,7 @@ int snd_rawmidi_open(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp,
                SNDERR("Invalid type for %s", snd_config_get_id(conf));
                return err;
        }
-       err = snd_config_searchv(snd_config, &type_conf, "rawmiditype", str, 0);
+       err = snd_config_search_alias(snd_config, "rawmidi_type", str, &type_conf);
        if (err >= 0) {
                snd_config_for_each(i, next, type_conf) {
                        snd_config_t *n = snd_config_iterator_entry(i);
index f281b4a..0a0c8ab 100644 (file)
@@ -48,15 +48,17 @@ int snd_seq_open(snd_seq_t **seqp, const char *name,
        int (*open_func)(snd_seq_t **seqp, const char *name, snd_config_t *conf, 
                         int streams, int mode);
        void *h;
+       const char *name1;
        assert(seqp && name);
        err = snd_config_update();
        if (err < 0)
                return err;
-       err = snd_config_searchv(snd_config, &seq_conf, "seq", name, 0);
-       if (err < 0) {
-               if (strcmp(name, "hw") == 0)
+       err = snd_config_search_alias(snd_config, "seq", name, &seq_conf);
+       name1 = name;
+       if (err < 0 || snd_config_get_string(seq_conf, &name1) >= 0) {
+               if (strcmp(name1, "hw") == 0)
                        return snd_seq_hw_open(seqp, name, streams, mode);
-               SNDERR("Unknown SEQ %s", name);
+               SNDERR("Unknown SEQ %s", name1);
                return -ENOENT;
        }
        if (snd_config_get_type(seq_conf) != SND_CONFIG_TYPE_COMPOUND) {
@@ -73,7 +75,7 @@ int snd_seq_open(snd_seq_t **seqp, const char *name,
                SNDERR("Invalid type for %s", snd_config_get_id(conf));
                return err;
        }
-       err = snd_config_searchv(snd_config, &type_conf, "seqtype", str, 0);
+       err = snd_config_search_alias(snd_config, "seq_type", str, &type_conf);
        if (err >= 0) {
                snd_config_for_each(i, next, type_conf) {
                        snd_config_t *n = snd_config_iterator_entry(i);