/*
 * 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"

#ifdef HAVE_HPUX_AUDIO
#include <Alib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#endif /* HAVE_HPUX_AUDIO */

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

#ifdef HAVE_HPUX_AUDIO
static Audio *audioServer = NULL;

struct PcmDeviceStruct {
  ATransID transaction;
  SStream stream;
  int socket;
};

static void
logAudioError (int level, long status, const char *action) {
  char message[132];
  AGetErrorText(audioServer, status, message, sizeof(message)-1);
  logMessage(level, "%s error %ld: %s", action, status, message);
}

static const AudioAttributes *
getAudioAttributes (PcmDevice *pcm) {
  return &pcm->stream.audio_attr;
}
#endif /* HAVE_HPUX_AUDIO */

PcmDevice *
openPcmDevice (int errorLevel, const char *device) {
#ifdef HAVE_HPUX_AUDIO
  PcmDevice *pcm;
  if ((pcm = malloc(sizeof(*pcm)))) {
    long status;
    AudioAttrMask mask = 0;
    AudioAttributes attributes;
    SSPlayParams parameters;
  
    if (!audioServer) {
      char *server = "";
      audioServer = AOpenAudio(server, &status);
      if (status != AENoError) {
        logAudioError(errorLevel, status, "AOpenAudio");
        audioServer = NULL;
        goto noServer;
      }
      logMessage(LOG_DEBUG, "connected to audio server: %s", AAudioString(audioServer));
  
      ASetCloseDownMode(audioServer, AKeepTransactions, &status);
      if (status != AENoError) {
        logAudioError(errorLevel, status, "ASetCloseDownMode");
      }
    }
  
    memset(&attributes, 0, sizeof(attributes));
  
    parameters.gain_matrix = *ASimplePlayer(audioServer);
    parameters.play_volume = AUnityGain;
    parameters.priority = APriorityUrgent;
    parameters.event_mask = 0;
  
    pcm->transaction = APlaySStream(audioServer, mask, &attributes, &parameters, &pcm->stream, &status);
    if (status == AENoError) {
      if ((pcm->socket = socket(AF_INET, SOCK_STREAM, 0)) != -1) {
        if (connect(pcm->socket, (struct sockaddr *)&pcm->stream.tcp_sockaddr, sizeof(pcm->stream.tcp_sockaddr)) != -1) {
          return pcm;
        } else {
          logSystemError("PCM socket connection");
        }
        close(pcm->socket);
      } else {
        logSystemError("PCM socket creation");
      }
    } else {
      logAudioError(errorLevel, status, "APlaySStream");
    }

  noServer:
    free(pcm);
  } else {
    logSystemError("PCM device allocation");
  }
#endif /* HAVE_HPUX_AUDIO */
  return NULL;
}

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

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

int
getPcmBlockSize (PcmDevice *pcm) {
  int size = 0X100;
#ifdef HAVE_HPUX_AUDIO
  size = MIN(size, pcm->stream.max_block_size);
#endif /* HAVE_HPUX_AUDIO */
  return size;
}

int
getPcmSampleRate (PcmDevice *pcm) {
#ifdef HAVE_HPUX_AUDIO
  return getAudioAttributes(pcm)->attr.sampled_attr.sampling_rate;
#else /* HAVE_HPUX_AUDIO */
  return 8000;
#endif /* HAVE_HPUX_AUDIO */
}

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

int
getPcmChannelCount (PcmDevice *pcm) {
#ifdef HAVE_HPUX_AUDIO
  return getAudioAttributes(pcm)->attr.sampled_attr.channels;
#else /* HAVE_HPUX_AUDIO */
  return 1;
#endif /* HAVE_HPUX_AUDIO */
}

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

PcmAmplitudeFormat
getPcmAmplitudeFormat (PcmDevice *pcm) {
#ifdef HAVE_HPUX_AUDIO
  switch (getAudioAttributes(pcm)->attr.sampled_attr.data_format) {
    default:
      break;
    case ADFLin8:
      return PCM_FMT_S8;
    case ADFLin8Offset:
      return PCM_FMT_U8;
    case ADFLin16:
      return PCM_FMT_S16B;
    case ADFMuLaw:
      return PCM_FMT_ULAW;
  }
#endif /* HAVE_HPUX_AUDIO */
  return PCM_FMT_UNKNOWN;
}

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

void
pushPcmOutput (PcmDevice *pcm) {
}

void
awaitPcmOutput (PcmDevice *pcm) {
}

void
cancelPcmOutput (PcmDevice *pcm) {
}
