]> git.alsa-project.org Git - alsa-lib.git/commitdiff
pcm: workaround for avoiding automatic start in mmap mode
authorTakashi Iwai <tiwai@suse.de>
Thu, 20 Aug 2009 23:18:00 +0000 (01:18 +0200)
committerTakashi Iwai <tiwai@suse.de>
Thu, 20 Aug 2009 23:23:08 +0000 (01:23 +0200)
In the normal mmap mode, the stream isn't started automatically even after
the data >= start_threshold has been written.   However, in the
mmap-emulation mode, the stream is started because it uses
snd_pcm_write_areas() internally.

As a workaround for this inconsistency, start_threshold value is changed
dynamically in sw_parmams and mmap_commit callbacks in mmap-emul plugin.
Meanwhile, start_threshold for slave PCM is set to boundary so that only
this plugin (or the one over it) can control the start of the stream.

This will fix problems in some apps using pulse plugin in the mmap mode.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
src/pcm/pcm_mmap_emul.c

index e356e0bff910f92a234844ac9a7756d0b43b4893..f6e7ae932ee96f64b313471a34a1adeccc73582e 100644 (file)
@@ -44,6 +44,7 @@ typedef struct {
        unsigned int mmap_emul :1;
        snd_pcm_uframes_t hw_ptr;
        snd_pcm_uframes_t appl_ptr;
+       snd_pcm_uframes_t start_threshold;
 } mmap_emul_t;
 #endif
 
@@ -205,6 +206,24 @@ static int snd_pcm_mmap_emul_hw_params(snd_pcm_t *pcm,
        return err;
 }
 
+static int snd_pcm_mmap_emul_sw_params(snd_pcm_t *pcm,
+                                      snd_pcm_sw_params_t *params)
+{
+       mmap_emul_t *map = pcm->private_data;
+       int err;
+
+       map->start_threshold = params->start_threshold;
+
+       /* HACK: don't auto-start in the slave PCM */
+       params->start_threshold = pcm->boundary;
+       err = snd_pcm_generic_sw_params(pcm, params);
+       if (err < 0)
+               return err;
+       /* restore the value for this PCM */
+       params->start_threshold = map->start_threshold;
+       return err;
+}
+
 static int snd_pcm_mmap_emul_prepare(snd_pcm_t *pcm)
 {
        mmap_emul_t *map = pcm->private_data;
@@ -256,13 +275,18 @@ sync_slave_write(snd_pcm_t *pcm)
        snd_pcm_uframes_t offset;
        snd_pcm_sframes_t size;
 
+       /* HACK: don't start stream automatically at commit in mmap mode */
+       pcm->start_threshold = pcm->boundary;
+
        size = map->appl_ptr - *slave->appl.ptr;
        if (size < 0)
                size += pcm->boundary;
-       if (!size)
-               return 0;
-       offset = *slave->appl.ptr % pcm->buffer_size;
-       return snd_pcm_write_mmap(pcm, offset, size);
+       if (size) {
+               offset = *slave->appl.ptr % pcm->buffer_size;
+               size = snd_pcm_write_mmap(pcm, offset, size);
+       }
+       pcm->start_threshold = map->start_threshold; /* restore */
+       return size;
 }
 
 /* read the available chunk on the slave PCM to mmap buffer */
@@ -337,7 +361,7 @@ static const snd_pcm_ops_t snd_pcm_mmap_emul_ops = {
        .hw_refine = snd_pcm_mmap_emul_hw_refine,
        .hw_params = snd_pcm_mmap_emul_hw_params,
        .hw_free = snd_pcm_generic_hw_free,
-       .sw_params = snd_pcm_generic_sw_params,
+       .sw_params = snd_pcm_mmap_emul_sw_params,
        .channel_info = snd_pcm_generic_channel_info,
        .dump = snd_pcm_mmap_emul_dump,
        .nonblock = snd_pcm_generic_nonblock,