mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-10-28 05:40:23 -04:00
Fix infinite parse of recursive definitions
Fixed the infinite parse (and eventually segfault) of recursive definitions. Also fixed the parse of a string slave PCM of direct plugins.
This commit is contained in:
parent
bf174b7046
commit
eccc92a34d
29 changed files with 127 additions and 36 deletions
|
|
@ -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
|
||||
|
|
|
|||
19
src/conf.c
19
src/conf.c
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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]);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue