summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2009-08-21 01:18:00 +0200
committerTakashi Iwai <tiwai@suse.de>2009-08-21 01:23:08 +0200
commitbd5389278c96f585afcac4058420e4f3ac201d2a (patch)
tree4962fae692d6e34b6cfb5f939722b3b53baf8216
parent96da0c842d14b40ce8e37726b259229634b3aa21 (diff)
downloadalsa-lib-bd5389278c96f585afcac4058420e4f3ac201d2a.tar.gz
pcm: workaround for avoiding automatic start in mmap mode
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>
-rw-r--r--src/pcm/pcm_mmap_emul.c34
1 files changed, 29 insertions, 5 deletions
diff --git a/src/pcm/pcm_mmap_emul.c b/src/pcm/pcm_mmap_emul.c
index e356e0bf..f6e7ae93 100644
--- a/src/pcm/pcm_mmap_emul.c
+++ b/src/pcm/pcm_mmap_emul.c
@@ -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,