// sb-send: Sonobus audio sender

// Functions to capture audio from STDIN.

#include "sb-send.h"

#define STDIN_CHUNK 480

#ifdef _WIN32
void *stdin_reader_thread(void *arg) {
    AudioRing *ring = (AudioRing *)arg;
    int16_t raw[STDIN_CHUNK * 2];
    float fchunk[STDIN_CHUNK * 2];
    int chunk_frames = STDIN_CHUNK;
    _setmode(_fileno(stdin), _O_BINARY);
    HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
    while (g_running && !atomic_load(&ring->done)) {
        DWORD result = WaitForSingleObject(hStdin, 100);
        if (result == WAIT_FAILED) {
            break;
        }
        if (result == WAIT_TIMEOUT) {
            continue;
        }
        int got = 0;
        int need = chunk_frames * ring->channels * (int)sizeof(int16_t);
        while (got < need && g_running && !atomic_load(&ring->done)) {
            int n = _read(_fileno(stdin), (char *)raw + got, need - got);
            if (n <= 0) { ring_signal_done(ring); return NULL; }
            got += n;
        }
        if (got > 0) {
            int samples = got / (int)sizeof(int16_t);
            for (int i = 0; i < samples; i++) {
                fchunk[i] = raw[i] / 32768.0f;
            }
            ring_put_float(ring, fchunk, samples);
        }
    }
    ring_signal_done(ring);
    return NULL;
}
#else
void *stdin_reader_thread(void *arg) {
    AudioRing *ring = (AudioRing *)arg;
    int16_t raw[STDIN_CHUNK * 2];
    float fchunk[STDIN_CHUNK * 2];
    int chunk_frames = STDIN_CHUNK;
    while (g_running && !atomic_load(&ring->done)) {
        fd_set rfds;
        FD_ZERO(&rfds);
        FD_SET(STDIN_FILENO, &rfds);
        struct timeval tv = {0, 100000};
        int sel = select(STDIN_FILENO + 1, &rfds, NULL, NULL, &tv);
        if (sel < 0) {
            if (errno == EINTR) continue;
            break;
        }
        if (sel == 0) {
            continue;
        }
        ssize_t got = 0;
        size_t need = chunk_frames * ring->channels * sizeof(int16_t);
        while (got < (ssize_t)need && g_running && !atomic_load(&ring->done)) {
            ssize_t n = read(STDIN_FILENO, (char *)raw + got, need - got);
            if (n <= 0) {
                if (n < 0 && errno == EINTR) {
                    continue;
                }
                ring_signal_done(ring);
                return NULL;
            }
            got += n;
        }
        if (got > 0) {
            int samples = got / sizeof(int16_t);
            for (int i = 0; i < samples; i++) {
                fchunk[i] = raw[i] / 32768.0f;
            }
            ring_put_float(ring, fchunk, samples);
        }
    }
    ring_signal_done(ring);
    return NULL;
}
#endif
// EOF
