//===========================================================================//
// File:	audseq.hpp                                                          //
// Project: MUNGA           Brick: Audio manager									  //
// Contents: 																					  //
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
// 01/30/95  ECH  Initial coding.                                            //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc.                //
// All Rights reserved worldwide                                             //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL               //
//===========================================================================//

#if !defined(AUDSEQ_HPP)
#	define AUDSEQ_HPP

#	if !defined(STYLE_HPP)
#		include <style.hpp>
#	endif

#	if !defined(AUDIO_HPP)
#		include <audio.hpp>
#	endif

#	if !defined(AUDMIDI_HPP)
#		include <audmidi.hpp>
#	endif

#	if !defined(VCHAIN_HPP)
#		include <vchain.hpp>
#	endif

#	if !defined(AUDTIME_HPP)
#		include <audtime.hpp>
#	endif

	//##########################################################################
	//#######################    AudioControlEvent    ##########################
	//##########################################################################

	class AudioControlEvent:
		public Plug
	{
		friend MemoryStream&
			MemoryStream_Read(
				MemoryStream *stream,
				AudioControlEvent *control_event
			);

		friend MemoryStream&
			MemoryStream_Write(
				MemoryStream *stream,
				const AudioControlEvent *control_event
			);

	public:
		AudioControlEvent(
			AudioTick start_tick,
			AudioControlID audio_control_ID,
			AudioControlValue audio_control_value
		);
		AudioControlEvent();
		~AudioControlEvent();

		Logical
			AudioControlEvent::TestInstance() const;

		AudioTick
			GetStartTick()
				{return startTick;}

		void
			Send(AudioComponent *audio_component);

		Logical
			Chase(AudioComponent *audio_component);

	public:
		friend ostream&
			operator << (
				ostream &strm,
				const AudioControlEvent &control_event
			);

	// private: // HACK
		AudioTick
      	startTick;
		AudioControlID
			audioControlID;
		AudioControlValue
			audioControlValue;
	};

	//##########################################################################
	//#######################    AudioControlSequence    #######################
	//##########################################################################

	class AudioControlSequence:
		public AudioComponent
	{
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Construction, Destruction, and Testing
	//
	public:
		AudioControlSequence(
			PlugStream *stream,
			Entity *entity
		);
		void
			AudioControlSequenceX(
				AudioComponent *audio_component,
				Entity *entity,
				Logical is_looped,
				AudioDivisionsPerBeat divisions_per_beat,
				AudioTempo tempo,
				Logical dump_value
			);
		~AudioControlSequence();

		Logical
			TestInstance() const;

		//
		//--------------------------------------------------------------------
		// BuildFromPage
		//--------------------------------------------------------------------
		//
		static void
			BuildFromPage(
				PlugStream *stream,
				NameList *name_list,
				ClassID class_ID,
				ObjectID object_ID
			);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Sequence methods
	//
	public:
		//
		//--------------------------------------------------------------------
		// Controller methods
		//--------------------------------------------------------------------
		//
		void
			ReceiveControl(
				AudioControlID control_ID,
				AudioControlValue control_value
			);

		//
		//--------------------------------------------------------------------
		// Sequence control
		//--------------------------------------------------------------------
		//
		void
			StartSequence();
		void
			RunSequence();
		void
			StopSequence();

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Private methods
	//
	private:
		Logical
			IsEventReady(AudioControlEvent *audio_control_event);
		Scalar
			CalculateEventSeconds(AudioControlEvent *audio_control_event);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Private data
	//
	private:
		typedef SChainOf<AudioControlEvent*>
			AudioControlEventSocket;
		typedef SChainIteratorOf<AudioControlEvent*>
			AudioControlEventIterator;

		Logical isLooped;
		Logical isRunning;
		AudioTime startTime;
		AudioDivisionsPerBeat divisionsPerBeat;
      AudioTempo tempo;

		SlotOf<AudioComponent*>
			audioComponentSocket;

		AudioControlEventSocket
			audioControlEventSocket;
		AudioControlEventIterator
			*audioControlEventIterator;

		#if DEBUG_LEVEL>0
			Logical
         	dumpValue;
		#endif
	};

	//##########################################################################
	//###################    CreateAudioControlEventStream    ##################
	//##########################################################################

	class CreateAudioControlEventStream:
		public MidiParse
	{
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Construction, Destruction, and Testing
	//
	public:
		CreateAudioControlEventStream();
		~CreateAudioControlEventStream();

		Logical
			TestInstance() const;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Parsing
	//
	public:
		void
			Parse(
				MemoryStream *input_stream,
				MemoryStream *output_stream,
            SignedLongWord tempo=100
			);
		AudioDivisionsPerBeat
			GetDivisionsPerBeat()
				{return divisionsPerBeat;}
		AudioTempo
			GetTempo()
				{return tempo;}
		CollectionSize
			GetNumberOfEvents();

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Implementations
	//
	private:
		SignedWord
			Mf_getc();
		void
			Mf_error(char *);

		void
			Mf_header(SignedWord,SignedWord,SignedWord);
		void
			Mf_on(SignedWord,SignedWord,SignedWord);
		void
			Mf_off(SignedWord,SignedWord,SignedWord);
		void
			Mf_tempo(SignedLongWord);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Private data
	//
	private:
		typedef VChainOf<AudioControlEvent*, AudioTick>
			AudioControlEventSocket;
		typedef VChainIteratorOf<AudioControlEvent*, AudioTick>
			AudioControlEventIterator;

		MemoryStream
			*inputStream;
		MemoryStream
			*outputStream;

		AudioDivisionsPerBeat
			divisionsPerBeat;
		AudioTempo
			tempo;

		AudioControlEventSocket
			audioControlEventSocket;
	};

#endif
