summaryrefslogtreecommitdiff
path: root/src/pcm/pcm_dsnoop.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2015-10-30 17:13:50 +0100
committerTakashi Iwai <tiwai@suse.de>2015-11-05 14:37:10 +0100
commit8985742d91dbdd74b2f605374207473393454fff (patch)
treee1bf5fc4aa8f20ba9f0f0ece038b59ef3e8275eb /src/pcm/pcm_dsnoop.c
parent99dc70f023cf118f1e23125301d9fd38fb805f6d (diff)
downloadalsa-lib-8985742d91dbdd74b2f605374207473393454fff.tar.gz
pcm: dmix: Handle slave PCM xrun and unexpected states properly
Currently, dmix & co plugins ignore the XRUN state of the slave PCM. It's (supposedly) because dmix deals with the PCM in a free-wheel mode, which is equivalent with XRUN. But, this difference (whether the correct freewheel or XRUN) should be done by the kernel, and we may have an XRUN state indeed (e.g. via xrun injection). This patch fixes this lack of behavior, to handle PCM xrun and does prepare when the slave PCM is in such a state. Also, the patch consolidates the prepare callback for all dmix, dsnoop and dshare plugins, and fix/cleanup a bit for dshare/dsnoop codes to align with dsnoop code. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'src/pcm/pcm_dsnoop.c')
-rw-r--r--src/pcm/pcm_dsnoop.c23
1 files changed, 7 insertions, 16 deletions
diff --git a/src/pcm/pcm_dsnoop.c b/src/pcm/pcm_dsnoop.c
index 8a2e87ad..576c35b1 100644
--- a/src/pcm/pcm_dsnoop.c
+++ b/src/pcm/pcm_dsnoop.c
@@ -201,12 +201,14 @@ static int snd_pcm_dsnoop_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
static snd_pcm_state_t snd_pcm_dsnoop_state(snd_pcm_t *pcm)
{
snd_pcm_direct_t *dsnoop = pcm->private_data;
- switch (snd_pcm_state(dsnoop->spcm)) {
+ snd_pcm_state_t state;
+ state = snd_pcm_state(dsnoop->spcm);
+ switch (state) {
+ case SND_PCM_STATE_XRUN:
case SND_PCM_STATE_SUSPENDED:
- return SND_PCM_STATE_SUSPENDED;
case SND_PCM_STATE_DISCONNECTED:
- dsnoop->state = SNDRV_PCM_STATE_DISCONNECTED;
- return -ENODEV;
+ dsnoop->state = state;
+ return state;
default:
break;
}
@@ -258,17 +260,6 @@ static int snd_pcm_dsnoop_hwsync(snd_pcm_t *pcm)
}
}
-static int snd_pcm_dsnoop_prepare(snd_pcm_t *pcm)
-{
- snd_pcm_direct_t *dsnoop = pcm->private_data;
-
- snd_pcm_direct_check_interleave(dsnoop, pcm);
- dsnoop->state = SND_PCM_STATE_PREPARED;
- dsnoop->appl_ptr = 0;
- dsnoop->hw_ptr = 0;
- return snd_pcm_direct_set_timer_params(dsnoop);
-}
-
static int snd_pcm_dsnoop_reset(snd_pcm_t *pcm)
{
snd_pcm_direct_t *dsnoop = pcm->private_data;
@@ -497,7 +488,7 @@ static const snd_pcm_fast_ops_t snd_pcm_dsnoop_fast_ops = {
.state = snd_pcm_dsnoop_state,
.hwsync = snd_pcm_dsnoop_hwsync,
.delay = snd_pcm_dsnoop_delay,
- .prepare = snd_pcm_dsnoop_prepare,
+ .prepare = snd_pcm_direct_prepare,
.reset = snd_pcm_dsnoop_reset,
.start = snd_pcm_dsnoop_start,
.drop = snd_pcm_dsnoop_drop,