/*
 * main.c - main loop for software synthesizer.
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#include "synth.h"
#include "midisim.h"
#include "osc.h"
#include "loadsamples.h"
#include "midievents.h"
#include "audioout.h"

typedef struct {
  unsigned char msg[4];
  long msglen;
  unsigned int sec;
  unsigned int nsec;
} timedmesg;

#define SAMPLEN 4096

int main(int argc, char **argv) {
  performance synth;
  long * leftsamples;
  long * rightsamples;
  midiHandle * midi;
  int midififo;

  if (perf_init("samples/piano1.au", &synth) != 0) {
    printf("Error initializing synthesis engine!\n");
    return -1;
  }

  if (audio_open(SAMPLEN) != 0) {
    printf("Error initializing audio output hardware!\n");
    return -1;
  }  

  mkfifo("/tmp/midififo", 0700);
  if ((midififo = open("/tmp/midififo", O_RDONLY)) == -1) {
    printf("Couldn't open MIDI Fifo!\n");
  }

  midi = MidiInit();

  leftsamples = malloc(sizeof(long) * SAMPLEN);
  rightsamples = malloc(sizeof(long) * SAMPLEN);

  while (1) {
    int i, msglen;
    timedmesg tmsg;
    int nextsamples;

    if (tmsg.msglen > 0) {
      for (i=0; i<tmsg.msglen; i++) {
        MidiAddByte(midi, tmsg.msg[i], &synth);
      }
    } 
    
    msglen = read(midififo, &tmsg, sizeof(timedmesg));
    if (msglen > 0) {
      nextsamples =  44100 * tmsg.sec;
      nextsamples += (44100 * (tmsg.nsec / 1000000)) / 1000;
   
      if (nextsamples > 0) { 
        while (nextsamples > SAMPLEN) {
          for (i=0; i<SAMPLEN; i++) {
            leftsamples[i] = 0;
          }
          perf_generate(&synth, SAMPLEN, leftsamples);
          audio_generate(leftsamples, leftsamples, SAMPLEN);
          nextsamples -= SAMPLEN;
        }

        for (i=0; i<nextsamples; i++) {
          leftsamples[i] = 0;
        }
        perf_generate(&synth, nextsamples, leftsamples);
        audio_generate(leftsamples, leftsamples, nextsamples);
      }
    }
  }

  return 0;
}

