/*!	
	@file
	@brief	サウンド管理クラスのコア部分
*/

#ifndef CSoundCore_h
#define CSoundCore_h

#include"../../Setup/CompileMode.h"
#include"../../Auxiliary/Thread/CThreadMutex.h"
#include"../../Auxiliary/Thread/CThreadController.h"
#include"../../Auxiliary/CTimer.h"
#include"../../template/GlobalPointer.h"
#include"CSoundMessage.h"
#include"Driver/CSoundCardDriver.h"

namespace Maid
{
	class CSoundCore : public GlobalPointer<CSoundCore>
	{
	public:
		CSoundCore();
		virtual ~CSoundCore();

		void Initialize( const SPSOUNDCARDDRIVER& pDriver, const SPTIMER& pTimer, const ISoundCardDriver::PCMBUFFERFORMAT& Format  );
		void Finalize();

		struct BUFFERSTATUS
		{
			enum
			{
				VOLUME_MIN = 0,
				VOLUME_MAX = 10000,

				PLAYLOOP = -1,
			};

			int	ID;			//	このオブジェクトのＩＤ

			bool IsPlay;	//	再生中か？
			int	PlayCount;	//	あと何回ループするか？( -1:ループ 0:停止中 1〜) 現在再生中で１になる
			int	Position;	//	現在の位置(ミリ秒単位)
			float db;		//	現在の波形の強さ
		};

		const BUFFERSTATUS* CreateBufferStatus();
			
		void PostMessage( const SPSOUNDMESSAGE& pMessage );

		void SendDeviceCaps();
		mstring GetDeviceCaps();

	private:
		CThreadController	m_Thread;

		SOUNDMESSAGEQUE		m_MessageQue;
		CThreadMutex		m_MessageMutex;		//!<	m_MessageQue の更新時の同期オブジェクト

	private:
		//	別スレッドから呼ばれる関数・メンバ
		unt ThreadFunction( volatile CThreadController::BRIGEDATA& brige );
		void ExecuteMessage( const SPSOUNDMESSAGE& pMessage );

		SPSOUNDCARDDRIVER	m_pDriver;
		SPTIMER				m_pTimer;

		ISoundCardDriver::PCMBUFFERFORMAT m_Format;
		mstring			m_CapsText;

		struct SOUNDINFO
		{
			enum STATE
			{
				STATE_EMPTY,	//	チャンネルが空いている
				STATE_STOP,		//	停止中
				STATE_PLAY,		//	再生中
				STATE_DELETE,	//	削除中
			};

			enum TYPE
			{
				TYPE_STATIC,
				TYPE_STREAM,
				TYPE_MIDI,
			};

			STATE			State;
			TYPE			Type;
			BUFFERSTATUS	Status;		//	ゲーム側からアクセスするデータ
			SPSOUNDBUFFER	pBuffer;	//	サウンドバッファ

			bool IsVolumeChanging;	//	ボリュームが変更中か？

			bool IsVolumeChangeEnd( unt time );
			int CalcVolume( unt time );

			unt BeginTime;
			unt EndTime;
			int BeginVolume;
			int EndVolume;
		};

		SOUNDINFO& FindEmptyInfo();
		void UpdateSoundInfo( SOUNDINFO& Info, unt delta, unt now );

		CThreadMutex				m_SoundInfoMutex;		//!<	m_SoundInfo の同期オブジェクト
		MySTL::vector<SOUNDINFO>	m_SoundInfo;
	};
}


#endif
