/*
 * 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 <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/soundcard.h>

#include "log.h"
#include "io_misc.h"
#include "midi.h"

#define MIDI_OSS_DEVICE_PATH "/dev/sequencer";

struct MidiDeviceStruct {
  int fileDescriptor;
  int deviceNumber;
/*SEQ_DEFINEBUF(0X80);*/
  unsigned char buffer[0X80];
  int bufferLength;
  int bufferUsed;
};

#ifndef SAMPLE_TYPE_AWE
#define SAMPLE_TYPE_AWE 0x20
#endif /* SAMPLE_TYPE_AWE */

static MidiDevice *midiDevice = NULL;
#define _seqbuf midiDevice->buffer
#define _seqbuflen midiDevice->bufferLength
#define _seqbufptr midiDevice->bufferUsed

void
seqbuf_dump (void) {
  if (_seqbufptr)
    if (writeFile(midiDevice->fileDescriptor, _seqbuf, _seqbufptr) == -1)
      logSystemError("MIDI write");
  _seqbufptr = 0;
}

MidiDevice *
openMidiDevice (int errorLevel, const char *device) {
  MidiDevice *midi;
  if ((midi = malloc(sizeof(*midi)))) {
    if (!*device) device = MIDI_OSS_DEVICE_PATH;
    if ((midi->fileDescriptor = open(device, O_WRONLY)) != -1) {
      {
        int count;
        int awe = -1;
        int fm = -1;
        int gus = -1;
        int ext = -1;

        if (ioctl(midi->fileDescriptor, SNDCTL_SEQ_NRSYNTHS, &count) != -1) {
          int index;
          for (index=0; index<count; ++index) {
            struct synth_info info;
            info.device = index;
            if (ioctl(midi->fileDescriptor, SNDCTL_SYNTH_INFO, &info) != -1) {
              switch (info.synth_type) {
                case SYNTH_TYPE_SAMPLE:
                  switch (info.synth_subtype) {
                    case SAMPLE_TYPE_AWE:
                      awe = index;
                      continue;

                    case SAMPLE_TYPE_GUS:
                      gus = index;
                      continue;
                  }
                  break;

                case SYNTH_TYPE_FM:
                  fm = index;
                  continue;
              }

              logMessage(LOG_DEBUG, "Unknown synthesizer: %d[%d]: %s",
                         info.synth_type, info.synth_subtype, info.name);
            } else {
              logMessage(errorLevel, "Cannot get description for synthesizer %d: %s",
                         index, strerror(errno));
            }
          }

          if (gus >= 0)
            if (ioctl(midi->fileDescriptor, SNDCTL_SEQ_RESETSAMPLES, &gus) == -1)
              logMessage(errorLevel, "Cannot reset samples for gus synthesizer %d: %s",
                         gus, strerror(errno));
        } else {
          logMessage(errorLevel, "Cannot get MIDI synthesizer count: %s",
                     strerror(errno));
        }

        if (ioctl(midi->fileDescriptor, SNDCTL_SEQ_NRMIDIS, &count) != -1) {
          if (count > 0) ext = count - 1;
        } else {
          logMessage(errorLevel, "Cannot get MIDI device count: %s",
                     strerror(errno));
        }

        midi->deviceNumber = (awe >= 0)? awe:
                             (gus >= 0)? gus:
                             (fm >= 0)? fm:
                             (ext >= 0)? ext:
                             0;
      }

      midi->bufferLength = sizeof(midi->buffer);
      midi->bufferUsed = 0;

      return midi;
    } else {
      logMessage(errorLevel, "Cannot open MIDI device: %s: %s", device, strerror(errno));
    }

    free(midi);
  } else {
    logSystemError("MIDI device allocation");
  }
  return NULL;
}

void
closeMidiDevice (MidiDevice *midi) {
  close(midi->fileDescriptor);
  free(midi);
}

static void
beginMidiOperation (MidiDevice *midi) {
  midiDevice = midi;
}

static int
endMidiOperation (MidiDevice *midi) {
  midiDevice = NULL;
  return 1;
}

int
flushMidiDevice (MidiDevice *midi) {
  beginMidiOperation(midi);
  seqbuf_dump();
  return endMidiOperation(midi);
}

int
setMidiInstrument (MidiDevice *midi, unsigned char channel, unsigned char instrument) {
  beginMidiOperation(midi);
  SEQ_SET_PATCH(midi->deviceNumber, channel, instrument);
  return endMidiOperation(midi);
}

int
beginMidiBlock (MidiDevice *midi) {
  beginMidiOperation(midi);
  SEQ_START_TIMER();
  return endMidiOperation(midi);
}

int
endMidiBlock (MidiDevice *midi) {
  beginMidiOperation(midi);
  SEQ_STOP_TIMER();
  seqbuf_dump();
  ioctl(midi->fileDescriptor, SNDCTL_SEQ_SYNC);
  return endMidiOperation(midi);
}

int
startMidiNote (MidiDevice *midi, unsigned char channel, unsigned char note, unsigned char volume) {
  beginMidiOperation(midi);
  SEQ_START_NOTE(midi->deviceNumber, channel, note, 0X7F*volume/100);
  return endMidiOperation(midi);
}

int
stopMidiNote (MidiDevice *midi, unsigned char channel) {
  beginMidiOperation(midi);
  SEQ_STOP_NOTE(midi->deviceNumber, channel, 0, 0);
  return endMidiOperation(midi);
}

int
insertMidiWait (MidiDevice *midi, int duration) {
  beginMidiOperation(midi);
  SEQ_DELTA_TIME((duration + 9) / 10);
  return endMidiOperation(midi);
}
