Commit 286a5d20 authored by Kővágó, Zoltán's avatar Kővágó, Zoltán Committed by Gerd Hoffmann
Browse files

alsaaudio: port to the new audio backend api



Signed-off-by: default avatarKővágó, Zoltán <DirtY.iCE.hu@gmail.com>
Message-id: ab9768e73dfe7b7305bd6a51629846e0d77622a5.1568927990.git.DirtY.iCE.hu@gmail.com
Signed-off-by: default avatarGerd Hoffmann <kraxel@redhat.com>
parent ff095e52
Loading
Loading
Loading
Loading
+80 −222
Original line number Diff line number Diff line
@@ -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;
        }
    }

    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);
    ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
    size_t pos = 0;
    size_t len_frames = len >> hw->info.shift;

        while (len) {
    while (len_frames) {
        char *src = advance(buf, pos);
        snd_pcm_sframes_t written;

            written = snd_pcm_writei (alsa->handle, src, len);
        written = snd_pcm_writei(alsa->handle, src, len_frames);

        if (written <= 0) {
            switch (written) {
            case 0:
                    trace_alsa_wrote_zero(len);
                    return;
                trace_alsa_wrote_zero(len_frames);
                return pos;

            case -EPIPE:
                if (alsa_recover(alsa->handle)) {
                        alsa_logerr (written, "Failed to write %d frames\n",
                                     len);
                        return;
                    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 */
                /*
                 * 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;
                    alsa_logerr(written, "Failed to write %zu frames\n",
                                len_frames);
                    return pos;
                }
                trace_alsa_resume_out();
                continue;

            case -EAGAIN:
                    return;
                return pos;

            default:
                    alsa_logerr (written, "Failed to write %d frames from %p\n",
                alsa_logerr(written, "Failed to write %zu frames from %p\n",
                            len, src);
                    return;
                return pos;
            }
        }

            alsa->wpos = (alsa->wpos + written) % hw->samples;
            alsa->pending -= written;
            len -= written;
        }
    }
        pos += written << hw->info.shift;
        if (written < len_frames) {
            break;
        }

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;
        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;
    }

    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;
    }
    size_t pos = 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;
    while (len) {
        void *dst = advance(buf, pos);
        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);
        nread = snd_pcm_readi(alsa->handle, dst, len >> hw->info.shift);

        if (nread <= 0) {
            switch (nread) {
            case 0:
                trace_alsa_read_zero(len);
                    goto exit;
                return pos;;

            case -EPIPE:
                if (alsa_recover(alsa->handle)) {
                        alsa_logerr (nread, "Failed to read %ld frames\n", len);
                        goto exit;
                    alsa_logerr(nread, "Failed to read %zu frames\n", len);
                    return pos;
                }
                trace_alsa_xrun_in();
                continue;

            case -EAGAIN:
                    goto exit;
                return pos;

            default:
                    alsa_logerr (
                        nread,
                        "Failed to read %ld frames from %p\n",
                        len,
                        src
                        );
                    goto exit;
                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:
    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,
};