diff --git a/src/conf/alsa.conf b/src/conf/alsa.conf index ab5dcc1d..a50037d2 100644 --- a/src/conf/alsa.conf +++ b/src/conf/alsa.conf @@ -57,6 +57,7 @@ defaults.pcm.nonblock 1 defaults.pcm.ipc_key 5678293 defaults.pcm.ipc_gid audio defaults.pcm.ipc_perm 0660 +defaults.pcm.dmix_variable_buffer true defaults.pcm.front.card defaults.pcm.card defaults.pcm.front.device defaults.pcm.device defaults.pcm.rear.card defaults.pcm.card diff --git a/src/conf/pcm/dmix.conf b/src/conf/pcm/dmix.conf index 32700f24..5533450e 100644 --- a/src/conf/pcm/dmix.conf +++ b/src/conf/pcm/dmix.conf @@ -92,4 +92,9 @@ pcm.!dmix { default 16 } } + # Allow apps different buffer sizes + variable_buffer_size { + @func refer + name defaults.pcm.dmix_variable_buffer + } } diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c index 8be4d2a5..22ac5426 100644 --- a/src/pcm/pcm_direct.c +++ b/src/pcm/pcm_direct.c @@ -632,6 +632,19 @@ static int hw_param_interval_refine_one(snd_pcm_hw_params_t *params, return 0; } +static int hw_param_interval_refine_minmax(snd_pcm_hw_params_t *params, + snd_pcm_hw_param_t var, + unsigned int imin, + unsigned int imax) +{ + snd_interval_t t; + + memset(&t, 0, sizeof(t)); + snd_interval_set_minmax(&t, imin, imax); + t.integer = 1; + return hw_param_interval_refine_one(params, var, &t); +} + #undef REFINE_DEBUG int snd_pcm_direct_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) @@ -682,14 +695,6 @@ int snd_pcm_direct_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) &dshare->shmptr->hw.rate); if (err < 0) return err; - err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_BUFFER_SIZE, - &dshare->shmptr->hw.buffer_size); - if (err < 0) - return err; - err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_BUFFER_TIME, - &dshare->shmptr->hw.buffer_time); - if (err < 0) - return err; err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_PERIOD_SIZE, &dshare->shmptr->hw.period_size); if (err < 0) @@ -698,10 +703,33 @@ int snd_pcm_direct_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) &dshare->shmptr->hw.period_time); if (err < 0) return err; - err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_PERIODS, - &dshare->shmptr->hw.periods); - if (err < 0) - return err; + if (! dshare->variable_buffer_size) { + err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_BUFFER_SIZE, + &dshare->shmptr->hw.buffer_size); + if (err < 0) + return err; + err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_BUFFER_TIME, + &dshare->shmptr->hw.buffer_time); + if (err < 0) + return err; + } else if (params->rmask & ((1<info = dshare->shmptr->s.info; #ifdef REFINE_DEBUG snd_output_puts(log, "DMIX REFINE (end):\n"); @@ -1376,6 +1404,7 @@ int snd_pcm_direct_parse_open_conf(snd_config_t *conf, struct snd_pcm_direct_ope rec->ipc_perm = 0600; rec->ipc_gid = -1; rec->slowptr = 0; + rec->variable_buffer_size = 0; snd_config_for_each(i, next, conf) { snd_config_t *n = snd_config_iterator_entry(i); @@ -1462,6 +1491,13 @@ int snd_pcm_direct_parse_open_conf(snd_config_t *conf, struct snd_pcm_direct_ope rec->slowptr = err; continue; } + if (strcmp(id, "variable_buffer_size") == 0) { + err = snd_config_get_bool(n); + if (err < 0) + return err; + rec->variable_buffer_size = err; + continue; + } SNDERR("Unknown field %s", id); return -EINVAL; } diff --git a/src/pcm/pcm_direct.h b/src/pcm/pcm_direct.h index 31d3c4a9..55fd7871 100644 --- a/src/pcm/pcm_direct.h +++ b/src/pcm/pcm_direct.h @@ -117,6 +117,7 @@ struct snd_pcm_direct { snd_timer_t *timer; /* timer used as poll_fd */ int interleaved; /* we have interleaved buffer */ int slowptr; /* use slow but more precise ptr updates */ + int variable_buffer_size; /* allow the variable buffer size */ unsigned int channels; /* client's channels */ unsigned int *bindings; union { @@ -196,6 +197,7 @@ struct snd_pcm_direct_open_conf { mode_t ipc_perm; int ipc_gid; int slowptr; + int variable_buffer_size; snd_config_t *slave; snd_config_t *bindings; }; diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c index 5c00820f..54706af0 100644 --- a/src/pcm/pcm_dmix.c +++ b/src/pcm/pcm_dmix.c @@ -760,12 +760,8 @@ static snd_pcm_fast_ops_t snd_pcm_dmix_fast_ops = { * \brief Creates a new dmix PCM * \param pcmp Returns created PCM handle * \param name Name of PCM - * \param ipc_key IPC key for semaphore and shared memory - * \param ipc_perm IPC permissions for semaphore and shared memory - * \param ipc_gid IPC group ID for semaphore and shared memory + * \param opts Direct PCM configurations * \param params Parameters for slave - * \param bindings Channel bindings - * \param slowptr Slow but more precise pointer updates * \param root Configuration root * \param sconf Slave configuration * \param stream PCM Direction (stream) @@ -776,10 +772,8 @@ static snd_pcm_fast_ops_t snd_pcm_dmix_fast_ops = { * changed in future. */ int snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name, - key_t ipc_key, mode_t ipc_perm, int ipc_gid, + struct snd_pcm_direct_open_conf *opts, struct slave_params *params, - snd_config_t *bindings, - int slowptr, snd_config_t *root, snd_config_t *sconf, snd_pcm_stream_t stream, int mode) { @@ -801,13 +795,13 @@ int snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name, goto _err_nosem; } - ret = snd_pcm_direct_parse_bindings(dmix, bindings); + ret = snd_pcm_direct_parse_bindings(dmix, opts->bindings); if (ret < 0) goto _err_nosem; - dmix->ipc_key = ipc_key; - dmix->ipc_perm = ipc_perm; - dmix->ipc_gid = ipc_gid; + dmix->ipc_key = opts->ipc_key; + dmix->ipc_perm = opts->ipc_perm; + dmix->ipc_gid = opts->ipc_gid; dmix->semid = -1; dmix->shmid = -1; @@ -842,7 +836,8 @@ int snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name, pcm->fast_ops = &snd_pcm_dmix_fast_ops; pcm->private_data = dmix; dmix->state = SND_PCM_STATE_OPEN; - dmix->slowptr = slowptr; + dmix->slowptr = opts->slowptr; + dmix->variable_buffer_size = opts->variable_buffer_size; dmix->sync_ptr = snd_pcm_dmix_sync_ptr; if (first_instance) { @@ -1132,8 +1127,7 @@ int _snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name, } dopen.ipc_key += ipc_offset; - err = snd_pcm_dmix_open(pcmp, name, dopen.ipc_key, dopen.ipc_perm, dopen.ipc_gid, - ¶ms, dopen.bindings, dopen.slowptr, + err = snd_pcm_dmix_open(pcmp, name, &dopen, ¶ms, root, sconf, stream, mode); if (err < 0) snd_config_delete(sconf); diff --git a/src/pcm/pcm_dshare.c b/src/pcm/pcm_dshare.c index 31905fde..fd665734 100644 --- a/src/pcm/pcm_dshare.c +++ b/src/pcm/pcm_dshare.c @@ -578,12 +578,8 @@ static snd_pcm_fast_ops_t snd_pcm_dshare_fast_ops = { * \brief Creates a new dshare PCM * \param pcmp Returns created PCM handle * \param name Name of PCM - * \param ipc_key IPC key for semaphore and shared memory - * \param ipc_perm IPC permissions for semaphore and shared memory - * \param ipc_gid IPC group ID for semaphore and shared memory + * \param opts Direct PCM configurations * \param params Parameters for slave - * \param bindings Channel bindings - * \param slowptr Slow but more precise pointer updates * \param root Configuration root * \param sconf Slave configuration * \param stream PCM Direction (stream) @@ -594,10 +590,8 @@ static snd_pcm_fast_ops_t snd_pcm_dshare_fast_ops = { * changed in future. */ int snd_pcm_dshare_open(snd_pcm_t **pcmp, const char *name, - key_t ipc_key, mode_t ipc_perm, int ipc_gid, + struct snd_pcm_direct_open_conf *opts, struct slave_params *params, - snd_config_t *bindings, - int slowptr, snd_config_t *root, snd_config_t *sconf, snd_pcm_stream_t stream, int mode) { @@ -620,7 +614,7 @@ int snd_pcm_dshare_open(snd_pcm_t **pcmp, const char *name, goto _err_nosem; } - ret = snd_pcm_direct_parse_bindings(dshare, bindings); + ret = snd_pcm_direct_parse_bindings(dshare, opts->bindings); if (ret < 0) goto _err_nosem; @@ -630,9 +624,9 @@ int snd_pcm_dshare_open(snd_pcm_t **pcmp, const char *name, goto _err_nosem; } - dshare->ipc_key = ipc_key; - dshare->ipc_perm = ipc_perm; - dshare->ipc_gid = ipc_gid; + dshare->ipc_key = opts->ipc_key; + dshare->ipc_perm = opts->ipc_perm; + dshare->ipc_gid = opts->ipc_gid; dshare->semid = -1; dshare->shmid = -1; @@ -667,7 +661,8 @@ int snd_pcm_dshare_open(snd_pcm_t **pcmp, const char *name, pcm->fast_ops = &snd_pcm_dshare_fast_ops; pcm->private_data = dshare; dshare->state = SND_PCM_STATE_OPEN; - dshare->slowptr = slowptr; + dshare->slowptr = opts->slowptr; + dshare->variable_buffer_size = opts->variable_buffer_size; dshare->sync_ptr = snd_pcm_dshare_sync_ptr; if (first_instance) { @@ -881,8 +876,7 @@ int _snd_pcm_dshare_open(snd_pcm_t **pcmp, const char *name, } dopen.ipc_key += ipc_offset; - err = snd_pcm_dshare_open(pcmp, name, dopen.ipc_key, dopen.ipc_perm, dopen.ipc_gid, - ¶ms, dopen.bindings, dopen.slowptr, + err = snd_pcm_dshare_open(pcmp, name, &dopen, ¶ms, root, sconf, stream, mode); if (err < 0) snd_config_delete(sconf); diff --git a/src/pcm/pcm_dsnoop.c b/src/pcm/pcm_dsnoop.c index a9ea1429..8ef83494 100644 --- a/src/pcm/pcm_dsnoop.c +++ b/src/pcm/pcm_dsnoop.c @@ -468,12 +468,8 @@ static snd_pcm_fast_ops_t snd_pcm_dsnoop_fast_ops = { * \brief Creates a new dsnoop PCM * \param pcmp Returns created PCM handle * \param name Name of PCM - * \param ipc_key IPC key for semaphore and shared memory - * \param ipc_perm IPC permissions for semaphore and shared memory - * \param ipc_gid IPC group ID for semaphore and shared memory + * \param opts Direct PCM configurations * \param params Parameters for slave - * \param bindings Channel bindings - * \param slowptr Slow but more precise pointer updates * \param root Configuration root * \param sconf Slave configuration * \param stream PCM Direction (stream) @@ -484,10 +480,8 @@ static snd_pcm_fast_ops_t snd_pcm_dsnoop_fast_ops = { * changed in future. */ int snd_pcm_dsnoop_open(snd_pcm_t **pcmp, const char *name, - key_t ipc_key, mode_t ipc_perm, int ipc_gid, + struct snd_pcm_direct_open_conf *opts, struct slave_params *params, - snd_config_t *bindings, - int slowptr, snd_config_t *root, snd_config_t *sconf, snd_pcm_stream_t stream, int mode) { @@ -508,13 +502,13 @@ int snd_pcm_dsnoop_open(snd_pcm_t **pcmp, const char *name, goto _err_nosem; } - ret = snd_pcm_direct_parse_bindings(dsnoop, bindings); + ret = snd_pcm_direct_parse_bindings(dsnoop, opts->bindings); if (ret < 0) goto _err_nosem; - dsnoop->ipc_key = ipc_key; - dsnoop->ipc_perm = ipc_perm; - dsnoop->ipc_gid = ipc_gid; + dsnoop->ipc_key = opts->ipc_key; + dsnoop->ipc_perm = opts->ipc_perm; + dsnoop->ipc_gid = opts->ipc_gid; dsnoop->semid = -1; dsnoop->shmid = -1; @@ -549,7 +543,8 @@ int snd_pcm_dsnoop_open(snd_pcm_t **pcmp, const char *name, pcm->fast_ops = &snd_pcm_dsnoop_fast_ops; pcm->private_data = dsnoop; dsnoop->state = SND_PCM_STATE_OPEN; - dsnoop->slowptr = slowptr; + dsnoop->slowptr = opts->slowptr; + dsnoop->variable_buffer_size = opts->variable_buffer_size; dsnoop->sync_ptr = snd_pcm_dsnoop_sync_ptr; if (first_instance) { @@ -753,8 +748,7 @@ int _snd_pcm_dsnoop_open(snd_pcm_t **pcmp, const char *name, } dopen.ipc_key += ipc_offset; - err = snd_pcm_dsnoop_open(pcmp, name, dopen.ipc_key, dopen.ipc_perm, dopen.ipc_gid, - ¶ms, dopen.bindings, dopen.slowptr, + err = snd_pcm_dsnoop_open(pcmp, name, &dopen, ¶ms, root, sconf, stream, mode); if (err < 0) snd_config_delete(sconf);