/////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////
////																					 ////
////																					 ////
////								  - SCOLwave.cpp -									 ////
////																					 ////
////																					 ////
////				Implémentation des fonctions SCOL de la librairie sonore			 ////
////									 Version  1.0									 ////
////																					 ////
////								  Hilaire Verschuere								 ////
////																					 ////
////																					 ////
/////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////

#include	"..\SCOL\ZooScol.h"


/////////////////////////////////////////////////////////////////////////////////////////////
// Static variables
/////////////////////////////////////////////////////////////////////////////////////////////
extern HSoundManager* pHSoundManager ;


/////////////////////////////////////////////////////////////////////////////////////////////
// Global variables
/////////////////////////////////////////////////////////////////////////////////////////////

int AsWave ;



//////////////////////////////////////////////////////////////////////////////////////////////
///		asWaveCreate													
//////////////////////////////////////////////////////////////////////////////////////////////
//fun [Chn P] AsWave
int asWaveCreate(mmachine m)
{
	int filename  = MTOP( MMpull(m) ) ;
	if( filename == NIL ) { MMset(m,0,NIL) ; return 0 ; }

	char* strFileName = (char*)MMstartstr(m,filename) ;
	HWave* pHWave = new HWave( false ) ;

	if( FAILED( pHWave->Open( strFileName ) ) )
	{ 
		MMechostr(1,"%s is not a wav file.\n", strFileName) ;
		SAFE_DELETE( pHWave ) ;
		MMset(m,0,NIL) ; 
		return 0 ; 
	}

	int wave = MMmalloc(m,1,TYPETAB) ;
	if ( wave == NIL ) { SAFE_DELETE( pHWave ) ; MMset(m,0,NIL) ; return MERRMEM ; }

	MMstore( m, wave, 0, (int)pHWave ) ;
	
	MMpush(m, PTOM( wave )) ;
	return OBJcreate(m, AsWave, (int)pHWave, -1, -1) ;
}


//////////////////////////////////////////////////////////////////////////////////////////////
///		asWaveDestroy 													
//////////////////////////////////////////////////////////////////////////////////////////////
//fun [AsWave] I
int asWaveDestroy (mmachine m)
{
	int	wave = MTOP( MMget(m,0) ) ;
	if ( wave == NIL ) { MMset(m,0,NIL) ; return 0 ; }

	OBJdelTM( m, wave, PTOM(wave) ) ;
	MMset(m,0,0);

	return 0 ;
}



// Delete the AsWave ///////////////////////////////////////////////////////////////////////
int destroyAsWave(mmachine m,int handsys,int wave)
{
	HWave* pHWave = (HWave*) MMfetch(m, MTOP(wave), 0) ;
	if( !pHWave ) { MMset(m,0,NIL) ; return 0 ; }

	SAFE_DELETE( pHWave ) ;	
	MMstore( m, MTOP(wave), 0, NULL ) ;
	MMechostr(1,"AsWave destroyed.\n");

	return 0;
}



//////////////////////////////////////////////////////////////////////////////////////////////
///		asWaveGetInfo													
//////////////////////////////////////////////////////////////////////////////////////////////
//fun [AsWave] [I I I I]
int asWaveGetInfo(mmachine m)
{
	int wave = MTOP( MMget(m,0) ) ;
	if( wave==NIL ) { MMset(m,0,NIL) ; return 0 ; }

	HWave*  pHWave = (HWave*)MMfetch(m, wave, 0) ;
	if( !pHWave ) { MMset(m,0,NIL) ; return 0 ; }
	
	int buff = MMmalloc(m,4,TYPETAB);
	if (buff<0) { MMset(m,0,NIL) ; return MERRMEM ; }
  
	MMstore(m, buff, 0, ITOM( pHWave->m_dwSize ) );
	MMstore(m, buff, 1, ITOM( pHWave->m_pwfx->nChannels ) );
	MMstore(m, buff, 2, ITOM( pHWave->m_pwfx->nSamplesPerSec ) );
	MMstore(m, buff, 3, ITOM( pHWave->m_pwfx->wBitsPerSample ) );

	MMset(m,0,PTOM(buff));

	return 0;
}



//////////////////////////////////////////////////////////////////////////////////////////////
///		asWaveRead													
//////////////////////////////////////////////////////////////////////////////////////////////
//fun [AsWave I I] S
int asWaveRead(mmachine m)
{
	int restart = MTOI( MMpull(m) ) ;
	int size	= MTOI( MMpull(m) ) ;
	int wave	= MTOP( MMget(m,0) ) ;
	if( wave==NIL ) { MMset(m,0,NIL) ; return 0 ; }

	HWave* pHWave = (HWave*)MMfetch(m, wave, 0) ;
	if( !pHWave ) { MMset(m,0,NIL) ; return 0 ; }

	if( size==NIL )
	{
		restart = 0 ;
		size = pHWave->m_dwSize - pHWave->GetFilePosition() ;
	}
	else if( restart==NIL ) restart = 0 ;

	int buff = MMmalloc( m, STR_SIZE(size), TYPEBUF ) ;
	if( buff<0 ) { MMset(m,0,NIL) ; return MERRMEM ; }

	char* buf = MMstartstr(m,buff) ;
	unsigned int sizeRead = pHWave->Read( buf, size ) ;

	if( restart == AS_WAVE_LOOP ) while( sizeRead != size )
	{
		pHWave->ResetFile() ;
		sizeRead += pHWave->Read( buf + sizeRead, size - sizeRead ) ;
	}
	
	buf[sizeRead] = 0 ;
	MMstore( m, buff, 0, sizeRead ) ;
	MMset(m, 0, PTOM(buff) ) ;

	return 0 ;
}




//////////////////////////////////////////////////////////////////////////////////////////////
///		asWaveSeek													
//////////////////////////////////////////////////////////////////////////////////////////////
//fun [AsWave I I] AsWave
int asWaveSeek(mmachine m)
{
	int flag	 = MTOI(MMpull(m)) ;
	int position = MTOI(MMpull(m)) ;
	int wave	 = MTOP(MMget(m,0)) ;
	if( (wave == NIL) || (flag == NIL) || (position == NIL) ) { MMset(m,0,NIL) ; return 0 ; }

	HWave* pHWave = (HWave*)MMfetch(m, wave, 0) ;
	if( !pHWave ) { MMset(m,0,NIL) ; return 0 ; }

	if( flag == SEEK_SET )  // From the begining of the file
	{
		position = labs( position ) ;
		if( position > pHWave->m_dwSize ) position = pHWave->m_dwSize ;
	}
	else if( flag == SEEK_CUR )  // From the current reading position
	{
		position = pHWave->GetFilePosition() + position ;
		if( position < 0 ) position = 0 ;
		else if( position > pHWave->m_dwSize ) position = pHWave->m_dwSize ;
	}
	else if( flag == SEEK_END )	// From the end of the file
	{
		position = pHWave->m_dwSize - labs( position ) ;
		if( position < 0 ) position = 0 ;
	}
	
	pHWave->SetFilePosition( position ) ;

	return 0 ;
}




/////////////////////////////////////////////////////// DEFINITIONS
#define NBWAVEPKG 10

char* WAVEname [ NBWAVEPKG ] = 
{
	////// TYPES             
	"AsWave",               // AsWave,
	"AS_WAVE_BEGIN",		// AS_WAVE_BEGIN,
	"AS_WAVE_CURRENT",		// AS_WAVE_CURRENT,
	"AS_WAVE_END",			// AS_WAVE_END,
	"AS_WAVE_LOOP",			// AS_WAVE_LOOP

	// WAVE I/O
	"asWaveCreate",			// asWaveCreate
	"asWaveDestroy",		// asWaveDestroy 
	"asWaveGetInfo",		// asWaveGetInfo
	"asWaveRead",			// asWaveRead
	"asWaveSeek",			// asWaveSeek
} ;

char * WAVEtype [ NBWAVEPKG ] = 
{
	////// TYPES                          
	NULL,						// AsWave,
	"I",						// AS_WAVE_BEGIN,
	"I",						// AS_WAVE_CURRENT,
	"I",						// AS_WAVE_END,
	"I",						// AS_WAVE_LOOP
								
	// WAVE I/O					
	"fun [Chn P] AsWave",		// asWaveCreate
	"fun [AsWave] I",			// asWaveDestroy 
	"fun [AsWave] [I I I I]",	// asWaveGetInfo
	"fun [AsWave I I] S",		// asWaveRead
	"fun [AsWave I I] I",		// asWaveSeek
} ;


int WAVEnarg [ NBWAVEPKG ] = 
{
	////// TYPES   
	TYPTYPE,		// AsWave,
	TYPVAR,			// AS_WAVE_BEGIN,
	TYPVAR,			// AS_WAVE_CURRENT,
	TYPVAR,			// AS_WAVE_END,
	TYPVAR,			// AS_WAVE_LOOP
					
	// WAVE I/O		
	2,				// asWaveCreate
	1,				// asWaveDestroy
	1,				// asWaveGetInfo
	3,				// asWaveRead
	3,				// asWaveSeek

} ;


int (*WAVEfun[NBWAVEPKG])(mmachine m)= 
{
	////// TYPES             
	NULL,													// AsWave,
	(int (__cdecl *)(struct Mmachine *))(2*SEEK_SET),		// AS_WAVE_BEGIN,
	(int (__cdecl *)(struct Mmachine *))(2*SEEK_CUR),		// AS_WAVE_CURRENT,
	(int (__cdecl *)(struct Mmachine *))(2*SEEK_END),		// AS_WAVE_END,
	(int (__cdecl *)(struct Mmachine *))(2*AS_WAVE_LOOP),	// AS_WAVE_LOOP,	

	// WAVE I/O
	asWaveCreate,											// asWaveCreate
	asWaveDestroy ,											// asWaveDestroy 
	asWaveGetInfo,											// asWaveGetInfo
	asWaveRead,												// asWaveRead
	asWaveSeek,												// asWaveSeek
} ;


int SCOLloadWave(mmachine m,cbmachine w)
{
	AsWave = OBJregister( 0, 1, destroyAsWave, "AsWave" ) ;

	return PKhardpak( m, "Wave", NBWAVEPKG, WAVEname, WAVEfun, WAVEnarg, WAVEtype );
}



int SCOLfreeWave()
{
	return 0;
}


