// ExportAVIDlg.cpp : implementation file
//

#include "stdafx.h"
#include "demopaja.h"
#include "ExportAVIDlg.h"
#include <mmsystem.h>
#include <mmreg.h>
#include <msacm.h>
#include <list>

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


using namespace PajaTypes;



class ACMFormatEntry
{
public:
	ACMFORMATDETAILS	afd;
	WAVEFORMATEX*			pwfex;
	bool							fCompatible;

	~ACMFormatEntry()
	{
		delete [] (uint8*)pwfex;
	}
};

class ACMTagEntry {
public:
	std::list<ACMFormatEntry*>	formats;
	ACMFORMATTAGDETAILS				aftd;
	HACMDRIVERID		m_hACMDriverId;

	~ACMTagEntry();
};

ACMTagEntry::~ACMTagEntry()
{
	for( std::list<ACMFormatEntry*>::iterator it = formats.begin(); it != formats.end(); ++it )
		delete (*it);
}


////////////////////////////////////////////////////////////////////////////

void CopyWaveFormat( WAVEFORMATEX *pDst, const WAVEFORMATEX *pSrc )
{
	if( pSrc->wFormatTag == WAVE_FORMAT_PCM )
		memcpy( pDst, pSrc, sizeof( PCMWAVEFORMAT ) );
	else
		memcpy( pDst, pSrc, sizeof( WAVEFORMATEX ) + pSrc->cbSize );
}


struct ACMEnumeratorData {
	CComboBox*			pDriverList;
	ACMTagEntry*		m_pCurrentTagEntry;
	HACMDRIVER			m_hACMDriver;
	WAVEFORMATEX*		pwfex;
	WAVEFORMATEX*		m_pSelectedWaveFormat;
	WAVEFORMATEX*		m_pSrcWaveFormat;
	DWORD						cbwfex;
	ACMFormatEntry*	pFormatSelect;
	ACMTagEntry*		pTagSelect;
	bool						fAttemptedWeird;
};


BOOL CALLBACK ACMFormatEnumerator( HACMDRIVERID hadid, LPACMFORMATDETAILS pafd, DWORD dwInstance, DWORD fdwSupport )
{
	ACMEnumeratorData*	pData = (ACMEnumeratorData *)dwInstance;
	ACMFormatEntry*			pFormatEntry = new ACMFormatEntry();

	if( !pFormatEntry )
		return TRUE;

	pFormatEntry->pwfex = (WAVEFORMATEX *)new uint8[sizeof( WAVEFORMATEX ) + pafd->pwfx->cbSize];

	if( !pFormatEntry->pwfex )
	{
		delete pFormatEntry;
		return TRUE;
	}

	pFormatEntry->afd = *pafd;

	memcpy( pFormatEntry->pwfex, pafd->pwfx, sizeof( WAVEFORMATEX ) + pafd->pwfx->cbSize );

	if( !pData->pTagSelect && pData->m_pSelectedWaveFormat && pafd->pwfx->wFormatTag == pData->m_pSelectedWaveFormat->wFormatTag )
	{
		if (pafd->pwfx->wFormatTag == WAVE_FORMAT_PCM ||
			(pafd->pwfx->cbSize == pData->m_pSelectedWaveFormat->cbSize && !memcmp(pafd->pwfx, pData->m_pSelectedWaveFormat, sizeof(WAVEFORMATEX)+pafd->pwfx->cbSize))) {

			pData->pTagSelect = pData->m_pCurrentTagEntry;
			pData->pFormatSelect = pFormatEntry;
		}
	}

	pFormatEntry->fCompatible = true;

	if (pData->m_pSrcWaveFormat) {
		pFormatEntry->fCompatible = !acmStreamOpen(NULL, pData->m_hACMDriver, pData->m_pSrcWaveFormat, pafd->pwfx, NULL, 0, 0, ACM_STREAMOPENF_QUERY)
						|| !acmStreamOpen(NULL, pData->m_hACMDriver, pData->m_pSrcWaveFormat, pafd->pwfx, NULL, 0, 0, ACM_STREAMOPENF_QUERY | ACM_STREAMOPENF_NONREALTIME);

		if (pafd->pwfx->nChannels == pData->m_pSrcWaveFormat->nChannels
			&& pafd->pwfx->wBitsPerSample == pData->m_pSrcWaveFormat->wBitsPerSample
			&& pafd->pwfx->nSamplesPerSec == pData->m_pSrcWaveFormat->nSamplesPerSec)
			pData->fAttemptedWeird = true;
	}

	pData->m_pCurrentTagEntry->formats.push_back( pFormatEntry );

	return TRUE;
}

BOOL CALLBACK ACMFormatTagEnumerator( HACMDRIVERID hadid, LPACMFORMATTAGDETAILS paftd, DWORD dwInstance, DWORD fdwSupport )
{
	ACMEnumeratorData *pData = (ACMEnumeratorData *)dwInstance;

	if( paftd->dwFormatTag != WAVE_FORMAT_PCM )
	{
		int index;

		index = pData->pDriverList->AddString( paftd->szFormatTag );

		if (index != CB_ERR)
		{
			ACMTagEntry *pate = new ACMTagEntry();
			ACMFORMATDETAILS afd;

			pate->m_hACMDriverId = hadid;

			pate->aftd = *paftd;
			pData->m_pCurrentTagEntry = pate;

			memset( &afd, 0, sizeof afd );
			afd.cbStruct = sizeof( ACMFORMATDETAILS );
			afd.pwfx = pData->pwfex;
			afd.cbwfx = pData->cbwfex;
			afd.dwFormatTag = paftd->dwFormatTag;
			pData->pwfex->wFormatTag = paftd->dwFormatTag;

			pData->fAttemptedWeird = false;
			acmFormatEnum( pData->m_hACMDriver, &afd, ACMFormatEnumerator, dwInstance, ACM_FORMATENUMF_WFORMATTAG );

			if (!pData->fAttemptedWeird && pData->m_pSrcWaveFormat) {

				CopyWaveFormat(pData->pwfex, pData->m_pSrcWaveFormat);

				pData->pwfex->wFormatTag = paftd->dwFormatTag;

				if (!acmFormatSuggest(pData->m_hACMDriver, pData->m_pSrcWaveFormat, pData->pwfex, pData->cbwfex, ACM_FORMATSUGGESTF_NCHANNELS|ACM_FORMATSUGGESTF_NSAMPLESPERSEC|ACM_FORMATSUGGESTF_WFORMATTAG)) {
					afd.dwFormatIndex = 0;
					afd.fdwSupport = 0;

					if (!acmFormatDetails(pData->m_hACMDriver, &afd, ACM_FORMATDETAILSF_FORMAT))
						ACMFormatEnumerator(hadid, &afd, dwInstance, 0);
				}
			}

			pData->pDriverList->SetItemDataPtr( index, (void*)pate );
		}
	}

	return TRUE;
}

BOOL CALLBACK ACMDriverEnumerator( HACMDRIVERID hadid, DWORD dwInstance, DWORD fdwSupport )
{
	ACMEnumeratorData *pData = (ACMEnumeratorData *)dwInstance;

	if( !acmDriverOpen( &pData->m_hACMDriver, hadid, 0 ) )
	{
		ACMDRIVERDETAILS add = { sizeof( ACMDRIVERDETAILS ) };
		acmDriverDetails( hadid, &add, 0 );

		ACMFORMATTAGDETAILS aftd;

		memset( &aftd, 0, sizeof aftd );
		aftd.cbStruct = sizeof aftd;

		acmFormatTagEnum( pData->m_hACMDriver, &aftd, ACMFormatTagEnumerator, dwInstance, 0 );

		acmDriverClose( pData->m_hACMDriver, 0 );
	}

	return TRUE;
}

/////////////////////////////////////////////////////////////////////////////

/*
struct CCInfo
{
	ICINFO*						pCompInfo;
	int								nComp;
	COMPVARS*					pCV;
	BITMAPINFOHEADER*	bih;
	char							tbuf[128];

	HIC								hic;
	FOURCC						fccSelect;
	ICINFO*						piiCurrent;

	void*							pState;
	int								cbState;
	char							szCurrentCompression[256];
};
*/

/////////////////////////////////////////////////////////////////////////////
// CExportAVIDlg dialog


CExportAVIDlg::CExportAVIDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CExportAVIDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CExportAVIDlg)
	m_iWidth = 0;
	m_iHeight = 0;
	m_iFPS = 0;
	//}}AFX_DATA_INIT

	m_bUpdating = false;
	m_pWaveFormat = 0;
	m_pWaveFormatOut = 0;
}


void CExportAVIDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CExportAVIDlg)
	DDX_Control(pDX, IDC_STATIC_TIMESTART, m_rStaticTimeStart);
	DDX_Control(pDX, IDC_STATIC_TIMEEND, m_rStaticTimeEnd);
	DDX_Control(pDX, IDC_EDIT_TIMESTART, m_rEditTimeStart);
	DDX_Control(pDX, IDC_EDIT_TIMEEND, m_rEditTimeEnd);
	DDX_Text(pDX, IDC_EDIT_WIDTH, m_iWidth);
	DDX_Text(pDX, IDC_EDIT_HEIGHT, m_iHeight);
	DDV_MinMaxInt(pDX, m_iHeight, 0, 10000);
	DDX_Text(pDX, IDC_EDIT_FPS, m_iFPS);
	DDV_MinMaxInt(pDX, m_iFPS, 1, 200);
	//}}AFX_DATA_MAP

	DDX_Control(pDX, IDC_COMBO_AUDIO_COMPRESSOR, m_ComboAudioCompressor);
	DDX_Control(pDX, IDC_COMBO_AUDIO_FORMAT, m_ComboAudioFormat);
	DDX_Control(pDX, IDC_COMBO_VIDEO_COMPRESSOR, m_ComboVideoCompressor);
	DDX_Control(pDX, IDC_STATIC_REPORT, m_StaticReport);
	DDX_Control(pDX, IDC_EDIT_QUALITY, m_EditQuality);
	DDX_Control(pDX, IDC_EDIT_DATARATE, m_EditRate);
	DDX_Control(pDX, IDC_EDIT_KEYFRAMES, m_EditKeyFrame);
	DDX_Control(pDX, IDC_CHECK_DATARATE, m_CheckRate);
	DDX_Control(pDX, IDC_CHECK_FORCE_KEYFRAME, m_CheckKeyframe);
	DDX_Control(pDX, IDC_BUTTON_CONFIGURE, m_ButtonCofigure);
	DDX_Control(pDX, IDC_EDIT_WIDTH, m_EditWidth);
	DDX_Control(pDX, IDC_EDIT_HEIGHT, m_EditHeight);
}


BEGIN_MESSAGE_MAP(CExportAVIDlg, CDialog)
	//{{AFX_MSG_MAP(CExportAVIDlg)
	ON_EN_CHANGE(IDC_EDIT_TIMEEND, OnChangeEditTimeend)
	ON_EN_CHANGE(IDC_EDIT_TIMESTART, OnChangeEditTimestart)
	//}}AFX_MSG_MAP
	ON_WM_DESTROY()
	ON_CBN_SELCHANGE(IDC_COMBO_AUDIO_COMPRESSOR, OnCbnSelchangeComboAudioCompressor)
	ON_BN_CLICKED(IDC_BUTTON_CONFIGURE, OnBnClickedButtonConfigure)
	ON_CBN_SELCHANGE(IDC_COMBO_VIDEO_COMPRESSOR, OnCbnSelchangeComboVideoCompressor)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CExportAVIDlg message handlers



BOOL CExportAVIDlg::OnInitDialog() 
{
	CDialog::OnInitDialog();
	
	m_bUpdating = true;

	// buttons
	if( !m_rSpinnerTimeStart.Create( WS_CHILD | WS_VISIBLE | SPNB_SETBUDDYINT, CRect( 0, 0, 0, 0 ), this, IDC_SPINNER1 ) )
		return FALSE;
	if( !m_rSpinnerTimeEnd.Create( WS_CHILD | WS_VISIBLE | SPNB_SETBUDDYINT, CRect( 0, 0, 0, 0 ), this, IDC_SPINNER2 ) )
		return FALSE;

	m_rSpinnerTimeStart.SetScale( 1 );
	m_rSpinnerTimeStart.SetBuddy( &m_rEditTimeStart, SPNB_ATTACH_RIGHT );

	m_rSpinnerTimeEnd.SetScale( 1 );
	m_rSpinnerTimeEnd.SetBuddy( &m_rEditTimeEnd, SPNB_ATTACH_RIGHT );

	CString	sVal;
	sVal.Format( "%d", m_i32StartTime / (256 / m_i32EditAccuracy) );
	m_rEditTimeStart.SetWindowText( sVal );

	sVal.Format( "%d", m_i32EndTime / (256 / m_i32EditAccuracy) );
	m_rEditTimeEnd.SetWindowText( sVal );


	// Quality spinner
	if( !m_rSpinnerQuality.Create( WS_CHILD | WS_VISIBLE | SPNB_SETBUDDYINT, CRect( 0, 0, 0, 0 ), this, IDC_SPINNER3 ) )
		return FALSE;
	m_rSpinnerQuality.SetScale( 1 );
	m_rSpinnerQuality.SetMinMax( 0, 100 );
	m_rSpinnerQuality.SetBuddy( &m_EditQuality, SPNB_ATTACH_RIGHT );
	
	m_EditQuality.SetWindowText( "100" );
	m_EditKeyFrame.SetWindowText( "1" );
	m_EditRate.SetWindowText( "0" );


	m_bUpdating = false;


	//
	// Audio compression
	//

	if( m_pWaveFormat )
	{
		ACMEnumeratorData aed;
		int								idx;

		acmMetrics( NULL, ACM_METRIC_MAX_SIZE_FORMAT, &aed.cbwfex );

		m_pWaveFormatOut = (WAVEFORMATEX*)new uint8[sizeof( WAVEFORMATEX )];
		CopyWaveFormat( m_pWaveFormatOut, m_pWaveFormat );

		aed.pwfex = (WAVEFORMATEX*)new uint8[aed.cbwfex];
		aed.m_pSelectedWaveFormat = m_pWaveFormat;
		aed.m_pSrcWaveFormat = m_pWaveFormat;
		aed.pTagSelect = NULL;
		aed.pFormatSelect = NULL;

		aed.pDriverList = &m_ComboAudioCompressor;

		// Add default item
		int32	i32Idx = m_ComboAudioCompressor.AddString( "(Uncompressed PCM)" );
		m_ComboAudioCompressor.SetItemDataPtr( i32Idx, 0 );

		acmDriverEnum( ACMDriverEnumerator, (DWORD)&aed, ACM_DRIVERENUMF_NOLOCAL );

		// Select no compression
		m_ComboAudioCompressor.SetCurSel( 0 );

		delete [] (uint8*)aed.pwfex;

		// Format
		m_ComboAudioFormat.AddString( "<default>" );
		m_ComboAudioFormat.SetCurSel( 0 );
	}
	else
	{
		m_ComboAudioCompressor.EnableWindow( FALSE );
		m_ComboAudioFormat.EnableWindow( FALSE );
	}

	//
	// Video compression
	//

	BITMAPINFOHEADER	BitmapInfo;
	memset( &BitmapInfo,0, sizeof( BITMAPINFOHEADER ) );
	BitmapInfo.biSize = sizeof( BITMAPINFOHEADER );
	BitmapInfo.biWidth = m_iWidth;
	BitmapInfo.biHeight = m_iWidth;
	BitmapInfo.biPlanes = 1;
	BitmapInfo.biBitCount = 24;
	BitmapInfo.biSizeImage = BitmapInfo.biWidth * BitmapInfo.biHeight * 3;
	BitmapInfo.biCompression = BI_RGB;

	ICINFO info;
	int i;
	int nComp;

	m_fccSelect	= NULL;
	m_pState		= NULL;
	m_cbState		= 0;
	m_hic			= NULL;
	m_piiCurrent	= NULL;

	if( m_pCompVars->dwFlags & ICMF_COMPVARS_VALID )
	{
		m_fccSelect	= m_pCompVars->fccHandler;

		if( m_pCompVars->hic )
		{
			m_cbState = ICGetStateSize( m_pCompVars->hic );

			if( m_cbState > 0 )
			{
				m_pState = new char[m_cbState];

				if (!m_pState)
					return FALSE;

				ICGetState( m_pCompVars->hic, m_pState, m_cbState );
			}
		}
	}

	nComp = 0;
	m_pCompInfo = NULL;
	m_nComp = 0;

	strcpy( m_szCurrentCompression, "(Uncompressed RGB)" );

	TRACE( "----->\n" );

	i = 0;

	while( 1 )
	{
		TRACE( "[%d] {\n", i );
		TRACE( " - info\n" );
		if( !ICInfo( ICTYPE_VIDEO, i, &info ) )
			break;

		HIC hic;

		// Use "special" routine for ASV1.

		union {
			FOURCC fcc;
			char buf[5];
		} u = {info.fccHandler};
		u.buf[4] = 0;

		TRACE( " - open\n" );

		hic = ICOpen( info.fccType, info.fccHandler, ICMODE_COMPRESS );

		if( hic )
		{
			TRACE( " - query\n" );

			ICINFO ici = { sizeof( ICINFO ) };
			char namebuf[64];

			namebuf[0] = 0;

			if( ICGetInfo( hic, &ici, sizeof( ICINFO ) ) )
				WideCharToMultiByte( CP_ACP, 0, ici.szDescription, -1, namebuf, sizeof( namebuf ), NULL, NULL);

			if( ICERR_OK == ICCompressQuery( hic, &BitmapInfo, NULL ) )
			{
				if( m_nComp + 1 > nComp )
				{
					ICINFO* pNewArray;
					nComp += 8;
					
					pNewArray = new ICINFO[nComp];

					if( !pNewArray )
					{
						delete m_pState;
						ICClose( hic );
						return FALSE;
					}

					if( m_nComp )
						memcpy( pNewArray, m_pCompInfo, m_nComp * sizeof( ICINFO ) );

					delete m_pCompInfo;
					m_pCompInfo = pNewArray;
				}

				m_pCompInfo[m_nComp] = ici;
				m_pCompInfo[m_nComp].fccHandler = info.fccHandler;
				++m_nComp;

				TRACE( " - close\n" );

				ICClose( hic );
			}
			TRACE( "}\n" );
		}

		i++;
	}

	TRACE( "<-----\n" );

	// Set the current compression (no compression).

	int32	idx;
	
	idx = m_ComboVideoCompressor.AddString( m_szCurrentCompression );
	if( idx != CB_ERR )
		m_ComboVideoCompressor.SetItemData( idx, -1 );

	for( i = 0; i < m_nComp; i++ )
	{
		WideCharToMultiByte( CP_ACP, 0, m_pCompInfo[i].szDescription, -1, m_tbuf, sizeof( m_tbuf ), NULL, NULL );

		idx = m_ComboVideoCompressor.AddString( m_tbuf );
		if( idx != CB_ERR )
			m_ComboVideoCompressor.SetItemData( idx, i );
	}

	m_ComboVideoCompressor.SetCurSel( 0 );
	SelectCompressor( 0 );

	return TRUE;
}

CString CExportAVIDlg::FormatTime( int32 i32Time )
{
	CString	sDuration;
	int32	i32Hours, i32Mins, i32Secs, i32Frames;
	int32	i32TimeScale = m_i32BeatsPerMin * m_i32QNotesPerBeat * 256;

	i32Frames = (i32Time * 60 * 60 / i32TimeScale); // / (256 / m_i32EditAccuracy);
	i32Secs = (i32Time * 60 / i32TimeScale) % 60;
	i32Mins = (i32Time / i32TimeScale) % 60;
	i32Hours = i32Time / 60 / i32TimeScale;
	i32Frames = (i32Time - ((i32Hours * 3600 + i32Mins * 60 + i32Secs) * i32TimeScale) / 60) / (256 / m_i32EditAccuracy);

	sDuration.Format( "%d:%02d:%02d:%02d", i32Hours, i32Mins, i32Secs, i32Frames );

	return sDuration;
}

void CExportAVIDlg::UpdateLabels()
{
	// start label
	CString	sVal;
//	sVal.Format( "%d\n", m_i32StartTime / (256 / m_i32EditAccuracy) );
	sVal = FormatTime( m_i32StartTime );
	m_rStaticTimeStart.SetWindowText( sVal );

	// end label
//	sVal.Format( "%d\n", i32EndTime / (256 / m_i32EditAccuracy) );
	sVal = FormatTime( m_i32EndTime );
	m_rStaticTimeEnd.SetWindowText( sVal );
}

void
CExportAVIDlg::SelectCompressor( int32 i32Comp )
{
	ICINFO*	pii = 0;

	// Get current size
	CString	sText;
	m_EditWidth.GetWindowText( sText );
	m_iWidth = _ttoi( sText );
	m_EditHeight.GetWindowText( sText );
	m_iHeight = _ttoi( sText );


	if( i32Comp > 0 )
	{
		pii = &m_pCompInfo[i32Comp];
	}

	HIC					hic;
	BITMAPINFO	bi;
	char				buf[256];
	char*				s;
	char*				slash;
	int					i;

	m_StaticReport.SetWindowText( "" );

	if( !pii || !pii->fccHandler )
	{
		if( m_hic )
		{
			ICClose( m_hic );
			m_hic = NULL;
		}

		m_piiCurrent = pii;
		ReenableOptions( NULL, pii );
		return;
	}

	// Attempt to open the compressor.

	if( m_hic )
	{
		ICClose( m_hic );
		m_hic = NULL;
	}

	hic = ICOpen( pii->fccType, pii->fccHandler, ICMODE_COMPRESS );

	if( !hic )
	{
//		SendMessage(hwndReport, LB_ADDSTRING, 0, (LPARAM)"<Unable to open driver>");
		return;
	}

	if( pii->fccHandler == m_fccSelect && m_pState )
		ICSetState( hic, m_pState, m_cbState );

	m_piiCurrent = pii;
	ReenableOptions( hic, pii );

	// Start querying the compressor for what it can handle

	bi.bmiHeader.biSize				= sizeof(BITMAPINFOHEADER);
	bi.bmiHeader.biPlanes			= 1;
	bi.bmiHeader.biCompression		= BI_RGB;
	bi.bmiHeader.biXPelsPerMeter	= 80;
	bi.bmiHeader.biYPelsPerMeter	= 72;
	bi.bmiHeader.biClrUsed			= 0;
	bi.bmiHeader.biClrImportant		= 0;
	bi.bmiHeader.biWidth = m_iWidth;
	bi.bmiHeader.biHeight = m_iHeight;
	bi.bmiHeader.biBitCount = 24;
	bi.bmiHeader.biSizeImage = m_iWidth * m_iHeight * 3;

	if( ICCompressQuery( hic, &bi.bmiHeader, NULL ) != ICERR_OK )
	{
		// Report error
		m_StaticReport.SetWindowText( "The Compressor does not support the resolution.\n" );
	}

	m_hic = hic;
}

void CExportAVIDlg::ReenableOptions( HIC hic, ICINFO *pii )
{
	BOOL		bSupports;
	ICINFO	info;
	DWORD		dwFlags;

	if( hic )
	{
		// Ask the compressor for its information again, because some
		// compressors change their flags after certain config options
		// are changed... that means you, SERGE ;-)
		//
		// Preserve the existing fccHandler during the copy.  This allows
		// overloaded codecs (i.e. 'MJPG' for miroVideo DRX, 'mjpx' for
		// PICVideo, 'mjpy' for MainConcept, etc.)

		if( ICGetInfo( hic, &info, sizeof( info ) ) )
		{
			FOURCC fccHandler = pii->fccHandler;

			memcpy( pii, &info, sizeof( ICINFO ) );
			pii->fccHandler = fccHandler;
		}

		// Query compressor for caps and enable buttons as appropriate.

		m_ButtonCofigure.EnableWindow( ICQueryConfigure( hic ) );
	}
	else
	{
		m_ButtonCofigure.EnableWindow( FALSE );
	}

	if( pii )
		dwFlags = pii->dwFlags;
	else
		dwFlags = 0;

	bSupports = (dwFlags & VIDCF_CRUNCH) != 0;

	m_CheckRate.EnableWindow( bSupports );
	m_EditRate.EnableWindow( bSupports );

	bSupports = (dwFlags & VIDCF_TEMPORAL) != 0;

	m_CheckKeyframe.EnableWindow( bSupports );
	m_EditKeyFrame.EnableWindow( bSupports );

	bSupports = (dwFlags & VIDCF_QUALITY) != 0;

	m_EditQuality.EnableWindow( bSupports );
	m_rSpinnerQuality.EnableWindow( bSupports );
}


void CExportAVIDlg::OnChangeEditTimeend() 
{
	CString	sText;
	m_rEditTimeEnd.GetWindowText( sText );
	m_i32EndTime = _ttoi( sText ) * 256 / m_i32EditAccuracy;

	CString	sVal;
	sVal = FormatTime( m_i32EndTime );
	m_rStaticTimeEnd.SetWindowText( sVal );
}

void CExportAVIDlg::OnChangeEditTimestart() 
{
	CString	sText;
	m_rEditTimeStart.GetWindowText( sText );
	m_i32StartTime = _ttoi( sText ) * 256 / m_i32EditAccuracy;

	CString	sVal;
	sVal = FormatTime( m_i32StartTime );
	m_rStaticTimeStart.SetWindowText( sVal );
}

void CExportAVIDlg::OnDestroy()
{
	CDialog::OnDestroy();

	int32	i;

	// Free audio compressor combo items
	for( i = 0; i < m_ComboAudioCompressor.GetCount(); i++ )
	{
		ACMTagEntry*	pate = (ACMTagEntry*)m_ComboAudioCompressor.GetItemDataPtr( i );
		if( pate )
			delete pate;
		m_ComboAudioCompressor.SetItemDataPtr( i, 0 );
	}

	if( m_hic )
		ICClose( m_hic );

	delete m_pCompInfo;
	delete m_pState;
}

void CExportAVIDlg::OnCbnSelchangeComboAudioCompressor()
{
	int32	i32Sel = m_ComboAudioCompressor.GetCurSel();
	ACMTagEntry*	pTag = 0;
	if( i32Sel != CB_ERR )
	{
		pTag = (ACMTagEntry*)m_ComboAudioCompressor.GetItemDataPtr( i32Sel );
	}

	// Show formats
	m_ComboAudioFormat.ResetContent();

	if( pTag )
	{
		for( std::list<ACMFormatEntry*>::iterator it = pTag->formats.begin(); it != pTag->formats.end(); ++it )
		{
			ACMFormatEntry*	pFormat = (*it);

//			if( !fShowCompatibleOnly || pFormat->fCompatible )
			if( pFormat->fCompatible )
			{
				int idx = m_ComboAudioFormat.AddString( pFormat->afd.szFormat );
				if (idx != CB_ERR)
					m_ComboAudioFormat.SetItemDataPtr( idx, pFormat );
			}
		}

		m_ComboAudioFormat.SetCurSel( 0 );
	}
	else
	{
		m_ComboAudioFormat.AddString( "<default>" );
		m_ComboAudioFormat.SetCurSel( 0 );
	}
}

void CExportAVIDlg::OnOK()
{
	int32	idx;

	//
	// Video compression
	//

	if(!(m_pCompVars->dwFlags & ICMF_COMPVARS_VALID) )
	{
		memset( m_pCompVars, 0, sizeof( COMPVARS ) );
		m_pCompVars->dwFlags = ICMF_COMPVARS_VALID;
	}
	m_pCompVars->fccType = 'CDIV';


	idx = m_ComboVideoCompressor.GetCurSel();
	if( idx > 0 )
	{
		idx = m_ComboVideoCompressor.GetItemData( idx );
		if( idx != -1 )
			m_pCompVars->fccHandler = m_pCompInfo[idx].fccHandler;
		else
			m_pCompVars->fccHandler = NULL;
	}
	else
		m_pCompVars->fccHandler = NULL;

	if( IsDlgButtonChecked( IDC_CHECK_FORCE_KEYFRAME ) )
		m_pCompVars->lKey = GetDlgItemInt( IDC_EDIT_KEYFRAMES, NULL, FALSE );
	else
		m_pCompVars->lKey = 0;

	if( IsDlgButtonChecked( IDC_CHECK_DATARATE ) )
		m_pCompVars->lDataRate = GetDlgItemInt( IDC_EDIT_DATARATE, NULL, FALSE );
	else
		m_pCompVars->lDataRate = 0;

	m_pCompVars->lQ = GetDlgItemInt( IDC_EDIT_QUALITY, NULL, FALSE ) * 100;

	if( m_hic )
		ICSendMessage( m_hic, ICM_SETQUALITY, (DWORD)&m_pCompVars->lQ, 0 );

	if( m_pCompVars->hic )
		ICClose( m_pCompVars->hic );
	m_pCompVars->hic = m_hic;
	m_hic = NULL;

	//
	// Audio compression
	//
	if( m_pWaveFormat )
	{
		idx = m_ComboAudioFormat.GetCurSel();

		// Delete old
		delete [] (uint8*)m_pWaveFormatOut;
		if( idx == CB_ERR )
		{
			m_pWaveFormatOut = 0;
		}
		else
		{
			ACMFormatEntry *pNewFormat = (ACMFormatEntry *)m_ComboAudioFormat.GetItemData( idx );
			m_pWaveFormatOut = pNewFormat->pwfex;
			pNewFormat->pwfex = NULL;
		}

		idx = m_ComboAudioCompressor.GetCurSel();
		if( idx != CB_ERR )
		{
			ACMTagEntry*	pTag = (ACMTagEntry*)m_ComboAudioCompressor.GetItemDataPtr( idx );
			m_hAudioDriverId = pTag->m_hACMDriverId;
		}
		else
		{
			m_hAudioDriverId = NULL;
		}
	}

	CDialog::OnOK();
}

void CExportAVIDlg::OnBnClickedButtonConfigure()
{
	if( m_hic )
	{
		ICConfigure( m_hic, GetSafeHwnd() );
		delete m_pState;
		m_pState = NULL;

		if( m_piiCurrent )
			ReenableOptions( m_hic, m_piiCurrent );
	}
	
}

void CExportAVIDlg::OnCbnSelchangeComboVideoCompressor()
{

	int32	i32Idx = m_ComboVideoCompressor.GetCurSel();
	if( i32Idx != CB_ERR ) 
	{
		int32	i32Data = m_ComboVideoCompressor.GetItemData( i32Idx );
		SelectCompressor( i32Data );
	}
}
