better handling of sound card reinits

This commit is contained in:
Volker Fischer 2012-01-28 11:51:14 +00:00
parent e2c98e2384
commit 3f75913dca
6 changed files with 1962 additions and 1975 deletions

View File

@ -256,7 +256,7 @@ int CSound::bufferSizeCallback ( jack_nframes_t, void *arg )
{ {
CSound* pSound = reinterpret_cast<CSound*> ( arg ); CSound* pSound = reinterpret_cast<CSound*> ( arg );
pSound->EmitReinitRequestSignal(); pSound->EmitReinitRequestSignal ( RS_ONLY_RESTART_AND_INIT );
return 0; // zero on success, non-zero on error return 0; // zero on success, non-zero on error
} }

View File

@ -498,11 +498,7 @@ OSStatus CSound::deviceNotification ( AudioDeviceID,
// xrun handling (it is important to act on xruns under CoreAudio // xrun handling (it is important to act on xruns under CoreAudio
// since it seems that the xrun situation stays stable for a // since it seems that the xrun situation stays stable for a
// while and would give you a long time bad audio // while and would give you a long time bad audio
pSound->EmitReinitRequestSignal ( RS_ONLY_RESTART );
// TEST we reuse the signal which was intended only for Windows OS but
// with a modification in the client (see client.cpp)
pSound->EmitReinitRequestSignal();
} }
return noErr; return noErr;

View File

@ -128,8 +128,8 @@ CClient::CClient ( const quint16 iPortNumber ) :
SIGNAL ( CLPingWithNumClientsReceived ( CHostAddress, int, int ) ), SIGNAL ( CLPingWithNumClientsReceived ( CHostAddress, int, int ) ),
this, SLOT ( OnCLPingWithNumClientsReceived ( CHostAddress, int, int ) ) ); this, SLOT ( OnCLPingWithNumClientsReceived ( CHostAddress, int, int ) ) );
QObject::connect ( &Sound, SIGNAL ( ReinitRequest() ), QObject::connect ( &Sound, SIGNAL ( ReinitRequest ( ESndCrdResetType ) ),
this, SLOT ( OnSndCrdReinitRequest() ) ); this, SLOT ( OnSndCrdReinitRequest ( ESndCrdResetType ) ) );
} }
void CClient::OnSendProtMessage ( CVector<uint8_t> vecMessage ) void CClient::OnSendProtMessage ( CVector<uint8_t> vecMessage )
@ -443,7 +443,7 @@ void CClient::SetSndCrdRightOutputChannel ( const int iNewChan )
} }
} }
void CClient::OnSndCrdReinitRequest() void CClient::OnSndCrdReinitRequest ( ESndCrdResetType eSndCrdResetType )
{ {
// if client was running then first // if client was running then first
// stop it and restart again after new initialization // stop it and restart again after new initialization
@ -453,31 +453,20 @@ void CClient::OnSndCrdReinitRequest()
Sound.Stop(); Sound.Stop();
} }
// reinit the driver (we use the currently selected driver) and // perform reinit request as indicated by the request type parameter
// init client object, too if ( eSndCrdResetType != RS_ONLY_RESTART )
{
// TODO possible bug: In ASIO driver if set dev is called, the driver is if ( eSndCrdResetType != RS_ONLY_RESTART_AND_INIT )
// unloaded. See ASIO manual: "Note: A host application has to defer {
// processing of these notification to a later "secure" time as the // reinit the driver if requested
// driver has finish its processing of the notification. Especially on // (we use the currently selected driver)
// the kAsioResetRequest it is a bad idea to unload the driver during
// the asioMessage callback since the callback has to return back into
// the driver, which is no longer present."
// TODO write separate driver reset function in sound base instead
// of doing setdev with the old driver ID -> avoid unloading driver
Sound.SetDev ( Sound.GetDev() ); Sound.SetDev ( Sound.GetDev() );
}
// This is a test. We reuse the SndCrdReinitRequest which was // init client object (must always be performed if the driver
// initially only intended for the Windows OS. But for Mac we // was changed)
// must not call the client Init function to work properly, therefore
// we add the preprocesser check here
// TODO better solution was to introduce a new signal in the sound base
// and a new signal handler in the client
#if !defined ( __APPLE__ ) && !defined ( __MACOSX )
Init(); Init();
#endif }
if ( bWasRunning ) if ( bWasRunning )
{ {

View File

@ -335,7 +335,7 @@ public slots:
int iMs, int iMs,
int iNumClients ); int iNumClients );
void OnSndCrdReinitRequest(); void OnSndCrdReinitRequest ( ESndCrdResetType eSndCrdResetType );
signals: signals:
void ConClientListMesReceived ( CVector<CChannelShortInfo> vecChanInfo ); void ConClientListMesReceived ( CVector<CChannelShortInfo> vecChanInfo );

View File

@ -32,6 +32,16 @@
#include "util.h" #include "util.h"
// TODO better solution with enum definition
// problem: in signals it seems not to work to use CSoundBase::ESndCrdResetType
enum ESndCrdResetType
{
RS_ONLY_RESTART,
RS_ONLY_RESTART_AND_INIT,
RS_RELOAD_RESTART_AND_INIT
};
/* Classes ********************************************************************/ /* Classes ********************************************************************/
class CSoundBase : public QThread class CSoundBase : public QThread
{ {
@ -73,7 +83,8 @@ public:
// TODO this should be protected but since it is used // TODO this should be protected but since it is used
// in a callback function it has to be public -> better solution // in a callback function it has to be public -> better solution
void EmitReinitRequestSignal() { emit ReinitRequest(); } void EmitReinitRequestSignal ( const ESndCrdResetType eSndCrdResetType )
{ emit ReinitRequest ( eSndCrdResetType ); }
protected: protected:
// driver handling // driver handling
@ -109,7 +120,7 @@ protected:
QString strDriverNames[MAX_NUMBER_SOUND_CARDS]; QString strDriverNames[MAX_NUMBER_SOUND_CARDS];
signals: signals:
void ReinitRequest(); void ReinitRequest ( ESndCrdResetType eSndCrdResetType );
}; };
#endif /* !defined ( SOUNDBASE_HOIHGEH8_3_4344456456345634565KJIUHF1912__INCLUDED_ ) */ #endif /* !defined ( SOUNDBASE_HOIHGEH8_3_4344456456345634565KJIUHF1912__INCLUDED_ ) */

View File

@ -959,6 +959,7 @@ long CSound::asioMessages ( long selector,
double* ) double* )
{ {
long ret = 0; long ret = 0;
switch ( selector ) switch ( selector )
{ {
case kAsioEngineVersion: case kAsioEngineVersion:
@ -968,26 +969,16 @@ long CSound::asioMessages ( long selector,
// both messages might be send if the buffer size changes // both messages might be send if the buffer size changes
case kAsioBufferSizeChange: case kAsioBufferSizeChange:
pSound->EmitReinitRequestSignal ( RS_ONLY_RESTART_AND_INIT );
ret = 1L; // 1L if request is accepted or 0 otherwise
break;
case kAsioResetRequest: case kAsioResetRequest:
pSound->EmitReinitRequestSignal ( RS_RELOAD_RESTART_AND_INIT );
// TODO implement separate ASIO reset function in base class!
// kAsioBufferSizeChange:
// Informs the application that the driver has a new preferred buffer size.
//
// kAsioResetRequest:
// Requests a driver reset. If accepted, this will close the driver
// (ASIOExit() ) and re-open it again (ASIOInit() etc.) at the next
// "safe" time (usually during the application IDLE time). Some
// drivers need to reconfigure for instance when the sample rate
// changes, or some basic changes have been made in ASIOControlPanel().
pSound->EmitReinitRequestSignal();
ret = 1L; // 1L if request is accepted or 0 otherwise ret = 1L; // 1L if request is accepted or 0 otherwise
break; break;
} }
return ret; return ret;
} }