better handling of sound card reinits
This commit is contained in:
parent
e2c98e2384
commit
3f75913dca
6 changed files with 1962 additions and 1975 deletions
542
linux/sound.cpp
542
linux/sound.cpp
|
@ -1,271 +1,271 @@
|
|||
/******************************************************************************\
|
||||
* Copyright (c) 2004-2011
|
||||
*
|
||||
* Author(s):
|
||||
* Volker Fischer
|
||||
*
|
||||
* 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
|
||||
* 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
|
||||
* version.
|
||||
*
|
||||
* 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
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* 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.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
\******************************************************************************/
|
||||
|
||||
#include "sound.h"
|
||||
|
||||
#ifdef WITH_SOUND
|
||||
void CSound::OpenJack()
|
||||
{
|
||||
jack_status_t JackStatus;
|
||||
|
||||
// try to become a client of the JACK server
|
||||
pJackClient = jack_client_open ( "llcon", JackNullOption, &JackStatus );
|
||||
if ( pJackClient == NULL )
|
||||
{
|
||||
throw CGenErr ( tr ( "Jack server not running" ) );
|
||||
}
|
||||
|
||||
// tell the JACK server to call "process()" whenever
|
||||
// there is work to be done
|
||||
jack_set_process_callback ( pJackClient, process, this );
|
||||
|
||||
// register a "buffer size changed" callback function
|
||||
jack_set_buffer_size_callback ( pJackClient, bufferSizeCallback, this );
|
||||
|
||||
// register shutdown callback function
|
||||
jack_on_shutdown ( pJackClient, shutdownCallback, this );
|
||||
|
||||
// TEST check sample rate, if not correct, just fire error
|
||||
if ( jack_get_sample_rate ( pJackClient ) != SYSTEM_SAMPLE_RATE_HZ )
|
||||
{
|
||||
throw CGenErr ( tr ( "Jack server sample rate is different from "
|
||||
"required one" ) );
|
||||
}
|
||||
|
||||
// create four ports (two for input, two for output -> stereo)
|
||||
input_port_left = jack_port_register ( pJackClient, "input left",
|
||||
JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0 );
|
||||
|
||||
input_port_right = jack_port_register ( pJackClient, "input right",
|
||||
JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0 );
|
||||
|
||||
output_port_left = jack_port_register ( pJackClient, "output left",
|
||||
JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0 );
|
||||
|
||||
output_port_right = jack_port_register ( pJackClient, "output right",
|
||||
JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0 );
|
||||
|
||||
if ( ( input_port_left == NULL ) ||
|
||||
( input_port_right == NULL ) ||
|
||||
( output_port_left == NULL ) ||
|
||||
( output_port_right == NULL ) )
|
||||
{
|
||||
throw CGenErr ( tr ( "Jack port registering failed" ) );
|
||||
}
|
||||
|
||||
const char** ports;
|
||||
|
||||
// tell the JACK server that we are ready to roll
|
||||
if ( jack_activate ( pJackClient ) )
|
||||
{
|
||||
throw CGenErr ( tr ( "Cannot activate client" ) );
|
||||
}
|
||||
|
||||
// connect the ports, note: you cannot do this before
|
||||
// the client is activated, because we cannot allow
|
||||
// connections to be made to clients that are not
|
||||
// running
|
||||
if ( ( ports = jack_get_ports ( pJackClient, NULL, NULL,
|
||||
JackPortIsPhysical | JackPortIsOutput ) ) == NULL )
|
||||
{
|
||||
throw CGenErr ( tr ( "Cannot find any physical capture ports" ) );
|
||||
}
|
||||
|
||||
if ( !ports[1] )
|
||||
{
|
||||
throw CGenErr ( tr ( "Cannot find enough physical capture ports" ) );
|
||||
}
|
||||
|
||||
if ( jack_connect ( pJackClient, ports[0], jack_port_name ( input_port_left ) ) )
|
||||
{
|
||||
throw CGenErr ( tr ( "Cannot connect input ports" ) );
|
||||
}
|
||||
if ( jack_connect ( pJackClient, ports[1], jack_port_name ( input_port_right ) ) )
|
||||
{
|
||||
throw CGenErr ( tr ( "Cannot connect input ports" ) );
|
||||
}
|
||||
|
||||
free ( ports );
|
||||
|
||||
if ( ( ports = jack_get_ports ( pJackClient, NULL, NULL,
|
||||
JackPortIsPhysical | JackPortIsInput ) ) == NULL )
|
||||
{
|
||||
throw CGenErr ( tr ( "Cannot find any physical playback ports" ) );
|
||||
}
|
||||
|
||||
if ( !ports[1] )
|
||||
{
|
||||
throw CGenErr ( tr ( "Cannot find enough physical playback ports" ) );
|
||||
}
|
||||
|
||||
if ( jack_connect ( pJackClient, jack_port_name ( output_port_left ), ports[0] ) )
|
||||
{
|
||||
throw CGenErr ( tr ( "Cannot connect output ports" ) );
|
||||
}
|
||||
if ( jack_connect ( pJackClient, jack_port_name ( output_port_right ), ports[1] ) )
|
||||
{
|
||||
throw CGenErr ( tr ( "Cannot connect output ports" ) );
|
||||
}
|
||||
|
||||
free ( ports );
|
||||
}
|
||||
|
||||
void CSound::CloseJack()
|
||||
{
|
||||
// deactivate client
|
||||
jack_deactivate ( pJackClient );
|
||||
|
||||
// unregister ports
|
||||
jack_port_unregister ( pJackClient, input_port_left );
|
||||
jack_port_unregister ( pJackClient, input_port_right );
|
||||
jack_port_unregister ( pJackClient, output_port_left );
|
||||
jack_port_unregister ( pJackClient, output_port_right );
|
||||
|
||||
// close client connection to jack server
|
||||
jack_client_close ( pJackClient );
|
||||
}
|
||||
|
||||
void CSound::Start()
|
||||
{
|
||||
// call base class
|
||||
CSoundBase::Start();
|
||||
}
|
||||
|
||||
void CSound::Stop()
|
||||
{
|
||||
// call base class
|
||||
CSoundBase::Stop();
|
||||
}
|
||||
|
||||
int CSound::Init ( const int /* iNewPrefMonoBufferSize */ )
|
||||
{
|
||||
// try setting buffer size
|
||||
// TODO seems not to work! -> no audio after this operation!
|
||||
//jack_set_buffer_size ( pJackClient, iNewPrefMonoBufferSize );
|
||||
|
||||
// get actual buffer size
|
||||
iJACKBufferSizeMono = jack_get_buffer_size ( pJackClient );
|
||||
|
||||
// init base class
|
||||
CSoundBase::Init ( iJACKBufferSizeMono );
|
||||
|
||||
// set internal buffer size value and calculate stereo buffer size
|
||||
iJACKBufferSizeStero = 2 * iJACKBufferSizeMono;
|
||||
|
||||
// create memory for intermediate audio buffer
|
||||
vecsTmpAudioSndCrdStereo.Init ( iJACKBufferSizeStero );
|
||||
|
||||
return iJACKBufferSizeMono;
|
||||
}
|
||||
|
||||
|
||||
// JACK callbacks --------------------------------------------------------------
|
||||
int CSound::process ( jack_nframes_t nframes, void* arg )
|
||||
{
|
||||
CSound* pSound = reinterpret_cast<CSound*> ( arg );
|
||||
int i;
|
||||
|
||||
if ( pSound->IsRunning() )
|
||||
{
|
||||
// get input data pointer
|
||||
jack_default_audio_sample_t* in_left =
|
||||
(jack_default_audio_sample_t*) jack_port_get_buffer (
|
||||
pSound->input_port_left, nframes );
|
||||
|
||||
jack_default_audio_sample_t* in_right =
|
||||
(jack_default_audio_sample_t*) jack_port_get_buffer (
|
||||
pSound->input_port_right, nframes );
|
||||
|
||||
// copy input data
|
||||
for ( i = 0; i < pSound->iJACKBufferSizeMono; i++ )
|
||||
{
|
||||
pSound->vecsTmpAudioSndCrdStereo[2 * i] =
|
||||
(short) ( in_left[i] * _MAXSHORT );
|
||||
|
||||
pSound->vecsTmpAudioSndCrdStereo[2 * i + 1] =
|
||||
(short) ( in_right[i] * _MAXSHORT );
|
||||
}
|
||||
|
||||
// call processing callback function
|
||||
pSound->ProcessCallback ( pSound->vecsTmpAudioSndCrdStereo );
|
||||
|
||||
// get output data pointer
|
||||
jack_default_audio_sample_t* out_left =
|
||||
(jack_default_audio_sample_t*) jack_port_get_buffer (
|
||||
pSound->output_port_left, nframes );
|
||||
|
||||
jack_default_audio_sample_t* out_right =
|
||||
(jack_default_audio_sample_t*) jack_port_get_buffer (
|
||||
pSound->output_port_right, nframes );
|
||||
|
||||
// copy output data
|
||||
for ( i = 0; i < pSound->iJACKBufferSizeMono; i++ )
|
||||
{
|
||||
out_left[i] = (jack_default_audio_sample_t)
|
||||
pSound->vecsTmpAudioSndCrdStereo[2 * i] / _MAXSHORT;
|
||||
|
||||
out_right[i] = (jack_default_audio_sample_t)
|
||||
pSound->vecsTmpAudioSndCrdStereo[2 * i + 1] / _MAXSHORT;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// get output data pointer
|
||||
jack_default_audio_sample_t* out_left =
|
||||
(jack_default_audio_sample_t*) jack_port_get_buffer (
|
||||
pSound->output_port_left, nframes );
|
||||
|
||||
jack_default_audio_sample_t* out_right =
|
||||
(jack_default_audio_sample_t*) jack_port_get_buffer (
|
||||
pSound->output_port_right, nframes );
|
||||
|
||||
// clear output data
|
||||
memset ( out_left,
|
||||
0, sizeof ( jack_default_audio_sample_t ) * nframes );
|
||||
|
||||
memset ( out_right,
|
||||
0, sizeof ( jack_default_audio_sample_t ) * nframes );
|
||||
}
|
||||
|
||||
return 0; // zero on success, non-zero on error
|
||||
}
|
||||
|
||||
int CSound::bufferSizeCallback ( jack_nframes_t, void *arg )
|
||||
{
|
||||
CSound* pSound = reinterpret_cast<CSound*> ( arg );
|
||||
|
||||
pSound->EmitReinitRequestSignal();
|
||||
|
||||
return 0; // zero on success, non-zero on error
|
||||
}
|
||||
|
||||
void CSound::shutdownCallback ( void* )
|
||||
{
|
||||
// without a Jack server, our software makes no sense to run, throw
|
||||
// error message
|
||||
throw CGenErr ( tr ( "Jack server was shut down" ) );
|
||||
}
|
||||
#endif // WITH_SOUND
|
||||
|
||||
/******************************************************************************\
|
||||
* Copyright (c) 2004-2011
|
||||
*
|
||||
* Author(s):
|
||||
* Volker Fischer
|
||||
*
|
||||
* 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
|
||||
* 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
|
||||
* version.
|
||||
*
|
||||
* 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
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* 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.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
\******************************************************************************/
|
||||
|
||||
#include "sound.h"
|
||||
|
||||
#ifdef WITH_SOUND
|
||||
void CSound::OpenJack()
|
||||
{
|
||||
jack_status_t JackStatus;
|
||||
|
||||
// try to become a client of the JACK server
|
||||
pJackClient = jack_client_open ( "llcon", JackNullOption, &JackStatus );
|
||||
if ( pJackClient == NULL )
|
||||
{
|
||||
throw CGenErr ( tr ( "Jack server not running" ) );
|
||||
}
|
||||
|
||||
// tell the JACK server to call "process()" whenever
|
||||
// there is work to be done
|
||||
jack_set_process_callback ( pJackClient, process, this );
|
||||
|
||||
// register a "buffer size changed" callback function
|
||||
jack_set_buffer_size_callback ( pJackClient, bufferSizeCallback, this );
|
||||
|
||||
// register shutdown callback function
|
||||
jack_on_shutdown ( pJackClient, shutdownCallback, this );
|
||||
|
||||
// TEST check sample rate, if not correct, just fire error
|
||||
if ( jack_get_sample_rate ( pJackClient ) != SYSTEM_SAMPLE_RATE_HZ )
|
||||
{
|
||||
throw CGenErr ( tr ( "Jack server sample rate is different from "
|
||||
"required one" ) );
|
||||
}
|
||||
|
||||
// create four ports (two for input, two for output -> stereo)
|
||||
input_port_left = jack_port_register ( pJackClient, "input left",
|
||||
JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0 );
|
||||
|
||||
input_port_right = jack_port_register ( pJackClient, "input right",
|
||||
JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0 );
|
||||
|
||||
output_port_left = jack_port_register ( pJackClient, "output left",
|
||||
JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0 );
|
||||
|
||||
output_port_right = jack_port_register ( pJackClient, "output right",
|
||||
JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0 );
|
||||
|
||||
if ( ( input_port_left == NULL ) ||
|
||||
( input_port_right == NULL ) ||
|
||||
( output_port_left == NULL ) ||
|
||||
( output_port_right == NULL ) )
|
||||
{
|
||||
throw CGenErr ( tr ( "Jack port registering failed" ) );
|
||||
}
|
||||
|
||||
const char** ports;
|
||||
|
||||
// tell the JACK server that we are ready to roll
|
||||
if ( jack_activate ( pJackClient ) )
|
||||
{
|
||||
throw CGenErr ( tr ( "Cannot activate client" ) );
|
||||
}
|
||||
|
||||
// connect the ports, note: you cannot do this before
|
||||
// the client is activated, because we cannot allow
|
||||
// connections to be made to clients that are not
|
||||
// running
|
||||
if ( ( ports = jack_get_ports ( pJackClient, NULL, NULL,
|
||||
JackPortIsPhysical | JackPortIsOutput ) ) == NULL )
|
||||
{
|
||||
throw CGenErr ( tr ( "Cannot find any physical capture ports" ) );
|
||||
}
|
||||
|
||||
if ( !ports[1] )
|
||||
{
|
||||
throw CGenErr ( tr ( "Cannot find enough physical capture ports" ) );
|
||||
}
|
||||
|
||||
if ( jack_connect ( pJackClient, ports[0], jack_port_name ( input_port_left ) ) )
|
||||
{
|
||||
throw CGenErr ( tr ( "Cannot connect input ports" ) );
|
||||
}
|
||||
if ( jack_connect ( pJackClient, ports[1], jack_port_name ( input_port_right ) ) )
|
||||
{
|
||||
throw CGenErr ( tr ( "Cannot connect input ports" ) );
|
||||
}
|
||||
|
||||
free ( ports );
|
||||
|
||||
if ( ( ports = jack_get_ports ( pJackClient, NULL, NULL,
|
||||
JackPortIsPhysical | JackPortIsInput ) ) == NULL )
|
||||
{
|
||||
throw CGenErr ( tr ( "Cannot find any physical playback ports" ) );
|
||||
}
|
||||
|
||||
if ( !ports[1] )
|
||||
{
|
||||
throw CGenErr ( tr ( "Cannot find enough physical playback ports" ) );
|
||||
}
|
||||
|
||||
if ( jack_connect ( pJackClient, jack_port_name ( output_port_left ), ports[0] ) )
|
||||
{
|
||||
throw CGenErr ( tr ( "Cannot connect output ports" ) );
|
||||
}
|
||||
if ( jack_connect ( pJackClient, jack_port_name ( output_port_right ), ports[1] ) )
|
||||
{
|
||||
throw CGenErr ( tr ( "Cannot connect output ports" ) );
|
||||
}
|
||||
|
||||
free ( ports );
|
||||
}
|
||||
|
||||
void CSound::CloseJack()
|
||||
{
|
||||
// deactivate client
|
||||
jack_deactivate ( pJackClient );
|
||||
|
||||
// unregister ports
|
||||
jack_port_unregister ( pJackClient, input_port_left );
|
||||
jack_port_unregister ( pJackClient, input_port_right );
|
||||
jack_port_unregister ( pJackClient, output_port_left );
|
||||
jack_port_unregister ( pJackClient, output_port_right );
|
||||
|
||||
// close client connection to jack server
|
||||
jack_client_close ( pJackClient );
|
||||
}
|
||||
|
||||
void CSound::Start()
|
||||
{
|
||||
// call base class
|
||||
CSoundBase::Start();
|
||||
}
|
||||
|
||||
void CSound::Stop()
|
||||
{
|
||||
// call base class
|
||||
CSoundBase::Stop();
|
||||
}
|
||||
|
||||
int CSound::Init ( const int /* iNewPrefMonoBufferSize */ )
|
||||
{
|
||||
// try setting buffer size
|
||||
// TODO seems not to work! -> no audio after this operation!
|
||||
//jack_set_buffer_size ( pJackClient, iNewPrefMonoBufferSize );
|
||||
|
||||
// get actual buffer size
|
||||
iJACKBufferSizeMono = jack_get_buffer_size ( pJackClient );
|
||||
|
||||
// init base class
|
||||
CSoundBase::Init ( iJACKBufferSizeMono );
|
||||
|
||||
// set internal buffer size value and calculate stereo buffer size
|
||||
iJACKBufferSizeStero = 2 * iJACKBufferSizeMono;
|
||||
|
||||
// create memory for intermediate audio buffer
|
||||
vecsTmpAudioSndCrdStereo.Init ( iJACKBufferSizeStero );
|
||||
|
||||
return iJACKBufferSizeMono;
|
||||
}
|
||||
|
||||
|
||||
// JACK callbacks --------------------------------------------------------------
|
||||
int CSound::process ( jack_nframes_t nframes, void* arg )
|
||||
{
|
||||
CSound* pSound = reinterpret_cast<CSound*> ( arg );
|
||||
int i;
|
||||
|
||||
if ( pSound->IsRunning() )
|
||||
{
|
||||
// get input data pointer
|
||||
jack_default_audio_sample_t* in_left =
|
||||
(jack_default_audio_sample_t*) jack_port_get_buffer (
|
||||
pSound->input_port_left, nframes );
|
||||
|
||||
jack_default_audio_sample_t* in_right =
|
||||
(jack_default_audio_sample_t*) jack_port_get_buffer (
|
||||
pSound->input_port_right, nframes );
|
||||
|
||||
// copy input data
|
||||
for ( i = 0; i < pSound->iJACKBufferSizeMono; i++ )
|
||||
{
|
||||
pSound->vecsTmpAudioSndCrdStereo[2 * i] =
|
||||
(short) ( in_left[i] * _MAXSHORT );
|
||||
|
||||
pSound->vecsTmpAudioSndCrdStereo[2 * i + 1] =
|
||||
(short) ( in_right[i] * _MAXSHORT );
|
||||
}
|
||||
|
||||
// call processing callback function
|
||||
pSound->ProcessCallback ( pSound->vecsTmpAudioSndCrdStereo );
|
||||
|
||||
// get output data pointer
|
||||
jack_default_audio_sample_t* out_left =
|
||||
(jack_default_audio_sample_t*) jack_port_get_buffer (
|
||||
pSound->output_port_left, nframes );
|
||||
|
||||
jack_default_audio_sample_t* out_right =
|
||||
(jack_default_audio_sample_t*) jack_port_get_buffer (
|
||||
pSound->output_port_right, nframes );
|
||||
|
||||
// copy output data
|
||||
for ( i = 0; i < pSound->iJACKBufferSizeMono; i++ )
|
||||
{
|
||||
out_left[i] = (jack_default_audio_sample_t)
|
||||
pSound->vecsTmpAudioSndCrdStereo[2 * i] / _MAXSHORT;
|
||||
|
||||
out_right[i] = (jack_default_audio_sample_t)
|
||||
pSound->vecsTmpAudioSndCrdStereo[2 * i + 1] / _MAXSHORT;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// get output data pointer
|
||||
jack_default_audio_sample_t* out_left =
|
||||
(jack_default_audio_sample_t*) jack_port_get_buffer (
|
||||
pSound->output_port_left, nframes );
|
||||
|
||||
jack_default_audio_sample_t* out_right =
|
||||
(jack_default_audio_sample_t*) jack_port_get_buffer (
|
||||
pSound->output_port_right, nframes );
|
||||
|
||||
// clear output data
|
||||
memset ( out_left,
|
||||
0, sizeof ( jack_default_audio_sample_t ) * nframes );
|
||||
|
||||
memset ( out_right,
|
||||
0, sizeof ( jack_default_audio_sample_t ) * nframes );
|
||||
}
|
||||
|
||||
return 0; // zero on success, non-zero on error
|
||||
}
|
||||
|
||||
int CSound::bufferSizeCallback ( jack_nframes_t, void *arg )
|
||||
{
|
||||
CSound* pSound = reinterpret_cast<CSound*> ( arg );
|
||||
|
||||
pSound->EmitReinitRequestSignal ( RS_ONLY_RESTART_AND_INIT );
|
||||
|
||||
return 0; // zero on success, non-zero on error
|
||||
}
|
||||
|
||||
void CSound::shutdownCallback ( void* )
|
||||
{
|
||||
// without a Jack server, our software makes no sense to run, throw
|
||||
// error message
|
||||
throw CGenErr ( tr ( "Jack server was shut down" ) );
|
||||
}
|
||||
#endif // WITH_SOUND
|
||||
|
||||
|
|
1100
mac/sound.cpp
1100
mac/sound.cpp
File diff suppressed because it is too large
Load diff
2029
src/client.cpp
2029
src/client.cpp
File diff suppressed because it is too large
Load diff
|
@ -335,7 +335,7 @@ public slots:
|
|||
int iMs,
|
||||
int iNumClients );
|
||||
|
||||
void OnSndCrdReinitRequest();
|
||||
void OnSndCrdReinitRequest ( ESndCrdResetType eSndCrdResetType );
|
||||
|
||||
signals:
|
||||
void ConClientListMesReceived ( CVector<CChannelShortInfo> vecChanInfo );
|
||||
|
|
241
src/soundbase.h
241
src/soundbase.h
|
@ -1,115 +1,126 @@
|
|||
/******************************************************************************\
|
||||
* Copyright (c) 2004-2011
|
||||
*
|
||||
* Author(s):
|
||||
* Volker Fischer
|
||||
*
|
||||
******************************************************************************
|
||||
*
|
||||
* 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
|
||||
* Foundation; either version 2 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* 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
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* 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.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
\******************************************************************************/
|
||||
|
||||
#if !defined ( SOUNDBASE_HOIHGEH8_3_4344456456345634565KJIUHF1912__INCLUDED_ )
|
||||
#define SOUNDBASE_HOIHGEH8_3_4344456456345634565KJIUHF1912__INCLUDED_
|
||||
|
||||
#include <qthread.h>
|
||||
#include <qstring.h>
|
||||
#include <qmessagebox.h>
|
||||
#include "global.h"
|
||||
#include "util.h"
|
||||
|
||||
|
||||
/* Classes ********************************************************************/
|
||||
class CSoundBase : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CSoundBase ( const QString& strNewSystemDriverTechniqueName,
|
||||
const bool bNewIsCallbackAudioInterface,
|
||||
void (*fpNewProcessCallback) ( CVector<int16_t>& psData, void* pParg ),
|
||||
void* pParg );
|
||||
|
||||
virtual int Init ( const int iNewPrefMonoBufferSize );
|
||||
virtual void Start();
|
||||
virtual void Stop();
|
||||
|
||||
// device selection
|
||||
virtual int GetNumDev() { return lNumDevs; }
|
||||
virtual QString GetDeviceName ( const int iDiD ) { return strDriverNames[iDiD]; }
|
||||
virtual QString SetDev ( const int );
|
||||
virtual int GetDev() { return lCurDev; }
|
||||
|
||||
virtual int GetNumInputChannels() { return 2; }
|
||||
virtual QString GetInputChannelName ( const int ) { return "Default"; }
|
||||
virtual void SetLeftInputChannel ( const int ) {}
|
||||
virtual void SetRightInputChannel ( const int ) {}
|
||||
virtual int GetLeftInputChannel() { return 0; }
|
||||
virtual int GetRightInputChannel() { return 1; }
|
||||
|
||||
virtual int GetNumOutputChannels() { return 2; }
|
||||
virtual QString GetOutputChannelName ( const int ) { return "Default"; }
|
||||
virtual void SetLeftOutputChannel ( const int ) {}
|
||||
virtual void SetRightOutputChannel ( const int ) {}
|
||||
virtual int GetLeftOutputChannel() { return 0; }
|
||||
virtual int GetRightOutputChannel() { return 1; }
|
||||
|
||||
virtual void OpenDriverSetup() {}
|
||||
|
||||
bool IsRunning() const { return bRun; }
|
||||
|
||||
// TODO this should be protected but since it is used
|
||||
// in a callback function it has to be public -> better solution
|
||||
void EmitReinitRequestSignal() { emit ReinitRequest(); }
|
||||
|
||||
protected:
|
||||
// driver handling
|
||||
virtual QString LoadAndInitializeDriver ( int ) { return ""; }
|
||||
virtual void UnloadCurrentDriver() {}
|
||||
QVector<QString> LoadAndInitializeFirstValidDriver();
|
||||
|
||||
// function pointer to callback function
|
||||
void (*fpProcessCallback) ( CVector<int16_t>& psData, void* arg );
|
||||
void* pProcessCallbackArg;
|
||||
|
||||
// callback function call for derived classes
|
||||
void ProcessCallback ( CVector<int16_t>& psData )
|
||||
{
|
||||
(*fpProcessCallback) ( psData, pProcessCallbackArg );
|
||||
}
|
||||
|
||||
// these functions should be overwritten by derived class for
|
||||
// non callback based audio interfaces
|
||||
virtual bool Read ( CVector<int16_t>& ) { printf ( "no sound!" ); return false; }
|
||||
virtual bool Write ( CVector<int16_t>& ) { printf ( "no sound!" ); return false; }
|
||||
|
||||
void run();
|
||||
bool bRun;
|
||||
|
||||
bool bIsCallbackAudioInterface;
|
||||
QString strSystemDriverTechniqueName;
|
||||
|
||||
CVector<int16_t> vecsAudioSndCrdStereo;
|
||||
|
||||
long lNumDevs;
|
||||
long lCurDev;
|
||||
QString strDriverNames[MAX_NUMBER_SOUND_CARDS];
|
||||
|
||||
signals:
|
||||
void ReinitRequest();
|
||||
};
|
||||
|
||||
#endif /* !defined ( SOUNDBASE_HOIHGEH8_3_4344456456345634565KJIUHF1912__INCLUDED_ ) */
|
||||
/******************************************************************************\
|
||||
* Copyright (c) 2004-2011
|
||||
*
|
||||
* Author(s):
|
||||
* Volker Fischer
|
||||
*
|
||||
******************************************************************************
|
||||
*
|
||||
* 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
|
||||
* Foundation; either version 2 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* 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
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* 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.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
\******************************************************************************/
|
||||
|
||||
#if !defined ( SOUNDBASE_HOIHGEH8_3_4344456456345634565KJIUHF1912__INCLUDED_ )
|
||||
#define SOUNDBASE_HOIHGEH8_3_4344456456345634565KJIUHF1912__INCLUDED_
|
||||
|
||||
#include <qthread.h>
|
||||
#include <qstring.h>
|
||||
#include <qmessagebox.h>
|
||||
#include "global.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 ********************************************************************/
|
||||
class CSoundBase : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CSoundBase ( const QString& strNewSystemDriverTechniqueName,
|
||||
const bool bNewIsCallbackAudioInterface,
|
||||
void (*fpNewProcessCallback) ( CVector<int16_t>& psData, void* pParg ),
|
||||
void* pParg );
|
||||
|
||||
virtual int Init ( const int iNewPrefMonoBufferSize );
|
||||
virtual void Start();
|
||||
virtual void Stop();
|
||||
|
||||
// device selection
|
||||
virtual int GetNumDev() { return lNumDevs; }
|
||||
virtual QString GetDeviceName ( const int iDiD ) { return strDriverNames[iDiD]; }
|
||||
virtual QString SetDev ( const int );
|
||||
virtual int GetDev() { return lCurDev; }
|
||||
|
||||
virtual int GetNumInputChannels() { return 2; }
|
||||
virtual QString GetInputChannelName ( const int ) { return "Default"; }
|
||||
virtual void SetLeftInputChannel ( const int ) {}
|
||||
virtual void SetRightInputChannel ( const int ) {}
|
||||
virtual int GetLeftInputChannel() { return 0; }
|
||||
virtual int GetRightInputChannel() { return 1; }
|
||||
|
||||
virtual int GetNumOutputChannels() { return 2; }
|
||||
virtual QString GetOutputChannelName ( const int ) { return "Default"; }
|
||||
virtual void SetLeftOutputChannel ( const int ) {}
|
||||
virtual void SetRightOutputChannel ( const int ) {}
|
||||
virtual int GetLeftOutputChannel() { return 0; }
|
||||
virtual int GetRightOutputChannel() { return 1; }
|
||||
|
||||
virtual void OpenDriverSetup() {}
|
||||
|
||||
bool IsRunning() const { return bRun; }
|
||||
|
||||
// TODO this should be protected but since it is used
|
||||
// in a callback function it has to be public -> better solution
|
||||
void EmitReinitRequestSignal ( const ESndCrdResetType eSndCrdResetType )
|
||||
{ emit ReinitRequest ( eSndCrdResetType ); }
|
||||
|
||||
protected:
|
||||
// driver handling
|
||||
virtual QString LoadAndInitializeDriver ( int ) { return ""; }
|
||||
virtual void UnloadCurrentDriver() {}
|
||||
QVector<QString> LoadAndInitializeFirstValidDriver();
|
||||
|
||||
// function pointer to callback function
|
||||
void (*fpProcessCallback) ( CVector<int16_t>& psData, void* arg );
|
||||
void* pProcessCallbackArg;
|
||||
|
||||
// callback function call for derived classes
|
||||
void ProcessCallback ( CVector<int16_t>& psData )
|
||||
{
|
||||
(*fpProcessCallback) ( psData, pProcessCallbackArg );
|
||||
}
|
||||
|
||||
// these functions should be overwritten by derived class for
|
||||
// non callback based audio interfaces
|
||||
virtual bool Read ( CVector<int16_t>& ) { printf ( "no sound!" ); return false; }
|
||||
virtual bool Write ( CVector<int16_t>& ) { printf ( "no sound!" ); return false; }
|
||||
|
||||
void run();
|
||||
bool bRun;
|
||||
|
||||
bool bIsCallbackAudioInterface;
|
||||
QString strSystemDriverTechniqueName;
|
||||
|
||||
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_ ) */
|
||||
|
|
|
@ -959,6 +959,7 @@ long CSound::asioMessages ( long selector,
|
|||
double* )
|
||||
{
|
||||
long ret = 0;
|
||||
|
||||
switch ( selector )
|
||||
{
|
||||
case kAsioEngineVersion:
|
||||
|
@ -968,26 +969,16 @@ long CSound::asioMessages ( long selector,
|
|||
|
||||
// both messages might be send if the buffer size changes
|
||||
case kAsioBufferSizeChange:
|
||||
pSound->EmitReinitRequestSignal ( RS_ONLY_RESTART_AND_INIT );
|
||||
ret = 1L; // 1L if request is accepted or 0 otherwise
|
||||
break;
|
||||
|
||||
case kAsioResetRequest:
|
||||
|
||||
|
||||
// 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();
|
||||
pSound->EmitReinitRequestSignal ( RS_RELOAD_RESTART_AND_INIT );
|
||||
ret = 1L; // 1L if request is accepted or 0 otherwise
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue