/////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////
////																					 ////
////																					 ////
////								- HSoundManager.cpp -								 ////
////																					 ////
////																					 ////
////				Implémentation des fonctions SCOL de la librairie sonore			 ////
////									 Version  1.0									 ////
////																					 ////
////								  Hilaire Verschuere								 ////
////																					 ////
////																					 ////
/////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////


#include "../Basic/ZooWorld.h"
DEFINE_HGUID(CLSID_DirectSound, 0x47d4d946, 0x62e8, 0x11cf, 0x93, 0xbc, 0x44, 0x45, 0x53, 0x54, 0x0, 0x0);
DEFINE_HGUID(IID_IDirectSound, 0x279AFA83, 0x4981, 0x11CE, 0xA5, 0x21, 0x00, 0x20, 0xAF, 0x0B, 0xE5, 0x60);

//-----------------------------------------------------------------------------
// Name: HSoundManager::HSoundManager()
// Desc: Constructs the class
//-----------------------------------------------------------------------------
HSoundManager::HSoundManager()
{
    m_pDS			= NULL ;
	enable			= true ;
	m_DS_OK			= false ;
	volume			= INIT_VOLUME_GLOBAL ;
	listHSound.resize(0) ;
}




//-----------------------------------------------------------------------------
// Name: HSoundManager::~HSoundManager()
// Desc: Destroys the class
//-----------------------------------------------------------------------------
HSoundManager::~HSoundManager()
{
	SAFE_RELEASE( HListener::m_pListener ) ;
    SAFE_RELEASE( m_pDS ) ; 
}



//-----------------------------------------------------------------------------
// Name: HSoundManager::~HSoundManager()
// Desc: Init DirectSound and Create primary Buffer
//-----------------------------------------------------------------------------
/* $MS : Crash Identification on Windows Vista */
HRESULT HSoundManager::Create( HWND hwnd )
{
	LPDIRECTSOUNDBUFFER pDSBPrimary = NULL ;

	CoInitialize (NULL);
	
	if( FAILED( CoCreateInstance( (REFCLSID)CLSID_DirectSound, NULL, CLSCTX_INPROC,	(REFIID)IID_IDirectSound, (LPVOID*)&m_pDS) ) )
	{
		//MessageBox(NULL,"DirectX is not properly installed.","Error",MB_OK|MB_ICONERROR) ;
		MMechostr( 1, "DirectX is not properly installed.\n" ) ;
		m_pDS = NULL ;
		return S_FALSE ;
	}

    // Create IDirectSound using the primary sound device
	if( FAILED( m_pDS->Initialize( NULL ) ) )
	{
		/* $MS : this under line crash on Vista and has no implication on older version */
		//SAFE_DELETE( m_pDS ) ;
		return S_FALSE ;
	}

	// Get the hardware capability
	DSCAPS dscaps ;
	ZeroMemory( &dscaps, sizeof(DSCAPS) );
    dscaps.dwSize = sizeof(DSCAPS);
	if( FAILED( m_pDS->GetCaps(&dscaps) ) )	return S_FALSE ;

	
    // Set DirectSound coop level 
    if( FAILED( m_pDS->SetCooperativeLevel( hwnd, DSSCL_PRIORITY ) ) ) 	return S_FALSE ;
    
    if( m_pDS==NULL ) return S_FALSE ;

    // Get the primary buffer 
    DSBUFFERDESC dsbd;
    ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) );
    dsbd.dwSize        = sizeof(DSBUFFERDESC);
    dsbd.dwFlags       = DSBCAPS_PRIMARYBUFFER ;
    dsbd.dwBufferBytes = 0;
    dsbd.lpwfxFormat   = NULL;
       
    if( FAILED( m_pDS->CreateSoundBuffer( &dsbd, &pDSBPrimary, NULL ) ) ) return S_FALSE ;
    WAVEFORMATEX wfx;
    ZeroMemory( &wfx, sizeof(WAVEFORMATEX) ); 
    wfx.wFormatTag      = WAVE_FORMAT_PCM; 
    wfx.nChannels       = (dsbd.dwFlags & DSCAPS_PRIMARYSTEREO) ? DS_PRIMARY_STEREO : DS_PRIMARY_MONO ;
    wfx.nSamplesPerSec  = DS_PRIMARY_FREQ ; 
    wfx.wBitsPerSample  = (dscaps.dwFlags & DSCAPS_PRIMARY16BIT) ? DS_PRIMARY_16BITS : DS_PRIMARY_8BITS ; 
    wfx.nBlockAlign     = wfx.wBitsPerSample / 8 * wfx.nChannels;
    wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;

    if( FAILED( pDSBPrimary->SetFormat(&wfx) ) ) { SAFE_RELEASE( pDSBPrimary ); return S_FALSE ; }

	SAFE_RELEASE( pDSBPrimary );
	m_DS_OK = true ;

	return S_OK ;
}





//-----------------------------------------------------------------------------
// Name: HSoundManager::SetGlobalVolume()
// Desc: Setting the global volume for SCOL
//-----------------------------------------------------------------------------
void HSoundManager::SetGlobalVolume(int vol)
{
	// Iterator is used to loop through the list.  
	HSOUNDLIST::iterator pHSound ;

	if( vol <0 )		vol = 0 ;
	else if( vol > 100) vol = 100 ;

	volume = vol ;
   
    for ( pHSound = listHSound.begin() ; pHSound != listHSound.end() ; pHSound++ )
    {
		(*pHSound)->m_pWSound->SetVolume( (int)(*pHSound)->m_pWSound->volume ) ;                                             
    }	
}




//-----------------------------------------------------------------------------
// Name: HSoundManager::EnableSound()
// Desc: Enable all sounds of the application
//-----------------------------------------------------------------------------
void HSoundManager::EnableSound()
{
	// Iterator is used to loop through the list.  
	HSOUNDLIST::iterator pHSound ;

	// Setting the sound manager enable to play a sound
	Enable() ;

    for ( pHSound = listHSound.begin() ; pHSound != listHSound.end() ; pHSound++ )
    {
		if( (*pHSound)->m_playing ) (*pHSound)->Play( (*pHSound)->m_loop ) ;                                             
    }	
}




//-----------------------------------------------------------------------------
// Name: HSoundManager::DisableSound()
// Desc: Disable all sounds of the application
//-----------------------------------------------------------------------------
void HSoundManager::DisableSound()
{
	// Iterator is used to loop through the list.  
	HSOUNDLIST::iterator pHSound ;

    for ( pHSound = listHSound.begin() ; pHSound != listHSound.end() ; pHSound++ )
    {
		if( (*pHSound)->m_playing ) 
		{
			(*pHSound)->Stop() ;
			(*pHSound)->m_playing = true ;
		}
    }

	// Setting the sound manager disable to play a sound
	Disable() ;
}



//-----------------------------------------------------------------------------
// Name: HSoundManager::Set3dMode()
// Desc: Set mode 3D enable or disable for each AsSnd 3D if Listener is 
//       in the same Scene
//-----------------------------------------------------------------------------
void HSoundManager::Set3dMode( ZScene* pZScene )
{
	// Iterator is used to loop through the list.  
	HSOUNDLIST::iterator pHSound ;

    for ( pHSound = listHSound.begin() ; pHSound != listHSound.end() ; pHSound++ )
    {
		(*pHSound)->Set3dMode( (*pHSound)->m_pWSound->pZScene == pZScene ? true : false ) ;
    }
}

