/** SGX

The   sss    gggg x   x   
     s      g      x x    Engine
      sss   g  gg   x
         s  g   g  x x          Copyright 1995-2009.
     ssss    gggg x   x         Steven Goodwin. All Rights Reserved.
    
This version has been released under the GNU Public License v2.0.

Please see the license files for details.

File: sgx/include/utils/audio/simplesequencer.hpp

*/

#ifndef SGX_UTILS_AUDIO_SIMPLE_SEQUENCER_HPP
#define SGX_UTILS_AUDIO_SIMPLE_SEQUENCER_HPP	1

#include "domains/midi/midi.hpp"

#define AUDIO_SEQUENCER_MAX_NOTES		128		// limited by MIDI sizes
#define AUDIO_SEQUENCER_MAX_PATCHES		128		// limited by MIDI sizes

class sgxAudioSequencerPatch { 
public:
	sgxAudioSequencerPatch();
	tBOOL	assignSample(const CSampleData *pSample, const tUINT32 note);
	tBOOL	assignSample(const CSampleData *pSample, const tUINT32 noteFrom, const tUINT32 noteTo);
	tBOOL	play(const tUINT32 note, const tUINT32 volume);
protected:
	const CSampleData *m_pSample[AUDIO_SEQUENCER_MAX_NOTES];
};


class sgxAudioSequencerNote {
public:
	tUINT32	note;
	tUINT32	channel;
	tUINT32	volume;
	tUINT32 position;
	tUINT32 track;
//	sgxAudioSequencerPatch *	pPatch;
	sgxAudioSequencerNote(){}
	sgxAudioSequencerNote(tUINT32 n, tUINT32 c, tUINT32 v) : note(n), channel(c), volume(v) {}
};

class sgxAudioSequencerCallbackHandler {
public:
	virtual tBOOL	onAudioSequencerClock();
	virtual tBOOL	onAudioSequencerBegins();
	virtual tBOOL	onAudioSequencerNoteOn(const sgxAudioSequencerNote &note);
	virtual tBOOL	onAudioSequencerNoteOff(const sgxAudioSequencerNote &note);
	virtual tBOOL	onAudioSequencerEnd();
};


class CSimpleSequencer : public sgxAudioSequencerCallbackHandler {
public:
	CSimpleSequencer();
	~CSimpleSequencer();

	tBOOL	loadMIDI(const sgxString &filename);	
	tBOOL	loadPatch(sgxAudioSequencerPatch *pPatch, const tUINT32 patch, const sgxString &path, const tBOOL scenario);
	tBOOL	loadDrumKit(sgxAudioSequencerPatch *pDrumSetPatch, const sgxString &path, const tBOOL scenario);

	void	setHandler(sgxAudioSequencerCallbackHandler *pHandler);

	void	setClockQuantize(const tBOOL state);

	// sgxAudioSequencerPatch
	//void	loadPatch(const tUINT32 patch, const tUINT32 channel);
	void	setTempo(const tUINT32 tempo);
	void	assignPatchToChannel(const tUINT32 patch, const tUINT32 channel);
	void	playToTime(const tUINT32 timecum);
	void	skipToTime(const tUINT32 timecum);
	void	processToTime(const tUINT32 timecum, const tBOOL bIncludeNoteMessages);

	tUINT32 getDuration(const sgxAudioSequencerNote &note);

	tBOOL	play();
	tBOOL	pause();
	tBOOL	stop();

	tBOOL	update(const tREAL32 telaps);

	tBOOL	playNote(const sgxAudioSequencerNote &note);

	virtual tBOOL	onAudioSequencerClock();
	virtual tBOOL	onAudioSequencerNoteOn(const sgxAudioSequencerNote &note);
	virtual tBOOL	onAudioSequencerNoteOff(const sgxAudioSequencerNote &note);
	virtual tBOOL	onAudioSequencerEnd();

	virtual void	setPatch(const tUINT32 idx, const sgxAudioSequencerPatch &patch);

protected:
	class SequencerTrack {
	public:
		MIDI_MSG	m_Data;
		tBOOL		m_DataValid;
	};

	MIDI_FILE *							m_pFile;
	sgxAudioSequencerPatch				m_Patch[AUDIO_SEQUENCER_MAX_PATCHES];
	sgxAudioSequencerPatch *			m_ChannelPatch[16];
	tUINT32								m_iTempo;
	tREAL32								m_iClockPeriod;	// from tempo

	tBOOL								m_bPlaying;
	tREAL32								m_fTimecum;

	tBOOL								m_bTightQuantize;	// this only plays the notes at the same moment as a clock signal
	tUINT32								m_LastAbsTime;
	tUINT32 							m_ClockDeltaTime;

	tUINT32								m_iNumTracks;
	SequencerTrack *					m_pTracks;
	sgxAudioSequencerCallbackHandler *	m_pHandler;

};


#endif
