Commit 866358211d8398823e72528daaa810eef49be8c5
Committed by
malc
1 parent
4c955388
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>
Showing
1 changed file
with
47 additions
and
2 deletions
audio/alsaaudio.c
| @@ -503,6 +503,16 @@ static int alsa_recover (snd_pcm_t *handle) | @@ -503,6 +503,16 @@ static int alsa_recover (snd_pcm_t *handle) | ||
| 503 | return 0; | 503 | return 0; |
| 504 | } | 504 | } |
| 505 | 505 | ||
| 506 | +static int alsa_resume (snd_pcm_t *handle) | ||
| 507 | +{ | ||
| 508 | + int err = snd_pcm_resume (handle); | ||
| 509 | + if (err < 0) { | ||
| 510 | + alsa_logerr (err, "Failed to resume handle %p\n", handle); | ||
| 511 | + return -1; | ||
| 512 | + } | ||
| 513 | + return 0; | ||
| 514 | +} | ||
| 515 | + | ||
| 506 | static snd_pcm_sframes_t alsa_get_avail (snd_pcm_t *handle) | 516 | static snd_pcm_sframes_t alsa_get_avail (snd_pcm_t *handle) |
| 507 | { | 517 | { |
| 508 | snd_pcm_sframes_t avail; | 518 | snd_pcm_sframes_t avail; |
| @@ -580,6 +590,19 @@ static int alsa_run_out (HWVoiceOut *hw) | @@ -580,6 +590,19 @@ static int alsa_run_out (HWVoiceOut *hw) | ||
| 580 | } | 590 | } |
| 581 | continue; | 591 | continue; |
| 582 | 592 | ||
| 593 | + case -ESTRPIPE: | ||
| 594 | + /* stream is suspended and waiting for an | ||
| 595 | + application recovery */ | ||
| 596 | + if (alsa_resume (alsa->handle)) { | ||
| 597 | + alsa_logerr (written, "Failed to write %d frames\n", | ||
| 598 | + len); | ||
| 599 | + goto exit; | ||
| 600 | + } | ||
| 601 | + if (conf.verbose) { | ||
| 602 | + dolog ("Resuming suspended output stream\n"); | ||
| 603 | + } | ||
| 604 | + continue; | ||
| 605 | + | ||
| 583 | case -EAGAIN: | 606 | case -EAGAIN: |
| 584 | goto exit; | 607 | goto exit; |
| 585 | 608 | ||
| @@ -779,8 +802,30 @@ static int alsa_run_in (HWVoiceIn *hw) | @@ -779,8 +802,30 @@ static int alsa_run_in (HWVoiceIn *hw) | ||
| 779 | return 0; | 802 | return 0; |
| 780 | } | 803 | } |
| 781 | 804 | ||
| 782 | - if (!avail && (snd_pcm_state (alsa->handle) == SND_PCM_STATE_PREPARED)) { | ||
| 783 | - avail = hw->samples; | 805 | + if (!avail) { |
| 806 | + snd_pcm_state_t state; | ||
| 807 | + | ||
| 808 | + state = snd_pcm_state (alsa->handle); | ||
| 809 | + switch (state) { | ||
| 810 | + case SND_PCM_STATE_PREPARED: | ||
| 811 | + avail = hw->samples; | ||
| 812 | + break; | ||
| 813 | + case SND_PCM_STATE_SUSPENDED: | ||
| 814 | + /* stream is suspended and waiting for an application recovery */ | ||
| 815 | + if (alsa_resume (alsa->handle)) { | ||
| 816 | + dolog ("Failed to resume suspended input stream\n"); | ||
| 817 | + return 0; | ||
| 818 | + } | ||
| 819 | + if (conf.verbose) { | ||
| 820 | + dolog ("Resuming suspended input stream\n"); | ||
| 821 | + } | ||
| 822 | + break; | ||
| 823 | + default: | ||
| 824 | + if (conf.verbose) { | ||
| 825 | + dolog ("No frames available and ALSA state is %d\n", state); | ||
| 826 | + } | ||
| 827 | + return 0; | ||
| 828 | + } | ||
| 784 | } | 829 | } |
| 785 | 830 | ||
| 786 | decr = audio_MIN (dead, avail); | 831 | decr = audio_MIN (dead, avail); |