OSDN Git Service

Continued config implementation. Added incomplete support for pcm
authorAbramo Bagnara <abramo@alsa-project.org>
Thu, 24 Aug 2000 17:07:44 +0000 (17:07 +0000)
committerAbramo Bagnara <abramo@alsa-project.org>
Thu, 24 Aug 2000 17:07:44 +0000 (17:07 +0000)
include/conf.h
include/pcm.h
src/Makefile.am
src/conf/conf.c
src/pcm/pcm.c
src/pcm/pcm_hw.c
src/pcm/pcm_multi.c
src/pcm/pcm_plug.c

index be686a1..a3eb650 100644 (file)
@@ -24,11 +24,14 @@ struct snd_config {
        snd_config_t *father;
 };
 
+int snd_config_top(snd_config_t **config);
 
-int snd_config_load(snd_config_t **config, FILE *fp);
+int snd_config_load(snd_config_t *config, FILE *fp);
 int snd_config_save(snd_config_t *config, FILE *fp);
 
 int snd_config_search(snd_config_t *config, char *key, snd_config_t **result);
+int snd_config_searchv(snd_config_t *config, 
+                      snd_config_t **result, ...);
 
 int snd_config_add(snd_config_t *config, snd_config_t *leaf);
 int snd_config_delete(snd_config_t *config);
@@ -55,3 +58,15 @@ typedef struct list_head *snd_config_iterator_t;
 
 #define snd_config_entry(iterator) list_entry(iterator, snd_config_t, list)
 
+static inline snd_config_type_t snd_config_type(snd_config_t *config)
+{
+       return config->type;
+}
+
+static inline char *snd_config_id(snd_config_t *config)
+{
+       return config->id;
+}
+
+snd_config_t *snd_config;
+int snd_config_update();
index 69e1e2c..a4b2d36 100644 (file)
@@ -122,6 +122,9 @@ int snd_pcm_synchro(snd_pcm_synchro_cmd_t cmd,
 #endif
 
 
+int snd_pcm_open(snd_pcm_t **handle, char *name, 
+                int stream, int mode);
+
 int snd_pcm_hw_open_subdevice(snd_pcm_t **handle, int card, int device, int subdevice, int stream, int mode);
 int snd_pcm_hw_open(snd_pcm_t **handle, int card, int device, int stream, int mode);
 
index c0eb002..4286ea4 100644 (file)
@@ -6,7 +6,7 @@ libasound_la_SOURCES = error.c
 libasound_la_LIBADD = control/libcontrol.la mixer/libmixer.la pcm/libpcm.la \
                       rawmidi/librawmidi.la timer/libtimer.la \
                      hwdep/libhwdep.la seq/libseq.la instr/libinstr.la \
-                     compat/libcompat.la
+                     compat/libcompat.la conf/libconf.la
 
 libasound_la_LDFLAGS = -version-info $(COMPATNUM)
 
@@ -37,4 +37,7 @@ instr/libinstr.la:
 compat/libcompat.la:
        $(MAKE) -C compat libcompat.la
 
+conf/libconf.la:
+       $(MAKE) -C conf libconf.la
+
 INCLUDES=-I$(top_srcdir)/include
index 3d5e488..ec277ac 100644 (file)
 #include <assert.h>
 #include <errno.h>
 #include <stdarg.h>
+#include <sys/stat.h>
 #include "asoundlib.h"
 #include "list.h"
 
+#define SYS_ASOUNDRC "/etc/asound.conf"
+#define USR_ASOUNDRC ".asoundrc"
+
 typedef struct {
        FILE *fp;
        unsigned int line, column;
@@ -183,7 +187,7 @@ static int get_freestring(char **string, input_t *input)
                }
                if (idx >= alloc) {
                        size_t old_alloc = alloc;
-                       alloc *= 2;
+                       alloc += bufsize;
                        if (old_alloc == bufsize) {
                                buf = malloc(alloc);
                                memcpy(buf, _buf, old_alloc);
@@ -227,7 +231,7 @@ static int get_delimstring(char **string, int delim, input_t *input)
                }
                if (idx >= alloc) {
                        size_t old_alloc = alloc;
-                       alloc *= 2;
+                       alloc += bufsize;
                        if (old_alloc == bufsize) {
                                buf = malloc(alloc);
                                memcpy(buf, _buf, old_alloc);
@@ -507,30 +511,30 @@ static int parse_defs(snd_config_t *father, input_t *input)
        return 0;
 }
 
+int snd_config_top(snd_config_t **config)
+{
+       assert(config);
+       return _snd_config_make(config, 0, SND_CONFIG_TYPE_COMPOUND);
+}
 
-int snd_config_load(snd_config_t **config, FILE *fp)
+int snd_config_load(snd_config_t *config, FILE *fp)
 {
        int err;
        input_t input;
-       snd_config_t *c;
        assert(config && fp);
-       err = _snd_config_make(&c, 0, SND_CONFIG_TYPE_COMPOUND);
-       if (err < 0)
-               return err;
        input.fp = fp;
        input.line = 1;
        input.column = 0;
        input.unget = 0;
-       err = parse_defs(c, &input);
+       err = parse_defs(config, &input);
        if (err < 0) {
-               snd_config_delete(c);
+               snd_config_delete(config);
                return err;
        }
        if (get_char(&input) != EOF) {
-               snd_config_delete(c);
+               snd_config_delete(config);
                return -1;
        }
-       *config = c;
        return 0;
 }
 
@@ -595,14 +599,18 @@ int snd_config_make(snd_config_t **config, char *id,
 
 int snd_config_integer_set(snd_config_t *config, long value)
 {
-       assert(config->type == SND_CONFIG_TYPE_INTEGER);
+       assert(config);
+       if (config->type != SND_CONFIG_TYPE_INTEGER)
+               return -EINVAL;
        config->u.integer = value;
        return 0;
 }
 
 int snd_config_real_set(snd_config_t *config, double value)
 {
-       assert(config->type == SND_CONFIG_TYPE_REAL);
+       assert(config);
+       if (config->type != SND_CONFIG_TYPE_REAL)
+               return -EINVAL;
        config->u.real = value;
        return 0;
 }
@@ -610,7 +618,8 @@ int snd_config_real_set(snd_config_t *config, double value)
 int snd_config_string_set(snd_config_t *config, char *value)
 {
        assert(config);
-       assert(config->type == SND_CONFIG_TYPE_INTEGER);
+       if (config->type != SND_CONFIG_TYPE_STRING)
+               return -EINVAL;
        if (config->u.string)
                free(config->u.string);
        config->u.string = strdup(value);
@@ -645,7 +654,8 @@ int snd_config_set(snd_config_t *config, ...)
 int snd_config_integer_get(snd_config_t *config, long *ptr)
 {
        assert(config && ptr);
-       assert(config->type == SND_CONFIG_TYPE_INTEGER);
+       if (config->type != SND_CONFIG_TYPE_INTEGER)
+               return -EINVAL;
        *ptr = config->u.integer;
        return 0;
 }
@@ -653,7 +663,8 @@ int snd_config_integer_get(snd_config_t *config, long *ptr)
 int snd_config_real_get(snd_config_t *config, double *ptr)
 {
        assert(config && ptr);
-       assert(config->type == SND_CONFIG_TYPE_REAL);
+       if (config->type != SND_CONFIG_TYPE_REAL)
+               return -EINVAL;
        *ptr = config->u.real;
        return 0;
 }
@@ -661,7 +672,8 @@ int snd_config_real_get(snd_config_t *config, double *ptr)
 int snd_config_string_get(snd_config_t *config, char **ptr)
 {
        assert(config && ptr);
-       assert(config->type == SND_CONFIG_TYPE_INTEGER);
+       if (config->type != SND_CONFIG_TYPE_STRING)
+               return -EINVAL;
        *ptr = config->u.string;
        return 0;
 }
@@ -860,4 +872,110 @@ int snd_config_search(snd_config_t *config, char *key, snd_config_t **result)
                        return _snd_config_search(config, key, -1, result);
        }
 }
+
+int snd_config_searchv(snd_config_t *config,
+                      snd_config_t **result, ...)
+{
+       va_list arg;
+       const size_t bufsize = 256;
+       char _buf[bufsize];
+       char *buf = _buf;
+       size_t alloc = bufsize;
+       size_t idx = 0;
+       size_t dot = 0;
+       assert(config && result);
+       va_start(arg, result);
+       while (1) {
+               char *k = va_arg(arg, char *);
+               size_t len;
+               if (!k)
+                       break;
+               len = strlen(k);
+               if (idx + len + dot>= alloc) {
+                       size_t old_alloc = alloc;
+                       alloc = idx + len + dot;
+                       alloc += bufsize - alloc % bufsize;
+                       if (old_alloc == bufsize) {
+                               buf = malloc(alloc);
+                               memcpy(buf, _buf, old_alloc);
+                       } else 
+                               buf = realloc(buf, alloc);
+               }
+               if (dot)
+                       buf[idx] = '.';
+               memcpy(buf + idx + dot, k, len);
+               idx += len + dot;
+               if (dot == 0)
+                       dot = 1;
+       }
+       buf[idx] = '\0';
+       return snd_config_search(config, buf, result);
+}
+
+snd_config_t *snd_config = 0;
+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 snd_config_update()
+{
+       int err;
+       char *usr_asoundrc = NULL;
+       char *home = getenv("HOME");
+       struct stat st;
+       int reload;
+       FILE *fp;
+       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';
+       }
+       reload = (snd_config == NULL);
+       if (!reload &&
+           stat(usr_asoundrc, &st) == 0 &&
+           (st.st_dev != usr_asoundrc_device ||
+            st.st_ino != usr_asoundrc_inode ||
+            st.st_mtime != usr_asoundrc_mtime))
+               reload = 1;
+       if (!reload &&
+           stat(SYS_ASOUNDRC, &st) == 0 &&
+           (st.st_dev != sys_asoundrc_device ||
+            st.st_ino != sys_asoundrc_inode ||
+            st.st_mtime != sys_asoundrc_mtime))
+               reload = 1;
+       if (!reload)
+               return 0;
+       if (snd_config == NULL) {
+               err = snd_config_top(&snd_config);
+               if (err < 0)
+                       return err;
+       }
+       fp = fopen(SYS_ASOUNDRC, "r");
+       if (fp) {
+               err = snd_config_load(snd_config, fp);
+               if (err < 0) {
+                       snd_config = NULL;
+                       fclose(fp);
+                       return err;
+               }
+               fclose(fp);
+       }
+       fp = fopen(usr_asoundrc, "r");
+       if (fp) {
+               err = snd_config_load(snd_config, fp);
+               if (err < 0) {
+                       snd_config = NULL;
+                       fclose(fp);
+                       return err;
+               }
+               fclose(fp);
+       }
+       return 0;
+}
index 658f0f0..948046c 100644 (file)
@@ -27,6 +27,7 @@
 #include <sys/poll.h>
 #include <sys/uio.h>
 #include "pcm_local.h"
+#include "list.h"
 
 snd_pcm_type_t snd_pcm_type(snd_pcm_t *handle)
 {
@@ -501,3 +502,170 @@ ssize_t snd_pcm_samples_to_bytes(snd_pcm_t *handle, ssize_t samples)
        return samples * handle->bits_per_sample / 8;
 }
 
+static int _snd_pcm_open_hw(snd_pcm_t **handlep, snd_config_t *conf, 
+                           int stream, int mode)
+{
+       snd_config_iterator_t i;
+       long card = -1, device = -1, subdevice = -1;
+       char *str;
+       int err;
+       snd_config_foreach(i, conf) {
+               snd_config_t *n = snd_config_entry(i);
+               if (strcmp(n->id, "comment") == 0)
+                       continue;
+               if (strcmp(n->id, "type") == 0)
+                       continue;
+               if (strcmp(n->id, "stream") == 0)
+                       continue;
+               if (strcmp(n->id, "card") == 0) {
+                       err = snd_config_integer_get(n, &card);
+                       if (err < 0) {
+                               err = snd_config_string_get(n, &str);
+                               if (err < 0)
+                                       return -EINVAL;
+                               card = snd_card_name(str);
+                               if (card < 0)
+                                       return card;
+                       }
+                       continue;
+               }
+               if (strcmp(n->id, "device") == 0) {
+                       err = snd_config_integer_get(n, &device);
+                       if (err < 0)
+                               return err;
+                       continue;
+               }
+               if (strcmp(n->id, "subdevice") == 0) {
+                       err = snd_config_integer_get(n, &subdevice);
+                       if (err < 0)
+                               return err;
+                       continue;
+               }
+               return -EINVAL;
+       }
+       if (card < 0 || device < 0)
+               return -EINVAL;
+       return snd_pcm_hw_open_subdevice(handlep, card, device, subdevice, stream, mode);
+}
+                               
+static int _snd_pcm_open_plug(snd_pcm_t **handlep, snd_config_t *conf, 
+                             int stream, int mode)
+{
+       snd_config_iterator_t i;
+       long card = -1, device = -1, subdevice = -1;
+       char *str;
+       int err;
+       snd_config_foreach(i, conf) {
+               snd_config_t *n = snd_config_entry(i);
+               if (strcmp(n->id, "comment") == 0)
+                       continue;
+               if (strcmp(n->id, "type") == 0)
+                       continue;
+               if (strcmp(n->id, "stream") == 0)
+                       continue;
+               if (strcmp(n->id, "card") == 0) {
+                       err = snd_config_integer_get(n, &card);
+                       if (err < 0) {
+                               err = snd_config_string_get(n, &str);
+                               if (err < 0)
+                                       return -EINVAL;
+                               card = snd_card_name(str);
+                               if (card < 0)
+                                       return card;
+                       }
+                       continue;
+               }
+               if (strcmp(n->id, "device") == 0) {
+                       err = snd_config_integer_get(n, &device);
+                       if (err < 0)
+                               return err;
+                       continue;
+               }
+               if (strcmp(n->id, "subdevice") == 0) {
+                       err = snd_config_integer_get(n, &subdevice);
+                       if (err < 0)
+                               return err;
+                       continue;
+               }
+               return -EINVAL;
+       }
+       if (card < 0 || device < 0)
+               return -EINVAL;
+       return snd_pcm_plug_open_subdevice(handlep, card, device, subdevice, stream, mode);
+}
+                               
+static int _snd_pcm_open_multi(snd_pcm_t **handle, snd_config_t *conf, 
+                             int stream, int mode)
+{
+       snd_config_iterator_t i;
+       char *str;
+       int err;
+       snd_config_foreach(i, conf) {
+               snd_config_t *n = snd_config_entry(i);
+               if (strcmp(n->id, "comment") == 0)
+                       continue;
+               if (strcmp(n->id, "type") == 0)
+                       continue;
+               if (strcmp(n->id, "stream") == 0)
+                       continue;
+               if (strcmp(n->id, "slave") == 0) {
+                       if (snd_config_type(n) != SND_CONFIG_TYPE_COMPOUND)
+                               return -EINVAL;
+                       /* Not yet implemented */
+                       continue;
+               }
+               if (strcmp(n->id, "binding") == 0) {
+                       if (snd_config_type(n) != SND_CONFIG_TYPE_COMPOUND)
+                               return -EINVAL;
+                       /* Not yet implemented */
+                       continue;
+               }
+               return -EINVAL;
+       }
+       return -ENOSYS;
+}
+
+int snd_pcm_open(snd_pcm_t **handlep, char *name, 
+                int stream, int mode)
+{
+       char *str;
+       int err;
+       snd_config_t *pcm_conf, *conf;
+       assert(handlep && name);
+       err = snd_config_update();
+       if (err < 0)
+               return err;
+       err = snd_config_searchv(snd_config, &pcm_conf, "pcm", name, 0);
+       if (err < 0)
+               return err;
+       if (snd_config_type(pcm_conf) != SND_CONFIG_TYPE_COMPOUND)
+               return -EINVAL;
+       err = snd_config_search(pcm_conf, "stream", &conf);
+       if (err >= 0) {
+               err = snd_config_string_get(conf, &str);
+               if (err < 0)
+                       return err;
+               if (strcmp(str, "playback") == 0) {
+                       if (stream != SND_PCM_STREAM_PLAYBACK)
+                               return -EINVAL;
+               } else if (strcmp(str, "capture") == 0) {
+                       if (stream != SND_PCM_STREAM_CAPTURE)
+                               return -EINVAL;
+               } else
+                       return -EINVAL;
+       }
+       err = snd_config_search(pcm_conf, "type", &conf);
+       if (err < 0)
+               return err;
+       err = snd_config_string_get(conf, &str);
+       if (err < 0)
+               return err;
+       if (strcmp(str, "hw") == 0)
+               return _snd_pcm_open_hw(handlep, pcm_conf, stream, mode);
+       else if (strcmp(str, "plug") == 0)
+               return _snd_pcm_open_plug(handlep, pcm_conf, stream, mode);
+       else if (strcmp(str, "multi") == 0)
+               return _snd_pcm_open_multi(handlep, pcm_conf, stream, mode);
+       else
+               return -EINVAL;
+}
index 531dea5..80f7fad 100644 (file)
@@ -406,6 +406,7 @@ int snd_pcm_hw_open_subdevice(snd_pcm_t **handlep, int card, int device, int sub
        snd_pcm_t *handle;
        snd_pcm_hw_t *hw;
 
+       assert(handlep);
        *handlep = 0;
 
        if ((ret = snd_ctl_open(&ctl, card)) < 0)
index 7abec1e..172aaf4 100644 (file)
@@ -737,6 +737,7 @@ int snd_pcm_multi_create(snd_pcm_t **handlep, size_t slaves_count,
        char client_map[32] = { 0 };
        char slave_map[32][32] = { { 0 } };
 
+       assert(handlep);
        assert(slaves_count > 0 && slaves_handle && slaves_channels_count);
        assert(binds_count > 0 && binds_slave && binds_client_channel && binds_slave_channel);
 
index 6feda18..d65e63c 100644 (file)
@@ -789,6 +789,7 @@ int snd_pcm_plug_create(snd_pcm_t **handlep, snd_pcm_t *slave, int close_slave)
 {
        snd_pcm_t *handle;
        snd_pcm_plug_t *plug;
+       assert(handlep && slave);
        handle = calloc(1, sizeof(snd_pcm_t));
        if (!handle)
                return -ENOMEM;