diff options
author | Kővágó, Zoltán <dirty.ice.hu@gmail.com> | 2019-09-19 23:24:10 +0200 |
---|---|---|
committer | Gerd Hoffmann <kraxel@redhat.com> | 2019-09-23 12:28:47 +0200 |
commit | 286a5d201e432ed2963e5d860f239bb276edffeb (patch) | |
tree | 29b65c1d4e42b26d4bbada86dd0e36820655c483 /audio/alsaaudio.c | |
parent | ff095e5231a189a0a4e57fc13b51590bff816552 (diff) |
alsaaudio: port to the new audio backend api
Signed-off-by: Kővágó, Zoltán <DirtY.iCE.hu@gmail.com>
Message-id: ab9768e73dfe7b7305bd6a51629846e0d77622a5.1568927990.git.DirtY.iCE.hu@gmail.com
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Diffstat (limited to 'audio/alsaaudio.c')
-rw-r--r-- | audio/alsaaudio.c | 302 |
1 files changed, 80 insertions, 222 deletions
diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index 591344dccd..19124d09d8 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -44,9 +44,6 @@ struct pollhlp { typedef struct ALSAVoiceOut { HWVoiceOut hw; - int wpos; - int pending; - void *pcm_buf; snd_pcm_t *handle; struct pollhlp pollhlp; Audiodev *dev; @@ -55,7 +52,6 @@ typedef struct ALSAVoiceOut { typedef struct ALSAVoiceIn { HWVoiceIn hw; snd_pcm_t *handle; - void *pcm_buf; struct pollhlp pollhlp; Audiodev *dev; } ALSAVoiceIn; @@ -602,102 +598,64 @@ static int alsa_open(bool in, struct alsa_params_req *req, return -1; } -static snd_pcm_sframes_t alsa_get_avail (snd_pcm_t *handle) +static size_t alsa_write(HWVoiceOut *hw, void *buf, size_t len) { - snd_pcm_sframes_t avail; - - avail = snd_pcm_avail_update (handle); - if (avail < 0) { - if (avail == -EPIPE) { - if (!alsa_recover (handle)) { - avail = snd_pcm_avail_update (handle); - } - } - - if (avail < 0) { - alsa_logerr (avail, - "Could not obtain number of available frames\n"); - return -1; - } - } + ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw; + size_t pos = 0; + size_t len_frames = len >> hw->info.shift; + + while (len_frames) { + char *src = advance(buf, pos); + snd_pcm_sframes_t written; + + written = snd_pcm_writei(alsa->handle, src, len_frames); + + if (written <= 0) { + switch (written) { + case 0: + trace_alsa_wrote_zero(len_frames); + return pos; + + case -EPIPE: + if (alsa_recover(alsa->handle)) { + alsa_logerr(written, "Failed to write %zu frames\n", + len_frames); + return pos; + } + trace_alsa_xrun_out(); + continue; + + case -ESTRPIPE: + /* + * stream is suspended and waiting for an application + * recovery + */ + if (alsa_resume(alsa->handle)) { + alsa_logerr(written, "Failed to write %zu frames\n", + len_frames); + return pos; + } + trace_alsa_resume_out(); + continue; - return avail; -} + case -EAGAIN: + return pos; -static void alsa_write_pending (ALSAVoiceOut *alsa) -{ - HWVoiceOut *hw = &alsa->hw; - - while (alsa->pending) { - int left_till_end_samples = hw->samples - alsa->wpos; - int len = MIN (alsa->pending, left_till_end_samples); - char *src = advance (alsa->pcm_buf, alsa->wpos << hw->info.shift); - - while (len) { - snd_pcm_sframes_t written; - - written = snd_pcm_writei (alsa->handle, src, len); - - if (written <= 0) { - switch (written) { - case 0: - trace_alsa_wrote_zero(len); - return; - - case -EPIPE: - if (alsa_recover (alsa->handle)) { - alsa_logerr (written, "Failed to write %d frames\n", - len); - return; - } - trace_alsa_xrun_out(); - 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); - return; - } - trace_alsa_resume_out(); - continue; - - case -EAGAIN: - return; - - default: - alsa_logerr (written, "Failed to write %d frames from %p\n", - len, src); - return; - } + default: + alsa_logerr(written, "Failed to write %zu frames from %p\n", + len, src); + return pos; } - - alsa->wpos = (alsa->wpos + written) % hw->samples; - alsa->pending -= written; - len -= written; } - } -} - -static size_t alsa_run_out(HWVoiceOut *hw, size_t live) -{ - ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw; - size_t decr; - snd_pcm_sframes_t avail; - avail = alsa_get_avail (alsa->handle); - if (avail < 0) { - dolog ("Could not get number of available playback frames\n"); - return 0; + pos += written << hw->info.shift; + if (written < len_frames) { + break; + } + len_frames -= written; } - decr = MIN (live, avail); - decr = audio_pcm_hw_clip_out (hw, alsa->pcm_buf, decr, alsa->pending); - alsa->pending += decr; - alsa_write_pending (alsa); - return decr; + return pos; } static void alsa_fini_out (HWVoiceOut *hw) @@ -706,9 +664,6 @@ static void alsa_fini_out (HWVoiceOut *hw) ldebug ("alsa_fini\n"); alsa_anal_close (&alsa->handle, &alsa->pollhlp); - - g_free(alsa->pcm_buf); - alsa->pcm_buf = NULL; } static int alsa_init_out(HWVoiceOut *hw, struct audsettings *as, @@ -737,14 +692,6 @@ static int alsa_init_out(HWVoiceOut *hw, struct audsettings *as, audio_pcm_init_info (&hw->info, &obt_as); hw->samples = obt.samples; - alsa->pcm_buf = audio_calloc(__func__, obt.samples, 1 << hw->info.shift); - if (!alsa->pcm_buf) { - dolog("Could not allocate DAC buffer (%zu samples, each %d bytes)\n", - hw->samples, 1 << hw->info.shift); - alsa_anal_close1 (&handle); - return -1; - } - alsa->pollhlp.s = hw->s; alsa->handle = handle; alsa->dev = dev; @@ -839,14 +786,6 @@ static int alsa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) audio_pcm_init_info (&hw->info, &obt_as); hw->samples = obt.samples; - alsa->pcm_buf = audio_calloc(__func__, hw->samples, 1 << hw->info.shift); - if (!alsa->pcm_buf) { - dolog("Could not allocate ADC buffer (%zu samples, each %d bytes)\n", - hw->samples, 1 << hw->info.shift); - alsa_anal_close1 (&handle); - return -1; - } - alsa->pollhlp.s = hw->s; alsa->handle = handle; alsa->dev = dev; @@ -858,129 +797,48 @@ static void alsa_fini_in (HWVoiceIn *hw) ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw; alsa_anal_close (&alsa->handle, &alsa->pollhlp); - - g_free(alsa->pcm_buf); - alsa->pcm_buf = NULL; } -static size_t alsa_run_in(HWVoiceIn *hw) +static size_t alsa_read(HWVoiceIn *hw, void *buf, size_t len) { ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw; - int hwshift = hw->info.shift; - int i; - size_t live = audio_pcm_hw_get_live_in (hw); - size_t dead = hw->samples - live; - size_t decr; - struct { - size_t add; - size_t len; - } bufs[2] = { - { .add = hw->wpos, .len = 0 }, - { .add = 0, .len = 0 } - }; - snd_pcm_sframes_t avail; - snd_pcm_uframes_t read_samples = 0; - - if (!dead) { - return 0; - } + size_t pos = 0; - avail = alsa_get_avail (alsa->handle); - if (avail < 0) { - dolog ("Could not get number of captured frames\n"); - return 0; - } - - 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; - } - trace_alsa_resume_in(); - break; - default: - trace_alsa_no_frames(state); - return 0; - } - } + while (len) { + void *dst = advance(buf, pos); + snd_pcm_sframes_t nread; - decr = MIN(dead, avail); - if (!decr) { - return 0; - } + nread = snd_pcm_readi(alsa->handle, dst, len >> hw->info.shift); - if (hw->wpos + decr > hw->samples) { - bufs[0].len = (hw->samples - hw->wpos); - bufs[1].len = (decr - (hw->samples - hw->wpos)); - } - else { - bufs[0].len = decr; - } + if (nread <= 0) { + switch (nread) { + case 0: + trace_alsa_read_zero(len); + return pos;; - for (i = 0; i < 2; ++i) { - void *src; - struct st_sample *dst; - snd_pcm_sframes_t nread; - snd_pcm_uframes_t len; - - len = bufs[i].len; - - src = advance (alsa->pcm_buf, bufs[i].add << hwshift); - dst = hw->conv_buf + bufs[i].add; - - while (len) { - nread = snd_pcm_readi (alsa->handle, src, len); - - if (nread <= 0) { - switch (nread) { - case 0: - trace_alsa_read_zero(len); - goto exit; - - case -EPIPE: - if (alsa_recover (alsa->handle)) { - alsa_logerr (nread, "Failed to read %ld frames\n", len); - goto exit; - } - trace_alsa_xrun_in(); - continue; - - case -EAGAIN: - goto exit; - - default: - alsa_logerr ( - nread, - "Failed to read %ld frames from %p\n", - len, - src - ); - goto exit; + case -EPIPE: + if (alsa_recover(alsa->handle)) { + alsa_logerr(nread, "Failed to read %zu frames\n", len); + return pos; } - } + trace_alsa_xrun_in(); + continue; - hw->conv (dst, src, nread); + case -EAGAIN: + return pos; - src = advance (src, nread << hwshift); - dst += nread; - - read_samples += nread; - len -= nread; + default: + alsa_logerr(nread, "Failed to read %zu frames to %p\n", + len, dst); + return pos;; + } } + + pos += nread << hw->info.shift; + len -= nread << hw->info.shift; } - exit: - hw->wpos = (hw->wpos + read_samples) % hw->samples; - return read_samples; + return pos; } static int alsa_ctl_in (HWVoiceIn *hw, int cmd, ...) @@ -1065,12 +923,12 @@ static void alsa_audio_fini (void *opaque) static struct audio_pcm_ops alsa_pcm_ops = { .init_out = alsa_init_out, .fini_out = alsa_fini_out, - .run_out = alsa_run_out, + .write = alsa_write, .ctl_out = alsa_ctl_out, .init_in = alsa_init_in, .fini_in = alsa_fini_in, - .run_in = alsa_run_in, + .read = alsa_read, .ctl_in = alsa_ctl_in, }; |