/* Output from p2c, the Pascal-to-C translator */
/* From input file "tp_midi.pas" */

#define TP_MIDI_G
#include "tp_midi.h"
#include <stdlib.h>
#include <math.h>
#include <string.h>


/********************************************/
Char *StaffIndex(Result,No)
Char *Result;
int No;
{
  /********************************************/
  switch (No) {

  case 1:
    strcpy(Result, "i");
    break;

  case 2:
    strcpy(Result, "ii");
    break;

  case 3:
    strcpy(Result, "iii");
    break;

  case 4:
    strcpy(Result, "iv");
    break;

  case 5:
    strcpy(Result, "v");
    break;

  case 6:
    strcpy(Result, "vi");
    break;

  case 7:
    strcpy(Result, "vii");
    break;

  case 8:
    strcpy(Result, "viii");
    break;

  case 9:
    strcpy(Result, "ix");
    break;

  case 10:
    strcpy(Result, "x");
    break;

  default:
    ErrorExit(8L);
    break;
  }/* case */
  return Result;
}


/**********************************************/
Char *GetPortees(Result)
Char *Result;
{
  /**********************************************/
  Char TmpSTr[256];
  int curtr;
  uchar curinstr, staff, StartStaff, nStaffsInInstr;
  boolean StartFound;
  TrackRecord *WITH;
  Char STR1[256];
  Char STR2[256];

  *TmpSTr = '\0';
  StartFound = false;
  for (curinstr = 1; curinstr <= 1; curinstr++)
  {   /* this version only supports one instrument */
    staff = 1;
    
    for (curtr = (int) (ntracks - 1); curtr >= 0; curtr--) { /* With */
      WITH = &TrackArray[TrackOrder[curtr] - 1];  
      if (!WITH->Skip) {
	if (!StartFound) {
	  if (WITH->Instrument) {
	    StartStaff = staff;
	    StartFound = true;
	    nStaffsInInstr = 1;  
	  }
	} else {
	  if (WITH->Instrument)
	    nStaffsInInstr++;   
	}
	staff++;
      } /* if Skip */
    }  /* for next curtr */
    sprintf(TmpSTr, "\\nbportees%s=%s",
	    StaffIndex(STR1, StartStaff), B2S(STR2, nStaffsInInstr));
  }  /* for next curinstr */
  strcpy(Result, TmpSTr);
  return Result;
}


/**********************************************/
Void WriteTexHeader()
{
  /**********************************************/
  unsigned short Year;
  unsigned short Month;
  unsigned short Day;
  unsigned short DoW;
  Char STR1[256], STR2[256];
  Char STR4[256];

  /*  getdate(&d);  */
  fprintf(TexFile,
    "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n");
  fprintf(TexFile, "%%    MIDI2TeX %s translation \n",VERSION);
  fprintf(TexFile, "%%           of MIDI file : \n");
  fprintf(TexFile, "%%          %s%s\n", MidiFileName.n, MidiFileName.e);
  fprintf(TexFile, "%% \n");
  fprintf(TexFile, "%%   Written by Hans Kuykens, Ad Verbruggen\n");
  fprintf(TexFile,
    "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n");
  fprintf(TexFile, "\\input musicnft\n");
  fprintf(TexFile, "\\input musictex\n");
  fprintf(TexFile, "\\input musicadd\n");
  fprintf(TexFile, "\\input musictrp\n");
  fprintf(TexFile, "\\normal\n");
  if (SizingChanged) {
    fprintf(TexFile, "\\hsize %ldmm ",ScoreWidth / 10);
    fprintf(TexFile, "\\vsize %ldmm\n",ScoreHeight / 10);
    fprintf(TexFile, "\\musicsize=%ld\n", MusicSize);
    fprintf(TexFile, "\\elemskip=%ldpt%%\n",(long)(ElemSkip / PT ));
    }
  if (ninstruments > 0) {
    fprintf(TexFile, "\\def\\nbinstruments{%ld}\n",
	      ntracks - NoOfSkips - nTracksInInstr + 1);
    fprintf(TexFile, "%s\n", GetPortees(STR4));
  } else
    fprintf(TexFile, "\\def\\nbinstruments{%d}\n",
	    (int)(ntracks - NoOfSkips));

  fprintf(TexFile,"\\generalsignature{%d}\\relax\n",PieceContr.KeySign);
  fprintf(TexFile,"\\def\\thename{%s}\n",TeXFileName.n);
  fprintf(TexFile,"%% \\centerline{\\enorme PUT A NAME HERE and remove }\n");
  fprintf(TexFile, "\\medskip\\centerline{\\moyen \\thename}\n");
  fprintf(TexFile, "\\rightline{translation by MIDI2TeX}\n");
  fprintf(TexFile, "\\rightline{by H.J.P. Kuykens}\n");
  fprintf(TexFile, "\\def\\date{\\number\\day -\\number\\month -\\number\\year}\n");
  fprintf(TexFile, "\\headline={\\ifnum\\pageno>1 \\otherpage \\else\\frontpage\\fi}\n");
  fprintf(TexFile, "\\def\\frontpage{\\hfil \\tenrm\\date}\n");
  fprintf(TexFile, "\\def\\otherpage{\\tenrm \\thename \\hfil \\tenrm\\date}\n");
  fflush(TexFile);
}


/*-----------------------------------------------*/
long FindStaff(ThisTrack)
long ThisTrack;
{
  /*-----------------------------------------------*/
  /* Watch it ! If the track is in an instrument than the parameter string */
  /* must be altered of cleftoks#                                          */
  long i, j;

  i = ntracks;
  j = 1;
  while (TrackOrder[i - 1] != ThisTrack) {
    if (!TrackArray[TrackOrder[i - 1] - 1].Skip)
      j++;
    i--;
  }
  return j;
}  /* FindStaff */

/*-----------------------------------------------*/
Char *FindClefStaff(Result, ThisTrack)
Char *Result;
long ThisTrack;
{
  /*-----------------------------------------------*/
  long i, j, k;
  Char STR1[256],C[2];


  i = ntracks;
  j = 1;
  k = 1;
  sprintf(C,"%d",TrackArray[ThisTrack-1].Clef);
  while (TrackOrder[i - 1] != ThisTrack) {
    if (!TrackArray[TrackOrder[i - 1] - 1].Skip) {
      if (TrackArray[TrackOrder[i - 1] - 1].Instrument)
	k++;
      else
	j++;
    }
    i--;
  }
  switch (k) {

  case 1:
    sprintf(Result, "\\cleftoks%s{{%s}{0}{0}{0}}", StaffIndex(STR1, (int)j),C);
    break;

  case 2:
    sprintf(Result, "\\cleftoks%s{{0}{%s}{0}{0}}", StaffIndex(STR1, (int)j),C);
    break;

  case 3:
    sprintf(Result, "\\cleftoks%s{{0}{0}{%s}{0}}", StaffIndex(STR1, (int)j),C);
    break;

  case 4:
    sprintf(Result, "\\cleftoks%s{{0}{0}{0}{%s}}", StaffIndex(STR1, (int)j),C);
    break;

  default:
    Warning("Something wrong with cleftoks#, check it out !");
    strcpy(Result, "\\cleftoks??");
    break;
  }

  return Result;
}  /* FindClefStaff */


/********************************************/
static Void FinishTeXHeader(num, den)
unsigned int num, den;
{
  /********************************************/
  int i;
  Char STR2[256];
  int FORLIM;

  fprintf(TexFile, "\\generalmeter{\\meterfrac{%d}{%d}}%%\n",num, Power(2, den));
  FORLIM = ntracks;
  /* determine clefs */
  for (i = 1; i <= FORLIM; i++) {
    if (TrackArray[i - 1].Clef == BASS)
      fprintf(TexFile, "%s\n", FindClefStaff(STR2, (long)i));
  }
  fprintf(TexFile,
	  "%%\\raggedlinestrue %% uncomment for ragged right lines \n");
  fprintf(TexFile, "%%\\relativeaccidentals\n");
  fprintf(TexFile, "\\debutmorceau\n");
  /*
  if (NoteSkip == 20)
    fprintf(TexFile, "\\autolines{16}{5}{16} \n");
  else
    fprintf(TexFile, "\\autolines{16}{7}{16} \n");
  */
  TeXHeaderFinished = true;
  fflush(TexFile);
}


/********************************************/
Void ChangeContext(N)
NoteRecord *N;
{
  /********************************************/
  Char STR1[256];

  switch (N->Event) {

  case KEYSIGN:
    fprintf(TexFile, "\\signaturegenerale{%s}\\changecontext%%\n",
	    B2S(STR1, (char) N->NoteVal));   /* N->NoteVal is uchar */
    PieceContr.KeySign = N->NoteVal;
    PieceContr.Minor = N->Velocity;
    break;

  case SIGNATURE:
    fprintf(TexFile, "\\generalmeter{\\meterfrac{%d}{%d}}%%\n",
	    N->NoteVal, Power(2, N->Velocity));
    fprintf(TexFile, "\\changecontext%%\n");
    PieceContr.Num = N->NoteVal;
    PieceContr.Den = N->Velocity;
    PieceContr.TicksPerMeasure = 4 * PieceContr.Division * PieceContr.Num  /
				 Power(2, PieceContr.Den);
    if (!PieceContr.PartOverRule)
      PieceContr.PartTime = PieceContr.TicksPerMeasure / PieceContr.Num;
    PieceContr.nparts = PieceContr.TicksPerMeasure / PieceContr.PartTime;
    PieceContr.Twindow = PieceContr.Division / 16;

    break;
  }/* case */
ChangedContext=TRUE;
}


/*****************************************************/
Void Quantize(N)
NoteRecord **N;
{
  /* Still needs updating !!! */
  /*****************************************************/
  long dt;
  MeasureTime T;
  NoteRecord *WITH;

  WITH = *N;
  dt = TimeDiff(WITH->EndTime, WITH->StartTime);
  if (dt <= QuantTime)
    return;
  /* quantize notelength first */
  dt = QuantTime * (long)floor((double)dt / QuantTime + 0.5);
  SetTim(&T, 0, (int)dt);
  /* quantize start time and end time*/
  WITH->StartTime.MPart =
    QuantTime * (long)floor((double)WITH->StartTime.MPart / QuantTime + 0.5);
  AddTime(WITH->StartTime, T, &WITH->EndTime);
}



/*******************************************************/
Void ReadDeltaTime(ThisTrack)
TrackRecord *ThisTrack;
{
  /*******************************************************/
  long delta;
  MeasureTime *WITH1;

  ThisTrack->OldOldTime = ThisTrack->OldTime;
  ThisTrack->OldTime = ThisTrack->Curtime;
  delta = ReadVarLen(&ThisTrack->FilRec);
  WITH1 = &ThisTrack->Curtime;
  /*    WriteDebugInfo('read deltatime :'+LI2S(delta)); */
  if (PieceContr.TicksPerMeasure == 0) {
    WITH1->MPart += delta;
    return;
  }
  WITH1->MPart += delta;
  if (WITH1->MPart >= PieceContr.TicksPerMeasure) {
    WITH1->Measure += WITH1->MPart / PieceContr.TicksPerMeasure;
    WITH1->MPart %= PieceContr.TicksPerMeasure;
  }
}



/******************************************************/
Void InsertRest(ThisTrack)
TrackRecord *ThisTrack;
{
  /******************************************************/
  NoteRecord *N;
  MeasureTime TmpTime1, TmpTime2;
  Char STR1[256];
  Char STR2[256];
  Char STR4[256];
  Char STR5[256];
  Char STR6[256];

  SetTim(&TmpTime1, (int)MeasureCount, 0);
  SetTim(&TmpTime2, (int)(MeasureCount + 1), 0);
  N = GetFreeNote();
  N->Event = REST;
  /*
  If (TimeDiff(TmpTime2,LastNoteOffTime)>0) AND
     (TimeDiff(TmpTime1,LastNoteOffTime)<=0) Then
     N^.STartTime:=LastNoteOffTime
  Else
     N^.STartTime:=TmpTime1;
  If TimeDiff(TmpTime2,CurTime)<0 Then
     N^.EndTime:=TmpTime2
  Else
     N^.EndTime:=CurTime;
  */
  N->EndTime = ThisTrack->Curtime;
  N->StartTime = ThisTrack->LastNoteOffTime;
  Append(&ThisTrack->NoteList, N);
  sprintf(STR6, "Inserted Rest between %3d:%3ld and %3d:%3ld",
	  (int)N->StartTime.Measure,
	  N->StartTime.MPart,(int)N->EndTime.Measure,
	  N->EndTime.MPart);
  WriteDebugInfo(STR6);
}


/******************************************************/
static Void ReadNoteOn(MidCode, ThisTrack)
unsigned int MidCode;
TrackRecord *ThisTrack;
{
  /******************************************************/
  NoteRecord *N, *P;
  long dt;
  uchar TmpVal, TmpVel;
  Char STR1[256];
  Char STR2[256];
  Char STR4[256];
  Char STR5[256];
  Char STR6[256];

  TmpVal = ReadByte(&ThisTrack->FilRec);
  TmpVel = ReadByte(&ThisTrack->FilRec);
      /* if TmpVel=0 Than it is a Note OFF ! */

  if (TmpVel > 0) {   /* With ThisTrack */
    if (ThisTrack->NotesSounding == 0) {
      dt = TimeDiff(ThisTrack->Curtime, ThisTrack->LastNoteOffTime);
      if (Quantizing) {
	if (dt > QuantTime)   /* only insert rest if longer than QuantTime */
	  InsertRest(ThisTrack);
      } else {
	if (dt >= PieceContr.Division / 4)
	      /* only insert rest if longer than 1/16th note */
		InsertRest(ThisTrack);
      }
    } else {  /* There are notes sounding, check if same note is already on */
      FirstNote(ThisTrack->NoteList, &N);
      P = NULL;
      while (N != P) {
	if (P == NULL)
	  P = N;
	if (N->NoteVal == TmpVal && N->Event == NOTEON)
	{   /* close this note down */
	  N->EndTime = ThisTrack->Curtime;
	  N->Event = NOTEOFF;
	  ThisTrack->LastNoteOffTime = ThisTrack->Curtime;
	  if (ThisTrack->NotesSounding > 0)
	    ThisTrack->NotesSounding--;
	  WriteDebugInfo("Closed down a double note");
	}
	NextNote(N, &N);
      }
    }

    N = GetFreeNote();
    Append(&ThisTrack->NoteList, N);
    N->MidiChnl = MidCode % 15;
    N->NoteVal = TmpVal;
    N->Velocity = TmpVel;
    N->Event = NOTEON;
    N->StartTime = ThisTrack->Curtime;
    SetTim(&N->EndTime, 1000, 0);   /* set EndTime to infinity */
    /*W2S(NoteArPoint)+*/
    sprintf(STR6, "NoteOn : %2d Vel : %3d at %3d:%3ld",
	    N->NoteVal,N->Velocity,(int)ThisTrack->Curtime.Measure,
	    ThisTrack->Curtime.MPart);
    WriteDebugInfo(STR6);
    ThisTrack->NotesSounding++;
    return;
  }

  sprintf(STR6, "NoteOff : %2d at %3d:%3ld",
	  TmpVal,(int)ThisTrack->Curtime.Measure,
	  ThisTrack->Curtime.MPart);
  WriteDebugInfo(STR6);
  if (ThisTrack->NoteList.Size <= 0) {
    WriteDebugInfo("There can`t be a NoteOff if there are no notes at all !");
    return;
  }  /* If NoteList.Size > 0 */
  LastNote(ThisTrack->NoteList, &N);   /* dit gaat soms fout ... ? */
  FirstNote(ThisTrack->NoteList, &P);
      /* een maat kan beginnen met een NoteOff !!!! */
  while (!EqualsNote(N, TmpVal) && N != P)
    PrevNote(N, &N);

  if (N == NULL)
    ErrorExit(6L);
  else {
    if (!EqualsNote(N, TmpVal))
      WriteDebugInfo("Could not find note-ON for this note-OFF");
    else {
      if (N->Event == NOTEON) {
	N->EndTime = ThisTrack->Curtime;
	N->Event = NOTEOFF;
      } else
	WriteDebugInfo("Note was already OFF, probably a double note...");
    }
  }
  ThisTrack->LastNoteOffTime = ThisTrack->Curtime;
  if (ThisTrack->NotesSounding > 0)
    ThisTrack->NotesSounding--;

  /* the Velocity value is 0 set Note Off */
  /* Set Note Off */
}  /* ReadNoteOn */


/******************************************************/
static Void ReadNoteOff(MidCode, ThisTrack)
unsigned int MidCode;
TrackRecord *ThisTrack;
{
  /******************************************************/
  NoteRecord *N, *P;
  uchar MidiChnl, velo, Note;
  Char STR1[256];
  Char STR2[256];
  Char STR4[256];
  Char STR5[256];

  MidiChnl = MidCode % 15;
  Note = ReadByte(&ThisTrack->FilRec);
  velo = ReadByte(&ThisTrack->FilRec);
  sprintf(STR5, "NoteOff : %2d at %3d:%3ld",
	  Note,(int)ThisTrack->Curtime.Measure,
	  ThisTrack->Curtime.MPart);
  WriteDebugInfo(STR5);
  if (ThisTrack->NoteList.Size <= 0) {   /* with this track */
    WriteDebugInfo("There can`t be a NoteOff if there are no notes at all !");
    return;
  }  /* If NoteList.Size > 0 */
  LastNote(ThisTrack->NoteList, &N);   /* dit gaat soms fout ... ? */
  FirstNote(ThisTrack->NoteList, &P);
      /* een maat kan beginnen met een NoteOff !!!! */
  while (!EqualsNote(N, Note) && N != P)
    PrevNote(N, &N);

  if (N == NULL)
    ErrorExit(6L);
  else {
    if (!EqualsNote(N, Note))
      WriteDebugInfo("Could not find note-ON for this note-OFF");
    else {
      if (N->Event == NOTEON) {
	N->EndTime = ThisTrack->Curtime;
	N->Event = NOTEOFF;
      } else
	WriteDebugInfo("Note was already OFF, probably a double note...");
    }
  }
  ThisTrack->LastNoteOffTime = ThisTrack->Curtime;
  if (ThisTrack->NotesSounding > 0)
    ThisTrack->NotesSounding--;
}  /* ReadNoteOff */



/******************************************************/
static Void ReadMetaText(Len, ThisTrack)
int Len;
TrackRecord *ThisTrack;
{
  /******************************************************/
  NoteRecord *N;
  Char STR1[256];
  Char STR3[256];
  Char STR4[256];

  N = GetFreeNote();
  Append(&ThisTrack->NoteList, N);
  N->Event = TXT;
  N->MetaTxt = (Char *)malloc(21L);
  if (N->MetaTxt==NULL) ErrorExit(9L);
  N->StartTime = ThisTrack->Curtime;
  N->EndTime = ThisTrack->Curtime;
  N->EndTime.Measure++;
  ReadString(N->MetaTxt, &ThisTrack->FilRec, (long)Len);
  sprintf(STR4, "MetaText :%s at %3ld:%3ld",
	  N->MetaTxt, ThisTrack->Curtime.Measure,
	  ThisTrack->Curtime.MPart);
  WriteDebugInfo(STR4);
}  /* ReadText */


/**********************************************************/
Void ReadMetaEvent(ThisTrack)
TrackRecord *ThisTrack;
{
  /**********************************************************/
  long i, DumInt;
  uchar DumByte, MetaType;
  unsigned short MetaByteCnt;
  long MetaLength;
  NoteRecord *N;
  Char STR1[256];
  Char STR2[256], STR3[256], STR4[256], STR5[256], STR6[256];

  MetaType = ReadByte(&ThisTrack->FilRec);
  MetaLength = ReadVarLen(&ThisTrack->FilRec);
  sprintf(STR3, " Read Meta event type : %2d of %2ld bytes",
	  MetaType,MetaLength);
  WriteDebugInfo(STR3);
  MetaByteCnt = 0;
  switch (MetaType) {

  case 0:
    DumByte = ReadByte(&ThisTrack->FilRec);
    DumInt = ReadInteger(&ThisTrack->FilRec);
    break;

  case 1:
  case 2:
  case 3:
  case 4:
  case 5:
  case 6:
  case 7:  /* Text events */
    /* DumStr:=ReadString(FilRec,MetaLength); */
    ReadMetaText((int)MetaLength, ThisTrack);
    break;

  case 32:   /* MIDI Chnl Prefix */
    DumByte = ReadByte(&ThisTrack->FilRec);
    break;

  case 47:
    ThisTrack->EndOfTrackRead = true;
    break;
    /* End of Track */

  case 81:  /* set tempo */
    PieceContr.Tempo = ReadByte(&ThisTrack->FilRec);
    PieceContr.Tempo <<= 8;
    PieceContr.Tempo += ReadByte(&ThisTrack->FilRec);
    PieceContr.Tempo <<= 8;
    PieceContr.Tempo += ReadByte(&ThisTrack->FilRec);
    break;

  case 84:  /* SMPTE OffSet */
    DumByte = ReadByte(&ThisTrack->FilRec);
    DumByte = ReadByte(&ThisTrack->FilRec);
    DumByte = ReadByte(&ThisTrack->FilRec);
    DumByte = ReadByte(&ThisTrack->FilRec);
    DumByte = ReadByte(&ThisTrack->FilRec);
    break;

  case 88:  /* Time Sign */
    if (TeXHeaderFinished) {   /* store the value on the note list */
      N = GetFreeNote();
      Append(&ThisTrack->NoteList, N);
      N->Event = SIGNATURE;
      N->NoteVal = ReadByte(&ThisTrack->FilRec);   /* NUM */
      N->Velocity = ReadByte(&ThisTrack->FilRec);   /* DEN */
      DumByte = ReadByte(&ThisTrack->FilRec);
      DumByte = ReadByte(&ThisTrack->FilRec);
      N->StartTime = ThisTrack->Curtime;
      N->EndTime = ThisTrack->Curtime;
      sprintf(STR6, "Signature : %2d/%2ld at %3ld:%3ld",
	      N->NoteVal,(long)Power(2, N->Velocity),
	      ThisTrack->Curtime.Measure,
	      ThisTrack->Curtime.MPart);
      WriteDebugInfo(STR6);
    } else {
      PieceContr.Num = ReadByte(&ThisTrack->FilRec);
      PieceContr.Den = ReadByte(&ThisTrack->FilRec);
      FinishTeXHeader(PieceContr.Num, PieceContr.Den);
      DumByte = ReadByte(&ThisTrack->FilRec);
      DumByte = ReadByte(&ThisTrack->FilRec);
      PieceContr.TicksPerMeasure = PieceContr.Division * PieceContr.Num * 4 /
				   Power(2, PieceContr.Den);
      if (!PieceContr.PartOverRule)
	PieceContr.PartTime = PieceContr.TicksPerMeasure / PieceContr.Num;
      else
	PieceContr.PartTime = PieceContr.Division * 4 / PieceContr.PartType;
      PieceContr.nparts = PieceContr.TicksPerMeasure / PieceContr.PartTime;
      PieceContr.Twindow = PieceContr.Division / 16;
      if (Quantizing)
	QuantTime = PieceContr.Division * 4 / QuantTime;
      sprintf(STR4, "4*%3ld*%3d div %3d = %4ld Ticks per measure",
	      (long)PieceContr.Division,PieceContr.Num,
	      PieceContr.Den,PieceContr.TicksPerMeasure);
      WriteDebugInfo(STR4);
    }
    break;

  case 89:  /* Key signature */
    if (TeXHeaderFinished) {   /* store the value on the note list */
      N = GetFreeNote();
      Append(&ThisTrack->NoteList, N);
      N->Event = KEYSIGN;
      N->NoteVal = ReadByte(&ThisTrack->FilRec);   /* KeySign */
      N->Velocity = ReadByte(&ThisTrack->FilRec);   /* Minor */
      N->StartTime = ThisTrack->Curtime;
      N->EndTime = ThisTrack->Curtime;

	  sprintf(STR4, "Keysign  : %2d at %3ld:%3ld",
    	(char)N->NoteVal,ThisTrack->Curtime.Measure,
	      ThisTrack->Curtime.MPart);
      WriteDebugInfo(STR4);
    } else {
      PieceContr.KeySign = ReadByte(&ThisTrack->FilRec);
      PieceContr.Minor = ReadByte(&ThisTrack->FilRec);
      if (PieceContr.KeySign > 0) {
	sprintf(STR6, "KeySignature : %2d sharps ",(int)PieceContr.KeySign);
	WriteDebugInfo(STR6);
      } else {
	sprintf(STR2, "KeySignature : %2d flats ",(int)PieceContr.KeySign);
	WriteDebugInfo(STR2);
      }
    }
    /* with */
    break;
 case 127:  /* specials.... */
    for (i = 1; i <= MetaLength; i++)
      DumByte = ReadByte(&ThisTrack->FilRec);
    break;

  default :
  /*  WriteDebugInfo("Found unknown Meta event :"+B2S(MetaType)); */
    sprintf(STR2,"Found unknown Meta event :%s ",B2S(STR6,(long)MetaType));
    WriteDebugInfo(STR2);
    for (i=1; i<=MetaLength; i++) DumByte=ReadByte(&ThisTrack->FilRec);
    break;


  }/* case */
}  /* ReadMetaEvent */



/*****************************************************/
Void ReadEvent(ThisTrack)
TrackRecord *ThisTrack;
{
  /*****************************************************/
  uchar DumByte, MidiCode;

  MidiCode = ReadByte(&ThisTrack->FilRec);
  switch (MidiCode) {

  case 0xff:
    ReadMetaEvent(ThisTrack);
    ThisTrack->StatusByte = MidiCode;
    break;

  case 0xf8:   /* do nothing */
    break;
    /* timing clock */

  case 0xf0:
    do {   /* SysEx code */
      DumByte = ReadByte(&ThisTrack->FilRec);
    } while (DumByte != 0xf7);
    ThisTrack->StatusByte = 0;
    break;

  case 0xf1:   /* quarter frame */
    DumByte = ReadByte(&ThisTrack->FilRec);
    break;
    /* WriteDebugInfo(' Unknown MidiEvent, type : '+B2S(MidiCode)); */

  default:
    if (MidiCode >= 0x90 && MidiCode <= 0x9f) {
      ReadNoteOn(MidiCode, ThisTrack);
      ThisTrack->StatusByte = MidiCode;
    } else if (MidiCode >= 0x80 && MidiCode <= 0x8f) {
      ReadNoteOff(MidiCode, ThisTrack);
      ThisTrack->StatusByte = MidiCode;
    } else if (MidiCode >= 0xa0 && MidiCode <= 0xaf) {
      /* polypress. */
      for (i = 1; i <= 2; i++)
	DumByte = ReadByte(&ThisTrack->FilRec);
      ThisTrack->StatusByte = MidiCode;
    } else if (MidiCode >= 0xb0 && MidiCode <= 0xbf) {
      for (i = 1; i <= 2; i++)
	DumByte = ReadByte(&ThisTrack->FilRec);
      ThisTrack->StatusByte = MidiCode;
    } else if (MidiCode >= 0xc0 && MidiCode <= 0xcf) {
      DumByte = ReadByte(&ThisTrack->FilRec);
      ThisTrack->StatusByte = MidiCode;
    } else if (MidiCode >= 0xd0 && MidiCode <= 0xdf) {
      DumByte = ReadByte(&ThisTrack->FilRec);
      ThisTrack->StatusByte = MidiCode;
    } else if (MidiCode >= 0xe0 && MidiCode <= 0xef) {
      for (i = 1; i <= 2; i++)
	DumByte = ReadByte(&ThisTrack->FilRec);
      ThisTrack->StatusByte = MidiCode;
    } else {
      /* This is a running status */
      RestoreLastRead(&ThisTrack->FilRec);
	  /* This will NOT work ALWAYS !!! */
      switch (ThisTrack->StatusByte) {

      case 0xff:
	ReadMetaEvent(ThisTrack);
	break;

      case 0xf8:   /* do nothing */
	break;
	/* timing clock */

      case 0xf0:
	do {   /* SysEx code */
	  DumByte = ReadByte(&ThisTrack->FilRec);
	} while (DumByte != 0xf7);
	break;

      case 0xf1:   /* quarter frame */
	DumByte = ReadByte(&ThisTrack->FilRec);
	break;

      default:
	if (ThisTrack->StatusByte >= 0x90 && ThisTrack->StatusByte <= 0x9f)
	  ReadNoteOn(ThisTrack->StatusByte, ThisTrack);
	else if (ThisTrack->StatusByte >= 0x80 &&
		 ThisTrack->StatusByte <= 0x8f)
	  ReadNoteOff(ThisTrack->StatusByte, ThisTrack);
	else if (ThisTrack->StatusByte >= 0xa0 &&
		 ThisTrack->StatusByte <= 0xaf) {
	  for (i = 1; i <= 2; i++)
	    DumByte = ReadByte(&ThisTrack->FilRec);
	} else if (ThisTrack->StatusByte >= 0xb0 &&
		   ThisTrack->StatusByte <= 0xbf) {
	  for (i = 1; i <= 2; i++)
	    DumByte = ReadByte(&ThisTrack->FilRec);
	} else if (ThisTrack->StatusByte >= 0xc0 &&
		   ThisTrack->StatusByte <= 0xcf)
	  DumByte = ReadByte(&ThisTrack->FilRec);
	else if (ThisTrack->StatusByte >= 0xd0 &&
		 ThisTrack->StatusByte <= 0xdf)
	  DumByte = ReadByte(&ThisTrack->FilRec);
	else if (ThisTrack->StatusByte >= 0xe0 &&
		 ThisTrack->StatusByte <= 0xef) {
	  for (i = 1; i <= 2; i++)
	    DumByte = ReadByte(&ThisTrack->FilRec);
	}
	break;
      }/* case */
    }
    break;
  }

  /* control change */
  /* progr. change */
  /* channel pressure */
  /* pitch wheel */
}  /* ReadEvent */




/**************************************************************/
boolean EndOfTrackReached(ThisTrack)
TrackRecord *ThisTrack;
{
  /*************************************************************/
  if (ThisTrack->EndOfTrackRead==true && ThisTrack->SpillList.Size == 0 &&
      ThisTrack->NoteList.Size == 0)
    return true;
  else
    return false;
}


void _TP_MIDI_init()
{
  static int _was_initialized = 0;
  if (_was_initialized++)
    return;
}
