/*
 * BRLTTY - A background process providing access to the console screen (when in
 *          text mode) for a blind person using a refreshable braille display.
 *
 * Copyright (C) 1995-2023 by The BRLTTY Developers.
 *
 * BRLTTY comes with ABSOLUTELY NO WARRANTY.
 *
 * This is free software, placed under the terms of the
 * GNU Lesser General Public License, as published by the Free Software
 * Foundation; either version 2.1 of the License, or (at your option) any
 * later version. Please see the file LICENSE-LGPL for details.
 *
 * Web Page: http://brltty.app/
 *
 * This software is maintained by Dave Mielke <dave@mielke.cc>.
 */

#include "prologue.h"

#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/audio.h>
#include <stropts.h>

#include "log.h"
#include "io_misc.h"
#include "pcm.h"

#define PCM_AUDIO_DEVICE_PATH "/dev/audio"

struct PcmDeviceStruct {
  int fileDescriptor;
};

PcmDevice *
openPcmDevice (int errorLevel, const char *device) {
  PcmDevice *pcm;
  if ((pcm = malloc(sizeof(*pcm)))) {
    if (!*device) device = getenv("AUDIODEV");
    if (!device || !*device) device = PCM_AUDIO_DEVICE_PATH;
    if ((pcm->fileDescriptor = open(device, O_WRONLY|O_NONBLOCK)) != -1) {
      audio_info_t info;
      AUDIO_INITINFO(&info);
#ifdef AUMODE_PLAY
      info.mode = AUMODE_PLAY;
#endif /* AUMODE_PLAY */
#ifdef AUDIO_ENCODING_SLINEAR
      info.play.encoding = AUDIO_ENCODING_SLINEAR;
#else /* AUDIO_ENCODING_SLINEAR */
      info.play.encoding = AUDIO_ENCODING_LINEAR;
#endif /* AUDIO_ENCODING_SLINEAR */
      info.play.sample_rate = 16000;
      info.play.channels = 1;
      info.play.precision = 16;
      info.play.gain = AUDIO_MAX_GAIN;
      if (ioctl(pcm->fileDescriptor, AUDIO_SETINFO, &info) == -1)
        logMessage(errorLevel, "Cannot set audio info: %s", strerror(errno));
      return pcm;
    } else {
      logMessage(errorLevel, "Cannot open PCM device: %s: %s", device, strerror(errno));
    }
    free(pcm);
  } else {
    logSystemError("PCM device allocation");
  }
  return NULL;
}

void
closePcmDevice (PcmDevice *pcm) {
  close(pcm->fileDescriptor);
  free(pcm);
}

int
writePcmData (PcmDevice *pcm, const unsigned char *buffer, int count) {
  return writeFile(pcm->fileDescriptor, buffer, count) != -1;
}

static int
getPcmAudioInfo (PcmDevice *pcm, audio_info_t *info) {
  if (ioctl(pcm->fileDescriptor, AUDIO_GETINFO, info) != -1) return 1;
  logSystemError("AUDIO_GETINFO");
  return 0;
}

int
getPcmBlockSize (PcmDevice *pcm) {
  audio_info_t info;
  if (getPcmAudioInfo(pcm, &info)) return (info.play.precision / 8 * info.play.channels) * 0X400;
  return 0X100;
}

int
getPcmSampleRate (PcmDevice *pcm) {
  audio_info_t info;
  if (getPcmAudioInfo(pcm, &info)) return info.play.sample_rate;
  return 8000;
}

int
setPcmSampleRate (PcmDevice *pcm, int rate) {
  return getPcmSampleRate(pcm);
}

int
getPcmChannelCount (PcmDevice *pcm) {
  audio_info_t info;
  if (getPcmAudioInfo(pcm, &info)) return info.play.channels;
  return 1;
}

int
setPcmChannelCount (PcmDevice *pcm, int channels) {
  return getPcmChannelCount(pcm);
}

PcmAmplitudeFormat
getPcmAmplitudeFormat (PcmDevice *pcm) {
  audio_info_t info;
  if (getPcmAudioInfo(pcm, &info)) {
    switch (info.play.encoding) {
      default:
        break;

#ifdef AUDIO_ENCODING_SLINEAR_BE
      case AUDIO_ENCODING_SLINEAR_BE:
        if (info.play.precision == 16) return PCM_FMT_S16B;
        goto testLinearSigned8;
#endif /* AUDIO_ENCODING_SLINEAR_BE */

#ifdef AUDIO_ENCODING_SLINEAR_LE
      case AUDIO_ENCODING_SLINEAR_LE:
        if (info.play.precision == 16) return PCM_FMT_S16L;
        goto testLinearSigned8;
#endif /* AUDIO_ENCODING_SLINEAR_LE */

#ifdef AUDIO_ENCODING_LINEAR
      case AUDIO_ENCODING_LINEAR:
#ifdef WORDS_BIGENDIAN
        if (info.play.precision == 16) return PCM_FMT_S16B;
#else /* WORDS_BIGENDIAN */
        if (info.play.precision == 16) return PCM_FMT_S16L;
#endif /* WORDS_BIGENDIAN */
        goto testLinearSigned8;
#endif /* AUDIO_ENCODING_LINEAR */

      testLinearSigned8:
        if (info.play.precision == 8) return PCM_FMT_S8;
        break;

      case AUDIO_ENCODING_LINEAR8:
        return PCM_FMT_U8;

      case AUDIO_ENCODING_ULAW:
        return PCM_FMT_ULAW;

      case AUDIO_ENCODING_ALAW:
        return PCM_FMT_ALAW;
    }
  }
  return PCM_FMT_UNKNOWN;
}

PcmAmplitudeFormat
setPcmAmplitudeFormat (PcmDevice *pcm, PcmAmplitudeFormat format) {
  return getPcmAmplitudeFormat(pcm);
}

void
pushPcmOutput (PcmDevice *pcm) {
}

void
awaitPcmOutput (PcmDevice *pcm) {
  ioctl(pcm->fileDescriptor, AUDIO_DRAIN);
}

void
cancelPcmOutput (PcmDevice *pcm) {
  ioctl(pcm->fileDescriptor, I_FLUSH);
}
