// sb-send: Sonobus audio sender

// Functions related to alsa audio capture.

#include "sb-send.h"

#ifdef ALSA
int init_alsa(AppState *state) {
    int err = snd_pcm_open(&state->capture, state->audio_device,
                           SND_PCM_STREAM_CAPTURE, 0);
    if (err < 0) { fprintf(stderr, "ALSA open failed: %s\n", snd_strerror(err)); return -1; }

    snd_pcm_hw_params_t *hw;
    snd_pcm_hw_params_alloca(&hw);
    err = snd_pcm_hw_params_any(state->capture, hw);
    if (err < 0) { fprintf(stderr, "ALSA hw_params_any failed: %s\n", snd_strerror(err)); return -1; }
    err = snd_pcm_hw_params_set_access(state->capture, hw, SND_PCM_ACCESS_RW_INTERLEAVED);
    if (err < 0) { fprintf(stderr, "ALSA set_access failed: %s\n", snd_strerror(err)); return -1; }
    err = snd_pcm_hw_params_set_format(state->capture, hw, SND_PCM_FORMAT_FLOAT_LE);
    if (err < 0) { fprintf(stderr, "ALSA set_format failed: %s\n", snd_strerror(err)); return -1; }

    unsigned int rate = SAMPLE_RATE;
    err = snd_pcm_hw_params_set_rate_near(state->capture, hw, &rate, 0);
    if (err < 0) { fprintf(stderr, "ALSA set_rate_near failed: %s\n", snd_strerror(err)); return -1; }
    err = snd_pcm_hw_params_set_channels(state->capture, hw, state->channels);
    if (err < 0) { fprintf(stderr, "ALSA set_channels failed: %s\n", snd_strerror(err)); return -1; }

    snd_pcm_uframes_t bufsize = state->frame_size * 8;
    err = snd_pcm_hw_params_set_buffer_size_near(state->capture, hw, &bufsize);
    if (err < 0) { fprintf(stderr, "ALSA set_buffer_size_near failed: %s\n", snd_strerror(err)); return -1; }
    snd_pcm_uframes_t period = state->frame_size;
    err = snd_pcm_hw_params_set_period_size_near(state->capture, hw, &period, 0);
    if (err < 0) { fprintf(stderr, "ALSA set_period_size_near failed: %s\n", snd_strerror(err)); return -1; }

    err = snd_pcm_hw_params(state->capture, hw);
    if (err < 0) { fprintf(stderr, "ALSA params failed: %s\n", snd_strerror(err)); return -1; }

    err = snd_pcm_prepare(state->capture);
    if (err < 0) { fprintf(stderr, "ALSA prepare failed: %s\n", snd_strerror(err)); return -1; }
    err = snd_pcm_start(state->capture);
    if (err < 0) { fprintf(stderr, "ALSA start failed: %s\n", snd_strerror(err)); return -1; }
    fprintf(stderr, "ALSA: %s %d Hz %d ch\n", state->audio_device, SAMPLE_RATE, state->channels);
    return 0;
}

int alsa_list_devices(void) {
    void **hints = NULL;
    if (snd_device_name_hint(-1, "pcm", &hints) < 0) {
        fprintf(stderr, "Failed to list ALSA devices\n");
        return -1;
    }
    fprintf(stderr, "ALSA capture devices:\n");
    for (int i = 0; hints[i]; i++) {
        char *name = snd_device_name_get_hint(hints[i], "NAME");
        char *desc = snd_device_name_get_hint(hints[i], "DESC");
        char *io = snd_device_name_get_hint(hints[i], "IOID");
        if (io && strcmp(io, "Input") == 0) {
            const char *print_name;
            if (name) {
                print_name = name;
            } else {
                print_name = "?";
            }
            const char *print_desc;
            if (desc) {
                print_desc = desc;
            } else {
                print_desc = "";
            }
            fprintf(stderr, "  %s - %s\n", print_name, print_desc);
        }
        free(name);
        free(desc);
        free(io);
    }
    snd_device_name_free_hint(hints);
    return 0;
}
#endif
// EOF
