//=========================================================
//  MusE
//  Linux Music Editor
//  $Id: midi.h,v 1.1.1.1 2003/10/29 10:05:10 wschweer Exp $
//
//  (C) Copyright 1999/2000 Werner Schweer (ws@seh.de)
//=========================================================

#ifndef __MIDI_H__
#define __MIDI_H__

#include <stdio.h>
#include <qstring.h>

extern unsigned const char gmOnMsg[];
extern unsigned const char gsOnMsg[];
extern unsigned const char xgOnMsg[];

extern unsigned const int gmOnMsgLen;
extern unsigned const int gsOnMsgLen;
extern unsigned const int xgOnMsgLen;

class MidiEvent;
class MidiTrack;
class PartList;

//---------------------------------------------------------
//   MidiFile
//---------------------------------------------------------

class MidiFile {
   public:
      MidiFile(FILE* f);
      bool read();
      bool save();

   private:
      PartList* parts;
      int timesig_z, timesig_n;
      MidiTrack* track;
      int status, lastchan, click;
      int sstatus;
      int lastport;
      int channelprefix;
      FILE* fp;
      int error;
      int format, ntracks, division;
      int curPos;

      bool read(void*, size_t);
      bool write(const void*, size_t);
      void put(unsigned char c) { write(&c, 1); }

      bool skip(size_t);
      int readShort();
      void writeShort(int);
      int readLong();
      void writeLong(int);
      MidiEvent* readEvent(MidiTrack*);
      bool readTrack(bool);
      void processTrack1(MidiTrack* track);
      void processTrack2(MidiTrack* track);
      bool writeTrack(MidiTrack*);
      int getvl();
      void putvl(unsigned);
      void writeEvent(int channel, MidiEvent*);
      bool checkSysex(MidiTrack*, unsigned int len, unsigned char* buf);
      void addKaraoke(MidiTrack* track);
      };

#define XCHG_SHORT(x) ((((x)&0xFF)<<8) | (((x)>>8)&0xFF))
#ifdef __i486__
#define XCHG_LONG(x) \
     ({ int __value; \
        asm ("bswap %1; movl %1,%0" : "=g" (__value) : "r" (x)); \
       __value; })
#else
#define XCHG_LONG(x) ((((x)&0xFF)<<24) | \
		      (((x)&0xFF00)<<8) | \
		      (((x)&0xFF0000)>>8) | \
		      (((x)>>24)&0xFF))
#endif

#if __BYTE_ORDER == __LITTLE_ENDIAN
#define BE_SHORT(x) XCHG_SHORT(x)
#define BE_LONG(x) XCHG_LONG(x)
#else
#define BE_SHORT(x) x
#define BE_LONG(x) x
#endif

#define ME_SYSEX        0xf0
#define ME_META         0xff
#define ME_TIMESIG      0x58

QString nameSysex(unsigned int len, const unsigned char* buf);
QString midiMetaName(int);

#endif

