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

@ -1,271 +1,271 @@
/******************************************************************************\ /******************************************************************************\
* Copyright (c) 2004-2011 * Copyright (c) 2004-2011
* *
* Author(s): * Author(s):
* Volker Fischer * Volker Fischer
* *
* This code is based on the simple_client example of the Jack audio interface. * This code is based on the simple_client example of the Jack audio interface.
****************************************************************************** ******************************************************************************
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software * the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later * Foundation; either version 2 of the License, or (at your option) any later
* version. * version.
* *
* This program is distributed in the hope that it will be useful, but WITHOUT * This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details. * details.
* *
* You should have received a copy of the GNU General Public License along with * You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., * this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* *
\******************************************************************************/ \******************************************************************************/
#include "sound.h" #include "sound.h"
#ifdef WITH_SOUND #ifdef WITH_SOUND
void CSound::OpenJack() void CSound::OpenJack()
{ {
jack_status_t JackStatus; jack_status_t JackStatus;
// try to become a client of the JACK server // try to become a client of the JACK server
pJackClient = jack_client_open ( "llcon", JackNullOption, &JackStatus ); pJackClient = jack_client_open ( "llcon", JackNullOption, &JackStatus );
if ( pJackClient == NULL ) if ( pJackClient == NULL )
{ {
throw CGenErr ( tr ( "Jack server not running" ) ); throw CGenErr ( tr ( "Jack server not running" ) );
} }
// tell the JACK server to call "process()" whenever // tell the JACK server to call "process()" whenever
// there is work to be done // there is work to be done
jack_set_process_callback ( pJackClient, process, this ); jack_set_process_callback ( pJackClient, process, this );
// register a "buffer size changed" callback function // register a "buffer size changed" callback function
jack_set_buffer_size_callback ( pJackClient, bufferSizeCallback, this ); jack_set_buffer_size_callback ( pJackClient, bufferSizeCallback, this );
// register shutdown callback function // register shutdown callback function
jack_on_shutdown ( pJackClient, shutdownCallback, this ); jack_on_shutdown ( pJackClient, shutdownCallback, this );
// TEST check sample rate, if not correct, just fire error // TEST check sample rate, if not correct, just fire error
if ( jack_get_sample_rate ( pJackClient ) != SYSTEM_SAMPLE_RATE_HZ ) if ( jack_get_sample_rate ( pJackClient ) != SYSTEM_SAMPLE_RATE_HZ )
{ {
throw CGenErr ( tr ( "Jack server sample rate is different from " throw CGenErr ( tr ( "Jack server sample rate is different from "
"required one" ) ); "required one" ) );
} }
// create four ports (two for input, two for output -> stereo) // create four ports (two for input, two for output -> stereo)
input_port_left = jack_port_register ( pJackClient, "input left", input_port_left = jack_port_register ( pJackClient, "input left",
JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0 ); JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0 );
input_port_right = jack_port_register ( pJackClient, "input right", input_port_right = jack_port_register ( pJackClient, "input right",
JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0 ); JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0 );
output_port_left = jack_port_register ( pJackClient, "output left", output_port_left = jack_port_register ( pJackClient, "output left",
JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0 ); JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0 );
output_port_right = jack_port_register ( pJackClient, "output right", output_port_right = jack_port_register ( pJackClient, "output right",
JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0 ); JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0 );
if ( ( input_port_left == NULL ) || if ( ( input_port_left == NULL ) ||
( input_port_right == NULL ) || ( input_port_right == NULL ) ||
( output_port_left == NULL ) || ( output_port_left == NULL ) ||
( output_port_right == NULL ) ) ( output_port_right == NULL ) )
{ {
throw CGenErr ( tr ( "Jack port registering failed" ) ); throw CGenErr ( tr ( "Jack port registering failed" ) );
} }
const char** ports; const char** ports;
// tell the JACK server that we are ready to roll // tell the JACK server that we are ready to roll
if ( jack_activate ( pJackClient ) ) if ( jack_activate ( pJackClient ) )
{ {
throw CGenErr ( tr ( "Cannot activate client" ) ); throw CGenErr ( tr ( "Cannot activate client" ) );
} }
// connect the ports, note: you cannot do this before // connect the ports, note: you cannot do this before
// the client is activated, because we cannot allow // the client is activated, because we cannot allow
// connections to be made to clients that are not // connections to be made to clients that are not
// running // running
if ( ( ports = jack_get_ports ( pJackClient, NULL, NULL, if ( ( ports = jack_get_ports ( pJackClient, NULL, NULL,
JackPortIsPhysical | JackPortIsOutput ) ) == NULL ) JackPortIsPhysical | JackPortIsOutput ) ) == NULL )
{ {
throw CGenErr ( tr ( "Cannot find any physical capture ports" ) ); throw CGenErr ( tr ( "Cannot find any physical capture ports" ) );
} }
if ( !ports[1] ) if ( !ports[1] )
{ {
throw CGenErr ( tr ( "Cannot find enough physical capture ports" ) ); throw CGenErr ( tr ( "Cannot find enough physical capture ports" ) );
} }
if ( jack_connect ( pJackClient, ports[0], jack_port_name ( input_port_left ) ) ) if ( jack_connect ( pJackClient, ports[0], jack_port_name ( input_port_left ) ) )
{ {
throw CGenErr ( tr ( "Cannot connect input ports" ) ); throw CGenErr ( tr ( "Cannot connect input ports" ) );
} }
if ( jack_connect ( pJackClient, ports[1], jack_port_name ( input_port_right ) ) ) if ( jack_connect ( pJackClient, ports[1], jack_port_name ( input_port_right ) ) )
{ {
throw CGenErr ( tr ( "Cannot connect input ports" ) ); throw CGenErr ( tr ( "Cannot connect input ports" ) );
} }
free ( ports ); free ( ports );
if ( ( ports = jack_get_ports ( pJackClient, NULL, NULL, if ( ( ports = jack_get_ports ( pJackClient, NULL, NULL,
JackPortIsPhysical | JackPortIsInput ) ) == NULL ) JackPortIsPhysical | JackPortIsInput ) ) == NULL )
{ {
throw CGenErr ( tr ( "Cannot find any physical playback ports" ) ); throw CGenErr ( tr ( "Cannot find any physical playback ports" ) );
} }
if ( !ports[1] ) if ( !ports[1] )
{ {
throw CGenErr ( tr ( "Cannot find enough physical playback ports" ) ); throw CGenErr ( tr ( "Cannot find enough physical playback ports" ) );
} }
if ( jack_connect ( pJackClient, jack_port_name ( output_port_left ), ports[0] ) ) if ( jack_connect ( pJackClient, jack_port_name ( output_port_left ), ports[0] ) )
{ {
throw CGenErr ( tr ( "Cannot connect output ports" ) ); throw CGenErr ( tr ( "Cannot connect output ports" ) );
} }
if ( jack_connect ( pJackClient, jack_port_name ( output_port_right ), ports[1] ) ) if ( jack_connect ( pJackClient, jack_port_name ( output_port_right ), ports[1] ) )
{ {
throw CGenErr ( tr ( "Cannot connect output ports" ) ); throw CGenErr ( tr ( "Cannot connect output ports" ) );
} }
free ( ports ); free ( ports );
} }
void CSound::CloseJack() void CSound::CloseJack()
{ {
// deactivate client // deactivate client
jack_deactivate ( pJackClient ); jack_deactivate ( pJackClient );
// unregister ports // unregister ports
jack_port_unregister ( pJackClient, input_port_left ); jack_port_unregister ( pJackClient, input_port_left );
jack_port_unregister ( pJackClient, input_port_right ); jack_port_unregister ( pJackClient, input_port_right );
jack_port_unregister ( pJackClient, output_port_left ); jack_port_unregister ( pJackClient, output_port_left );
jack_port_unregister ( pJackClient, output_port_right ); jack_port_unregister ( pJackClient, output_port_right );
// close client connection to jack server // close client connection to jack server
jack_client_close ( pJackClient ); jack_client_close ( pJackClient );
} }
void CSound::Start() void CSound::Start()
{ {
// call base class // call base class
CSoundBase::Start(); CSoundBase::Start();
} }
void CSound::Stop() void CSound::Stop()
{ {
// call base class // call base class
CSoundBase::Stop(); CSoundBase::Stop();
} }
int CSound::Init ( const int /* iNewPrefMonoBufferSize */ ) int CSound::Init ( const int /* iNewPrefMonoBufferSize */ )
{ {
// try setting buffer size // try setting buffer size
// TODO seems not to work! -> no audio after this operation! // TODO seems not to work! -> no audio after this operation!
//jack_set_buffer_size ( pJackClient, iNewPrefMonoBufferSize ); //jack_set_buffer_size ( pJackClient, iNewPrefMonoBufferSize );
// get actual buffer size // get actual buffer size
iJACKBufferSizeMono = jack_get_buffer_size ( pJackClient ); iJACKBufferSizeMono = jack_get_buffer_size ( pJackClient );
// init base class // init base class
CSoundBase::Init ( iJACKBufferSizeMono ); CSoundBase::Init ( iJACKBufferSizeMono );
// set internal buffer size value and calculate stereo buffer size // set internal buffer size value and calculate stereo buffer size
iJACKBufferSizeStero = 2 * iJACKBufferSizeMono; iJACKBufferSizeStero = 2 * iJACKBufferSizeMono;
// create memory for intermediate audio buffer // create memory for intermediate audio buffer
vecsTmpAudioSndCrdStereo.Init ( iJACKBufferSizeStero ); vecsTmpAudioSndCrdStereo.Init ( iJACKBufferSizeStero );
return iJACKBufferSizeMono; return iJACKBufferSizeMono;
} }
// JACK callbacks -------------------------------------------------------------- // JACK callbacks --------------------------------------------------------------
int CSound::process ( jack_nframes_t nframes, void* arg ) int CSound::process ( jack_nframes_t nframes, void* arg )
{ {
CSound* pSound = reinterpret_cast<CSound*> ( arg ); CSound* pSound = reinterpret_cast<CSound*> ( arg );
int i; int i;
if ( pSound->IsRunning() ) if ( pSound->IsRunning() )
{ {
// get input data pointer // get input data pointer
jack_default_audio_sample_t* in_left = jack_default_audio_sample_t* in_left =
(jack_default_audio_sample_t*) jack_port_get_buffer ( (jack_default_audio_sample_t*) jack_port_get_buffer (
pSound->input_port_left, nframes ); pSound->input_port_left, nframes );
jack_default_audio_sample_t* in_right = jack_default_audio_sample_t* in_right =
(jack_default_audio_sample_t*) jack_port_get_buffer ( (jack_default_audio_sample_t*) jack_port_get_buffer (
pSound->input_port_right, nframes ); pSound->input_port_right, nframes );
// copy input data // copy input data
for ( i = 0; i < pSound->iJACKBufferSizeMono; i++ ) for ( i = 0; i < pSound->iJACKBufferSizeMono; i++ )
{ {
pSound->vecsTmpAudioSndCrdStereo[2 * i] = pSound->vecsTmpAudioSndCrdStereo[2 * i] =
(short) ( in_left[i] * _MAXSHORT ); (short) ( in_left[i] * _MAXSHORT );
pSound->vecsTmpAudioSndCrdStereo[2 * i + 1] = pSound->vecsTmpAudioSndCrdStereo[2 * i + 1] =
(short) ( in_right[i] * _MAXSHORT ); (short) ( in_right[i] * _MAXSHORT );
} }
// call processing callback function // call processing callback function
pSound->ProcessCallback ( pSound->vecsTmpAudioSndCrdStereo ); pSound->ProcessCallback ( pSound->vecsTmpAudioSndCrdStereo );
// get output data pointer // get output data pointer
jack_default_audio_sample_t* out_left = jack_default_audio_sample_t* out_left =
(jack_default_audio_sample_t*) jack_port_get_buffer ( (jack_default_audio_sample_t*) jack_port_get_buffer (
pSound->output_port_left, nframes ); pSound->output_port_left, nframes );
jack_default_audio_sample_t* out_right = jack_default_audio_sample_t* out_right =
(jack_default_audio_sample_t*) jack_port_get_buffer ( (jack_default_audio_sample_t*) jack_port_get_buffer (
pSound->output_port_right, nframes ); pSound->output_port_right, nframes );
// copy output data // copy output data
for ( i = 0; i < pSound->iJACKBufferSizeMono; i++ ) for ( i = 0; i < pSound->iJACKBufferSizeMono; i++ )
{ {
out_left[i] = (jack_default_audio_sample_t) out_left[i] = (jack_default_audio_sample_t)
pSound->vecsTmpAudioSndCrdStereo[2 * i] / _MAXSHORT; pSound->vecsTmpAudioSndCrdStereo[2 * i] / _MAXSHORT;
out_right[i] = (jack_default_audio_sample_t) out_right[i] = (jack_default_audio_sample_t)
pSound->vecsTmpAudioSndCrdStereo[2 * i + 1] / _MAXSHORT; pSound->vecsTmpAudioSndCrdStereo[2 * i + 1] / _MAXSHORT;
} }
} }
else else
{ {
// get output data pointer // get output data pointer
jack_default_audio_sample_t* out_left = jack_default_audio_sample_t* out_left =
(jack_default_audio_sample_t*) jack_port_get_buffer ( (jack_default_audio_sample_t*) jack_port_get_buffer (
pSound->output_port_left, nframes ); pSound->output_port_left, nframes );
jack_default_audio_sample_t* out_right = jack_default_audio_sample_t* out_right =
(jack_default_audio_sample_t*) jack_port_get_buffer ( (jack_default_audio_sample_t*) jack_port_get_buffer (
pSound->output_port_right, nframes ); pSound->output_port_right, nframes );
// clear output data // clear output data
memset ( out_left, memset ( out_left,
0, sizeof ( jack_default_audio_sample_t ) * nframes ); 0, sizeof ( jack_default_audio_sample_t ) * nframes );
memset ( out_right, memset ( out_right,
0, sizeof ( jack_default_audio_sample_t ) * nframes ); 0, sizeof ( jack_default_audio_sample_t ) * nframes );
} }
return 0; // zero on success, non-zero on error return 0; // zero on success, non-zero on error
} }
int CSound::bufferSizeCallback ( jack_nframes_t, void *arg ) 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
} }
void CSound::shutdownCallback ( void* ) void CSound::shutdownCallback ( void* )
{ {
// without a Jack server, our software makes no sense to run, throw // without a Jack server, our software makes no sense to run, throw
// error message // error message
throw CGenErr ( tr ( "Jack server was shut down" ) ); throw CGenErr ( tr ( "Jack server was shut down" ) );
} }
#endif // WITH_SOUND #endif // WITH_SOUND

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

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

@ -1,115 +1,126 @@
/******************************************************************************\ /******************************************************************************\
* Copyright (c) 2004-2011 * Copyright (c) 2004-2011
* *
* Author(s): * Author(s):
* Volker Fischer * Volker Fischer
* *
****************************************************************************** ******************************************************************************
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software * the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later * Foundation; either version 2 of the License, or (at your option) any later
* version. * version.
* *
* This program is distributed in the hope that it will be useful, but WITHOUT * This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details. * details.
* *
* You should have received a copy of the GNU General Public License along with * You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., * this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* *
\******************************************************************************/ \******************************************************************************/
#if !defined ( SOUNDBASE_HOIHGEH8_3_4344456456345634565KJIUHF1912__INCLUDED_ ) #if !defined ( SOUNDBASE_HOIHGEH8_3_4344456456345634565KJIUHF1912__INCLUDED_ )
#define SOUNDBASE_HOIHGEH8_3_4344456456345634565KJIUHF1912__INCLUDED_ #define SOUNDBASE_HOIHGEH8_3_4344456456345634565KJIUHF1912__INCLUDED_
#include <qthread.h> #include <qthread.h>
#include <qstring.h> #include <qstring.h>
#include <qmessagebox.h> #include <qmessagebox.h>
#include "global.h" #include "global.h"
#include "util.h" #include "util.h"
/* Classes ********************************************************************/ // TODO better solution with enum definition
class CSoundBase : public QThread // problem: in signals it seems not to work to use CSoundBase::ESndCrdResetType
{ enum ESndCrdResetType
Q_OBJECT {
RS_ONLY_RESTART,
public: RS_ONLY_RESTART_AND_INIT,
CSoundBase ( const QString& strNewSystemDriverTechniqueName, RS_RELOAD_RESTART_AND_INIT
const bool bNewIsCallbackAudioInterface, };
void (*fpNewProcessCallback) ( CVector<int16_t>& psData, void* pParg ),
void* pParg );
/* Classes ********************************************************************/
virtual int Init ( const int iNewPrefMonoBufferSize ); class CSoundBase : public QThread
virtual void Start(); {
virtual void Stop(); Q_OBJECT
// device selection public:
virtual int GetNumDev() { return lNumDevs; } CSoundBase ( const QString& strNewSystemDriverTechniqueName,
virtual QString GetDeviceName ( const int iDiD ) { return strDriverNames[iDiD]; } const bool bNewIsCallbackAudioInterface,
virtual QString SetDev ( const int ); void (*fpNewProcessCallback) ( CVector<int16_t>& psData, void* pParg ),
virtual int GetDev() { return lCurDev; } void* pParg );
virtual int GetNumInputChannels() { return 2; } virtual int Init ( const int iNewPrefMonoBufferSize );
virtual QString GetInputChannelName ( const int ) { return "Default"; } virtual void Start();
virtual void SetLeftInputChannel ( const int ) {} virtual void Stop();
virtual void SetRightInputChannel ( const int ) {}
virtual int GetLeftInputChannel() { return 0; } // device selection
virtual int GetRightInputChannel() { return 1; } virtual int GetNumDev() { return lNumDevs; }
virtual QString GetDeviceName ( const int iDiD ) { return strDriverNames[iDiD]; }
virtual int GetNumOutputChannels() { return 2; } virtual QString SetDev ( const int );
virtual QString GetOutputChannelName ( const int ) { return "Default"; } virtual int GetDev() { return lCurDev; }
virtual void SetLeftOutputChannel ( const int ) {}
virtual void SetRightOutputChannel ( const int ) {} virtual int GetNumInputChannels() { return 2; }
virtual int GetLeftOutputChannel() { return 0; } virtual QString GetInputChannelName ( const int ) { return "Default"; }
virtual int GetRightOutputChannel() { return 1; } virtual void SetLeftInputChannel ( const int ) {}
virtual void SetRightInputChannel ( const int ) {}
virtual void OpenDriverSetup() {} virtual int GetLeftInputChannel() { return 0; }
virtual int GetRightInputChannel() { return 1; }
bool IsRunning() const { return bRun; }
virtual int GetNumOutputChannels() { return 2; }
// TODO this should be protected but since it is used virtual QString GetOutputChannelName ( const int ) { return "Default"; }
// in a callback function it has to be public -> better solution virtual void SetLeftOutputChannel ( const int ) {}
void EmitReinitRequestSignal() { emit ReinitRequest(); } virtual void SetRightOutputChannel ( const int ) {}
virtual int GetLeftOutputChannel() { return 0; }
protected: virtual int GetRightOutputChannel() { return 1; }
// driver handling
virtual QString LoadAndInitializeDriver ( int ) { return ""; } virtual void OpenDriverSetup() {}
virtual void UnloadCurrentDriver() {}
QVector<QString> LoadAndInitializeFirstValidDriver(); bool IsRunning() const { return bRun; }
// function pointer to callback function // TODO this should be protected but since it is used
void (*fpProcessCallback) ( CVector<int16_t>& psData, void* arg ); // in a callback function it has to be public -> better solution
void* pProcessCallbackArg; void EmitReinitRequestSignal ( const ESndCrdResetType eSndCrdResetType )
{ emit ReinitRequest ( eSndCrdResetType ); }
// callback function call for derived classes
void ProcessCallback ( CVector<int16_t>& psData ) protected:
{ // driver handling
(*fpProcessCallback) ( psData, pProcessCallbackArg ); virtual QString LoadAndInitializeDriver ( int ) { return ""; }
} virtual void UnloadCurrentDriver() {}
QVector<QString> LoadAndInitializeFirstValidDriver();
// these functions should be overwritten by derived class for
// non callback based audio interfaces // function pointer to callback function
virtual bool Read ( CVector<int16_t>& ) { printf ( "no sound!" ); return false; } void (*fpProcessCallback) ( CVector<int16_t>& psData, void* arg );
virtual bool Write ( CVector<int16_t>& ) { printf ( "no sound!" ); return false; } void* pProcessCallbackArg;
void run(); // callback function call for derived classes
bool bRun; void ProcessCallback ( CVector<int16_t>& psData )
{
bool bIsCallbackAudioInterface; (*fpProcessCallback) ( psData, pProcessCallbackArg );
QString strSystemDriverTechniqueName; }
CVector<int16_t> vecsAudioSndCrdStereo; // these functions should be overwritten by derived class for
// non callback based audio interfaces
long lNumDevs; virtual bool Read ( CVector<int16_t>& ) { printf ( "no sound!" ); return false; }
long lCurDev; virtual bool Write ( CVector<int16_t>& ) { printf ( "no sound!" ); return false; }
QString strDriverNames[MAX_NUMBER_SOUND_CARDS];
void run();
signals: bool bRun;
void ReinitRequest();
}; bool bIsCallbackAudioInterface;
QString strSystemDriverTechniqueName;
#endif /* !defined ( SOUNDBASE_HOIHGEH8_3_4344456456345634565KJIUHF1912__INCLUDED_ ) */
CVector<int16_t> vecsAudioSndCrdStereo;
long lNumDevs;
long lCurDev;
QString strDriverNames[MAX_NUMBER_SOUND_CARDS];
signals:
void ReinitRequest ( ESndCrdResetType eSndCrdResetType );
};
#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;
} }