]> git.alsa-project.org Git - alsa-lib.git/commitdiff
Completed parametric configuration and begun to use it
authorAbramo Bagnara <abramo@alsa-project.org>
Tue, 22 May 2001 09:19:43 +0000 (09:19 +0000)
committerAbramo Bagnara <abramo@alsa-project.org>
Tue, 22 May 2001 09:19:43 +0000 (09:19 +0000)
12 files changed:
include/error.h
include/local.h
src/Makefile.am
src/alsa.conf [new file with mode: 0644]
src/conf.c
src/control/cards_id.c
src/control/control.c
src/control/control_shm.c
src/pcm/pcm.c
src/pcm/pcm_surr.c
src/rawmidi/rawmidi.c
src/seq/seq.c

index 08c7c836a81bde7e18a5275e06c5d7baf561c106..6e6f0446522804a03f7bfd3f66d6adfb725a7323 100644 (file)
@@ -22,7 +22,7 @@ const char *snd_strerror(int errnum);
  * \param fmt printf(3) format
  * \param ... printf(3) arguments
  */
-typedef void (snd_lib_error_handler_t)(const char *file, int line, const char *function, int err, const char *fmt, ...) /* __attribute__ ((weak, format (printf, 5, 6))) */;
+typedef void (snd_lib_error_handler_t)(const char *file, int line, const char *function, int err, const char *fmt, ...) /* __attribute__ ((format (printf, 5, 6))) */;
 extern snd_lib_error_handler_t *snd_lib_error;
 extern int snd_lib_error_set_handler(snd_lib_error_handler_t *handler);
 
index 903c36a4a9f6cfda5e2e65605c1a668b6a4a9d95..3bf29f93bd1647c94b6001663f683f752c219714 100644 (file)
 #ifndef __LOCAL_H
 #define __LOCAL_H
 
+#ifndef DATADIR
+#define DATADIR "/usr/share"
+#endif
+
 #define _snd_config_iterator list_head
 #define _snd_interval sndrv_interval
 #define _snd_pcm_info sndrv_pcm_info
index 7dc09e3799fd99d6529f3cb029a2db7d9b464f32..37076abcd5ca9fe80b2398adcf0b1523d0d138de 100644 (file)
@@ -10,6 +10,11 @@ libasound_la_LIBADD = control/libcontrol.la mixer/libmixer.la pcm/libpcm.la \
 
 libasound_la_LDFLAGS = -version-info $(COMPATNUM)
 
+EXTRA_DIST = alsa.conf
+
+alsadir = $(datadir)/alsa
+alsa_DATA = alsa.conf
+
 control/libcontrol.la:
        $(MAKE) -C control libcontrol.la
 
diff --git a/src/alsa.conf b/src/alsa.conf
new file mode 100644 (file)
index 0000000..b6b6474
--- /dev/null
@@ -0,0 +1,199 @@
+
+pcm.default {
+       type plug
+       slave.pcm {
+               type hw
+               card 0
+               device 0
+       }
+}
+
+pcm.hw {
+       $.0 CARD
+       $.1 DEV
+       $.2 SUBDEV
+       $.CARD {
+               type integer
+       }
+       $.DEV {
+               type integer
+       }
+       $.SUBDEV {
+               type integer
+               default -1
+       }               
+       type hw
+       card $CARD
+       device $DEV
+       subdevice $SUBDEV
+}
+
+pcm.plughw {
+       $.0 CARD
+       $.1 DEV
+       $.2 SUBDEV
+       $.CARD {
+               type integer
+       }
+       $.DEV {
+               type integer
+       }
+       $.SUBDEV {
+               type integer
+               default -1
+       }               
+       type plug
+       slave.pcm {
+               type hw
+               card $CARD
+               device $DEV
+               subdevice $SUBDEV
+       }
+}
+
+pcm.plug {
+       $.0 SLAVE
+       $.SLAVE {
+               type string
+       }
+       type plug
+       slave.pcm $SLAVE
+}
+
+pcm.shm {
+       $.0 SOCKET
+       $.1 PCM
+       $.SOCKET {
+               type string
+       }
+       $.PCM {
+               type string
+       }
+       type shm
+       server $SOCKET
+       pcm $PCM
+}
+
+pcm.tee {
+       $.0 SLAVE
+       $.1 FILE
+       $.2 FORMAT
+       $.SLAVE {
+               type string
+       }
+       $.FILE {
+               type string
+       }
+       $.FORMAT {
+               type string
+               default raw
+       }
+       type file
+       slave.pcm $SLAVE
+       file $FILE
+       format $FORMAT
+}
+
+pcm.file {
+       $.0 FILE
+       $.1 FORMAT
+       $.FILE {
+               type string
+       }
+       $.FORMAT {
+               type string
+               default raw
+       }
+       type file
+       slave.pcm null
+       file $FILE
+       format $FORMAT
+}
+
+pcm.surround40 {
+       $.0 CARD
+       $.1 DEV
+       $.CARD {
+               type integer
+       }
+       $.DEV {
+               type integer
+               default 0
+       }
+       type surround
+       card $CARD
+       device $DEVICE
+       stype 4.0
+}
+       
+pcm.surround51 {
+       $.0 CARD
+       $.1 DEV
+       $.CARD {
+               type integer
+       }
+       $.DEV {
+               type integer
+               default 0
+       }
+       type surround
+       card $CARD
+       device $DEVICE
+       stype 5.1
+}
+       
+pcm.null {
+       type null
+}
+       
+ctl.default {
+       type hw
+       card 0
+}
+
+ctl.hw {
+       $.0 CARD
+       $.CARD {
+               type integer
+       }
+       type hw
+       card $CARD
+}
+
+ctl.shm {
+       $.0 SOCKET
+       $.1 PCM
+       $.SOCKET {
+               type string
+       }
+       $.PCM {
+               type string
+       }
+       type shm
+       server $SOCKET
+       ctl $PCM
+}
+
+rawmidi.hw {
+       $.0 CARD
+       $.1 DEV
+       $.2 SUBDEV
+       $.CARD {
+               type integer
+       }
+       $.DEV {
+               type integer
+       }
+       $.SUBDEV {
+               type integer
+               default -1
+       }               
+       type hw
+       card $CARD
+       device $DEV
+       subdevice $SUBDEV
+}
+
+seq.hw {
+       type hw
+}
index 2be0e7452e50f7cf7e0951aaffe19327d4df3c94..8fc889b00dbfc6464c524055399c2f0d4ea1b892 100644 (file)
@@ -20,6 +20,7 @@
  */
 
 #include <stdarg.h>
+#include <wordexp.h>
 #include <sys/stat.h>
 #include "local.h"
 #include "list.h"
@@ -1194,17 +1195,29 @@ int snd_config_search_alias(snd_config_t *config,
        return 0;
 }
 
-/** File used for system wide ALSA configuration */
-#define SYS_ASOUNDRC "/etc/asound.conf"
-/** File resident in home directory used for user specific ALSA configuration */
-#define USR_ASOUNDRC ".asoundrc"
+/** Environment variable containing files list for #snd_config_update */
+#define ASOUND_CONFIGS_VAR "ASOUND_CONFIGS"
+
+/** Default files used by #snd_config_update */
+#define ASOUND_CONFIGS_DEFAULT DATADIR "/alsa/alsa.conf:/etc/asound.conf:~/.asoundrc"
 
 /** \ingroup Config
   * Config top node */
 snd_config_t *snd_config = NULL;
 
+static struct finfo {
+       char *name;
+       dev_t dev;
+       ino_t ino;
+       time_t mtime;
+} *files_info = NULL;
+
+static unsigned int files_info_count = 0;
+
 /** 
- * \brief Update #snd_config rereading if needed #SYS_ASOUNDRC and #USR_ASOUNDRC
+ * \brief Update #snd_config rereading (if needed) files specified in
+ * environment variable ASOUND_CONFIGS. If it's not set the default value is
+ * "/usr/share/alsa/alsa.conf:/etc/asound.conf:~/.asoundrc"
  * \return 0 if no action is needed, 1 if tree has been rebuilt otherwise a negative error code
  *
  * Warning: If config tree is reread all the string pointer and config 
@@ -1212,80 +1225,120 @@ snd_config_t *snd_config = NULL;
  */
 int snd_config_update()
 {
-       static dev_t sys_asoundrc_device;
-       static ino_t sys_asoundrc_inode;
-       static time_t sys_asoundrc_mtime;
-       static dev_t usr_asoundrc_device;
-       static ino_t usr_asoundrc_inode;
-       static time_t usr_asoundrc_mtime;
        int err;
-       char *usr_asoundrc = NULL;
-       char *home = getenv("HOME");
-       struct stat usr_st, sys_st;
-       int reload;
-       snd_input_t *in;
-       if (home) {
-               size_t len = strlen(home);
-               size_t len1 = strlen(USR_ASOUNDRC);
-               usr_asoundrc = alloca(len + len1 + 2);
-               memcpy(usr_asoundrc, home, len);
-               usr_asoundrc[len] = '/';
-               memcpy(usr_asoundrc + len + 1, USR_ASOUNDRC, len1);
-               usr_asoundrc[len + 1 + len1] = '\0';
+       char *configs, *c;
+       unsigned int k;
+       wordexp_t we;
+       size_t l;
+       struct finfo *fi;
+       unsigned int fi_count;
+       configs = getenv(ASOUND_CONFIGS_VAR);
+       if (!configs)
+               configs = ASOUND_CONFIGS_DEFAULT;
+       for (k = 0, c = configs; (l = strcspn(c, ": ")) > 0; ) {
+               c += l;
+               k++;
+               if (!*c)
+                       break;
+               c++;
+       }
+       fi_count = k;
+       fi = calloc(fi_count, sizeof(*fi));
+       if (!fi)
+               return -ENOMEM;
+       for (k = 0, c = configs; (l = strcspn(c, ": ")) > 0; ) {
+               char name[l + 1];
+               memcpy(name, c, l);
+               name[l] = 0;
+               err = wordexp(name, &we, WRDE_NOCMD);
+               switch (err) {
+               case WRDE_NOSPACE:
+                       err = -ENOMEM;
+                       goto _end;
+               case 0:
+                       if (we.we_wordc == 1)
+                               break;
+                       /* Fall through */
+               default:
+                       err = -EINVAL;
+                       goto _end;
+               }
+               fi[k].name = strdup(we.we_wordv[0]);
+               wordfree(&we);
+               if (!fi[k].name) {
+                       err = -ENOMEM;
+                       goto _end;
+               }
+               c += l;
+               k++;
+               if (!*c)
+                       break;
+               c++;
+       }
+       for (k = 0; k < fi_count; ++k) {
+               struct stat st;
+               if (stat(fi[k].name, &st) >= 0) {
+                       fi[k].dev = st.st_dev;
+                       fi[k].ino = st.st_ino;
+                       fi[k].mtime = st.st_mtime;
+               }
+       }
+       if (!files_info)
+               goto _reread;
+       if (fi_count != files_info_count)
+               goto _reread;
+       for (k = 0; k < fi_count; ++k) {
+               if (strcmp(fi[k].name, files_info[k].name) != 0 ||
+                   fi[k].dev != files_info[k].dev ||
+                   fi[k].ino != files_info[k].ino ||
+                   fi[k].mtime != files_info[k].mtime)
+                       goto _reread;
+       }
+       err = 0;
+
+ _end:
+       if (err < 0 && snd_config) {
+               snd_config_delete(snd_config);
+               snd_config = NULL;
+       }
+       for (k = 0; k < fi_count; ++k)
+               free(fi[k].name);
+       free(fi);
+       return err;
+
+ _reread:
+       if (files_info) {
+               for (k = 0; k < files_info_count; ++k)
+                       free(files_info[k].name);
+               free(files_info);
+               files_info = NULL;
+               files_info_count = 0;
        }
-       reload = (snd_config == NULL);
-       if (stat(SYS_ASOUNDRC, &sys_st) == 0 &&
-           (sys_st.st_dev != sys_asoundrc_device ||
-            sys_st.st_ino != sys_asoundrc_inode ||
-            sys_st.st_mtime != sys_asoundrc_mtime))
-               reload = 1;
-       if (stat(usr_asoundrc, &usr_st) == 0 &&
-           (usr_st.st_dev != usr_asoundrc_device ||
-            usr_st.st_ino != usr_asoundrc_inode ||
-            usr_st.st_mtime != usr_asoundrc_mtime))
-               reload = 1;
-       if (!reload)
-               return 0;
        if (snd_config) {
-               err = snd_config_delete(snd_config);
-               if (err < 0)
-                       return err;
-               snd_config = 0;
+               snd_config_delete(snd_config);
+               snd_config = NULL;
        }
        err = snd_config_top(&snd_config);
        if (err < 0)
-               return err;
-       err = snd_input_stdio_open(&in, SYS_ASOUNDRC, "r");
-       if (err >= 0) {
-               err = snd_config_load(snd_config, in);
-               snd_input_close(in);
-               if (err < 0) {
-                       SNDERR(SYS_ASOUNDRC " may be old or corrupted: consider to remove or fix it");
-                       snd_config_delete(snd_config);
-                       snd_config = NULL;
-                       return err;
-               }
-               sys_asoundrc_device = sys_st.st_dev;
-               sys_asoundrc_inode = sys_st.st_ino;
-               sys_asoundrc_mtime = sys_st.st_mtime;
-       }
-       err = snd_input_stdio_open(&in, usr_asoundrc, "r");
-       if (err >= 0) {
-               err = snd_config_load(snd_config, in);
-               snd_input_close(in);
-               if (err < 0) {
-                       SNDERR("%s may be old or corrupted: consider to remove or fix it", usr_asoundrc);
-                       snd_config_delete(snd_config);
-                       snd_config = NULL;
-                       return err;
+               goto _end;
+       for (k = 0; k < fi_count; ++k) {
+               snd_input_t *in;
+               err = snd_input_stdio_open(&in, fi[k].name, "r");
+               if (err >= 0) {
+                       err = snd_config_load(snd_config, in);
+                       snd_input_close(in);
+                       if (err < 0) {
+                               SNDERR("%s may be old or corrupted: consider to remove or fix it", fi[k].name);
+                               goto _end;
+                       }
                }
-               usr_asoundrc_device = usr_st.st_dev;
-               usr_asoundrc_inode = usr_st.st_ino;
-               usr_asoundrc_mtime = usr_st.st_mtime;
        }
+       files_info = fi;
+       files_info_count = fi_count;
        return 1;
 }
 
+
 /**
  * \brief Return an iterator pointing to first leaf of a compound config node
  * \param node Config node handle
@@ -1770,12 +1823,56 @@ static int parse_arg(const char **ptr, unsigned int *varlen, char **val)
 }
 
 
+/* val1, val2, ...
+ * var1=val1,var2=val2,...
+ * { conf syntax }
+ */
 static int parse_args(snd_config_t *subs, const char *str, snd_config_t *defs)
 {
        int err;
        int arg = 0;
+       skip_blank(&str);
        if (!*str)
                return 0;
+       if (*str == '{') {
+               int len = strlen(str);
+               snd_input_t *input;
+               snd_config_iterator_t i, next;
+               while (1) {
+                       switch (str[--len]) {
+                       case ' ':
+                       case '\f':
+                       case '\t':
+                       case '\n':
+                       case '\r':
+                               continue;
+                       default:
+                               break;
+                       }
+                       break;
+               }
+               if (str[len] != '}')
+                       return -EINVAL;
+               err = snd_input_buffer_open(&input, str + 1, len - 1);
+               if (err < 0)
+                       return err;
+               err = snd_config_load(subs, input);
+               snd_input_close(input);
+               if (err < 0)
+                       return err;
+               snd_config_for_each(i, next, subs) {
+                       snd_config_t *n = snd_config_iterator_entry(i);
+                       snd_config_t *d;
+                       const char *id = snd_config_get_id(n);
+                       err = snd_config_search(defs, id, &d);
+                       if (err < 0) {
+                               SNDERR("Unknown parameter %s", id);
+                               return err;
+                       }
+               }
+               return 0;
+       }
+       
        while (1) {
                char buf[256];
                const char *var = buf;
@@ -1812,7 +1909,6 @@ static int parse_args(snd_config_t *subs, const char *str, snd_config_t *defs)
                if (err < 0) {
                _invalid_type:
                        SNDERR("Parameter %s definition is missing a valid type info", var);
-                       err = -EINVAL;
                        goto _err;
                }
                err = snd_config_get_string(typ, &tmp);
@@ -1851,8 +1947,10 @@ static int parse_args(snd_config_t *subs, const char *str, snd_config_t *defs)
                        err = snd_config_set_string(sub, val);
                        if (err < 0)
                                goto _err;
-               } else
+               } else {
+                       err = -EINVAL;
                        goto _invalid_type;
+               }
                err = snd_config_set_id(sub, var);
                if (err < 0)
                        goto _err;
@@ -1906,3 +2004,21 @@ int snd_config_expand(snd_config_t *config, const char *args,
        return err;
 }
        
+
+#if 0
+/* Not strictly needed, but useful to check for memory leaks */
+void _snd_config_end(void) __attribute__ ((destructor));
+
+static void _snd_config_end(void)
+{
+       int k;
+       if (snd_config)
+               snd_config_delete(snd_config);
+       snd_config = 0;
+       for (k = 0; k < files_info_count; ++k)
+               free(files_info[k].name);
+       free(files_info);
+       files_info = NULL;
+       files_info_count = 0;
+}
+#endif
index 6703cf8905aa7016d843e8300121e61d2e5a85ee..514e76e69419126e946d81c693531ebdd0a3e727 100644 (file)
@@ -28,9 +28,6 @@
 #include <sys/ioctl.h>
 #include "control_local.h"
 
-#ifndef DATADIR
-#define DATADIR "/usr/share"
-#endif
 #define ALSA_CARDS_FILE DATADIR "/alsa/cards.conf"
 
 static int build_config(snd_config_t **r_conf)
index 94d1c1a8384436c50b407bd63104824e9f756079..937ae28aaf002ddcea47ba7bf773bb4fbcf3c7a3 100644 (file)
@@ -380,57 +380,38 @@ int snd_ctl_wait(snd_ctl_t *ctl, int timeout)
        return 0;
 }
 
-/**
- * \brief Opens a CTL
- * \param ctlp Returned CTL handle
- * \param name ASCII identifier of the CTL handle
- * \param mode Open mode (see #SND_CTL_NONBLOCK, #SND_CTL_ASYNC)
- * \return 0 on success otherwise a negative error code
- */
-int snd_ctl_open(snd_ctl_t **ctlp, const char *name, int mode)
+int snd_ctl_open_conf(snd_ctl_t **ctlp, const char *name,
+                     snd_config_t *ctl_conf, int mode)
 {
        const char *str;
        char buf[256];
        int err;
-       snd_config_t *ctl_conf, *conf, *type_conf;
+       snd_config_t *conf, *type_conf = NULL;
        snd_config_iterator_t i, next;
        const char *lib = NULL, *open_name = NULL;
        int (*open_func)(snd_ctl_t **, const char *, snd_config_t *, int);
        void *h;
-       const char *name1;
-       assert(ctlp && name);
-       err = snd_config_update();
-       if (err < 0)
-               return err;
-
-       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(name1, "hw:%d", &card);
-               if (err == 1)
-                       return snd_ctl_hw_open(ctlp, name, card, mode);
-               err = sscanf(name1, "shm:%256[^,],%256[^,]", socket, sname);
-               if (err == 2)
-                       return snd_ctl_shm_open(ctlp, name, socket, sname, mode);
-               SNDERR("Unknown ctl %s", name1);
-               return -ENOENT;
-       }
        if (snd_config_get_type(ctl_conf) != SND_CONFIG_TYPE_COMPOUND) {
-               SNDERR("Invalid type for %s", snd_config_get_id(ctl_conf));
+               if (name)
+                       SNDERR("Invalid type for CTL %s definition", name);
+               else
+                       SNDERR("Invalid type for CTL definition");
                return -EINVAL;
        }
        err = snd_config_search(ctl_conf, "type", &conf);
-       if (err < 0)
+       if (err < 0) {
+               SNDERR("type is not defined");
                return err;
+       }
        err = snd_config_get_string(conf, &str);
-       if (err < 0)
+       if (err < 0) {
+               SNDERR("Invalid type for %s", snd_config_get_id(conf));
                return err;
+       }
        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);
+                       SNDERR("Invalid type for CTL type %s definition", str);
                        return -EINVAL;
                }
                snd_config_for_each(i, next, type_conf) {
@@ -440,14 +421,18 @@ int snd_ctl_open(snd_ctl_t **ctlp, const char *name, int mode)
                                continue;
                        if (strcmp(id, "lib") == 0) {
                                err = snd_config_get_string(n, &lib);
-                               if (err < 0)
+                               if (err < 0) {
+                                       SNDERR("Invalid type for %s", id);
                                        return -EINVAL;
+                               }
                                continue;
                        }
                        if (strcmp(id, "open") == 0) {
                                err = snd_config_get_string(n, &open_name);
-                               if (err < 0)
+                               if (err < 0) {
+                                       SNDERR("Invalid type for %s", id);
                                        return -EINVAL;
+                               }
                                continue;
                        }
                        SNDERR("Unknown field %s", id);
@@ -474,6 +459,52 @@ int snd_ctl_open(snd_ctl_t **ctlp, const char *name, int mode)
        return open_func(ctlp, name, ctl_conf, mode);
 }
 
+int snd_ctl_open_noupdate(snd_ctl_t **ctlp, const char *name, int mode)
+{
+       int err;
+       snd_config_t *ctl_conf;
+       const char *args = strchr(name, ':');
+       char *base;
+       if (args) {
+               args++;
+               base = alloca(args - name);
+               memcpy(base, name, args - name - 1);
+               base[args - name - 1] = 0;
+       } else
+               base = (char *) name;
+       err = snd_config_search_alias(snd_config, "ctl", base, &ctl_conf);
+       if (err < 0) {
+               SNDERR("Unknown CTL %s", name);
+               return err;
+       }
+       if (args) {
+               err = snd_config_expand(ctl_conf, args, &ctl_conf);
+               if (err < 0)
+                       return err;
+       }
+       err = snd_ctl_open_conf(ctlp, name, ctl_conf, mode);
+       if (args)
+               snd_config_delete(ctl_conf);
+       return err;
+}
+
+/**
+ * \brief Opens a CTL
+ * \param ctlp Returned CTL handle
+ * \param name ASCII identifier of the CTL handle
+ * \param mode Open mode (see #SND_CTL_NONBLOCK, #SND_CTL_ASYNC)
+ * \return 0 on success otherwise a negative error code
+ */
+int snd_ctl_open(snd_ctl_t **ctlp, const char *name, int mode)
+{
+       int err;
+       assert(ctlp && name);
+       err = snd_config_update();
+       if (err < 0)
+               return err;
+       return snd_ctl_open_noupdate(ctlp, name, mode);
+}
+
 /**
  * \brief Set CTL element #SND_CTL_ELEM_TYPE_BYTES value
  * \param ctl CTL handle
index e2527f02916f4756c43b53bae9cd3bcd392aa37f..6554d08a63aece35a7dfc8c0903b9db9d97132dc 100644 (file)
@@ -528,7 +528,7 @@ int _snd_ctl_shm_open(snd_ctl_t **handlep, char *name, snd_config_t *conf, int m
 {
        snd_config_iterator_t i, next;
        const char *server = NULL;
-       const char *sname = NULL;
+       const char *ctl_name = NULL;
        snd_config_t *sconfig;
        const char *host = NULL;
        const char *sockname = NULL;
@@ -551,8 +551,8 @@ int _snd_ctl_shm_open(snd_ctl_t **handlep, char *name, snd_config_t *conf, int m
                        }
                        continue;
                }
-               if (strcmp(id, "sname") == 0) {
-                       err = snd_config_get_string(n, &sname);
+               if (strcmp(id, "ctl") == 0) {
+                       err = snd_config_get_string(n, &ctl_name);
                        if (err < 0) {
                                SNDERR("Invalid type for %s", id);
                                return -EINVAL;
@@ -562,8 +562,8 @@ int _snd_ctl_shm_open(snd_ctl_t **handlep, char *name, snd_config_t *conf, int m
                SNDERR("Unknown field %s", id);
                return -EINVAL;
        }
-       if (!sname) {
-               SNDERR("sname is not defined");
+       if (!ctl_name) {
+               SNDERR("ctl is not defined");
                return -EINVAL;
        }
        if (!server) {
@@ -630,6 +630,6 @@ int _snd_ctl_shm_open(snd_ctl_t **handlep, char *name, snd_config_t *conf, int m
                SNDERR("%s is not the local host", host);
                return -EINVAL;
        }
-       return snd_ctl_shm_open(handlep, name, sockname, sname, mode);
+       return snd_ctl_shm_open(handlep, name, sockname, ctl_name, mode);
 }
                                
index 9890235a99a7292ceb14c855e071105c06a3fe12..6095bd65c6a3548064558971037754912ed2d30e 100644 (file)
@@ -995,91 +995,30 @@ static int snd_pcm_open_noupdate(snd_pcm_t **pcmp, const char *name,
 {
        int err;
        snd_config_t *pcm_conf;
-       const char *name1;
-
-       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(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(name1, "hw:%d,%d", &card, &dev);
-               if (err == 2)
-                       return snd_pcm_hw_open(pcmp, name, card, dev, -1, stream, mode);
-               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(name1, "plug:%d,%d", &card, &dev);
-               if (err == 2)
-                       return snd_pcm_plug_open_hw(pcmp, name, card, dev, -1, stream, mode);
-               err = sscanf(name1, "plug:%256[^,]", sname);
-               if (err == 1) {
-                       snd_pcm_t *slave;
-                       err = snd_pcm_open(&slave, sname, stream, mode);
-                       if (err < 0)
-                               return err;
-                       return snd_pcm_plug_open(pcmp, name, NULL, 0, 0, 0, slave, 1);
-               }
-               err = sscanf(name1, "shm:%256[^,],%256[^,]", socket, sname);
-               if (err == 2)
-                       return snd_pcm_shm_open(pcmp, name, socket, sname, stream, mode);
-               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, name1, file, -1, format, slave, 1);
-               }
-               err = sscanf(name1, "file:%256[^,],%16[^,]", file, format);
-               if (err == 2) {
-                       snd_pcm_t *slave;
-                       err = snd_pcm_null_open(&slave, name, stream, mode);
-                       if (err < 0)
-                               return err;
-                       return snd_pcm_file_open(pcmp, name, file, -1, format, slave, 1);
-               }
-               err = sscanf(name1, "file:%256[^,]", file);
-               if (err == 1) {
-                       snd_pcm_t *slave;
-                       err = snd_pcm_null_open(&slave, name, stream, mode);
-                       if (err < 0)
-                               return err;
-                       return snd_pcm_file_open(pcmp, name, file, -1, "raw", slave, 1);
-               }
-               if (strcmp(name1, "null") == 0)
-                       return snd_pcm_null_open(pcmp, name, stream, mode);
-               err = sscanf(name1, "surround40:%d,%d", &card, &dev);           
-               if (err == 2)
-                       return snd_pcm_surround_open(pcmp, name, card, dev, SND_PCM_SURROUND_40, stream, mode);
-               err = sscanf(name1, "surround40:%d", &card);
-               if (err == 1)
-                       return snd_pcm_surround_open(pcmp, name, card, 0, SND_PCM_SURROUND_40, stream, mode);
-               err = sscanf(name1, "surround51:%d,%d", &card, &dev);           
-               if (err == 2)
-                       return snd_pcm_surround_open(pcmp, name, card, dev, SND_PCM_SURROUND_51, stream, mode);
-               err = sscanf(name1, "surround51:%d", &card);
-               if (err == 1)
-                       return snd_pcm_surround_open(pcmp, name, card, 0, SND_PCM_SURROUND_51, stream, mode);
-               SNDERR("Unknown PCM %s", name1);
-               return -ENOENT;
+       const char *args = strchr(name, ':');
+       char *base;
+       if (args) {
+               args++;
+               base = alloca(args - name);
+               memcpy(base, name, args - name - 1);
+               base[args - name - 1] = 0;
+       } else
+               base = (char *) name;
+       err = snd_config_search_alias(snd_config, "pcm", base, &pcm_conf);
+       if (err < 0) {
+               SNDERR("Unknown PCM %s", name);
+               return err;
        }
-       return snd_pcm_open_conf(pcmp, name, pcm_conf, stream, mode);
-}
-
-#ifndef DOC_HIDDEN
-int snd_pcm_open_slave(snd_pcm_t **pcmp, snd_config_t *conf,
-                      snd_pcm_stream_t stream, int mode)
-{
-       const char *str;
-       if (snd_config_get_string(conf, &str) >= 0)
-               return snd_pcm_open_noupdate(pcmp, str, stream, mode);
-       return snd_pcm_open_conf(pcmp, NULL, conf, stream, mode);
+       if (args) {
+               err = snd_config_expand(pcm_conf, args, &pcm_conf);
+               if (err < 0)
+                       return err;
+       }
+       err = snd_pcm_open_conf(pcmp, name, pcm_conf, stream, mode);
+       if (args)
+               snd_config_delete(pcm_conf);
+       return err;
 }
-#endif
 
 /**
  * \brief Opens a PCM
@@ -1100,6 +1039,17 @@ int snd_pcm_open(snd_pcm_t **pcmp, const char *name,
        return snd_pcm_open_noupdate(pcmp, name, stream, mode);
 }
 
+#ifndef DOC_HIDDEN
+int snd_pcm_open_slave(snd_pcm_t **pcmp, snd_config_t *conf,
+                      snd_pcm_stream_t stream, int mode)
+{
+       const char *str;
+       if (snd_config_get_string(conf, &str) >= 0)
+               return snd_pcm_open_noupdate(pcmp, str, stream, mode);
+       return snd_pcm_open_conf(pcmp, NULL, conf, stream, mode);
+}
+#endif
+
 /**
  * \brief Wait for a PCM to become ready
  * \param pcm PCM handle
index 327b4ea7ed39b553b012757591c0a1ff1a996082..ec94b16d6d267ba8a4acbc374d8a511f6e3588d6 100644 (file)
@@ -36,9 +36,6 @@
 #include "pcm_local.h"
 #include "pcm_plugin.h"
 
-#ifndef DATADIR
-#define DATADIR "/usr/share"
-#endif
 #define ALSA_SURROUND_FILE DATADIR "/alsa/surround.conf"
 
 #define SURR_CAP_CAPTURE       (1<<0)
index 90c0fc90d2c8e8d1e2e4ac7b8db06f970a660566..5603176e54e8aba692835abe21cfba7e371a18ae 100644 (file)
@@ -60,54 +60,25 @@ static int snd_rawmidi_params_default(snd_rawmidi_t *rawmidi, snd_rawmidi_params
        return 0;
 }
 
-/**
- * \brief Opens a new connection to the RawMidi interface.
- * \param inputp Returned input handle (NULL if not wanted)
- * \param outputp Returned output handle (NULL if not wanted)
- * \param name ASCII identifier of the RawMidi handle
- * \param mode Open mode
- * \return 0 on success otherwise a negative error code
- *
- * Opens a new connection to the RawMidi interface specified with
- * an ASCII identifier and mode.
- */
-int snd_rawmidi_open(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp,
-                    const char *name, int mode)
+int snd_rawmidi_open_conf(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp,
+                         const char *name, snd_config_t *rawmidi_conf,
+                         int mode)
 {
        const char *str;
        char buf[256];
        int err;
-       snd_config_t *rawmidi_conf, *conf, *type_conf;
+       snd_config_t *conf, *type_conf;
        snd_config_iterator_t i, next;
        snd_rawmidi_params_t params;
        const char *lib = NULL, *open_name = NULL;
        int (*open_func)(snd_rawmidi_t **, snd_rawmidi_t **,
                         const char *, snd_config_t *, int);
        void *h;
-       const char *name1;
-       assert((inputp || outputp) && name);
-       err = snd_config_update();
-       if (err < 0)
-               return err;
-       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(name1, "hw:%d,%d,%d", &card, &dev, &subdev);
-               if (err == 3) {
-                       err = snd_rawmidi_hw_open(inputp, outputp, name, card, dev, subdev, mode);
-                       goto _init;
-               }
-               err = sscanf(name1, "hw:%d,%d", &card, &dev);
-               if (err == 2) {
-                       err = snd_rawmidi_hw_open(inputp, outputp, name, card, dev, -1, mode);
-                       goto _init;
-               }
-               SNDERR("Unknown RAWMIDI %s", name1);
-               return -ENOENT;
-       }
        if (snd_config_get_type(rawmidi_conf) != SND_CONFIG_TYPE_COMPOUND) {
-               SNDERR("Invalid type for RAWMIDI %s definition", name);
+               if (name)
+                       SNDERR("Invalid type for RAWMIDI %s definition", name);
+               else
+                       SNDERR("Invalid type for RAWMIDI definition");
                return -EINVAL;
        }
        err = snd_config_search(rawmidi_conf, "type", &conf);
@@ -122,6 +93,10 @@ int snd_rawmidi_open(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp,
        }
        err = snd_config_search_alias(snd_config, "rawmidi_type", str, &type_conf);
        if (err >= 0) {
+               if (snd_config_get_type(type_conf) != SND_CONFIG_TYPE_COMPOUND) {
+                       SNDERR("Invalid type for RAWMIDI 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);
@@ -165,7 +140,6 @@ int snd_rawmidi_open(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp,
                return -ENXIO;
        }
        err = open_func(inputp, outputp, name, rawmidi_conf, mode);
- _init:
        if (err < 0)
                return err;
        if (inputp) {
@@ -181,6 +155,58 @@ int snd_rawmidi_open(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp,
        return 0;
 }
 
+int snd_rawmidi_open_noupdate(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp,
+                             const char *name, int mode)
+{
+       int err;
+       snd_config_t *rawmidi_conf;
+       const char *args = strchr(name, ':');
+       char *base;
+       if (args) {
+               args++;
+               base = alloca(args - name);
+               memcpy(base, name, args - name - 1);
+               base[args - name - 1] = 0;
+       } else
+               base = (char *) name;
+       err = snd_config_search_alias(snd_config, "rawmidi", base, &rawmidi_conf);
+       if (err < 0) {
+               SNDERR("Unknown RAWMIDI %s", name);
+               return err;
+       }
+       if (args) {
+               err = snd_config_expand(rawmidi_conf, args, &rawmidi_conf);
+               if (err < 0)
+                       return err;
+       }
+       err = snd_rawmidi_open_conf(inputp, outputp, name, rawmidi_conf, mode);
+       if (args)
+               snd_config_delete(rawmidi_conf);
+       return err;
+}
+
+/**
+ * \brief Opens a new connection to the RawMidi interface.
+ * \param inputp Returned input handle (NULL if not wanted)
+ * \param outputp Returned output handle (NULL if not wanted)
+ * \param name ASCII identifier of the RawMidi handle
+ * \param mode Open mode
+ * \return 0 on success otherwise a negative error code
+ *
+ * Opens a new connection to the RawMidi interface specified with
+ * an ASCII identifier and mode.
+ */
+int snd_rawmidi_open(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp,
+                    const char *name, int mode)
+{
+       int err;
+       assert((inputp || outputp) && name);
+       err = snd_config_update();
+       if (err < 0)
+               return err;
+       return snd_rawmidi_open_noupdate(inputp, outputp, name, mode);
+}
+
 /**
  * \brief close RawMidi handle
  * \param rawmidi RawMidi handle
index 8203f5362985c55ad17df7985b3d5ec995f5f5eb..8de8449fc65b04533a56540eab1dbca7d7c380f7 100644 (file)
@@ -36,33 +36,24 @@ snd_seq_type_t snd_seq_type(snd_seq_t *seq)
        return seq->type;
 }
 
-int snd_seq_open(snd_seq_t **seqp, const char *name, 
-                int streams, int mode)
+static int snd_seq_open_conf(snd_seq_t **seqp, const char *name,
+                            snd_config_t *seq_conf,
+                            int streams, int mode)
 {
        const char *str;
        char buf[256];
        int err;
-       snd_config_t *seq_conf, *conf, *type_conf;
+       snd_config_t *conf, *type_conf = NULL;
        snd_config_iterator_t i, next;
        const char *lib = NULL, *open_name = NULL;
        int (*open_func)(snd_seq_t **, const char *, snd_config_t *, 
                         int, int);
        void *h;
-       const char *name1;
-       assert(seqp && name);
-       err = snd_config_update();
-       if (err < 0)
-               return err;
-       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", name1);
-               return -ENOENT;
-       }
        if (snd_config_get_type(seq_conf) != SND_CONFIG_TYPE_COMPOUND) {
-               SNDERR("Invalid type for SEQ %s definition", name);
+               if (name)
+                       SNDERR("Invalid type for SEQ %s definition", name);
+               else
+                       SNDERR("Invalid type for SEQ definition");
                return -EINVAL;
        }
        err = snd_config_search(seq_conf, "type", &conf);
@@ -77,6 +68,10 @@ int snd_seq_open(snd_seq_t **seqp, const char *name,
        }
        err = snd_config_search_alias(snd_config, "seq_type", str, &type_conf);
        if (err >= 0) {
+               if (snd_config_get_type(type_conf) != SND_CONFIG_TYPE_COMPOUND) {
+                       SNDERR("Invalid type for SEQ 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);
@@ -122,6 +117,47 @@ int snd_seq_open(snd_seq_t **seqp, const char *name,
        return open_func(seqp, name, seq_conf, streams, mode);
 }
 
+static int snd_seq_open_noupdate(snd_seq_t **seqp, const char *name, 
+                                int streams, int mode)
+{
+       int err;
+       snd_config_t *seq_conf;
+       const char *args = strchr(name, ':');
+       char *base;
+       if (args) {
+               args++;
+               base = alloca(args - name);
+               memcpy(base, name, args - name - 1);
+               base[args - name - 1] = 0;
+       } else
+               base = (char *) name;
+       err = snd_config_search_alias(snd_config, "seq", base, &seq_conf);
+       if (err < 0) {
+               SNDERR("Unknown SEQ %s", name);
+               return err;
+       }
+       if (args) {
+               err = snd_config_expand(seq_conf, args, &seq_conf);
+               if (err < 0)
+                       return err;
+       }
+       err = snd_seq_open_conf(seqp, name, seq_conf, streams, mode);
+       if (args)
+               snd_config_delete(seq_conf);
+       return err;
+}
+
+int snd_seq_open(snd_seq_t **seqp, const char *name, 
+                int streams, int mode)
+{
+       int err;
+       assert(seqp && name);
+       err = snd_config_update();
+       if (err < 0)
+               return err;
+       return snd_seq_open_noupdate(seqp, name, streams, mode);
+}
+
 /*
  * release sequencer client
  */