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>
This commit is contained in:
parent
ff095e5231
commit
286a5d201e
@ -44,9 +44,6 @@ struct pollhlp {
|
|||||||
|
|
||||||
typedef struct ALSAVoiceOut {
|
typedef struct ALSAVoiceOut {
|
||||||
HWVoiceOut hw;
|
HWVoiceOut hw;
|
||||||
int wpos;
|
|
||||||
int pending;
|
|
||||||
void *pcm_buf;
|
|
||||||
snd_pcm_t *handle;
|
snd_pcm_t *handle;
|
||||||
struct pollhlp pollhlp;
|
struct pollhlp pollhlp;
|
||||||
Audiodev *dev;
|
Audiodev *dev;
|
||||||
@ -55,7 +52,6 @@ typedef struct ALSAVoiceOut {
|
|||||||
typedef struct ALSAVoiceIn {
|
typedef struct ALSAVoiceIn {
|
||||||
HWVoiceIn hw;
|
HWVoiceIn hw;
|
||||||
snd_pcm_t *handle;
|
snd_pcm_t *handle;
|
||||||
void *pcm_buf;
|
|
||||||
struct pollhlp pollhlp;
|
struct pollhlp pollhlp;
|
||||||
Audiodev *dev;
|
Audiodev *dev;
|
||||||
} ALSAVoiceIn;
|
} ALSAVoiceIn;
|
||||||
@ -602,102 +598,64 @@ static int alsa_open(bool in, struct alsa_params_req *req,
|
|||||||
return -1;
|
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return avail;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
|
||||||
size_t decr;
|
size_t pos = 0;
|
||||||
snd_pcm_sframes_t avail;
|
size_t len_frames = len >> hw->info.shift;
|
||||||
|
|
||||||
avail = alsa_get_avail (alsa->handle);
|
while (len_frames) {
|
||||||
if (avail < 0) {
|
char *src = advance(buf, pos);
|
||||||
dolog ("Could not get number of available playback frames\n");
|
snd_pcm_sframes_t written;
|
||||||
return 0;
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
case -EAGAIN:
|
||||||
|
return pos;
|
||||||
|
|
||||||
|
default:
|
||||||
|
alsa_logerr(written, "Failed to write %zu frames from %p\n",
|
||||||
|
len, src);
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pos += written << hw->info.shift;
|
||||||
|
if (written < len_frames) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
len_frames -= written;
|
||||||
}
|
}
|
||||||
|
|
||||||
decr = MIN (live, avail);
|
return pos;
|
||||||
decr = audio_pcm_hw_clip_out (hw, alsa->pcm_buf, decr, alsa->pending);
|
|
||||||
alsa->pending += decr;
|
|
||||||
alsa_write_pending (alsa);
|
|
||||||
return decr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void alsa_fini_out (HWVoiceOut *hw)
|
static void alsa_fini_out (HWVoiceOut *hw)
|
||||||
@ -706,9 +664,6 @@ static void alsa_fini_out (HWVoiceOut *hw)
|
|||||||
|
|
||||||
ldebug ("alsa_fini\n");
|
ldebug ("alsa_fini\n");
|
||||||
alsa_anal_close (&alsa->handle, &alsa->pollhlp);
|
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,
|
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);
|
audio_pcm_init_info (&hw->info, &obt_as);
|
||||||
hw->samples = obt.samples;
|
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->pollhlp.s = hw->s;
|
||||||
alsa->handle = handle;
|
alsa->handle = handle;
|
||||||
alsa->dev = dev;
|
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);
|
audio_pcm_init_info (&hw->info, &obt_as);
|
||||||
hw->samples = obt.samples;
|
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->pollhlp.s = hw->s;
|
||||||
alsa->handle = handle;
|
alsa->handle = handle;
|
||||||
alsa->dev = dev;
|
alsa->dev = dev;
|
||||||
@ -858,129 +797,48 @@ static void alsa_fini_in (HWVoiceIn *hw)
|
|||||||
ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
|
ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
|
||||||
|
|
||||||
alsa_anal_close (&alsa->handle, &alsa->pollhlp);
|
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;
|
ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
|
||||||
int hwshift = hw->info.shift;
|
size_t pos = 0;
|
||||||
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) {
|
while (len) {
|
||||||
return 0;
|
void *dst = advance(buf, pos);
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
decr = MIN(dead, avail);
|
|
||||||
if (!decr) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < 2; ++i) {
|
|
||||||
void *src;
|
|
||||||
struct st_sample *dst;
|
|
||||||
snd_pcm_sframes_t nread;
|
snd_pcm_sframes_t nread;
|
||||||
snd_pcm_uframes_t len;
|
|
||||||
|
|
||||||
len = bufs[i].len;
|
nread = snd_pcm_readi(alsa->handle, dst, len >> hw->info.shift);
|
||||||
|
|
||||||
src = advance (alsa->pcm_buf, bufs[i].add << hwshift);
|
if (nread <= 0) {
|
||||||
dst = hw->conv_buf + bufs[i].add;
|
switch (nread) {
|
||||||
|
case 0:
|
||||||
|
trace_alsa_read_zero(len);
|
||||||
|
return pos;;
|
||||||
|
|
||||||
while (len) {
|
case -EPIPE:
|
||||||
nread = snd_pcm_readi (alsa->handle, src, len);
|
if (alsa_recover(alsa->handle)) {
|
||||||
|
alsa_logerr(nread, "Failed to read %zu frames\n", len);
|
||||||
if (nread <= 0) {
|
return pos;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
trace_alsa_xrun_in();
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case -EAGAIN:
|
||||||
|
return pos;
|
||||||
|
|
||||||
|
default:
|
||||||
|
alsa_logerr(nread, "Failed to read %zu frames to %p\n",
|
||||||
|
len, dst);
|
||||||
|
return pos;;
|
||||||
}
|
}
|
||||||
|
|
||||||
hw->conv (dst, src, nread);
|
|
||||||
|
|
||||||
src = advance (src, nread << hwshift);
|
|
||||||
dst += nread;
|
|
||||||
|
|
||||||
read_samples += nread;
|
|
||||||
len -= nread;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pos += nread << hw->info.shift;
|
||||||
|
len -= nread << hw->info.shift;
|
||||||
}
|
}
|
||||||
|
|
||||||
exit:
|
return pos;
|
||||||
hw->wpos = (hw->wpos + read_samples) % hw->samples;
|
|
||||||
return read_samples;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int alsa_ctl_in (HWVoiceIn *hw, int cmd, ...)
|
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 = {
|
static struct audio_pcm_ops alsa_pcm_ops = {
|
||||||
.init_out = alsa_init_out,
|
.init_out = alsa_init_out,
|
||||||
.fini_out = alsa_fini_out,
|
.fini_out = alsa_fini_out,
|
||||||
.run_out = alsa_run_out,
|
.write = alsa_write,
|
||||||
.ctl_out = alsa_ctl_out,
|
.ctl_out = alsa_ctl_out,
|
||||||
|
|
||||||
.init_in = alsa_init_in,
|
.init_in = alsa_init_in,
|
||||||
.fini_in = alsa_fini_in,
|
.fini_in = alsa_fini_in,
|
||||||
.run_in = alsa_run_in,
|
.read = alsa_read,
|
||||||
.ctl_in = alsa_ctl_in,
|
.ctl_in = alsa_ctl_in,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user