Files
AccompanyCube/MicSetFormUnit.cpp
2026-06-13 00:10:11 +08:00

790 lines
19 KiB
C++

//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "GlobalUnit.h"
#include "MessageFormUnit.h"
#include "MicSetFormUnit.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;
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "PNGButton"
#pragma resource "*.dfm"
USEFORM("MessageFormUnit.cpp", MessageForm);
TMicSetForm *MicSetForm;
//---------------------------------------------------------------------------
__fastcall TMicSetForm::TMicSetForm(TComponent* Owner)
: TForm(Owner)
{
m_pImgCheck = new TBitmap();
m_pImgCheck->LoadFromResourceName(int(HInstance), L"AutoLoginCheck");
Font->Color = RGB(60,43,23);
m_iCurrPlaybackDevice = m_iCurrRecordDevice = -1;
m_iCurrOutput = m_iCurrInput = -1;
m_PopupMenu = NULL;
}
//---------------------------------------------------------------------------
__fastcall TMicSetForm::~TMicSetForm()
{
if( m_pImgCheck ){
delete m_pImgCheck;
m_pImgCheck = NULL;
}
if( m_PopupMenu ){
delete m_PopupMenu;
m_PopupMenu = NULL;
}
}
//---------------------------------------------------------------------------
void __fastcall TMicSetForm::FormCreate(TObject *Sender)
{
m_tbVolume->ControlStyle>>csOpaque;
Font->Color = RGB(60,43,23);
//绘制圆角窗体
HRGN hRgn = CreateRoundRectRgn( 0, 0, Width+1, Height+1, 16, 16 );
SetWindowRgn( Handle, hRgn, false );
DeleteObject( hRgn );
m_bAutoAdjust = g_bRecordAutoAdjust;
m_bMoniter = 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_aCommonRc.empty();
m_rbASIO->Enabled = !m_aAsioPb.empty();
m_rbWASAPI->Enabled = !m_aWasapiPb.empty();// && !m_aWasapiPb.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;
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;
SetTransparent( this );
}
//---------------------------------------------------------------------------
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( m_bAutoAdjust!=g_bRecordAutoAdjust )
f_MM_SetRecordAutoAdjust( g_bRecordAutoAdjust );
if( m_bMoniter!=g_bRecordMoniter )
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->Items->Count;
if( iType==0 && !strcmp( rDevs[i]->name, "Default" ))
m_cbPlayDev->AddItem( "系统默认设备", (TObject*)rDevs[i]->iDevice );
else
m_cbPlayDev->AddItem( rDevs[i]->name, (TObject*)rDevs[i]->iDevice );
}
}
m_cbPlayDev->ItemIndex = iDevice;
m_cbPlayDev->Enabled = m_cbPlayDev->Items->Count > 0;
}
//---------------------------------------------------------------------------
void TMicSetForm::ReloadRecDev()
{
if( !m_rbASIO->Checked ){
m_cbRecDevOrOutput->Clear();
int iDevice = -1;
if( m_iCurrRecordDevice>=0 ){
int iType = m_iCurrRecordDevice & 0xF0000;
m_lblRecDevOrOutput->Caption = "录音设备";
m_cbRecDevOrOutput->Width = m_cbPlayDev->Width;
m_lblASIO->Visible = false;
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_cbRecDevOrOutput->Items->Count;
if( iType==0 && !strcmp( rDevs[i]->name, "Default" ))
m_cbRecDevOrOutput->AddItem( "系统默认设备", (TObject*)rDevs[i]->iDevice );
else
m_cbRecDevOrOutput->AddItem( rDevs[i]->name, (TObject*)rDevs[i]->iDevice );
}
}
m_cbRecDevOrOutput->ItemIndex = iDevice;
m_cbRecDevOrOutput->Enabled = m_cbRecDevOrOutput->Items->Count > 0;
}
}
//---------------------------------------------------------------------------
void TMicSetForm::ReloadOutput()
{
if( m_rbASIO->Checked ){
int iDevice = -1;
m_cbRecDevOrOutput->Clear();
m_lblRecDevOrOutput->Caption = "播放输出";
m_cbRecDevOrOutput->Width = m_cbInput->Width;
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_cbRecDevOrOutput->AddItem( chanInfo[i].name, (TObject*)i );
}
if( iChannel>=0 )
m_cbRecDevOrOutput->ItemIndex = iChannel/2;
m_iCurrOutput = iChannel;
m_lblASIO->Enabled = iChannel>=0;
m_cbRecDevOrOutput->Enabled = m_cbRecDevOrOutput->Items->Count > 0;
}
}
//---------------------------------------------------------------------------
void TMicSetForm::ReloadInput()
{
m_cbInput->Clear();
if( !m_cbRecDevOrOutput->Enabled ){
m_cbInput->Enabled = false;
return;
}
IO_CHANNEL_INFO chanInfo[20];
int iChannel = -1;
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, (TObject*)i );
if( iChannel<0 ){
iChannel = i;
}
}
if( iChannel<0 ){
iChannel = 0;
}
m_cbInput->ItemIndex = iChannel;
}
else if( (m_iCurrPlaybackDevice & 0xF0000)!=IO_DEVICE_ASIO ){
m_cbInput->AddItem( "默认输入", (TObject*)0 );
m_cbInput->ItemIndex = 0;
}
m_cbInput->Enabled = m_cbInput->Items->Count > 0;
m_iCurrInput = iChannel;
}
//---------------------------------------------------------------------------
void __fastcall TMicSetForm::WMNCHitTest(TWMNCHitTest &Msg)
{
TForm::Dispatch(&Msg);
if( Msg.Result==HTCLIENT && Msg.YPos<Top+24
&& Msg.XPos>Left+35 && Msg.XPos<Left+275 )
Msg.Result = HTCAPTION;
}
//---------------------------------------------------------------------------
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_btnCancel->Visible )
ModalResult = mrCancel;
break;
}
}
//---------------------------------------------------------------------------
void __fastcall TMicSetForm::CheckPaint(TObject *Sender)
{
TPaintBox* pPB = (TPaintBox*)Sender;
//绘制Check状态
int x = 0;
if( pPB==m_pbAutoCheck && !m_bAutoAdjust
|| pPB==m_pbMoniter && !m_bMoniter ){
x = -m_pImgCheck->Width/2;
}
pPB->Canvas->Draw(x, 0, m_pImgCheck);
}
//---------------------------------------------------------------------------
void __fastcall TMicSetForm::CheckClick(TObject *Sender)
{
TPaintBox* pPB = (TPaintBox*)Sender;
//切换Check状态
if( pPB==m_pbAutoCheck ){
m_bAutoAdjust = !m_bAutoAdjust;
f_MM_SetRecordAutoAdjust( m_bAutoAdjust );
}
else{
m_bMoniter = !m_bMoniter;
f_MM_SetRecordMoniter( m_bMoniter );
}
pPB->Invalidate();
}
//---------------------------------------------------------------------------
void __fastcall TMicSetForm::OkClick(TObject *Sender)
{
g_iPlaybackDevice = m_iCurrPlaybackDevice;
g_iRecordDevice = m_iCurrRecordDevice;
g_iPlaybackOutput = m_iCurrOutput;
g_iRecordInput = m_iCurrInput;
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;
}
}
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_bAutoAdjust;
g_bRecordMoniter = m_bMoniter;
}
//---------------------------------------------------------------------------
void __fastcall TMicSetForm::PlayDevChange(TObject *Sender)
{
int iNewDev = (int)(m_cbPlayDev->Items->Objects[m_cbPlayDev->ItemIndex]);
if( iNewDev==m_iCurrPlaybackDevice )
return;
BeginRecordTest( false );
int iType = (m_iCurrPlaybackDevice & 0xF0000);
int iPlayDev = iNewDev, iOutput = -1,
iRecDev = m_iCurrRecordDevice,
iInput = m_iCurrInput;
if( 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();
ReloadInput();
}
if( hr==S_OK ){
if( m_iCurrRecordDevice>=0 )
BeginRecordTest();
}
else
ShowErrorMessage( hr );
m_tbVolume->Enabled = hr==S_OK && m_iCurrRecordDevice>=0;
Screen->Cursor = crDefault;
}
//---------------------------------------------------------------------------
void __fastcall TMicSetForm::RecDevOrOutputChange(TObject *Sender)
{
int iIndex = (int)(m_cbRecDevOrOutput->Items->Objects[m_cbRecDevOrOutput->ItemIndex]);
int iPlayDev = m_iCurrPlaybackDevice,
iOutput = m_iCurrOutput,
iRecDev = m_iCurrRecordDevice,
iInput = m_iCurrInput;
if( m_rbASIO->Checked ){
if( iIndex==m_iCurrOutput )
return;
else
iOutput = iIndex;
}
else{
if( iIndex==m_iCurrRecordDevice )
return;
else
iRecDev = iIndex;
}
BeginRecordTest( false );
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( !m_rbASIO->Checked )
ReloadInput();
if( hr==S_OK ){
if( m_iCurrRecordDevice>=0 )
BeginRecordTest();
}
else
ShowErrorMessage( hr );
m_tbVolume->Enabled = hr==S_OK && m_iCurrRecordDevice>=0;
Screen->Cursor = crDefault;
}
//---------------------------------------------------------------------------
void __fastcall TMicSetForm::InputChange(TObject *Sender)
{
int iInput = m_cbInput->ItemIndex;
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::VolumeChange(TObject *Sender)
{
int nVol = m_tbVolume->Position;
m_tbVolume->Hint = IntToStr(nVol);
f_MM_SetStreamVolume( 1, nVol/100.0 );
if( m_bAutoAdjust ){
m_bAutoAdjust = false;
m_pbAutoCheck->Invalidate();
f_MM_SetRecordAutoAdjust( m_bAutoAdjust );
}
}
//---------------------------------------------------------------------------
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 TMicSetForm::BeginRecordTest(bool bStart)
{
if( bStart ){
HRESULT hr = f_MM_RecordTest( Handle );
if( hr==S_OK ){
if( m_bAutoAdjust ){
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 __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::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->Enabled)
msg += "输入";
if(errPlay>1 && m_cbRecDevOrOutput->Enabled)
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::ASIOMouseDown(TObject *Sender, TMouseButton Button,
TShiftState Shift, int X, int Y)
{
if( Button==mbLeft ){
if( m_PopupMenu ){
delete m_PopupMenu;
m_PopupMenu = NULL;
}
m_PopupMenu = new TPopMenu(NULL);
m_PopupMenu->CreateCustomMenuItem( "显示面板", DoShowPanel );
m_PopupMenu->CreateCustomMenuItem( "重启设备", DoRestart );
TPoint point( m_lblASIO->Left, m_lblASIO->Top+m_lblASIO->Height );
point = ClientToScreen(point);
m_PopupMenu->Popup( point.X, point.Y );
}
}
//---------------------------------------------------------------------------
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::DeviceTypeClick(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( 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;
}
//---------------------------------------------------------------------------