diff options
author | Takashi Iwai <tiwai@suse.de> | 2009-08-21 01:18:00 +0200 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2009-08-21 01:23:08 +0200 |
commit | bd5389278c96f585afcac4058420e4f3ac201d2a (patch) | |
tree | 4962fae692d6e34b6cfb5f939722b3b53baf8216 | |
parent | 96da0c842d14b40ce8e37726b259229634b3aa21 (diff) |
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.c | 34 |
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, |