// midiLew.C
// 
// midi software interface for particle fountain application
//
// this is an objectification of the /usr/share/src/dmedia/midi/simple/simple.c
// dmedia example program source code  provided with silicon graphics systems.

#include "midiLew.h"

midiLew::midiLew(){
  init();
}

midiLew::~midiLew(){
  m_Lew_exit();
}

void midiLew::init(){
  stamp = 0;

  octaves = 8;		/* Octave range */
  mode = 0;		/* Play mode */
  startnote = 0x48;	/* Lowest note to play */

  upflag = 1;		/* Play notes up, or down */
  
  channel = 1;		/* Channel to transmit on */
  velocity = 0x48;	/* Velocity for note */
  program = 0x0;		/* Selected program */
  future = 0;  	        /* Amount of time before play starts */
  length = 500000000;   /* Amount of time note is held */ 
  
  /* Initialize the MIDI library */
  num_interfaces = mdInit();
  if (num_interfaces < 0) {
    printf("MIDI not initialized!\n");
    exit(-1);
  }
  
  interface = NULL;
  printf("Using default output device\n");
  
  /* Now open up the port, if possible */
  if ((outport = mdOpenOutPort(interface)) == NULL) {
    fprintf(stderr, "scale: could not open port '%s'\n",
	    interface);
    exit(1);
  }
  
  mdSetStampMode(outport, MD_RELATIVESTAMP);
  mdSetStartPoint(outport, 0, 0);
  
  dmGetUST(&stamp);
  stamp += future;
  
  
  ev.stamp = stamp;
  ev.msg[0] = MD_PROGRAMCHANGE;
  ev.msg[1] = program;
  mdSend(outport, &ev, 1);
  
  
  playnote(startnote, length, channel, velocity);	
}


void midiLew::m_Lew_exit(){	
  
  for(;;) {
    unsigned long long now;
    
    dmGetUST(&now);
    if (now > stamp) {
      mdClosePort(outport);
      exit(0);
    } else {
      sleep(1);
    }   
  }
}

void midiLew::playnote( char note, unsigned long long mlength, 
			char channel, char velocity){
  MDevent mdv;
  
  /* Transmit a NOTE ON event. */	
  mdv.stamp = stamp; 
  mdv.msg[0] = MD_NOTEON | (channel & 0xf);
  mdv.msg[1] = note;
  mdv.msg[2] = velocity;
  stamp += mlength;
  if (mdSend(outport, &mdv, 1) < 0) {
    exit(-1);
  }
  
  /* This is slightly tricky.  We turn off the note by sending
   * a NOTE ON event with a velocity of 0 which is equivalent
   * to sending a NOTE OFF event.
   */
  
  mdv.stamp = stamp;
  mdv.msg[2] = 0;
  if (mdSend(outport, &mdv, 1) < 0) {
    exit(-1);
  }
  
  /* The inter-note period is fixed at 10 milliseconds */
  stamp += 1000;
}

void midiLew::playSound(MidiEvent* event){
  
  char note = event->getNote();
  char channel = event->getChannel();
  char velocity = event->getVelocity();
  unsigned long long length= 5000;

  playnote(note, length, channel, velocity);

}

