/*
 *  Copyright 1994-2022 Olivier Girondel
 *
 *  This file is part of lebiniou.
 *
 *  lebiniou is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  lebiniou is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with lebiniou. If not, see <http://www.gnu.org/licenses/>.
 */

#include "context.h"

#include <pulse/simple.h>
#include <pulse/error.h>
#include "pthread_utils.h"


uint32_t options = BO_NONE;
uint32_t version = 0;

static uint32_t insize, buff_size;
static float *pa_buff = NULL;
static pa_simple *pa_s;


int8_t
create(Context_t *ctx)
{
  int error;
  pa_sample_spec ss;

  insize = Context_get_input_size(ctx);
  buff_size = insize * 2 * sizeof(float);
  pa_buff = xcalloc(buff_size, sizeof(float));

  ss.format = PA_SAMPLE_FLOAT32LE;
  ss.channels = 2;
  ss.rate = 44100;

  pa_s = pa_simple_new(NULL,               /* PulseAudio server. */
                       "Biniou",           /* Application's name. */
                       PA_STREAM_RECORD,   /* Stream direction. */
                       NULL,               /* Sink Device. */
                       "Biniou-read",      /* Stream description. */
                       &ss,                /* Sample format. */
                       NULL,               /* Channel map */
                       NULL,               /* Buffering attributes. */
                       &error              /* Error code. */
                      );
  if (NULL == pa_s)
    xerror(__FILE__": pa_simple_new() failed: %s\n",
           pa_strerror(error));

#ifdef DEBUG
  char ss_a[PA_SAMPLE_SPEC_SNPRINT_MAX];
  pa_sample_spec_snprint(ss_a, sizeof(ss_a), &ss);
  printf("Opening the recording stream with sample specification '%s'.\n", ss_a);
#endif

  ctx->input = Input_new(insize);
  okdone("pulseaudio initialized");

  return 1;
}


void
destroy(Context_t *ctx)
{
  pa_simple_free(pa_s);
  Input_delete(ctx->input);
  xfree(pa_buff);
}


void *
jthread(void *args)
{
  Context_t *ctx = (Context_t *)args;

  while (ctx->running) {
    int n;
    int error;

    n = pa_simple_read(pa_s, (void *)pa_buff, buff_size, &error);

    if (!ctx->input->mute && (n != -1)) {
      uint32_t m, idx;

      if (!xpthread_mutex_lock(&ctx->input->mutex)) {
        for (m = 0, idx = 0; idx < insize; idx++) {
          ctx->input->data[A_LEFT][idx] = pa_buff[m++];
          ctx->input->data[A_RIGHT][idx] = pa_buff[m++];
        }
        Input_set(ctx->input, A_STEREO);
        xpthread_mutex_unlock(&ctx->input->mutex);
      }
    }
  }

  return NULL;
}
