diff options
author | Bjørn Mork <bjorn@mork.no> | 2009-07-30 09:44:26 +0200 |
---|---|---|
committer | malc <av1474@comtv.ru> | 2009-07-30 14:45:50 +0400 |
commit | 866358211d8398823e72528daaa810eef49be8c5 (patch) | |
tree | 8130d8279e1157e29646ef6ab7ba296987b415df /audio | |
parent | 4c955388572068c57bb8cd205b61fa5dfa1a84f1 (diff) | |
download | qemu-866358211d8398823e72528daaa810eef49be8c5.zip qemu-866358211d8398823e72528daaa810eef49be8c5.tar.gz qemu-866358211d8398823e72528daaa810eef49be8c5.tar.bz2 |
alsa: add host suspend/resume support
Both input and output streams may be in SND_PCM_STATE_SUSPENDED
after the host is suspended and resumed, meaning "Hardware is
suspended". snd_pcm_readi() and snd_pcm_writei() will return
-ESTRPIPE if called while the stream is in this state.
Call snd_pcm_resume() to enable audio output and capture after
host resume.
Signed-off-by: Bjørn Mork <bjorn@mork.no>
Signed-off-by: malc <av1474@comtv.ru>
Diffstat (limited to 'audio')
-rw-r--r-- | audio/alsaaudio.c | 49 |
1 files changed, 47 insertions, 2 deletions
diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index d0b7cd0..5a49eb5 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -503,6 +503,16 @@ static int alsa_recover (snd_pcm_t *handle) return 0; } +static int alsa_resume (snd_pcm_t *handle) +{ + int err = snd_pcm_resume (handle); + if (err < 0) { + alsa_logerr (err, "Failed to resume handle %p\n", handle); + return -1; + } + return 0; +} + static snd_pcm_sframes_t alsa_get_avail (snd_pcm_t *handle) { snd_pcm_sframes_t avail; @@ -580,6 +590,19 @@ static int alsa_run_out (HWVoiceOut *hw) } continue; + case -ESTRPIPE: + /* stream is suspended and waiting for an + application recovery */ + if (alsa_resume (alsa->handle)) { + alsa_logerr (written, "Failed to write %d frames\n", + len); + goto exit; + } + if (conf.verbose) { + dolog ("Resuming suspended output stream\n"); + } + continue; + case -EAGAIN: goto exit; @@ -779,8 +802,30 @@ static int alsa_run_in (HWVoiceIn *hw) return 0; } - if (!avail && (snd_pcm_state (alsa->handle) == SND_PCM_STATE_PREPARED)) { - avail = hw->samples; + if (!avail) { + snd_pcm_state_t state; + + state = snd_pcm_state (alsa->handle); + switch (state) { + case SND_PCM_STATE_PREPARED: + avail = hw->samples; + break; + case SND_PCM_STATE_SUSPENDED: + /* stream is suspended and waiting for an application recovery */ + if (alsa_resume (alsa->handle)) { + dolog ("Failed to resume suspended input stream\n"); + return 0; + } + if (conf.verbose) { + dolog ("Resuming suspended input stream\n"); + } + break; + default: + if (conf.verbose) { + dolog ("No frames available and ALSA state is %d\n", state); + } + return 0; + } } decr = audio_MIN (dead, avail); |