#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "midifile.h"

FILE *F;
int division;        /* from the file header */
long tempo = 500000; /* the default tempo is 120 beats/minute (500000 microsec/quarternote) */

int midformat = 0;
int only_text = 0;

filegetc()
{
       return(getc(F));
}


main(int argc,char **argv)
{
       char fname[80];

       if(argc > 1) {
               if((argc > 2) && (argv[2][0] == 't'))
                       only_text = 1;

               strcpy(fname, argv[1]);

               if(! strchr(fname, '.'))
                       strcat(fname, ".MID");

               if(F = fopen(fname, "rb")) {
                       initfuncs();
                       Mf_getc = filegetc;
                       mfread();
                       fclose(F);
               } else {
                       printf("MID file not found!\n");
                       exit(1);
               }
       } else {
               printf("mf2t  Converts a MIDI file to text  Mats Petersson 1995\n");
               printf("usage: mf2t <midifile[.mid]> [t]\n");
       }
}


error(s)
char *s;
{
       fprintf(stderr,"Error: %s\n",s);
}


txt_header(format,ntrks,ldivision)
{
       division = ldivision;
       if(! only_text)
               printf("Header format=%d ntrks=%d division=%d\n",format,ntrks,division);
}

txt_trackstart()
{
       if(! only_text)
               printf("Track start\n");
}

txt_trackend()
{
       if(! only_text)
               printf("Track end\n");
}

txt_noteon(chan,pitch,vol)
{
       if(! only_text) {
               prtime();
               printf("Note on, chan=%d pitch=%d vol=%d\n",chan+1,pitch,vol);
       }
}

txt_noteoff(chan,pitch,vol)
{
       if(! only_text) {
               prtime();
               printf("Note off, chan=%d pitch=%d vol=%d\n",chan+1,pitch,vol);
       }
}

txt_pressure(chan,pitch,press)
{
       if(! only_text) {
               prtime();
               printf("Pressure, chan=%d pitch=%d press=%d\n",chan+1,pitch,press);
       }
}

txt_parameter(chan,control,value)
{
       if(! only_text) {
               prtime();
               printf("Parameter, chan=%d c1=%d c2=%d\n",chan+1,control,value);
       }
}

txt_pitchbend(chan,lsb,msb)
{
       if(! only_text) {
               prtime();
               printf("Pitchbend, chan=%d lsb=%d msb=%d\n",chan+1,lsb,msb);
       }
}

txt_program(chan,program)
{
       if(! only_text) {
               prtime();
               printf("Program, chan=%d program=%d\n",chan+1,program);
       }
}

txt_chanpressure(chan,press)
{
       if(! only_text) {
               prtime();
               printf("Channel pressure, chan=%d pressure=%d\n",chan+1,press);
       }
}

txt_sysex(leng,mess)
char *mess;
{
       if(! only_text) {
               prtime();
               printf("Sysex, leng=%d\n",leng);
       }
}

txt_metamisc(type,leng,mess)
char *mess;
{
       if(! only_text) {
               prtime();
               printf("Meta event, unrecognized, type=0x%02x leng=%d\n",type,leng);
       }
}

txt_metaspecial(type,leng,mess)
char *mess;
{
       if(! only_text) {
               prtime();
               printf("Meta event, sequencer-specific, type=0x%02x leng=%d\n",type,leng);
       }
}

txt_metatext(type,leng,mess)
char *mess;
{
       static int oldtype = 0xffff;

       static char *ttype[] = {
               NULL,
               "Text Event",           /* type=0x01 */
               "Copyright Notice",     /* type=0x02 */
               "Sequence/Track Name",
               "Instrument Name",      /* ...       */
               "Lyric",
               "Marker",
               "Cue Point",            /* type=0x07 */
               "Unrecognized"
       };
       int unrecognized = (sizeof(ttype)/sizeof(char *)) - 1;
       register int n, c;
       register char *p = mess;


       if ( type < 1 || type > unrecognized )
               type = unrecognized;

       if(! only_text) {
               prtime();
               printf("Meta Text, type=0x%02x (%s)  leng=%d\n",type,ttype[type],leng);
               printf("     Text = <");
       } else {
               if(oldtype != type) {
                       oldtype = type;
                       printf("\n  %s\n\n", ttype[type]);
               }
       }
       for ( n=0; n<leng; n++ ) {
               c = *p++;
               printf( (isprint(c)||isspace(c)) ? "%c" : "\\0x%02x" , c);
       }
       if(! only_text)
               printf(">\n");
       else
               printf("\n");
}

txt_metaseq(num)
{
       if(! only_text) {
               prtime();
               printf("Meta event, sequence number = %d\n",num);
       }
}

txt_metaeot()
{
       if(! only_text) {
               prtime();
               printf("Meta event, end of track\n");
       }
}

txt_keysig(sf,mi)
{
       if(! only_text) {
               prtime();
               printf("Key signature, sharp/flats=%d  minor=%d\n",sf,mi);
       }
}

txt_tempo(ltempo)
long ltempo;
{
       if(! only_text) {
               tempo = ltempo;
               prtime();
               printf("Tempo, microseconds-per-MIDI-quarter-note=%lu\n",tempo);
       }
}

txt_timesig(nn,dd,cc,bb)
{
       if(! only_text) {
               int denom = 1;
               while ( dd-- > 0 )
                       denom *= 2;
               prtime();
               printf("Time signature=%d/%d  MIDI-clocks/click=%d  32nd-notes/24-MIDI-clocks=%d\n",
                       nn,denom,cc,bb);
       }
}

txt_smpte(hr,mn,se,fr,ff)
{
       if(! only_text) {
               prtime();
               printf("SMPTE, hour=%d minute=%d second=%d frame=%d fract-frame=%d\n",
                       hr,mn,se,fr,ff);
       }
}

txt_arbitrary(leng,mess)
char *mess;
{
       if(! only_text) {
               prtime();
               printf("Arbitrary bytes, leng=%d\n",leng);
       }
}

prtime()
{
       printf("Time=%lu   ", mf_ticks2msec(Mf_currtime,division,tempo));
}

initfuncs()
{
       Mf_error = error;
       Mf_header =  txt_header;
       Mf_trackstart =  txt_trackstart;
       Mf_trackend =  txt_trackend;
       Mf_noteon =  txt_noteon;
       Mf_noteoff =  txt_noteoff;
       Mf_pressure =  txt_pressure;
       Mf_parameter =  txt_parameter;
       Mf_pitchbend =  txt_pitchbend;
       Mf_program =  txt_program;
       Mf_chanpressure =  txt_chanpressure;
       Mf_sysex =  txt_sysex;
       Mf_metamisc =  txt_metamisc;
       Mf_seqnum =  txt_metaseq;
       Mf_eot =  txt_metaeot;
       Mf_timesig =  txt_timesig;
       Mf_smpte =  txt_smpte;
       Mf_tempo =  txt_tempo;
       Mf_keysig =  txt_keysig;
       Mf_seqspecific =  txt_metaspecial;
       Mf_text =  txt_metatext;
       Mf_arbitrary =  txt_arbitrary;
}