new feature: soundcard selection
This commit is contained in:
parent
d72746279d
commit
1c2535db16
8 changed files with 274 additions and 104 deletions
|
@ -1,5 +1,5 @@
|
|||
/******************************************************************************\
|
||||
* Copyright (c) 2004-2005
|
||||
* Copyright (c) 2004-2008
|
||||
*
|
||||
* Author(s):
|
||||
* Volker Fischer, Alexander Kurpiers
|
||||
|
@ -53,15 +53,11 @@ public:
|
|||
{}
|
||||
virtual ~CSound() {Close();}
|
||||
|
||||
/* Not implemented yet, always return one device and default string */
|
||||
int GetNumDev() {return 1;}
|
||||
void SetOutDev(int iNewDev) {}
|
||||
void SetInDev(int iNewDev) {}
|
||||
|
||||
/* Return invalid device ID which is the same as using "wave mapper" which
|
||||
we assume here to be used */
|
||||
int GetOutDev() {return 1;}
|
||||
int GetInDev() {return 1;}
|
||||
// not implemented yet, always return one device and default string
|
||||
int GetNumDev() { return 1; }
|
||||
std::string GetDeviceName ( const int iDiD ) { return "wave mapper"; }
|
||||
int SetDev ( const int iNewDev ) {} // dummy
|
||||
int GetDev() { return 0; }
|
||||
|
||||
#if WITH_SOUND
|
||||
void SetInNumBuf(int iNewNum);
|
||||
|
|
|
@ -108,6 +108,14 @@ CClientSettingsDlg::CClientSettingsDlg ( CClient* pNCliP, QWidget* parent,
|
|||
double ( iCurNetBufSiFactOut * MIN_BLOCK_DURATION_MS), 'f', 2 ) +
|
||||
" ms" );
|
||||
|
||||
// init combo box containing all available sound cards in the system
|
||||
cbSoundcard->clear();
|
||||
for ( int iSndDevIdx = 0; iSndDevIdx < pClient->GetSndInterface()->GetNumDev(); iSndDevIdx++ )
|
||||
{
|
||||
cbSoundcard->addItem ( pClient->GetSndInterface()->GetDeviceName ( iSndDevIdx ).c_str() );
|
||||
}
|
||||
cbSoundcard->setCurrentIndex ( pClient->GetSndInterface()->GetDev() );
|
||||
|
||||
// "OpenChatOnNewMessage" check box
|
||||
if ( pClient->GetOpenChatOnNewMessage() )
|
||||
{
|
||||
|
@ -164,6 +172,10 @@ CClientSettingsDlg::CClientSettingsDlg ( CClient* pNCliP, QWidget* parent,
|
|||
QObject::connect ( cbOpenChatOnNewMessage, SIGNAL ( stateChanged ( int ) ),
|
||||
this, SLOT ( OnOpenChatOnNewMessageStateChanged ( int ) ) );
|
||||
|
||||
// combo boxes
|
||||
QObject::connect ( cbSoundcard, SIGNAL ( activated ( int ) ),
|
||||
this, SLOT ( OnSoundCrdSelection ( int ) ) );
|
||||
|
||||
// misc
|
||||
QObject::connect ( pClient, SIGNAL ( PingTimeReceived ( int ) ),
|
||||
this, SLOT ( OnPingTimeResult ( int ) ) );
|
||||
|
@ -228,6 +240,23 @@ void CClientSettingsDlg::OnSliderNetBufSiFactOut ( int value )
|
|||
UpdateDisplay();
|
||||
}
|
||||
|
||||
void CClientSettingsDlg::OnSoundCrdSelection ( int iSndDevIdx )
|
||||
{
|
||||
try
|
||||
{
|
||||
pClient->GetSndInterface()->SetDev ( iSndDevIdx );
|
||||
}
|
||||
catch ( CGenErr generr )
|
||||
{
|
||||
QMessageBox::critical ( 0, APP_NAME,
|
||||
QString ( "The selected audio device could not be used because "
|
||||
"of the following error: " ) + generr.GetErrorText(), "Ok", 0 );
|
||||
|
||||
// recover old selection
|
||||
cbSoundcard->setCurrentIndex ( pClient->GetSndInterface()->GetDev() );
|
||||
}
|
||||
}
|
||||
|
||||
void CClientSettingsDlg::OnOpenChatOnNewMessageStateChanged ( int value )
|
||||
{
|
||||
pClient->SetOpenChatOnNewMessage ( value == Qt::Checked );
|
||||
|
|
|
@ -83,4 +83,5 @@ public slots:
|
|||
void OnOpenChatOnNewMessageStateChanged ( int value );
|
||||
void OnAudioCompressionButtonGroupClicked ( QAbstractButton* button );
|
||||
void OnPingTimeResult ( int iPingTime );
|
||||
void OnSoundCrdSelection ( int iSndDevIdx );
|
||||
};
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>478</width>
|
||||
<height>310</height>
|
||||
<width>506</width>
|
||||
<height>329</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
|
@ -723,6 +723,33 @@
|
|||
<string>Misc</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<item>
|
||||
<layout class="QVBoxLayout" >
|
||||
<item>
|
||||
<widget class="QLabel" name="lSoundcard" >
|
||||
<property name="text" >
|
||||
<string>Soundcard</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="cbSoundcard" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy vsizetype="Fixed" hsizetype="Minimum" >
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
<width>153</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<item>
|
||||
|
@ -733,7 +760,7 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label" >
|
||||
<widget class="QLabel" name="lOpenChat" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
|
||||
<horstretch>0</horstretch>
|
||||
|
@ -796,7 +823,7 @@
|
|||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<item>
|
||||
<widget class="QLabel" name="TextLabel1_3" >
|
||||
<widget class="QLabel" name="lPingTime" >
|
||||
<property name="text" >
|
||||
<string>Ping Time:</string>
|
||||
</property>
|
||||
|
@ -863,7 +890,7 @@
|
|||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="TextLabel1_2" >
|
||||
<widget class="QLabel" name="lProtocolStat" >
|
||||
<property name="text" >
|
||||
<string>Protocol Status:</string>
|
||||
</property>
|
||||
|
|
|
@ -81,6 +81,9 @@
|
|||
// number of ticks of audio in/out buffer sliders
|
||||
# define AUD_SLIDER_LENGTH 8
|
||||
|
||||
// maximum number of recognized sound cards installed in the system
|
||||
#define MAX_NUMBER_SOUND_CARDS 10
|
||||
|
||||
// maximum number of internet connections (channels)
|
||||
// if you want to change this paramter, there has to be done code modifications
|
||||
// on other places, too! The code tag "MAX_NUM_CHANNELS_TAG" shows these places
|
||||
|
|
|
@ -77,10 +77,24 @@ void CSettings::ReadIniFile ( const QString& sFileName )
|
|||
pClient->SetReverbOnLeftChan ( bValue );
|
||||
}
|
||||
|
||||
// sound card selection
|
||||
// special case with this setting: the sound card initialization depends on this setting
|
||||
// call, therefore, if no setting file parameter could be retrieved, the sound card is
|
||||
// initialized with a default setting defined here
|
||||
if ( GetNumericIniSet ( IniXMLDocument, "client", "auddevidx", 1, MAX_NUMBER_SOUND_CARDS, iValue ) )
|
||||
{
|
||||
pClient->GetSndInterface()->SetDev ( iValue );
|
||||
}
|
||||
else
|
||||
{
|
||||
// default setting: use first sound card in system
|
||||
pClient->GetSndInterface()->SetDev ( 0 );
|
||||
}
|
||||
|
||||
// sound card in number of buffers
|
||||
if ( GetNumericIniSet ( IniXMLDocument, "client", "audinbuf", 1, AUD_SLIDER_LENGTH, iValue ) )
|
||||
{
|
||||
pClient->GetSndInterface()->SetInNumBuf( iValue );
|
||||
pClient->GetSndInterface()->SetInNumBuf ( iValue );
|
||||
}
|
||||
|
||||
// sound card out number of buffers
|
||||
|
@ -156,6 +170,9 @@ void CSettings::WriteIniFile ( const QString& sFileName )
|
|||
// reverberation channel assignment
|
||||
SetFlagIniSet ( IniXMLDocument, "client", "reverblchan", pClient->IsReverbOnLeftChan() );
|
||||
|
||||
// sound card selection
|
||||
SetNumericIniSet ( IniXMLDocument, "client", "auddevidx", pClient->GetSndInterface()->GetDev() );
|
||||
|
||||
// sound card in number of buffers
|
||||
SetNumericIniSet ( IniXMLDocument, "client", "audinbuf", pClient->GetSndInterface()->GetInNumBuf() );
|
||||
|
||||
|
|
|
@ -249,6 +249,150 @@ void CSound::SetOutNumBuf ( int iNewNum )
|
|||
/******************************************************************************\
|
||||
* Common *
|
||||
\******************************************************************************/
|
||||
void CSound::SetDev ( const int iNewDev )
|
||||
{
|
||||
// check if an ASIO driver was already initialized
|
||||
if ( lCurDev >= 0 )
|
||||
{
|
||||
// a device was already been initialized and is used, kill working
|
||||
// thread and clean up
|
||||
// set event to ensure that thread leaves the waiting function
|
||||
if ( m_ASIOEvent != NULL )
|
||||
{
|
||||
SetEvent ( m_ASIOEvent );
|
||||
}
|
||||
|
||||
// wait for the thread to terminate
|
||||
Sleep ( 500 );
|
||||
|
||||
// stop audio and dispose ASIO buffers
|
||||
ASIOStop();
|
||||
ASIODisposeBuffers();
|
||||
|
||||
// remove old driver
|
||||
ASIOExit();
|
||||
asioDrivers->removeCurrentDriver();
|
||||
|
||||
const std::string strErrorMessage = LoadAndInitializeDriver ( iNewDev );
|
||||
|
||||
if ( !strErrorMessage.empty() )
|
||||
{
|
||||
// loading and initializing the new driver failed, go back to original
|
||||
// driver and display error message
|
||||
LoadAndInitializeDriver ( lCurDev );
|
||||
|
||||
throw CGenErr ( strErrorMessage.c_str() );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is the first time a driver is to be initialized, we first try
|
||||
// to load the selected driver, if this fails, we try to load the first
|
||||
// available driver in the system. If this fails, too, we throw an error
|
||||
// that no driver is available -> it does not make sense to start the llcon
|
||||
// software if no audio hardware is available
|
||||
const std::string strErrorMessage = LoadAndInitializeDriver ( iNewDev );
|
||||
|
||||
if ( !strErrorMessage.empty() )
|
||||
{
|
||||
// loading and initializing the new driver failed, try to find at
|
||||
// least one usable driver
|
||||
if ( !LoadAndInitializeFirstValidDriver() )
|
||||
{
|
||||
throw CGenErr ( "No usable ASIO audio device (driver) found." );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string CSound::LoadAndInitializeDriver ( const int iDriverIdx )
|
||||
{
|
||||
// load driver
|
||||
loadAsioDriver ( cDriverNames[iDriverIdx] );
|
||||
if ( ASIOInit ( &driverInfo ) != ASE_OK )
|
||||
{
|
||||
// clean up and return error string
|
||||
asioDrivers->removeCurrentDriver();
|
||||
return "The audio driver could not be initialized.";
|
||||
}
|
||||
|
||||
// check the number of available channels
|
||||
long lNumInChan;
|
||||
long lNumOutChan;
|
||||
ASIOGetChannels ( &lNumInChan, &lNumOutChan );
|
||||
if ( ( lNumInChan < NUM_IN_OUT_CHANNELS ) ||
|
||||
( lNumOutChan < NUM_IN_OUT_CHANNELS ) )
|
||||
{
|
||||
// clean up and return error string
|
||||
ASIOExit();
|
||||
asioDrivers->removeCurrentDriver();
|
||||
return "The audio device does not support the "
|
||||
"required number of channels.";
|
||||
}
|
||||
|
||||
// set the sample rate and check if sample rate is supported
|
||||
ASIOSetSampleRate ( SND_CRD_SAMPLE_RATE );
|
||||
|
||||
ASIOSampleRate sampleRate;
|
||||
ASIOGetSampleRate ( &sampleRate );
|
||||
if ( sampleRate != SND_CRD_SAMPLE_RATE )
|
||||
{
|
||||
// clean up and return error string
|
||||
ASIOExit();
|
||||
asioDrivers->removeCurrentDriver();
|
||||
return "The audio device does not support the "
|
||||
"required sample rate.";
|
||||
}
|
||||
|
||||
// query the usable buffer sizes
|
||||
ASIOGetBufferSize ( &HWBufferInfo.lMinSize,
|
||||
&HWBufferInfo.lMaxSize,
|
||||
&HWBufferInfo.lPreferredSize,
|
||||
&HWBufferInfo.lGranularity );
|
||||
|
||||
// check wether the driver requires the ASIOOutputReady() optimization
|
||||
// (can be used by the driver to reduce output latency by one block)
|
||||
bASIOPostOutput = ( ASIOOutputReady() == ASE_OK );
|
||||
|
||||
// store ID of selected driver
|
||||
lCurDev = iDriverIdx;
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
bool CSound::LoadAndInitializeFirstValidDriver()
|
||||
{
|
||||
// load and initialize first valid ASIO driver
|
||||
bool bValidDriverDetected = false;
|
||||
int iCurDriverIdx = 0;
|
||||
|
||||
// try all available drivers in the system ("lNumDevs" devices)
|
||||
while ( !bValidDriverDetected && iCurDriverIdx < lNumDevs )
|
||||
{
|
||||
if ( loadAsioDriver ( cDriverNames[iCurDriverIdx] ) )
|
||||
{
|
||||
if ( ASIOInit ( &driverInfo ) == ASE_OK )
|
||||
{
|
||||
// initialization was successful
|
||||
bValidDriverDetected = true;
|
||||
|
||||
// store ID of selected driver
|
||||
lCurDev = iCurDriverIdx;
|
||||
}
|
||||
else
|
||||
{
|
||||
// driver could not be loaded, free memory
|
||||
asioDrivers->removeCurrentDriver();
|
||||
}
|
||||
}
|
||||
|
||||
// try next driver
|
||||
iCurDriverIdx++;
|
||||
}
|
||||
|
||||
return bValidDriverDetected;
|
||||
}
|
||||
|
||||
void CSound::InitRecordingAndPlayback ( int iNewBufferSize )
|
||||
{
|
||||
int i;
|
||||
|
@ -429,8 +573,6 @@ void CSound::Close()
|
|||
|
||||
CSound::CSound()
|
||||
{
|
||||
int i;
|
||||
|
||||
// init number of sound buffers
|
||||
iNewNumSndBufIn = NUM_SOUND_BUFFERS_IN;
|
||||
iCurNumSndBufIn = NUM_SOUND_BUFFERS_IN;
|
||||
|
@ -441,85 +583,26 @@ CSound::CSound()
|
|||
m_ASIOEvent = NULL;
|
||||
|
||||
// get available ASIO driver names in system
|
||||
char* cDriverNames[MAX_NUMBER_SOUND_CARDS];
|
||||
for ( i = 0; i < MAX_NUMBER_SOUND_CARDS; i++ )
|
||||
for ( int i = 0; i < MAX_NUMBER_SOUND_CARDS; i++ )
|
||||
{
|
||||
cDriverNames[i] = new char[32];
|
||||
}
|
||||
|
||||
loadAsioDriver ( "dummy" ); // to initialize external object
|
||||
const long lNumDetDriv =
|
||||
asioDrivers->getDriverNames ( cDriverNames, MAX_NUMBER_SOUND_CARDS );
|
||||
|
||||
|
||||
// load and initialize first valid ASIO driver
|
||||
bool bValidDriverDetected = false;
|
||||
int iCurDriverIdx = 0;
|
||||
|
||||
while ( !bValidDriverDetected && iCurDriverIdx < lNumDetDriv )
|
||||
{
|
||||
if ( loadAsioDriver ( cDriverNames[iCurDriverIdx] ) )
|
||||
{
|
||||
if ( ASIOInit ( &driverInfo ) == ASE_OK )
|
||||
{
|
||||
bValidDriverDetected = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// driver could not be loaded, free memory
|
||||
asioDrivers->removeCurrentDriver();
|
||||
}
|
||||
}
|
||||
|
||||
// try next driver
|
||||
iCurDriverIdx++;
|
||||
}
|
||||
lNumDevs = asioDrivers->getDriverNames ( cDriverNames, MAX_NUMBER_SOUND_CARDS );
|
||||
|
||||
// in case we do not have a driver available, throw error
|
||||
if ( !bValidDriverDetected )
|
||||
if ( lNumDevs == 0 )
|
||||
{
|
||||
throw CGenErr ( "No suitable ASIO audio device found." );
|
||||
throw CGenErr ( "No ASIO audio device (driver) found." );
|
||||
}
|
||||
|
||||
asioDrivers->removeCurrentDriver();
|
||||
|
||||
// TEST we only use one driver for a first try
|
||||
iNumDevs = 1;
|
||||
pstrDevices[0] = driverInfo.name;
|
||||
// init device index with illegal value to show that driver is not initialized
|
||||
lCurDev = -1;
|
||||
|
||||
|
||||
// check the number of available channels
|
||||
long lNumInChan;
|
||||
long lNumOutChan;
|
||||
ASIOGetChannels ( &lNumInChan, &lNumOutChan );
|
||||
if ( ( lNumInChan < NUM_IN_OUT_CHANNELS ) ||
|
||||
( lNumOutChan < NUM_IN_OUT_CHANNELS ) )
|
||||
{
|
||||
throw CGenErr ( "The audio device does not support the "
|
||||
"required number of channels." );
|
||||
}
|
||||
|
||||
// query the usable buffer sizes
|
||||
ASIOGetBufferSize ( &HWBufferInfo.lMinSize,
|
||||
&HWBufferInfo.lMaxSize,
|
||||
&HWBufferInfo.lPreferredSize,
|
||||
&HWBufferInfo.lGranularity );
|
||||
|
||||
// set the sample rate and check if sample rate is supported
|
||||
ASIOSetSampleRate ( SND_CRD_SAMPLE_RATE );
|
||||
|
||||
ASIOSampleRate sampleRate;
|
||||
ASIOGetSampleRate ( &sampleRate );
|
||||
if ( sampleRate != SND_CRD_SAMPLE_RATE )
|
||||
{
|
||||
throw CGenErr ( "The audio device does not support the "
|
||||
"required sample rate." );
|
||||
}
|
||||
|
||||
// check wether the driver requires the ASIOOutputReady() optimization
|
||||
// (can be used by the driver to reduce output latency by one block)
|
||||
bASIOPostOutput = ( ASIOOutputReady() == ASE_OK );
|
||||
|
||||
// set up the asioCallback structure and create the ASIO data buffer
|
||||
// set up the asioCallback structure
|
||||
asioCallbacks.bufferSwitch = &bufferSwitch;
|
||||
asioCallbacks.sampleRateDidChange = &sampleRateChanged;
|
||||
asioCallbacks.asioMessage = &asioMessages;
|
||||
|
@ -533,9 +616,9 @@ pstrDevices[0] = driverInfo.name;
|
|||
// create event
|
||||
m_ASIOEvent = CreateEvent ( NULL, FALSE, FALSE, NULL );
|
||||
|
||||
// init flags
|
||||
bChangParamIn = false;
|
||||
bChangParamOut = false;
|
||||
// init flags (initiate init for first run)
|
||||
bChangParamIn = true;
|
||||
bChangParamOut = true;
|
||||
}
|
||||
|
||||
CSound::~CSound()
|
||||
|
|
|
@ -50,9 +50,6 @@
|
|||
#define NUM_SOUND_BUFFERS_IN 4
|
||||
#define NUM_SOUND_BUFFERS_OUT 4
|
||||
|
||||
// maximum number of recognized sound cards installed in the system
|
||||
#define MAX_NUMBER_SOUND_CARDS 10
|
||||
|
||||
|
||||
/* Classes ********************************************************************/
|
||||
#ifdef USE_ASIO_SND_INTERFACE
|
||||
|
@ -71,26 +68,36 @@ public:
|
|||
CSound();
|
||||
virtual ~CSound();
|
||||
|
||||
void InitRecording ( int iNewBufferSize, bool bNewBlocking = true ) { bBlockingRec = bNewBlocking; InitRecordingAndPlayback ( iNewBufferSize ); }
|
||||
void InitPlayback ( int iNewBufferSize, bool bNewBlocking = false ) { bBlockingPlay = bNewBlocking; InitRecordingAndPlayback ( iNewBufferSize ); }
|
||||
void InitRecording ( const int iNewBufferSize, const bool bNewBlocking = true )
|
||||
{
|
||||
bBlockingRec = bNewBlocking;
|
||||
InitRecordingAndPlayback ( iNewBufferSize );
|
||||
}
|
||||
void InitPlayback ( const int iNewBufferSize, const bool bNewBlocking = false )
|
||||
{
|
||||
bBlockingPlay = bNewBlocking;
|
||||
InitRecordingAndPlayback ( iNewBufferSize );
|
||||
}
|
||||
bool Read ( CVector<short>& psData );
|
||||
bool Write ( CVector<short>& psData );
|
||||
|
||||
int GetNumDev() { return iNumDevs; }
|
||||
std::string GetDeviceName ( int iDiD ) { return pstrDevices[iDiD]; }
|
||||
void SetOutDev ( int iNewDev ) {} // not supported
|
||||
int GetOutDev() { return 0; } // not supported
|
||||
void SetInDev ( int iNewDev ) {} // not supported
|
||||
int GetInDev() { return 0; } // not supported
|
||||
void SetOutNumBuf ( int iNewNum );
|
||||
int GetNumDev() { return lNumDevs; }
|
||||
std::string GetDeviceName ( const int iDiD ) { return cDriverNames[iDiD]; }
|
||||
|
||||
void SetDev ( const int iNewDev );
|
||||
int GetDev() { return lCurDev; }
|
||||
|
||||
void SetOutNumBuf ( const int iNewNum );
|
||||
int GetOutNumBuf();
|
||||
void SetInNumBuf ( int iNewNum );
|
||||
void SetInNumBuf ( const int iNewNum );
|
||||
int GetInNumBuf();
|
||||
|
||||
void Close();
|
||||
|
||||
protected:
|
||||
void InitRecordingAndPlayback ( int iNewBufferSize );
|
||||
bool LoadAndInitializeFirstValidDriver();
|
||||
std::string LoadAndInitializeDriver ( const int iIdx );
|
||||
void InitRecordingAndPlayback ( const int iNewBufferSize );
|
||||
|
||||
// audio hardware buffer info
|
||||
struct sHWBufferInfo
|
||||
|
@ -107,8 +114,10 @@ protected:
|
|||
static void sampleRateChanged ( ASIOSampleRate sRate ) {}
|
||||
static long asioMessages ( long selector, long value, void* message, double* opt );
|
||||
|
||||
int iNumDevs;
|
||||
std::string pstrDevices[MAX_NUMBER_SOUND_CARDS];
|
||||
long lNumDevs;
|
||||
long lCurDev;
|
||||
char* cDriverNames[MAX_NUMBER_SOUND_CARDS];
|
||||
|
||||
bool bChangParamIn;
|
||||
bool bChangParamOut;
|
||||
|
||||
|
@ -131,6 +140,11 @@ public:
|
|||
|
||||
int GetNumDev() { return iNumDevs; }
|
||||
std::string GetDeviceName ( int iDiD ) { return pstrDevices[iDiD]; }
|
||||
|
||||
// dummy functions
|
||||
int SetDev ( const int iNewDev ) {}
|
||||
int GetDev() { return 0; }
|
||||
|
||||
void SetOutDev ( int iNewDev );
|
||||
int GetOutDev() { return iCurOutDev; }
|
||||
void SetInDev ( int iNewDev );
|
||||
|
|
Loading…
Reference in a new issue