/*
 * Implements WAVE/AU/AIFF Parser.
 *
 * hidenori@a2.ctktv.ne.jp
 */

#include "config.h"

#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "mmsystem.h"
#include "mmreg.h"
#include "winerror.h"
#include "strmif.h"
#include "control.h"
#include "vfwmsgs.h"
#include "uuids.h"

#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL(quartz);

#include "quartz_private.h"
#include "audioutl.h"
#include "parser.h"


static const WCHAR QUARTZ_WaveParser_Name[] =
{ 'W','a','v','e',' ','P','a','r','s','e','r',0 };
static const WCHAR QUARTZ_WaveParserInPin_Name[] =
{ 'I','n',0 };
static const WCHAR QUARTZ_WaveParserOutPin_Name[] =
{ 'O','u','t',0 };


/****************************************************************************/

/* S_OK = found, S_FALSE = not found */
HRESULT RIFF_GetNext(
	CParserImpl* pImpl, LONGLONG llOfs,
	DWORD* pdwCode, DWORD* pdwLength )
{
	BYTE bTemp[8];
	HRESULT hr;

	hr = IAsyncReader_SyncRead( pImpl->m_pReader, llOfs, 8, bTemp );
	if ( hr == S_OK )
	{
		*pdwCode = mmioFOURCC(bTemp[0],bTemp[1],bTemp[2],bTemp[3]);
		*pdwLength = PARSER_LE_UINT32(&bTemp[4]);
	}
	else
	{
		*pdwCode = 0;
		*pdwLength = 0;
	}

	return hr;
}

/* S_OK = found, S_FALSE = not found */
HRESULT RIFF_SearchChunk(
	CParserImpl* pImpl,
	DWORD dwSearchLengthMax,
	LONGLONG llOfs, DWORD dwChunk,
	LONGLONG* pllOfs, DWORD* pdwChunkLength )
{
	HRESULT hr;
	DWORD dwCurCode;
	DWORD dwCurLen;
	LONGLONG llCurLen;

	while ( 1 )
	{
		hr = RIFF_GetNext( pImpl, llOfs, &dwCurCode, &dwCurLen );
		if ( hr != S_OK )
			break;
		TRACE("%c%c%c%c len %lu\n",
			(int)(dwCurCode>> 0)&0xff,
			(int)(dwCurCode>> 8)&0xff,
			(int)(dwCurCode>>16)&0xff,
			(int)(dwCurCode>>24)&0xff,
			(unsigned long)dwCurLen);
		if ( dwChunk == dwCurCode )
			break;
		llCurLen = 8 + (LONGLONG)((dwCurLen+1)&(~1));
		llOfs += llCurLen;
		if ( (LONGLONG)dwSearchLengthMax <= llCurLen )
			return S_FALSE;
		if ( dwSearchLengthMax != (DWORD)0xffffffff )
			dwSearchLengthMax -= (DWORD)llCurLen;
	}

	*pllOfs = llOfs + 8;
	*pdwChunkLength = dwCurLen;

	return hr;
}

/* S_OK = found, S_FALSE = not found */
HRESULT RIFF_SearchList(
	CParserImpl* pImpl,
	DWORD dwSearchLengthMax,
	LONGLONG llOfs, DWORD dwListChunk,
	LONGLONG* pllOfs, DWORD* pdwChunkLength )
{
	HRESULT hr;
	DWORD dwCurLen;
	LONGLONG llCurLen;
	BYTE bTemp[4];

	while ( 1 )
	{
		hr = RIFF_SearchChunk(
			pImpl, dwSearchLengthMax,
			llOfs, PARSER_LIST,
			&llOfs, &dwCurLen );
		if ( hr != S_OK )
			break;

		hr = IAsyncReader_SyncRead( pImpl->m_pReader, llOfs, 4, bTemp );
		if ( hr != S_OK )
			break;

		if ( mmioFOURCC(bTemp[0],bTemp[1],bTemp[2],bTemp[3]) == dwListChunk )
			break;

		llCurLen = (LONGLONG)((dwCurLen+1)&(~1));
		llOfs += llCurLen;
		if ( (LONGLONG)dwSearchLengthMax <= (llCurLen+8) )
			return S_FALSE;
		if ( dwSearchLengthMax != (DWORD)0xffffffff )
			dwSearchLengthMax -= (DWORD)(llCurLen+8);
	}

	if ( dwCurLen < 12 )
		return E_FAIL;

	*pllOfs = llOfs+4;
	*pdwChunkLength = dwCurLen-4;

	return hr;
}




/****************************************************************************
 *
 *	CWavParseImpl
 */

typedef enum WavParseFmtType
{
	WaveParse_Native,
	WaveParse_Signed8,
	WaveParse_Signed16BE,
	WaveParse_Unsigned16LE,
	WaveParse_Unsigned16BE,
} WavParseFmtType;

typedef struct CWavParseImpl
{
	DWORD	cbFmt;
	WAVEFORMATEX*	pFmt;
	DWORD	dwBlockSize;
	LONGLONG	llDataStart;
	LONGLONG	llBytesTotal;
	LONGLONG	llBytesProcessed;
	WavParseFmtType	iFmtType;
} CWavParseImpl;


static HRESULT CWavParseImpl_InitWAV( CParserImpl* pImpl, CWavParseImpl* This )
{
	HRESULT hr;
	LONGLONG	llOfs;
	DWORD	dwChunkLength;

	hr = RIFF_SearchChunk(
		pImpl, (DWORD)0xffffffff,
		PARSER_RIFF_OfsFirst, PARSER_fmt,
		&llOfs, &dwChunkLength );
	if ( FAILED(hr) )
		return hr;
	if ( hr != S_OK || ( dwChunkLength < (sizeof(WAVEFORMATEX)-2) ) )
		return E_FAIL;

	This->cbFmt = dwChunkLength;
	if ( dwChunkLength < sizeof(WAVEFORMATEX) )
		This->cbFmt = sizeof(WAVEFORMATEX);
	This->pFmt = (WAVEFORMATEX*)QUARTZ_AllocMem( dwChunkLength );
	if ( This->pFmt == NULL )
		return E_OUTOFMEMORY;
	ZeroMemory( This->pFmt, This->cbFmt );

	hr = IAsyncReader_SyncRead(
		pImpl->m_pReader, llOfs, dwChunkLength, (BYTE*)This->pFmt );
	if ( hr != S_OK )
	{
		if ( SUCCEEDED(hr) )
			hr = E_FAIL;
		return hr;
	}


	hr = RIFF_SearchChunk(
		pImpl, (DWORD)0xffffffff,
		PARSER_RIFF_OfsFirst, PARSER_data,
		&llOfs, &dwChunkLength );
	if ( FAILED(hr) )
		return hr;
	if ( hr != S_OK || dwChunkLength == 0 )
		return E_FAIL;

	This->llDataStart = llOfs;
	This->llBytesTotal = (LONGLONG)dwChunkLength;

	return NOERROR;
}

static HRESULT CWavParseImpl_InitAU( CParserImpl* pImpl, CWavParseImpl* This )
{
	BYTE	au_hdr[24];
	DWORD	dataofs;
	DWORD	datalen;
	DWORD	datafmt;
	DWORD	datarate;
	DWORD	datachannels;
	HRESULT hr;
	WAVEFORMATEX	wfx;

	hr = IAsyncReader_SyncRead( pImpl->m_pReader, 0, 24, au_hdr );
	if ( FAILED(hr) )
		return hr;

	dataofs = PARSER_BE_UINT32(&au_hdr[4]);
	datalen = PARSER_BE_UINT32(&au_hdr[8]);
	datafmt = PARSER_BE_UINT32(&au_hdr[12]);
	datarate = PARSER_BE_UINT32(&au_hdr[16]);
	datachannels = PARSER_BE_UINT32(&au_hdr[20]);

	if ( dataofs < 24U || datalen == 0U )
		return E_FAIL;
	if ( datachannels != 1 && datachannels != 2 )
		return E_FAIL;

	ZeroMemory( &wfx, sizeof(WAVEFORMATEX) );
	wfx.nChannels = datachannels;
	wfx.nSamplesPerSec = datarate;

	switch ( datafmt )
	{
	case 1:
		wfx.wFormatTag = WAVE_FORMAT_MULAW;
		wfx.nBlockAlign = datachannels;
		wfx.wBitsPerSample = 8;
		break;
	case 2:
		wfx.wFormatTag = WAVE_FORMAT_PCM;
		wfx.nBlockAlign = datachannels;
		wfx.wBitsPerSample = 8;
		This->iFmtType = WaveParse_Signed8;
		break;
	case 3:
		wfx.wFormatTag = WAVE_FORMAT_PCM;
		wfx.nBlockAlign = datachannels;
		wfx.wBitsPerSample = 16;
		This->iFmtType = WaveParse_Signed16BE;
		break;
	default:
		FIXME("audio/basic - unknown format %lu\n", datafmt );
		return E_FAIL;
	}
	wfx.nAvgBytesPerSec = (datarate * datachannels * (DWORD)wfx.wBitsPerSample) >> 3;

	This->cbFmt = sizeof(WAVEFORMATEX);
	This->pFmt = (WAVEFORMATEX*)QUARTZ_AllocMem( sizeof(WAVEFORMATEX) );
	if ( This->pFmt == NULL )
		return E_OUTOFMEMORY;
	memcpy( This->pFmt, &wfx, sizeof(WAVEFORMATEX) );

	This->llDataStart = dataofs;
	This->llBytesTotal = datalen;

	TRACE("offset %lu, length %lu\n",dataofs,datalen);

	return NOERROR;
}

static HRESULT CWavParseImpl_InitAIFF( CParserImpl* pImpl, CWavParseImpl* This )
{
	FIXME( "AIFF is not supported now.\n" );
	return E_FAIL;
}

static HRESULT CWavParseImpl_InitParser( CParserImpl* pImpl, ULONG* pcStreams )
{
	CWavParseImpl*	This = NULL;
	HRESULT hr;
	BYTE	header[12];

	TRACE("(%p,%p)\n",pImpl,pcStreams);

	if ( pImpl->m_pReader == NULL )
		return E_UNEXPECTED;

	This = (CWavParseImpl*)QUARTZ_AllocMem( sizeof(CWavParseImpl) );
	if ( This == NULL )
		return E_OUTOFMEMORY;
	pImpl->m_pUserData = This;

	/* construct */
	This->cbFmt = 0;
	This->pFmt = NULL;
	This->dwBlockSize = 0;
	This->llDataStart = 0;
	This->llBytesTotal = 0;
	This->llBytesProcessed = 0;
	This->iFmtType = WaveParse_Native;

	hr = IAsyncReader_SyncRead( pImpl->m_pReader, 0, 12, header );
	if ( FAILED(hr) )
		return hr;
	if ( hr != S_OK )
		return E_FAIL;

	if ( !memcmp( &header[0], "RIFF", 4 ) &&
		 !memcmp( &header[8], "WAVE", 4 ) )
	{
		TRACE( "(%p) - it's audio/wav.\n", pImpl );
		hr = CWavParseImpl_InitWAV( pImpl, This );
	}
	else
	if ( !memcmp( &header[0], ".snd", 4 ) )
	{
		TRACE( "(%p) - it's audio/basic.\n", pImpl );
		hr = CWavParseImpl_InitAU( pImpl, This );
	}
	else
	if ( !memcmp( &header[0], "FORM", 4 ) &&
		 !memcmp( &header[8], "AIFF", 4 ) )
	{
		TRACE( "(%p) - it's audio/aiff.\n", pImpl );
		hr = CWavParseImpl_InitAIFF( pImpl, This );
	}
	else
	{
		FIXME( "(%p) - unknown format.\n", pImpl );
		hr = E_FAIL;
	}

	if ( FAILED(hr) )
	{
		return hr;
	}

	/* initialized successfully. */
	*pcStreams = 1;

	This->dwBlockSize = (This->pFmt->nAvgBytesPerSec + (DWORD)This->pFmt->nBlockAlign - 1U) / (DWORD)This->pFmt->nBlockAlign;

	TRACE( "(%p) returned successfully.\n", pImpl );

	return NOERROR;
}

static HRESULT CWavParseImpl_UninitParser( CParserImpl* pImpl )
{
	CWavParseImpl*	This = (CWavParseImpl*)pImpl->m_pUserData;

	TRACE("(%p)\n",This);

	if ( This == NULL )
		return NOERROR;

	/* destruct */
	if ( This->pFmt != NULL ) QUARTZ_FreeMem(This->pFmt);

	QUARTZ_FreeMem( This );
	pImpl->m_pUserData = NULL;

	return NOERROR;
}

static LPCWSTR CWavParseImpl_GetOutPinName( CParserImpl* pImpl, ULONG nStreamIndex )
{
	CWavParseImpl*	This = (CWavParseImpl*)pImpl->m_pUserData;

	TRACE("(%p)\n",This);

	return QUARTZ_WaveParserOutPin_Name;
}

static HRESULT CWavParseImpl_GetStreamType( CParserImpl* pImpl, ULONG nStreamIndex, AM_MEDIA_TYPE* pmt )
{
	CWavParseImpl*	This = (CWavParseImpl*)pImpl->m_pUserData;

	TRACE("(%p)\n",This);

	if ( This == NULL || This->pFmt == NULL )
		return E_UNEXPECTED;

	ZeroMemory( pmt, sizeof(AM_MEDIA_TYPE) );
	memcpy( &pmt->majortype, &MEDIATYPE_Audio, sizeof(GUID) );
	QUARTZ_MediaSubType_FromFourCC( &pmt->subtype, (DWORD)This->pFmt->wFormatTag );
	pmt->bFixedSizeSamples = 1;
	pmt->bTemporalCompression = 0;
	pmt->lSampleSize = This->pFmt->nBlockAlign;
	memcpy( &pmt->formattype, &FORMAT_WaveFormatEx, sizeof(GUID) );
	pmt->pUnk = NULL;

	pmt->pbFormat = (BYTE*)CoTaskMemAlloc( This->cbFmt );
	if ( pmt->pbFormat == NULL )
		return E_OUTOFMEMORY;
	pmt->cbFormat = This->cbFmt;
	memcpy( pmt->pbFormat, This->pFmt, This->cbFmt );

	return NOERROR;
}

static HRESULT CWavParseImpl_CheckStreamType( CParserImpl* pImpl, ULONG nStreamIndex, const AM_MEDIA_TYPE* pmt )
{
	if ( !IsEqualGUID( &pmt->majortype, &MEDIATYPE_Audio ) ||
		 !IsEqualGUID( &pmt->formattype, &FORMAT_WaveFormatEx ) )
		return E_FAIL;
	if ( pmt->pbFormat == NULL || pmt->cbFormat < sizeof(WAVEFORMATEX) )
		return E_FAIL;

	return NOERROR;
}

static HRESULT CWavParseImpl_GetAllocProp( CParserImpl* pImpl, ALLOCATOR_PROPERTIES* pReqProp )
{
	CWavParseImpl*	This = (CWavParseImpl*)pImpl->m_pUserData;

	TRACE("(%p)\n",This);

	if ( This == NULL || This->pFmt == NULL )
		return E_UNEXPECTED;

	ZeroMemory( pReqProp, sizeof(ALLOCATOR_PROPERTIES) );
	pReqProp->cBuffers = 1;
	pReqProp->cbBuffer = This->dwBlockSize;

	return NOERROR;
}

static HRESULT CWavParseImpl_GetNextRequest( CParserImpl* pImpl, ULONG* pnStreamIndex, LONGLONG* pllStart, LONG* plLength, REFERENCE_TIME* prtStart, REFERENCE_TIME* prtStop )
{
	CWavParseImpl*	This = (CWavParseImpl*)pImpl->m_pUserData;
	LONGLONG	llAvail;
	LONGLONG	llStart;
	LONGLONG	llEnd;

	TRACE("(%p)\n",This);

	if ( This == NULL || This->pFmt == NULL )
		return E_UNEXPECTED;

	llAvail = This->llBytesTotal - This->llBytesProcessed;
	if ( llAvail > (LONGLONG)This->dwBlockSize )
		llAvail = (LONGLONG)This->dwBlockSize;
	llStart = This->llDataStart + This->llBytesProcessed;
	llEnd = llStart + llAvail;
	This->llBytesProcessed = llEnd;

	*pllStart = This->llBytesProcessed;
	*plLength = (LONG)llAvail;
	*prtStart = llStart * QUARTZ_TIMEUNITS / (LONGLONG)This->pFmt->nAvgBytesPerSec;
	*prtStop = llEnd * QUARTZ_TIMEUNITS / (LONGLONG)This->pFmt->nAvgBytesPerSec;

	return NOERROR;
}

static HRESULT CWavParseImpl_ProcessSample( CParserImpl* pImpl, ULONG nStreamIndex, LONGLONG llStart, LONG lLength, IMediaSample* pSample )
{
	CWavParseImpl*	This = (CWavParseImpl*)pImpl->m_pUserData;
	BYTE*	pData;
	LONG	lActLen;
	HRESULT hr;

	TRACE("(%p)\n",This);

	hr = IMediaSample_GetPointer(pSample,&pData);
	if ( FAILED(hr) )
		return hr;
	lActLen = (LONG)IMediaSample_GetActualDataLength(pSample);
	if ( lActLen != lLength )
		return E_FAIL;

	switch ( This->iFmtType )
	{
	case WaveParse_Native:
		break;
	case WaveParse_Signed8:
		AUDIOUTL_ChangeSign8(pData,lActLen);
		break;
	case WaveParse_Signed16BE:
		AUDIOUTL_ByteSwap(pData,lActLen);
		break;
	case WaveParse_Unsigned16LE:
		AUDIOUTL_ChangeSign16LE(pData,lActLen);
		break;
	case WaveParse_Unsigned16BE:
		AUDIOUTL_ChangeSign16BE(pData,lActLen);
		AUDIOUTL_ByteSwap(pData,lActLen);
		break;
	default:
		FIXME("(%p) - %d not implemented\n", This, This->iFmtType );
		return E_FAIL;
	}

	return NOERROR;
}


static const struct ParserHandlers CWavParseImpl_Handlers =
{
	CWavParseImpl_InitParser,
	CWavParseImpl_UninitParser,
	CWavParseImpl_GetOutPinName,
	CWavParseImpl_GetStreamType,
	CWavParseImpl_CheckStreamType,
	CWavParseImpl_GetAllocProp,
	CWavParseImpl_GetNextRequest,
	CWavParseImpl_ProcessSample,

	/* for IQualityControl */
	NULL, /* pQualityNotify */

	/* for seeking */
	NULL, /* pGetSeekingCaps */
	NULL, /* pIsTimeFormatSupported */
	NULL, /* pGetCurPos */
	NULL, /* pSetCurPos */
	NULL, /* pGetDuration */
	NULL, /* pSetDuration */
	NULL, /* pGetStopPos */
	NULL, /* pSetStopPos */
	NULL, /* pGetPreroll */
	NULL, /* pSetPreroll */
};

HRESULT QUARTZ_CreateWaveParser(IUnknown* punkOuter,void** ppobj)
{
	return QUARTZ_CreateParser(
		punkOuter,ppobj,
		&CLSID_quartzWaveParser,
		QUARTZ_WaveParser_Name,
		QUARTZ_WaveParserInPin_Name,
		&CWavParseImpl_Handlers );
}


