//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "MicSetFormUnit.h"
#include "Instruments.h"
#include "MessageFormUnit.h"

#define IO_DEVICE_WASAPI	0x10000
#define IO_DEVICE_ASIO		0x20000
#define IO_DEVICE_MIDI		0x40000
#define DEVICE_DEFAULT 		0x02
#define REC_INPUT_OFF		0x10000

// source info structure
typedef struct {
	char name[256];
	DWORD flags;
} IO_CHANNEL_INFO;

#define CLR_TEXT_HOT RGB( 201, 214, 229 )
#define CLR_TEXT_NOR RGB( 156, 170, 189 )

//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "GeneralDialogPanel"
#pragma link "TextButton"
#pragma link "CKBox"
#pragma resource "*.dfm"
TMicSetForm *MicSetForm;
//---------------------------------------------------------------------------
__fastcall TMicSetForm::TMicSetForm(TComponent* Owner)
	: TForm(Owner)
{
	//加载图片
	Font->Color = RGB(60,43,23);
	m_iCurrPlaybackDevice = m_iCurrRecordDevice = -1;
	m_iCurrOutput = m_iCurrInput = -1;

	m_PopupMenu = NULL;
}

//---------------------------------------------------------------------------
void __fastcall TMicSetForm::FormCreate(TObject *Sender)
{
	SetTransparent( this );

	m_panGeneral->Font->Size = g_szFont9;

	m_cbPlayDev->SetFontSize(g_szFont9);
	m_cbOutput->SetFontSize(g_szFont9);
	m_cbRecDev->SetFontSize(g_szFont9);
	m_cbInput->SetFontSize(g_szFont9);
	m_ckAuto->Font->Size = g_szFont9;
	m_ckMoniter->Font->Size = g_szFont9;
	m_rbCommon->Font->Size = g_szFont9;
	m_rbASIO->Font->Size = g_szFont8;
	m_rbWASAPI->Font->Size = g_szFont8;
	m_ckMIDI->Font->Size = g_szFont8;

	m_btnOk->FontSize = g_szFont9;
	m_btnCanel->FontSize = g_szFont9;

	//字体以及字体颜色修改
	m_lblVolume->Font->Color = CLR_TEXT_NOR;
	m_lblPlayback->Font->Color = CLR_TEXT_NOR;
	m_lblOutput->Font->Color = CLR_TEXT_NOR;
	m_lblRecord->Font->Color = CLR_TEXT_NOR;
	m_lblInput->Font->Color = CLR_TEXT_NOR;
	m_lblLatencyTime->Font->Color = CLR_TEXT_NOR;
	m_lblHint->Font->Color = CLR_TEXT_NOR;
	m_lblHintMsg->Font->Color = CLR_TEXT_NOR;
	m_lblLatency->Font->Color = CLR_TEXT_NOR;
   	m_lblType->Font->Color = CLR_TEXT_NOR;

	//-------------------------------选中状态判断
	m_ckAuto->Checked = g_bRecordAutoAdjust;
	m_ckMoniter->Checked = g_bRecordMoniter;

	m_iCurrPlaybackDevice = g_iPlaybackDevice;
	m_iCurrOutput = g_iPlaybackOutput;
	m_iCurrRecordDevice = g_iRecordDevice;
	m_iCurrInput = g_iRecordInput;

	IO_DEVICE_INFO aPbDevs[20], 	//播放设备
				aRcDevs[20];	   	//录音设备

	int nPbDev = f_MM_GetPlaybackDeviceInfo( 20, aPbDevs );
	int nRcDev = f_MM_GetRecordDeviceInfo( 20, aRcDevs );

	for( int i=0; i<nPbDev; i++ ){
		IO_DEVICE_INFO * pDev = new IO_DEVICE_INFO(aPbDevs[i]);

		if( pDev->iDevice & IO_DEVICE_WASAPI )
			m_aWasapiPb.push_back( pDev );
		else if( pDev->iDevice & IO_DEVICE_ASIO )
			m_aAsioPb.push_back( pDev );
		else
			m_aCommonPb.push_back( pDev );
	}

	for( int i=0; i<nRcDev; i++ ){
		IO_DEVICE_INFO * pDev = new IO_DEVICE_INFO(aRcDevs[i]);

		if( pDev->iDevice & IO_DEVICE_WASAPI )
			m_aWasapiRc.push_back( pDev );
		else if( pDev->iDevice & IO_DEVICE_MIDI )
			m_aMidiRc.push_back( pDev );
		else
			m_aCommonRc.push_back( pDev );
	}

	m_rbCommon->Enabled = !m_aCommonPb.empty();
	m_rbASIO->Enabled = !m_aAsioPb.empty();
	m_rbWASAPI->Enabled = !m_aWasapiPb.empty();
	m_ckMIDI->Enabled = !m_aMidiRc.empty();

	int iType = m_iCurrPlaybackDevice>=0 ? (m_iCurrPlaybackDevice & 0xF0000) : -1;

	if( m_iCurrPlaybackDevice<0 && !m_aCommonPb.empty()
							|| m_iCurrRecordDevice<0 && ( iType==0 && !m_aCommonRc.empty()
							|| iType==IO_DEVICE_WASAPI && !m_aWasapiRc.empty() ) ){
		f_MM_SetIODevice( m_iCurrPlaybackDevice, m_iCurrOutput,
							m_iCurrRecordDevice, m_iCurrInput );
	}

	if( iType<0 )
		iType = m_iCurrPlaybackDevice>=0 ? (m_iCurrPlaybackDevice & 0xF0000) : -1;

	m_rbCommon->Checked = iType==0;
	m_rbASIO->Checked = iType==IO_DEVICE_ASIO;
	m_rbWASAPI->Checked = iType==IO_DEVICE_WASAPI;
	m_ckMIDI->Checked = m_iCurrRecordDevice>=0 && (m_iCurrRecordDevice & IO_DEVICE_MIDI);

	ReloadPlayDev();
	ReloadOutput();

	ReloadRecDev();
	ReloadInput();

	m_pTimerLatency = new TTimer(this);
	m_pTimerLatency->Enabled = false;
	m_pTimerLatency->Interval = 250;
	m_pTimerLatency->OnTimer = LatencyTimerProc;

	m_tbVolume->Position = g_fRecordVolume * 100;
	m_tbVolume->Hint = IntToStr(m_tbVolume->Position);

	if( m_iCurrPlaybackDevice>=0 && m_iCurrRecordDevice>=0 )
		BeginRecordTest();
	else
		m_tbVolume->Enabled = false;
}
//---------------------------------------------------------------------------

void __fastcall TMicSetForm::FormClose(TObject *Sender, TCloseAction &Action)
{
	BeginRecordTest( false );

	if( m_pTimerLatency ){
		delete m_pTimerLatency;
		m_pTimerLatency = NULL;
	}
/*	if( m_PopupMenu ){
		delete m_PopupMenu;
		m_PopupMenu = NULL;
	}
*/
	while( !m_aCommonPb.empty() ){
		delete m_aCommonPb.back();
		m_aCommonPb.pop_back();
	}
	while( !m_aCommonRc.empty() ){
		delete m_aCommonRc.back();
		m_aCommonRc.pop_back();
	}
	while( !m_aWasapiPb.empty() ){
		delete m_aWasapiPb.back();
		m_aWasapiPb.pop_back();
	}
	while( !m_aWasapiRc.empty() ){
		delete m_aWasapiRc.back();
		m_aWasapiRc.pop_back();
	}
	while( !m_aAsioPb.empty() ){
		delete m_aAsioPb.back();
		m_aAsioPb.pop_back();
	}
	while( !m_aMidiRc.empty() ){
		delete m_aMidiRc.back();
		m_aMidiRc.pop_back();
	}

	if( ModalResult!=mrOk ){
		if( !(g_iPlaybackDevice==m_iCurrPlaybackDevice
					&& g_iRecordDevice==m_iCurrRecordDevice
					&& g_iPlaybackOutput==m_iCurrOutput
					&& g_iRecordInput==m_iCurrInput) ){
			f_MM_SetIODevice( g_iPlaybackDevice, g_iPlaybackOutput,
								   g_iRecordDevice,	g_iRecordInput );
		}

		if( g_bRecordAutoAdjust!=m_ckAuto->Checked )
			f_MM_SetRecordAutoAdjust( g_bRecordAutoAdjust );
		if( g_bRecordMoniter!=m_ckMoniter->Checked )
			f_MM_SetRecordMoniter( g_bRecordMoniter );
		f_MM_SetStreamVolume( 1, g_fRecordVolume );
	}
}
//---------------------------------------------------------------------------

void TMicSetForm::ReloadPlayDev()
{
	m_cbPlayDev->Clear();

	int iDevice = -1;

	if( m_iCurrPlaybackDevice>=0 ){
		int iType = m_iCurrPlaybackDevice & 0xF0000;
		vector<IO_DEVICE_INFO*>& rDevs = iType==IO_DEVICE_WASAPI ? m_aWasapiPb
											: iType==IO_DEVICE_ASIO ? m_aAsioPb
											: m_aCommonPb;
		for( int i=0; i<rDevs.size(); i++ ){
			if( rDevs[i]->iDevice==m_iCurrPlaybackDevice )
				iDevice = m_cbPlayDev->ItemsCount;

			if( iType==0 && !stricmp( rDevs[i]->name, "Default" ))
				m_cbPlayDev->AddItem( "系统默认设备" )->Tag = rDevs[i]->iDevice;
			else
				m_cbPlayDev->AddItem( rDevs[i]->name )->Tag = rDevs[i]->iDevice;
		}
	}

	m_cbPlayDev->DefItemIndex = iDevice;
	m_cbPlayDev->Enabled = m_cbPlayDev->ItemsCount>0;
}
//---------------------------------------------------------------------------

void TMicSetForm::ReloadRecDev()
{
	m_cbRecDev->Clear();

	int iDevice = -1;
	if( m_iCurrRecordDevice>=0 ){
		int iType = m_iCurrRecordDevice & 0xF0000;

		if( iType==IO_DEVICE_ASIO ){
			for( int i=0; i<m_aAsioPb.size(); i++ ){
				if( m_aAsioPb[i]->iDevice==m_iCurrRecordDevice ){
					m_cbRecDev->AddItem( m_aAsioPb[i]->name )->Tag = m_aAsioPb[i]->iDevice;
					break;
				}
			}
			iDevice = 0;
		}
		else{
			vector<IO_DEVICE_INFO*>& rDevs = iType==IO_DEVICE_WASAPI ? m_aWasapiRc
												: iType==IO_DEVICE_MIDI ? m_aMidiRc
												: m_aCommonRc;
			for( int i=0; i<rDevs.size(); i++ ){
				if( rDevs[i]->iDevice==m_iCurrRecordDevice )
					iDevice = m_cbRecDev->ItemsCount;

				if( iType==0 && !strcmp( rDevs[i]->name, "Default" ))
					m_cbRecDev->AddItem( "系统默认设备" )->Tag = rDevs[i]->iDevice;
				else
					m_cbRecDev->AddItem( rDevs[i]->name )->Tag = rDevs[i]->iDevice;
			}
		}
	}

	m_cbRecDev->DefItemIndex = iDevice;
	m_cbRecDev->Enabled = m_cbRecDev->ItemsCount>0;
	if( !m_cbRecDev->Enabled )
		m_cbRecDev->Caption = "";
}
//---------------------------------------------------------------------------

void TMicSetForm::ReloadOutput()
{
	m_cbOutput->Clear();

	int iType = m_iCurrPlaybackDevice & 0xF0000;

	if( iType==IO_DEVICE_ASIO ){
		m_lblASIO->Visible = true;

		IO_CHANNEL_INFO chanInfo[20];
		int nSize = f_MM_GetPlaybackOutputInfo( 20, chanInfo );
		int iChannel = -1;

		if( m_iCurrOutput>=0 && m_iCurrOutput<nSize)
			iChannel = m_iCurrOutput;
		else if( nSize>0 )
			iChannel = 0;

		for( int i=0; i<nSize; i+=2 ){
			m_cbOutput->AddItem( chanInfo[i].name );
		}

		if( iChannel>=0 )
			m_cbOutput->DefItemIndex = iChannel/2;

		m_lblASIO->Enabled = iChannel>=0;
		m_iCurrOutput = iChannel;
	}
	else{
		m_lblASIO->Visible = false;

		m_cbOutput->AddItem( "默认输出" );
		m_cbOutput->DefItemIndex = 0;
	}

	m_cbOutput->Enabled = m_cbOutput->ItemsCount>0;
	if( !m_cbOutput->Enabled )
		m_cbOutput->Caption = "";
}
//---------------------------------------------------------------------------

void TMicSetForm::ReloadInput()
{
	m_cbInput->Clear();

	bool bMidi = m_iCurrRecordDevice>=0 && (m_iCurrRecordDevice & IO_DEVICE_MIDI);
	m_ckAuto->Visible = !bMidi;
	m_ckMoniter->Visible = !bMidi;

	if( bMidi ){
//		m_lblLatency->Top = m_lblVolume->Top;
//		m_lblLatencyTime->Top = m_lblVolume->Top;
//		m_lblVolume->Caption = "缓冲时间：";
		m_lblInput->Caption = "乐器音色：";

		for( int i=0; i<112; i++ ){
			m_cbInput->AddItem( GM_INSTRUMENT[i] );
		}

		m_cbInput->DefItemIndex = m_iCurrInput;
	}
	else{
//		m_lblLatency->Top = m_lblInput->Top;
//		m_lblLatencyTime->Top = m_lblInput->Top;
//		m_lblVolume->Caption = "录音音量：";
		m_lblInput->Caption = "录音输入：";

		int iChannel = -1;
		if( m_cbRecDev->DefItemIndex>=0 ){
			IO_CHANNEL_INFO chanInfo[20];
			int nSize = f_MM_GetRecordInputInfo( 20, chanInfo );

			if( m_iCurrInput>=0 && m_iCurrInput<nSize){
				iChannel = m_iCurrInput;
			}

			if( nSize>0 ){
				for( int i=0; i<nSize; i++ ){
					m_cbInput->AddItem( chanInfo[i].name );
					if( iChannel<0 ){
						iChannel = i;
					}
				}

				if( iChannel<0 ){
					iChannel = 0;
				}

				m_cbInput->DefItemIndex = iChannel;
			}
			else if( (m_iCurrPlaybackDevice & 0xF0000)!=IO_DEVICE_ASIO ){
				m_cbInput->AddItem( "默认输入" );
				m_cbInput->DefItemIndex = 0;
			}
		}

		m_iCurrInput = iChannel;
	}

	m_cbInput->Enabled = m_cbInput->ItemsCount>0;
	m_tbVolume->Enabled = m_cbInput->ItemsCount>0;
	if( !m_cbInput->Enabled )
		m_cbInput->Caption = "";
}
//---------------------------------------------------------------------------

void __fastcall TMicSetForm::FormKeyDown(TObject *Sender, WORD &Key, TShiftState Shift)

{
	switch( Key ){
	case VK_RETURN:
	case ' ':
		if( m_btnOk->Visible ){
			OkClick( NULL );
			ModalResult = mrOk;
		}
		break;

	case VK_ESCAPE:
		if( m_btnCanel->Visible ){
			ModalResult = mrCancel;
		}
		break;
	}
}
//---------------------------------------------------------------------------
void __fastcall TMicSetForm::VolumeChange(TObject *Sender)
{
	if( m_iCurrRecordDevice<0 )
		return;

	int nPos = m_tbVolume->Position;
	m_tbVolume->Hint = IntToStr(nPos);

/*	if( m_iCurrRecordDevice & IO_DEVICE_MIDI ){
			f_MM_SetMidiInBuffer( nPos );
	}
	else{
*/		if( m_ckAuto->Visible && m_ckAuto->Checked ){
			m_ckAuto->Checked = false;
			f_MM_SetRecordAutoAdjust( m_ckAuto->Checked );
		}

		f_MM_SetStreamVolume( 1, nPos/100.0 );
//	}
}
//---------------------------------------------------------------------------

void __fastcall TMicSetForm::LatencyTimerProc(TObject* Sender)
{
	float fLatency = f_MM_GetLatency( true );
	char str[16];
	sprintf( str, "%.1f ms", fLatency );
	m_lblLatencyTime->Caption = str;
}
//---------------------------------------------------------------------------

void TMicSetForm::BeginRecordTest(bool bStart)
{
	if( bStart ){
		HRESULT hr = f_MM_RecordTest( Handle );
		if( hr==S_OK ){
			if( m_ckAuto->Checked ){
				m_tbVolume->OnChange = NULL;
				m_tbVolume->Position = 100;
				m_tbVolume->Hint = IntToStr(100);

				f_MM_SetStreamVolume( 1, 1 );
			}

			m_tbVolume->Enabled = true;
			m_tbVolume->OnChange = VolumeChange;
			m_pTimerLatency->Enabled = true;
			m_lblLatencyTime->Caption = "0.0 ms";
		}
		else{
			m_pTimerLatency->Enabled = false;
			m_tbVolume->Enabled = false;
			m_lblLatencyTime->Caption = "---- ms";

			ShowErrorMessage( hr );
		}
	}
	else{
		m_pTimerLatency->Enabled = false;
		f_MM_Stop();
		m_tbVolume->Enabled = false;
		m_lblLatencyTime->Caption = "---- ms";
	}
}
// ---------------------------------------------------------------------------

void TMicSetForm::ShowErrorMessage( int errcode )
{
	String msg;

	int errRec = LOWORD( errcode ),
		errPlay = HIWORD( errcode ),
		err = errRec>0 ? errRec : errPlay;

    if( err==1 ){
		msg += L"内存空间不足。";
	}
	else{
		if(errRec>1 && m_cbInput->ItemsCount>0)
			msg += "输入";
		if(errPlay>1 && m_cbOutput->ItemsCount>0)
			msg += "输出";
	}

	if( msg.Length()==0 )
		return;

	if( err==46 ){
		msg += L"设备被其它程序独占。";
	}
	else if( err==37 ){
		msg += L"设备无法打开。";
	}
	else if( err==3 || err==23 ){
		msg += L"设备无效。";
	}
	else{
		msg += L"设备启动失败。";
	}

	MessageForm->ShowMessage( msg, MB_ICONERROR | MB_OK );
}
//---------------------------------------------------------------------------

void __fastcall TMicSetForm::OkClick(TObject *Sender)
{
	g_iPlaybackDevice = m_iCurrPlaybackDevice;
	g_iRecordDevice = m_iCurrRecordDevice;
	g_iPlaybackOutput = m_iCurrOutput;
	g_iRecordInput = m_iCurrInput;

	if( m_iCurrPlaybackDevice>=0 ){
		int iType = m_iCurrPlaybackDevice & 0xF0000;
		vector<IO_DEVICE_INFO*>& rDevsPb = iType==IO_DEVICE_WASAPI ? m_aWasapiPb
											: iType==IO_DEVICE_ASIO ? m_aAsioPb
											: m_aCommonPb;
		for( int i=0; i<rDevsPb.size(); i++ ){
			if( rDevsPb[i]->iDevice==m_iCurrPlaybackDevice ){
				strcpy( g_strPlaybackDevice, rDevsPb[i]->name );
				break;
			}
		}
	}

	if( m_iCurrRecordDevice>=0 ){
		int iType = m_iCurrRecordDevice & 0xF0000;
		if( iType==IO_DEVICE_ASIO ){
			strcpy( g_strRecordDevice, g_strPlaybackDevice );
		}
		else{
			vector<IO_DEVICE_INFO*>& rDevsRc = iType==IO_DEVICE_WASAPI ? m_aWasapiRc
												: iType==IO_DEVICE_MIDI ? m_aMidiRc
												: m_aCommonRc;

			for( int i=0; i<rDevsRc.size(); i++ ){
				if( rDevsRc[i]->iDevice==m_iCurrRecordDevice ){
					strcpy( g_strRecordDevice, rDevsRc[i]->name );
					break;
				}
			}
		}
	}

	//保存所有状态
	g_fRecordVolume = m_tbVolume->Position / 100.0;
//	g_fRecordVolume = f_MM_GetStreamVolume( 1 ) / 100.0;
	g_bRecordAutoAdjust = m_ckAuto->Checked;
	g_bRecordMoniter = !(m_iCurrRecordDevice&IO_DEVICE_MIDI) && m_ckMoniter->Checked;
	f_MM_SetRecordMoniter( g_bRecordMoniter );
}
//---------------------------------------------------------------------------

void __fastcall TMicSetForm::UMRecordVolJust(TMessage &Message)
{
	m_tbVolume->OnChange = NULL;
	m_tbVolume->Position = (int)Message.WParam;
	m_tbVolume->Hint = IntToStr((int)Message.WParam);
	m_tbVolume->OnChange = VolumeChange;
}
//---------------------------------------------------------------------------

void __fastcall TMicSetForm::AutoChange(TObject *Sender)
{
	f_MM_SetRecordAutoAdjust( m_ckAuto->Checked );
}
//---------------------------------------------------------------------------

void __fastcall TMicSetForm::MoniterChange(TObject *Sender)
{
	f_MM_SetRecordMoniter( m_ckMoniter->Checked );
}
//---------------------------------------------------------------------------

void __fastcall TMicSetForm::PlayDevChange(TComboBoxItem *Sender, int Index)
{
	int iNewDev = m_cbPlayDev->GetItem(Index)->Tag;
	if( iNewDev==m_iCurrPlaybackDevice )
		return;

	BeginRecordTest( false );

	int iType = (m_iCurrPlaybackDevice & 0xF0000);
	int iPlayDev = iNewDev, iOutput = -1,
		iRecDev = m_iCurrRecordDevice,
		iInput = m_iCurrInput;

	if( !m_ckMIDI->Checked && iType==IO_DEVICE_ASIO ){
		iRecDev = iNewDev;
		iInput = -1;
	}

	Screen->Cursor = crHourGlass;

	HRESULT hr = f_MM_SetIODevice( iPlayDev, iOutput, iRecDev, iInput );

	m_iCurrPlaybackDevice = iPlayDev;
	m_iCurrOutput = iOutput;
	m_iCurrRecordDevice = iRecDev;
	m_iCurrInput = iInput;

	if( iType==IO_DEVICE_ASIO ){
		ReloadOutput();

		if( !m_ckMIDI->Checked ){
			ReloadRecDev();
			ReloadInput();
		}
	}

	if( hr==S_OK ){
		if( m_iCurrRecordDevice>=0 )
			BeginRecordTest();
	}
	else
		ShowErrorMessage( hr );

	m_tbVolume->Enabled = hr==S_OK;
	Screen->Cursor = crDefault;
}
//---------------------------------------------------------------------------

void __fastcall TMicSetForm::RecDevChange(TComboBoxItem *Sender, int Index)
{
	int iNewDev = m_cbRecDev->GetItem(Index)->Tag;
	if( iNewDev==m_iCurrRecordDevice )
		return;

	BeginRecordTest( false );

	int iPlayDev = m_iCurrPlaybackDevice,
		iOutput = m_iCurrOutput,
		iRecDev = iNewDev,
		iInput = (iNewDev & IO_DEVICE_MIDI) ? 0 : -1;

	Screen->Cursor = crHourGlass;

	HRESULT hr = f_MM_SetIODevice( iPlayDev, iOutput, iRecDev, iInput );

	m_iCurrPlaybackDevice = iPlayDev;
	m_iCurrOutput = iOutput;
	m_iCurrRecordDevice = iRecDev;
	m_iCurrInput = iInput;

	ReloadInput();

	if( hr==S_OK ){
		if( m_iCurrRecordDevice>=0 )
			BeginRecordTest();
	}
	else{
		ShowErrorMessage( hr );
	}

	m_tbVolume->Enabled = hr==S_OK;
	Screen->Cursor = crDefault;
}
//---------------------------------------------------------------------------

void __fastcall TMicSetForm::OutputChange(TComboBoxItem *Sender, int Index)
{
	if( !m_rbASIO->Checked )
		return;

	int iIndex = Index * 2;

	if( iIndex==m_iCurrOutput )
		return;

	BeginRecordTest( false );

	int iPlayDev = m_iCurrPlaybackDevice,
		iOutput = iIndex,
		iRecDev = m_iCurrRecordDevice,
		iInput = m_iCurrInput;

	Screen->Cursor = crHourGlass;

	HRESULT hr = f_MM_SetIODevice( iPlayDev, iOutput, iRecDev, iInput );

	m_iCurrPlaybackDevice = iPlayDev;
	m_iCurrOutput = iOutput;
	m_iCurrRecordDevice = iRecDev;
	m_iCurrInput = iInput;

	if( hr==S_OK ){
		if( m_iCurrRecordDevice>=0 )
			BeginRecordTest();
	}
	else{
		ShowErrorMessage( hr );
	}

	m_tbVolume->Enabled = hr==S_OK;
	Screen->Cursor = crDefault;
}
//---------------------------------------------------------------------------

void __fastcall TMicSetForm::InputChange(TComboBoxItem *Sender, int Index)
{
	if( m_rbWASAPI->Checked && !m_ckMIDI->Checked )
		return;

	int iInput = m_cbInput->DefItemIndex;
	if( iInput==m_iCurrInput )
		return;

	BeginRecordTest( false );

	int iPlayDev = m_iCurrPlaybackDevice,
		iOutput = m_iCurrOutput,
		iRecDev = m_iCurrRecordDevice;

	Screen->Cursor = crHourGlass;

	HRESULT hr = f_MM_SetIODevice( iPlayDev, iOutput, iRecDev, iInput );

	m_iCurrInput = iInput;

	if( hr==S_OK )
		BeginRecordTest();
	else{
		ShowErrorMessage( hr );
	}

	m_tbVolume->Enabled = hr==S_OK;
	Screen->Cursor = crDefault;
}
//---------------------------------------------------------------------------

void __fastcall TMicSetForm::DoShowPanel(TObject* Sender)
{
	if( m_iCurrPlaybackDevice & IO_DEVICE_ASIO )
		f_MM_ShowAsioPanel();
}
//---------------------------------------------------------------------------

void __fastcall TMicSetForm::DoRestart(TObject* Sender)
{
	if( m_iCurrPlaybackDevice & IO_DEVICE_ASIO ){
		if( f_MM_RestartAsioDevice()==S_OK ){
			ReloadOutput();
			ReloadInput();
		}
	}
}
//---------------------------------------------------------------------------

void __fastcall TMicSetForm::MIDIInputClick(TObject *Sender)
{
	bool bMidi = m_iCurrRecordDevice>0 && (m_iCurrRecordDevice & IO_DEVICE_MIDI);
	if( bMidi==m_ckMIDI->Checked )
		return;

	BeginRecordTest( false );

	int iPlayDev = m_iCurrPlaybackDevice,
		iOutput = m_iCurrOutput,
		iRecDev = -1,
		iInput = -1;

	if( m_ckMIDI->Checked ){
		iRecDev = m_aMidiRc[0]->iDevice;
		iInput = 0;
	}
	else{
		int iPbType = m_iCurrPlaybackDevice & 0xF0000;

		if( iPbType==IO_DEVICE_ASIO ){
			iRecDev = iPlayDev;
		}
		else{
			vector<IO_DEVICE_INFO*>& rDevsRc = iPbType==IO_DEVICE_WASAPI ? m_aWasapiRc
																	: m_aCommonRc;

			if( rDevsRc.empty() ){
				iRecDev = iPbType;
			}
			else{
				for( int i=0; i<rDevsRc.size(); i++ ){
					if( rDevsRc[i]->flags & DEVICE_DEFAULT ){
						iRecDev = rDevsRc[i]->iDevice;
						break;
					}
				}
			}
		}
	}

	Screen->Cursor = crHourGlass;

	HRESULT hr = f_MM_SetIODevice( iPlayDev, iOutput, iRecDev, iInput );

	m_iCurrPlaybackDevice = iPlayDev;
	m_iCurrOutput = iOutput;
	m_iCurrRecordDevice = iRecDev;
	m_iCurrInput = iInput;

	ReloadRecDev();
	ReloadInput();

	if( hr==S_OK ){
		if( m_iCurrRecordDevice>=0 )
			BeginRecordTest();
	}
	else{
		ShowErrorMessage( hr );
	}

	Screen->Cursor = crDefault;
}
//---------------------------------------------------------------------------

void __fastcall TMicSetForm::DevTypeClick(TObject *Sender)
{
	int iTypeOld = m_iCurrPlaybackDevice & 0xF0000;
	int iType = m_rbASIO->Checked ? IO_DEVICE_ASIO
					: m_rbWASAPI->Checked ? IO_DEVICE_WASAPI
					: 0;

	if( iType==iTypeOld )
		return;

	BeginRecordTest( false );

	int iPlayDev = -1, iOutput = -1,
		iRecDev = -1, iInput = -1;

	if( m_ckMIDI->Checked ){
		iRecDev = m_iCurrRecordDevice;
		iInput = m_iCurrInput;
	}

	if( iType==IO_DEVICE_ASIO ){
		iPlayDev = m_aAsioPb[0]->iDevice;

		if( iRecDev<0 )
			iRecDev = iPlayDev;
	}
	else{
		vector<IO_DEVICE_INFO*>& rDevsPb = iType==IO_DEVICE_WASAPI ? m_aWasapiPb
											: iType==IO_DEVICE_ASIO ? m_aAsioPb
											: m_aCommonPb;
		for( int i=0; i<rDevsPb.size(); i++ ){
			if( rDevsPb[i]->flags & DEVICE_DEFAULT ){
				iPlayDev = rDevsPb[i]->iDevice;
				break;
			}
		}

		if( iRecDev<0 ){
			vector<IO_DEVICE_INFO*>& rDevsRc = iType==IO_DEVICE_WASAPI ? m_aWasapiRc
												: m_aCommonRc;

			for( int i=0; i<rDevsRc.size(); i++ ){
				if( rDevsRc[i]->flags & DEVICE_DEFAULT ){
					iRecDev = rDevsRc[i]->iDevice;
					break;
				}
			}
		}
	}

	Screen->Cursor = crHourGlass;

	m_iCurrPlaybackDevice = iPlayDev;
	m_iCurrOutput = iOutput;

	HRESULT hr = f_MM_SetIODevice( iPlayDev, iOutput, iRecDev, iInput );

	if( iPlayDev>=0 ){
		m_iCurrPlaybackDevice = iPlayDev;
		m_iCurrOutput = iOutput;
	}

	m_iCurrRecordDevice = iRecDev;
	m_iCurrInput = iInput;

	ReloadPlayDev();
	ReloadOutput();

	ReloadRecDev();
	ReloadInput();

	if( hr==S_OK ){
		if( m_cbInput->Enabled )
			BeginRecordTest();
	}
	else
		ShowErrorMessage( hr );

	Screen->Cursor = crDefault;
}
//---------------------------------------------------------------------------

void __fastcall TMicSetForm::ASIOClick(TObject *Sender)
{
	if( m_PopupMenu ){
		delete m_PopupMenu;
		m_PopupMenu = NULL;
	}

	m_PopupMenu = new TMenuPanel();
	m_PopupMenu->Parent = this;

	m_PopupMenu->CreateMenu( "显示面板", "", DoShowPanel );
	m_PopupMenu->CreateMenu( "重启设备", "", DoRestart );

	m_PopupMenu->Width = m_lblASIO->Width;
	m_PopupMenu->Show( m_lblASIO->Left, m_lblASIO->Top+m_lblASIO->Height );
}
//---------------------------------------------------------------------------


