#pragma once

#include "node.h"

//##########################################################################
//##########################    MidiParse    ###############################
//##########################################################################

class MidiParse:
	public Node
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Construction, Destruction, and Testing
//
public:
	typedef long SignedLongWord; // 4 bytes
	typedef short int SignedWord; // 2 bytes
	typedef char SignedByte; // 1 bytes

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Construction, Destruction, and Testing
//
public:
	MidiParse();
	~MidiParse();
	Logical
		TestInstance() const;

	void
		Parse();

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Accessors
//
protected:
	SignedLongWord
		CurTime();

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Sub-class callbacks
//
private:
	virtual SignedWord
		Mf_getc();
	virtual void
		Mf_error(char *);

	virtual void
		Mf_starttrack() {}
	virtual void
		Mf_endtrack() {}
	virtual void
		Mf_eot() {}
	virtual void
		Mf_header(SignedWord,SignedWord,SignedWord) {}
	virtual void
		Mf_on(SignedWord,SignedWord,SignedWord) {}
	virtual void
		Mf_off(SignedWord,SignedWord,SignedWord) {}
	virtual void
		Mf_pressure(SignedWord,SignedWord,SignedWord) {}
	virtual void
		Mf_controller(SignedWord,SignedWord,SignedWord) {}
	virtual void
		Mf_pitchbend(SignedWord,SignedWord,SignedWord) {}
	virtual void
		Mf_program(SignedWord,SignedWord) {}
	virtual void
		Mf_chanpressure(SignedWord,SignedWord) {}
	virtual void
		Mf_sysex(SignedWord,char*) {}
	virtual void
		Mf_arbitrary(SignedWord,char*) {}
	virtual void
		Mf_metamisc(SignedWord,SignedWord,char*) {}
	virtual void
		Mf_seqnum(SignedWord) {}
	virtual void
		Mf_smpte(SignedWord,SignedWord,SignedWord,SignedWord,SignedWord) {}
	virtual void
		Mf_timesig(SignedWord,SignedWord,SignedWord,SignedWord) {}
	virtual void
		Mf_tempo(SignedLongWord) {}
	virtual void
		Mf_keysig(SignedWord,SignedWord) {}
	virtual void
		Mf_sqspecific(SignedWord,char*) {}
	virtual void
		Mf_text(SignedWord,SignedWord,char*) {}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Private methods
//
private:
	SignedWord
		readmt(char *s,SignedWord skip);
	SignedWord
		egetc();
	SignedWord
		readheader();
	void
		readtrack();
	void
		badbyte(SignedWord c);
	void
		metaevent(SignedWord type);
	void
		sysex();
	void
		chanmessage(SignedWord status,SignedWord c1,SignedWord c2);
	SignedLongWord
		readvarinum();
	SignedLongWord
		to32bit(SignedWord c1, SignedWord c2,SignedWord c3, SignedWord c4);
	SignedWord
		to16bit(SignedWord c1,SignedWord c2);
	SignedLongWord
		read32bit();
	SignedWord
		read16bit();
	void
		mferror(char *s);
	void
		msginit();
	char*
		msg();
	SignedWord
		msgleng();
	void
		msgadd(SignedWord c);
	void
		msgenlarge();

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Private data
//
private:
	SignedWord Mf_nomerge;
	SignedLongWord Mf_currtime;
	SignedWord Mf_skipinit;

	SignedLongWord Mf_toberead;

	char *Msgbuff;
	SignedWord Msgsize;
	SignedWord Msgindex;
};
