/* -*- mode: C; compile-command: "cc fmplay.c -ofmplay"; -*-  */


/* Simple test of /dev/music */
/* Plays notes coming from MIDI in */

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/resource.h>
#include <sys/soundcard.h>

unsigned char channel, note, vel, pgm, cntrl, cntrlval, in_runstatus;
int seqfd,sbfd,i,j;

struct sbi_instrument inst;

SEQ_DEFINEBUF(4096);
unsigned char inbuf[8];

main(int argc, char **argv)
{
       char instfile[80];
       unsigned char inbuf[8];
       int n,kuk;

       strcpy(instfile,argv[1]);

       if ((seqfd = open ("/dev/sequencer2",O_RDWR, 0))== -1 ) {
               printf("Error opening /dev/music!\n");
               exit(1);
       }

       sbfd = open(instfile,O_RDONLY);

       for(i=0; i<128; i++) {
               inst.key = FM_PATCH;
               inst.device = 0;
               inst.channel = i;
               lseek(sbfd,(off_t)(52*i+36),SEEK_SET);
               read(sbfd,inst.operators,11);
               SEQ_WRPATCH(&inst,sizeof(inst));
       }
       close(sbfd);

       SEQ_START_TIMER();

       while(1) {
               ioctl(seqfd, SNDCTL_SEQ_GETINCOUNT, &n);
               if(n > 0)
                       parse_midiin();
       }

       SEQ_DUMPBUF();
       close(seqfd);
}


parse_midiin()
{
       read(seqfd, inbuf, 4);
       printf("%d",inbuf[0]);

       if(inbuf[0] != SEQ_MIDIPUTC)
               return;

       if(inbuf[1] >= 0x80) {
               if(inbuf[1] <= 247)               /* Ignore System realtime */
                       in_runstatus = inbuf[1];
       } else {
               channel = in_runstatus & 0x0f;

               if((in_runstatus >= 0x90 ) && (in_runstatus <= 0x9f)) {
                       note = inbuf[1];
                       vel = 255;
                       while(vel > 127) {
                               while(read(seqfd, inbuf, 4) != 4);
                               if(inbuf[0] == SEQ_MIDIPUTC)
                                       vel = inbuf[1];
                       }

                       if(vel > 0) {
                               SEQ_START_NOTE(0, channel, note, vel);
                       }
                       else {
                               SEQ_START_NOTE(0, channel, note, 0);
                       }
                       SEQ_DUMPBUF();
               }  else
               if((in_runstatus >= 0xC0) && (in_runstatus <= 0xCF)) {
                       pgm = inbuf[1];
                       SEQ_SET_PATCH(0, channel, pgm);
                       SEQ_DUMPBUF();
               } else
               if((in_runstatus >= 0xB0) && (in_runstatus <= 0xBF)) {
                       cntrl = inbuf[1];
                       cntrlval = 255;
                       while(cntrlval > 127) {
                               while(read(seqfd, inbuf, 4) != 4);
                               if(inbuf[0] == SEQ_MIDIPUTC)
                                       cntrlval = inbuf[1];
                       }
               }
       }
}



void
seqbuf_dump(void)
{
       if(_seqbufptr)
               if( write(seqfd, _seqbuf, _seqbufptr) == -1) {
                       perror("write /dev/sequencer");
                       exit (-1);
               }

       _seqbufptr = 0;
}