]> git.alsa-project.org Git - alsa-lib.git/commitdiff
Fix buffer size handling of direct plugins
authorTakashi Iwai <tiwai@suse.de>
Thu, 6 Apr 2006 16:49:11 +0000 (18:49 +0200)
committerTakashi Iwai <tiwai@suse.de>
Thu, 6 Apr 2006 16:49:11 +0000 (18:49 +0200)
Introduce "max_periods" option to specify the max number of periods
per buffer to each plugin.

- When max_periods = -1, the fixed buffer size as the slave size is
  used (old behavior).
- When max_periods = 0 (or 1), the number of periods is variable
  between 2 and the slave buffer size.
- When max_periods greater than 2 is given, it specifies the max
  periods of that pcm explicitly.

When no option is given in the PCM defintion, the value
"defaults.pcm.dmix_max_periods" is referred as default.
The default value is 0, as defined in alsa.conf.
You can override this in ~/.asoundrc or /etc/asound.conf as you like.

src/conf/alsa.conf
src/conf/pcm/dmix.conf
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

index a50037d26d7ffd642e134189924316f830bc2b95..e37100415903a992254790d644a26a5f500a0b94 100644 (file)
@@ -57,7 +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.dmix_max_periods 0
 defaults.pcm.front.card defaults.pcm.card
 defaults.pcm.front.device defaults.pcm.device
 defaults.pcm.rear.card defaults.pcm.card
index 5533450ee110ae0c66a13027cd01e20d83d02557..32700f240491e7318ee2fd45f42e6b7531be4601 100644 (file)
@@ -92,9 +92,4 @@ pcm.!dmix {
                        default 16
                }
        }
-       # Allow apps different buffer sizes
-       variable_buffer_size {
-               @func refer
-               name defaults.pcm.dmix_variable_buffer
-       }
 }
index 744757078ef3a00c2748580c809a1efd733a1ec7..6c4ad89e8ebbade2b427a1ee939efb38a34b8c4c 100644 (file)
@@ -697,7 +697,7 @@ 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;
-       if (! dshare->variable_buffer_size) {
+       if (dshare->max_periods < 0) {
                err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_BUFFER_SIZE,
                                                   &dshare->shmptr->hw.buffer_size);
                if (err < 0)
@@ -711,13 +711,13 @@ int snd_pcm_direct_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
                                    (1<<SND_PCM_HW_PARAM_BUFFER_SIZE)|
                                    (1<<SND_PCM_HW_PARAM_BUFFER_TIME))) {
                int changed;
+               unsigned int max_periods = dshare->max_periods;
+               if (max_periods < 2)
+                       max_periods = dshare->slave_buffer_size / dshare->slave_period_size;
                do {
                        changed = 0;
-                       /* Set min/max size to [2:1024] since INT_MAX as the
-                        * upper-limit results in a too big buffer on some apps.
-                        */
                        err = hw_param_interval_refine_minmax(params, SND_PCM_HW_PARAM_PERIODS,
-                                                             2, 1024);
+                                                             2, max_periods);
                        if (err < 0)
                                return err;
                        changed |= err;
@@ -1382,17 +1382,19 @@ static int _snd_pcm_direct_get_slave_ipc_offset(snd_config_t *root,
        return (direction << 1) + (device << 2) + (subdevice << 8) + (card << 12);
 }
 
-int snd_pcm_direct_get_slave_ipc_offset(snd_config_t *root,
+static 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)
+int snd_pcm_direct_parse_open_conf(snd_config_t *root, snd_config_t *conf,
+                                  int stream, struct snd_pcm_direct_open_conf *rec)
 {
        snd_config_iterator_t i, next;
        int ipc_key_add_uid = 0;
+       snd_config_t *n;
        int err;
 
        rec->slave = NULL;
@@ -1401,10 +1403,18 @@ 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;
+       rec->max_periods = 0;
+
+       /* read defaults */
+       if (snd_config_search(root, "defaults.pcm.dmix_max_periods", &n) >= 0) {
+               long val;
+               err = snd_config_get_integer(n, &val);
+               if (err >= 0)
+                       rec->max_periods = val;
+       }
 
        snd_config_for_each(i, next, conf) {
-               snd_config_t *n = snd_config_iterator_entry(i);
+               n = snd_config_iterator_entry(i);
                const char *id;
                if (snd_config_get_id(n, &id) < 0)
                        continue;
@@ -1488,11 +1498,12 @@ 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 (strcmp(id, "max_periods") == 0) {
+                       long val;
+                       err = snd_config_get_integer(n, &val);
                        if (err < 0)
                                return err;
-                       rec->variable_buffer_size = err;
+                       rec->max_periods = val;
                        continue;
                }
                SNDERR("Unknown field %s", id);
@@ -1502,11 +1513,16 @@ int snd_pcm_direct_parse_open_conf(snd_config_t *conf, struct snd_pcm_direct_ope
                SNDERR("slave is not defined");
                return -EINVAL;
        }
-       if (ipc_key_add_uid)
-               rec->ipc_key += getuid();
        if (!rec->ipc_key) {
                SNDERR("Unique IPC key is not defined");
                return -EINVAL;
        }
+       if (ipc_key_add_uid)
+               rec->ipc_key += getuid();
+       err = snd_pcm_direct_get_slave_ipc_offset(root, rec->slave, stream);
+       if (err < 0)
+               return err;
+       rec->ipc_key += err;
+
        return 0;
 }
index 55fd787154001fd363158e40f32dd469b64f1682..d520e53e58c1a6f2aa267c313cd69846b90b6dbf 100644 (file)
@@ -117,7 +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 */
+       int max_periods;                /* max periods (-1 = fixed periods, 0 = max buffer size) */
        unsigned int channels;          /* client's channels */
        unsigned int *bindings;
        union {
@@ -187,7 +187,6 @@ 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 *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);
@@ -197,9 +196,9 @@ struct snd_pcm_direct_open_conf {
        mode_t ipc_perm;
        int ipc_gid;
        int slowptr;
-       int variable_buffer_size;
+       int max_periods;
        snd_config_t *slave;
        snd_config_t *bindings;
 };
 
-int snd_pcm_direct_parse_open_conf(snd_config_t *conf, struct snd_pcm_direct_open_conf *rec);
+int snd_pcm_direct_parse_open_conf(snd_config_t *root, snd_config_t *conf, int stream, struct snd_pcm_direct_open_conf *rec);
index e3f4aa06d269896195b6522fe5ee873191175955..d8cc8adf88d73598fee74bd84cf195b81c4d4e47 100644 (file)
@@ -487,8 +487,7 @@ static int snd_pcm_dmix_prepare(snd_pcm_t *pcm)
 static void reset_slave_ptr(snd_pcm_t *pcm, snd_pcm_direct_t *dmix)
 {
        dmix->slave_appl_ptr = dmix->slave_hw_ptr = *dmix->spcm->hw.ptr;
-       if (! dmix->variable_buffer_size ||
-           pcm->buffer_size > pcm->period_size * 2)
+       if (pcm->buffer_size > pcm->period_size * 2)
                return;
        /* If we have too litte periods, better to align the start position
         * to the period boundary so that the interrupt can be handled properly
@@ -851,7 +850,7 @@ int snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name,
        pcm->private_data = dmix;
        dmix->state = SND_PCM_STATE_OPEN;
        dmix->slowptr = opts->slowptr;
-       dmix->variable_buffer_size = opts->variable_buffer_size;
+       dmix->max_periods = opts->max_periods;
        dmix->sync_ptr = snd_pcm_dmix_sync_ptr;
 
        if (first_instance) {
@@ -1092,10 +1091,9 @@ int _snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name,
        struct slave_params params;
        struct snd_pcm_direct_open_conf dopen;
        int bsize, psize;
-       int ipc_offset;
        int err;
 
-       err = snd_pcm_direct_parse_open_conf(conf, &dopen);
+       err = snd_pcm_direct_parse_open_conf(root, conf, stream, &dopen);
        if (err < 0)
                return err;
 
@@ -1134,13 +1132,6 @@ 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(root, sconf, stream);
-       if (ipc_offset < 0) {
-               snd_config_delete(sconf);
-               return ipc_offset;
-       }
-       dopen.ipc_key += ipc_offset;
-
        err = snd_pcm_dmix_open(pcmp, name, &dopen, &params,
                                root, sconf, stream, mode);
        if (err < 0)
index fd665734ab67e66ceff92fab9b70aeeaede6758d..4f9ba9c897dfd7a7372dd4fff3a239acad0aa255 100644 (file)
@@ -662,7 +662,7 @@ int snd_pcm_dshare_open(snd_pcm_t **pcmp, const char *name,
        pcm->private_data = dshare;
        dshare->state = SND_PCM_STATE_OPEN;
        dshare->slowptr = opts->slowptr;
-       dshare->variable_buffer_size = opts->variable_buffer_size;
+       dshare->max_periods = opts->max_periods;
        dshare->sync_ptr = snd_pcm_dshare_sync_ptr;
 
        if (first_instance) {
@@ -835,10 +835,9 @@ int _snd_pcm_dshare_open(snd_pcm_t **pcmp, const char *name,
        struct slave_params params;
        struct snd_pcm_direct_open_conf dopen;
        int bsize, psize;
-       int ipc_offset;
        int err;
 
-       err = snd_pcm_direct_parse_open_conf(conf, &dopen);
+       err = snd_pcm_direct_parse_open_conf(root, conf, stream, &dopen);
        if (err < 0)
                return err;
 
@@ -869,13 +868,6 @@ 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(root, sconf, stream);
-       if (ipc_offset < 0) {
-               snd_config_delete(sconf);
-               return ipc_offset;
-       }
-       dopen.ipc_key += ipc_offset;
-
        err = snd_pcm_dshare_open(pcmp, name, &dopen, &params,
                                  root, sconf, stream, mode);
        if (err < 0)
index 8ef834942eed737f9f219ec5a6b91088c033cbce..4d44e76f23e255d3def6709eb0dc7ff68eb95806 100644 (file)
@@ -544,7 +544,7 @@ int snd_pcm_dsnoop_open(snd_pcm_t **pcmp, const char *name,
        pcm->private_data = dsnoop;
        dsnoop->state = SND_PCM_STATE_OPEN;
        dsnoop->slowptr = opts->slowptr;
-       dsnoop->variable_buffer_size = opts->variable_buffer_size;
+       dsnoop->max_periods = opts->max_periods;
        dsnoop->sync_ptr = snd_pcm_dsnoop_sync_ptr;
 
        if (first_instance) {
@@ -707,10 +707,9 @@ int _snd_pcm_dsnoop_open(snd_pcm_t **pcmp, const char *name,
        struct slave_params params;
        struct snd_pcm_direct_open_conf dopen;
        int bsize, psize;
-       int ipc_offset;
        int err;
 
-       err = snd_pcm_direct_parse_open_conf(conf, &dopen);
+       err = snd_pcm_direct_parse_open_conf(root, conf, stream, &dopen);
        if (err < 0)
                return err;
 
@@ -741,13 +740,6 @@ 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(root, sconf, stream);
-       if (ipc_offset < 0) {
-               snd_config_delete(sconf);
-               return ipc_offset;
-       }
-       dopen.ipc_key += ipc_offset;
-
        err = snd_pcm_dsnoop_open(pcmp, name, &dopen, &params,
                                  root, sconf, stream, mode);
        if (err < 0)