]> git.alsa-project.org Git - alsa-lib.git/commitdiff
Fix infinite parse of recursive definitions
authorTakashi Iwai <tiwai@suse.de>
Mon, 30 Jan 2006 14:41:51 +0000 (14:41 +0000)
committerTakashi Iwai <tiwai@suse.de>
Mon, 30 Jan 2006 14:41:51 +0000 (14:41 +0000)
Fixed the infinite parse (and eventually segfault) of recursive definitions.
Also fixed the parse of a string slave PCM of direct plugins.

29 files changed:
include/local.h
src/conf.c
src/pcm/pcm.c
src/pcm/pcm_adpcm.c
src/pcm/pcm_alaw.c
src/pcm/pcm_asym.c
src/pcm/pcm_copy.c
src/pcm/pcm_direct.c
src/pcm/pcm_direct.h
src/pcm/pcm_dmix.c
src/pcm/pcm_dshare.c
src/pcm/pcm_dsnoop.c
src/pcm/pcm_extplug.c
src/pcm/pcm_file.c
src/pcm/pcm_hooks.c
src/pcm/pcm_iec958.c
src/pcm/pcm_ladspa.c
src/pcm/pcm_lfloat.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_softvol.c
src/rawmidi/rawmidi_virt.c
src/seq/seq.c

index bf53d512fef88fdd39ab1dc3ad441a1d3f0a2de6..b18d77a9699503a0ecc31557394ac4af13ec5427 100644 (file)
@@ -249,4 +249,9 @@ void *snd_dlobj_cache_lookup(const char *name);
 int snd_dlobj_cache_add(const char *name, void *dlobj, void *open_func);
 void snd_dlobj_cache_cleanup(void);
 
+/* for recursive checks */
+void snd_config_set_hop(snd_config_t *conf, int hop);
+int snd_config_check_hop(snd_config_t *conf);
+#define SND_CONF_MAX_HOPS      64
+
 #endif
index 78cc4cb363208dd1e0eb0e9c614a47b2a12120fc..3667ac065b7cb4c0dd09b32caa85f1e5cbc546af 100644 (file)
@@ -440,6 +440,7 @@ struct _snd_config {
        } u;
        struct list_head list;
        snd_config_t *father;
+       int hop;
 };
 
 struct filedesc {
@@ -4011,6 +4012,24 @@ int snd_config_search_definition(snd_config_t *config,
        return snd_config_expand(conf, config, args, NULL, result);
 }
 
+#ifndef DOC_HIDDEN
+void snd_config_set_hop(snd_config_t *conf, int hop)
+{
+       conf->hop = hop;
+}
+
+int snd_config_check_hop(snd_config_t *conf)
+{
+       if (conf) {
+               if (conf->hop >= SND_CONF_MAX_HOPS) {
+                       SYSERR("Too many definition levels (looped?)\n");
+                       return -EINVAL;
+               }
+               return conf->hop;
+       }
+       return 0;
+}
+#endif
 
 #if 0
 /* Not strictly needed, but useful to check for memory leaks */
index b3f3e6bd5b415632108a07ad95ddec80bc12a672..6974aa0b240827abe35cd8225c0cc6a7c21207cd 100644 (file)
@@ -2098,7 +2098,8 @@ static int snd_pcm_open_conf(snd_pcm_t **pcmp, const char *name,
 }
 
 static int snd_pcm_open_noupdate(snd_pcm_t **pcmp, snd_config_t *root,
-                                const char *name, snd_pcm_stream_t stream, int mode)
+                                const char *name, snd_pcm_stream_t stream,
+                                int mode, int hop)
 {
        int err;
        snd_config_t *pcm_conf;
@@ -2107,6 +2108,7 @@ static int snd_pcm_open_noupdate(snd_pcm_t **pcmp, snd_config_t *root,
                SNDERR("Unknown PCM %s", name);
                return err;
        }
+       snd_config_set_hop(pcm_conf, hop);
        err = snd_pcm_open_conf(pcmp, name, root, pcm_conf, stream, mode);
        snd_config_delete(pcm_conf);
        return err;
@@ -2128,7 +2130,7 @@ int snd_pcm_open(snd_pcm_t **pcmp, const char *name,
        err = snd_config_update();
        if (err < 0)
                return err;
-       return snd_pcm_open_noupdate(pcmp, snd_config, name, stream, mode);
+       return snd_pcm_open_noupdate(pcmp, snd_config, name, stream, mode, 0);
 }
 
 /**
@@ -2145,7 +2147,7 @@ int snd_pcm_open_lconf(snd_pcm_t **pcmp, const char *name,
                       snd_config_t *lconf)
 {
        assert(pcmp && name && lconf);
-       return snd_pcm_open_noupdate(pcmp, lconf, name, stream, mode);
+       return snd_pcm_open_noupdate(pcmp, lconf, name, stream, mode, 0);
 }
 
 #ifndef DOC_HIDDEN
@@ -2187,11 +2189,16 @@ int snd_pcm_free(snd_pcm_t *pcm)
 
 int snd_pcm_open_slave(snd_pcm_t **pcmp, snd_config_t *root,
                       snd_config_t *conf, snd_pcm_stream_t stream,
-                      int mode)
+                      int mode, snd_config_t *parent_conf)
 {
        const char *str;
+       int hop;
+
+       if ((hop = snd_config_check_hop(parent_conf)) < 0)
+               return hop;
        if (snd_config_get_string(conf, &str) >= 0)
-               return snd_pcm_open_noupdate(pcmp, root, str, stream, mode);
+               return snd_pcm_open_noupdate(pcmp, root, str, stream, mode,
+                                            hop + 1);
        return snd_pcm_open_conf(pcmp, NULL, root, conf, stream, mode);
 }
 #endif
index e5cb450613260a22422f255f5673baa2f3d58dba..8350dbec4c5bbe7a5e3c71c3356aa6501515165c 100644 (file)
@@ -666,7 +666,7 @@ int _snd_pcm_adpcm_open(snd_pcm_t **pcmp, const char *name,
                SNDERR("invalid slave format");
                return -EINVAL;
        }
-       err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode);
+       err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode, conf);
        snd_config_delete(sconf);
        if (err < 0)
                return err;
index 19045ec8b58d49c3ffba1b29b1082a016941a2d6..767e69fdbd2634b9e877ce9817ad105da5ec8c1d 100644 (file)
@@ -538,7 +538,7 @@ int _snd_pcm_alaw_open(snd_pcm_t **pcmp, const char *name,
                SNDERR("invalid slave format");
                return -EINVAL;
        }
-       err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode);
+       err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode, conf);
        snd_config_delete(sconf);
        if (err < 0)
                return err;
index 5a2a4d64701ab43b4594f72558acdf7be65c9825..660f3107ed96000b32809967cae80aea3694c161 100644 (file)
@@ -109,7 +109,7 @@ int _snd_pcm_asym_open(snd_pcm_t **pcmp, const char *name ATTRIBUTE_UNUSED,
        err = snd_pcm_slave_conf(root, slave, &sconf, 0);
        if (err < 0)
                return err;
-       err = snd_pcm_open_slave(pcmp, root, sconf, stream, mode);
+       err = snd_pcm_open_slave(pcmp, root, sconf, stream, mode, conf);
        snd_config_delete(sconf);
        return err;
 }
index 1e8510f4045d0d835008983d06259fb9afa65427..b1525bfa3969beab85bdaada0140d6e07e51008a 100644 (file)
@@ -284,7 +284,7 @@ int _snd_pcm_copy_open(snd_pcm_t **pcmp, const char *name,
        err = snd_pcm_slave_conf(root, slave, &sconf, 0);
        if (err < 0)
                return err;
-       err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode);
+       err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode, conf);
        snd_config_delete(sconf);
        if (err < 0)
                return err;
index 113930e172a6cd7e16727021dcfab6386b8d84d9..ff4bddbffb65bbc77498e1511035f177c2e21ce2 100644 (file)
@@ -1260,11 +1260,34 @@ int snd_pcm_direct_parse_bindings(snd_pcm_direct_t *dmix, snd_config_t *cfg)
 /*
  * parse slave config and calculate the ipc_key offset
  */
-int snd_pcm_direct_get_slave_ipc_offset(snd_config_t *sconf, int direction)
+
+static int _snd_pcm_direct_get_slave_ipc_offset(snd_config_t *root,
+                                               snd_config_t *sconf,
+                                               int direction,
+                                               int hop)
 {
        snd_config_iterator_t i, next;
        int err;
        long card = 0, device = 0, subdevice = 0;
+       const char *str;
+
+       if (snd_config_get_string(sconf, &str) >= 0) {
+               snd_config_t *pcm_conf;
+               if (hop > SND_CONF_MAX_HOPS) {
+                       SNDERR("Too many definition levels (looped?)");
+                       return -EINVAL;
+               }
+               err = snd_config_search_definition(root, "pcm", str, &pcm_conf);
+               if (err < 0) {
+                       SNDERR("Unknown slave PCM %s", str);
+                       return err;
+               }
+               err = _snd_pcm_direct_get_slave_ipc_offset(root, pcm_conf,
+                                                          direction,
+                                                          hop + 1);
+               snd_config_delete(pcm_conf);
+               return err;
+       }
 
        snd_config_for_each(i, next, sconf) {
                snd_config_t *n = snd_config_iterator_entry(i);
@@ -1325,6 +1348,12 @@ int snd_pcm_direct_get_slave_ipc_offset(snd_config_t *sconf, int direction)
        return direction + (card << 1) + (device << 4) + (subdevice << 8);
 }
 
+int snd_pcm_direct_get_slave_ipc_offset(snd_config_t *root,
+                                       snd_config_t *sconf,
+                                       int direction)
+{
+       return _snd_pcm_direct_get_slave_ipc_offset(root, sconf, direction, 0);
+}
 
 int snd_pcm_direct_parse_open_conf(snd_config_t *conf, struct snd_pcm_direct_open_conf *rec)
 {
index 6a8bf791df07a180fb1d8521530cedf2168a1b38..31d3c4a926a8f99398fbba465a2cdc106f06a385 100644 (file)
@@ -186,7 +186,7 @@ int snd_pcm_direct_timer_stop(snd_pcm_direct_t *dmix);
 void snd_pcm_direct_clear_timer_queue(snd_pcm_direct_t *dmix);
 int snd_pcm_direct_set_timer_params(snd_pcm_direct_t *dmix);
 int snd_pcm_direct_open_secondary_client(snd_pcm_t **spcmp, snd_pcm_direct_t *dmix, const char *client_name);
-int snd_pcm_direct_get_slave_ipc_offset(snd_config_t *sconf, int direction);
+int snd_pcm_direct_get_slave_ipc_offset(snd_config_t *root, snd_config_t *sconf, int direction);
 
 int snd_timer_async(snd_timer_t *timer, int sig, pid_t pid);
 struct timespec snd_pcm_hw_fast_tstamp(snd_pcm_t *pcm);
index 4f61a368e84e3110ba218b2d37147c2d9e9bfd98..41a6bd8feadeb6b3fd4b8b2279a6a38c460f3cb0 100644 (file)
@@ -847,7 +847,10 @@ int snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name,
        dmix->sync_ptr = snd_pcm_dmix_sync_ptr;
 
        if (first_instance) {
-               ret = snd_pcm_open_slave(&spcm, root, sconf, stream, mode | SND_PCM_NONBLOCK);
+               /* recursion is already checked in
+                  snd_pcm_direct_get_slave_ipc_offset() */
+               ret = snd_pcm_open_slave(&spcm, root, sconf, stream,
+                                        mode | SND_PCM_NONBLOCK, NULL);
                if (ret < 0) {
                        SNDERR("unable to open slave");
                        goto _err;
@@ -1124,7 +1127,7 @@ int _snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name,
        params.period_size = psize;
        params.buffer_size = bsize;
 
-       ipc_offset = snd_pcm_direct_get_slave_ipc_offset(sconf, stream);
+       ipc_offset = snd_pcm_direct_get_slave_ipc_offset(root, sconf, stream);
        if (ipc_offset < 0) {
                snd_config_delete(sconf);
                return ipc_offset;
index c7cd9922d94503fa22c40bb34b171c32db2865a7..2d719dc93589c13b7986a36d52aab30524b09f03 100644 (file)
@@ -672,7 +672,10 @@ int snd_pcm_dshare_open(snd_pcm_t **pcmp, const char *name,
        dshare->sync_ptr = snd_pcm_dshare_sync_ptr;
 
        if (first_instance) {
-               ret = snd_pcm_open_slave(&spcm, root, sconf, stream, mode | SND_PCM_NONBLOCK);
+               /* recursion is already checked in
+                  snd_pcm_direct_get_slave_ipc_offset() */
+               ret = snd_pcm_open_slave(&spcm, root, sconf, stream,
+                                        mode | SND_PCM_NONBLOCK, NULL);
                if (ret < 0) {
                        SNDERR("unable to open slave");
                        goto _err;
@@ -873,7 +876,7 @@ int _snd_pcm_dshare_open(snd_pcm_t **pcmp, const char *name,
        params.period_size = psize;
        params.buffer_size = bsize;
 
-       ipc_offset = snd_pcm_direct_get_slave_ipc_offset(sconf, stream);
+       ipc_offset = snd_pcm_direct_get_slave_ipc_offset(root, sconf, stream);
        if (ipc_offset < 0) {
                snd_config_delete(sconf);
                return ipc_offset;
index 6fe1bd52cab95ecf99c1d8c9c2255a6a7dc6307f..e2b91bbeb154524eb26ae4d3530d473ec7dac48d 100644 (file)
@@ -554,7 +554,10 @@ int snd_pcm_dsnoop_open(snd_pcm_t **pcmp, const char *name,
        dsnoop->sync_ptr = snd_pcm_dsnoop_sync_ptr;
 
        if (first_instance) {
-               ret = snd_pcm_open_slave(&spcm, root, sconf, stream, mode | SND_PCM_NONBLOCK);
+               /* recursion is already checked in
+                  snd_pcm_direct_get_slave_ipc_offset() */
+               ret = snd_pcm_open_slave(&spcm, root, sconf, stream,
+                                        mode | SND_PCM_NONBLOCK, NULL);
                if (ret < 0) {
                        SNDERR("unable to open slave");
                        goto _err;
@@ -745,7 +748,7 @@ int _snd_pcm_dsnoop_open(snd_pcm_t **pcmp, const char *name,
        params.period_size = psize;
        params.buffer_size = bsize;
 
-       ipc_offset = snd_pcm_direct_get_slave_ipc_offset(sconf, stream);
+       ipc_offset = snd_pcm_direct_get_slave_ipc_offset(root, sconf, stream);
        if (ipc_offset < 0) {
                snd_config_delete(sconf);
                return ipc_offset;
index 36d4d2481b3b9336fafb21876769da53c094f454..2bde9e5bd0c89c553b7a3b4dd97a129e0961f8a1 100644 (file)
@@ -622,7 +622,7 @@ int snd_pcm_extplug_create(snd_pcm_extplug_t *extplug, const char *name,
        err = snd_pcm_slave_conf(root, slave_conf, &sconf, 0);
        if (err < 0)
                return err;
-       err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode);
+       err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode, NULL);
        snd_config_delete(sconf);
        if (err < 0)
                return err;
index 4560bf4a123628b4b9c98d50e206d9bc7781a7d9..18951cc298bd0aff992fb778a64bbe9c9d2182d7 100644 (file)
@@ -556,7 +556,7 @@ int _snd_pcm_file_open(snd_pcm_t **pcmp, const char *name,
                SNDERR("file is not defined");
                return -EINVAL;
        }
-       err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode);
+       err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode, conf);
        snd_config_delete(sconf);
        if (err < 0)
                return err;
index ce5f221cd7ce13c0a66e9f186acd5c58d97e12a4..f5136862bd292c49c160782cb11de4746a0bb46c 100644 (file)
@@ -460,7 +460,7 @@ int _snd_pcm_hooks_open(snd_pcm_t **pcmp, const char *name,
        err = snd_pcm_slave_conf(root, slave, &sconf, 0);
        if (err < 0)
                return err;
-       err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode);
+       err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode, conf);
        snd_config_delete(sconf);
        if (err < 0)
                return err;
index 3b120adcba52a5dd838b2bc0847212aa8927ee8e..79d611d10852f177db01540ee61f6619d0f23cf1 100644 (file)
@@ -662,7 +662,7 @@ int _snd_pcm_iec958_open(snd_pcm_t **pcmp, const char *name,
                SNDERR("invalid slave format");
                return -EINVAL;
        }
-       err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode);
+       err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode, conf);
        snd_config_delete(sconf);
        if (err < 0)
                return err;
index 03f31f769c206bad183ea2432dfb16f47c1ecc13..d4432ae3843f9544337236066b588779257144aa 100644 (file)
@@ -1782,7 +1782,7 @@ int _snd_pcm_ladspa_open(snd_pcm_t **pcmp, const char *name,
        err = snd_pcm_slave_conf(root, slave, &sconf, 0);
        if (err < 0)
                return err;
-       err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode);
+       err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode, conf);
        snd_config_delete(sconf);
        if (err < 0)
                return err;
index d22277ba8eb2b662cedc0775a54dffb46576bbab..7d946cbc48313b8445d7bcc487040dab0c9e4585 100644 (file)
@@ -497,7 +497,7 @@ int _snd_pcm_lfloat_open(snd_pcm_t **pcmp, const char *name,
                SNDERR("slave format is not linear integer or linear float");
                return -EINVAL;
        }
-       err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode);
+       err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode, conf);
        snd_config_delete(sconf);
        if (err < 0)
                return err;
index 43663787e5dd0b3232574c409bd84fad31e1cbe2..6fc222cbdfa4d1dfcb73b64dba1512636842faf8 100644 (file)
@@ -552,7 +552,7 @@ int _snd_pcm_linear_open(snd_pcm_t **pcmp, const char *name,
                SNDERR("slave format is not linear");
                return -EINVAL;
        }
-       err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode);
+       err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode, conf);
        snd_config_delete(sconf);
        if (err < 0)
                return err;
index 247863921327b61713c8c18b113becea9d149372..e458b4690be2305e90456292f7d59a36165a0364 100644 (file)
@@ -748,7 +748,7 @@ int snd_pcm_slave_conf(snd_config_t *root, snd_config_t *conf,
 
 int snd_pcm_open_slave(snd_pcm_t **pcmp, snd_config_t *root,
                       snd_config_t *conf, snd_pcm_stream_t stream,
-                      int mode);
+                      int mode, snd_config_t *parent_conf);
 int snd_pcm_conf_generic_id(const char *id);
 
 int snd_pcm_hw_open_fd(snd_pcm_t **pcmp, const char *name, int fd, int mmap_emulation, int sync_ptr_ioctl);
index 413b3cb45ac9a06367161cfafd4f10b233cadbae..b84747c4b97435c8f4e0bdf95e8e7ef2f492a7fe 100644 (file)
@@ -779,7 +779,7 @@ int _snd_pcm_meter_open(snd_pcm_t **pcmp, const char *name,
        err = snd_pcm_slave_conf(root, slave, &sconf, 0);
        if (err < 0)
                return err;
-       err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode);
+       err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode, conf);
        snd_config_delete(sconf);
        if (err < 0)
                return err;
index 87b3235ea0c9d03eeb5985e8fd5c3e84f20fbef3..389326b61ab2bd36a78731a4747facfff5cc35bb 100644 (file)
@@ -553,7 +553,7 @@ int _snd_pcm_mulaw_open(snd_pcm_t **pcmp, const char *name,
                SNDERR("invalid slave format");
                return -EINVAL;
        }
-       err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode);
+       err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode, conf);
        snd_config_delete(sconf);
        if (err < 0)
                return err;
index c2ade36122472f634845dfb8807bb12aca7a97b2..9c492f95a9818a6837f60799a79fcd7c5ec76e06 100644 (file)
@@ -1103,7 +1103,9 @@ int _snd_pcm_multi_open(snd_pcm_t **pcmp, const char *name,
        }
        
        for (idx = 0; idx < slaves_count; ++idx) {
-               err = snd_pcm_open_slave(&slaves_pcm[idx], root, slaves_conf[idx], stream, mode);
+               err = snd_pcm_open_slave(&slaves_pcm[idx], root,
+                                        slaves_conf[idx], stream, mode,
+                                        conf);
                if (err < 0)
                        goto _free;
                snd_config_delete(slaves_conf[idx]);
index 0f5264c63be9e7588f916d7aec9cd67a12ba5262..ad3e6507d107916c05c5441d9bb69d69b10e4cbc 100644 (file)
@@ -1215,7 +1215,7 @@ int _snd_pcm_plug_open(snd_pcm_t **pcmp, const char *name,
        }
 #endif
        
-       err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode);
+       err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode, conf);
        snd_config_delete(sconf);
        if (err < 0)
                return err;
index 28490ccc596d66705535611568810a0424398d86..f675a583483428efca8046235fc6ec5250cdfac6 100644 (file)
@@ -1532,7 +1532,7 @@ int _snd_pcm_rate_open(snd_pcm_t **pcmp, const char *name,
                SNDERR("slave format is not linear");
                return -EINVAL;
        }
-       err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode);
+       err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode, conf);
        snd_config_delete(sconf);
        if (err < 0)
                return err;
index 09c1bd6f8a7b4b3bbd1f844cbead41038c46ab4a..daddf7c743d89d1bd6b9b63546eb771221010431 100644 (file)
@@ -1152,7 +1152,7 @@ int _snd_pcm_route_open(snd_pcm_t **pcmp, const char *name,
                return err;
        }
 
-       err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode);
+       err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode, conf);
        snd_config_delete(sconf);
        if (err < 0) {
                free(ttable);
index 5c0413d83045a10c6fa583cf74d313ce19129d19..d59d03150dd3ba0cf5d8f1682a0b8cfbcfd85d81 100644 (file)
@@ -814,7 +814,7 @@ int _snd_pcm_softvol_open(snd_pcm_t **pcmp, const char *name,
                snd_config_delete(sconf);
                return -EINVAL;
        }
-       err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode);
+       err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode, conf);
        snd_config_delete(sconf);
        if (err < 0)
                return err;
index 99c4be2291aa9940a0012438abcb7cc943ebc186..2cee7b34fb79ad984b9db3a4d5a4d6a6bcfdaaa2 100644 (file)
@@ -53,6 +53,10 @@ typedef struct {
        snd_seq_event_t out_event;
        int pending;
 } snd_rawmidi_virtual_t;
+
+int _snd_seq_open_lconf(snd_seq_t **seqp, const char *name, 
+                       int streams, int mode, snd_config_t *lconf,
+                       snd_config_t *parent_conf);
 #endif
 
 static int snd_rawmidi_virtual_close(snd_rawmidi_t *rmidi)
@@ -439,7 +443,8 @@ int _snd_rawmidi_virtual_open(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp,
 
        if (! slave_str)
                slave_str = "default";
-       err = snd_seq_open_lconf(&seq_handle, slave_str, streams, seq_mode, root);
+       err = _snd_seq_open_lconf(&seq_handle, slave_str, streams, seq_mode,
+                                 root, conf);
        if (err < 0)
                return err;
 
index 2ae83a7a649011a5cdcb6da5df945feae0e0d5d2..df7b64e6a73819fac66b91f79359cccdde7a8c9a 100644 (file)
@@ -919,7 +919,8 @@ static int snd_seq_open_conf(snd_seq_t **seqp, const char *name,
 }
 
 static int snd_seq_open_noupdate(snd_seq_t **seqp, snd_config_t *root,
-                                const char *name, int streams, int mode)
+                                const char *name, int streams, int mode,
+                                int hop)
 {
        int err;
        snd_config_t *seq_conf;
@@ -928,6 +929,7 @@ static int snd_seq_open_noupdate(snd_seq_t **seqp, snd_config_t *root,
                SNDERR("Unknown SEQ %s", name);
                return err;
        }
+       snd_config_set_hop(seq_conf, hop);
        err = snd_seq_open_conf(seqp, name, root, seq_conf, streams, mode);
        snd_config_delete(seq_conf);
        return err;
@@ -971,7 +973,7 @@ int snd_seq_open(snd_seq_t **seqp, const char *name,
        err = snd_config_update();
        if (err < 0)
                return err;
-       return snd_seq_open_noupdate(seqp, snd_config, name, streams, mode);
+       return snd_seq_open_noupdate(seqp, snd_config, name, streams, mode, 0);
 }
 
 /**
@@ -993,9 +995,22 @@ int snd_seq_open_lconf(snd_seq_t **seqp, const char *name,
                       int streams, int mode, snd_config_t *lconf)
 {
        assert(seqp && name && lconf);
-       return snd_seq_open_noupdate(seqp, lconf, name, streams, mode);
+       return snd_seq_open_noupdate(seqp, lconf, name, streams, mode, 0);
 }
 
+#ifndef DOC_HIDDEN
+int _snd_seq_open_lconf(snd_seq_t **seqp, const char *name, 
+                       int streams, int mode, snd_config_t *lconf,
+                       snd_config_t *parent_conf)
+{
+       int hop;
+       assert(seqp && name && lconf);
+       if ((hop = snd_config_check_hop(parent_conf)) < 0)
+               return hop;
+       return snd_seq_open_noupdate(seqp, lconf, name, streams, mode, hop + 1);
+}
+#endif
+
 /**
  * \brief Close the sequencer
  * \param seq Handle returned from #snd_seq_open()