mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-14 18:46:34 +01:00
[Summary] Added backend/engine update mechanism when device configuration changes (I/O layout, etc.)
[Reviewed by] The idea of event handling queue has been reviewed by Paul Davis
This commit is contained in:
parent
149e6dcea6
commit
489ead12ba
6 changed files with 158 additions and 98 deletions
|
|
@ -108,6 +108,7 @@ public:
|
|||
uint32_t process_thread_count ();
|
||||
|
||||
void request_backend_reset();
|
||||
void request_device_list_update();
|
||||
|
||||
bool is_realtime() const;
|
||||
bool connected() const;
|
||||
|
|
@ -190,7 +191,6 @@ public:
|
|||
*/
|
||||
int process_callback (pframes_t nframes);
|
||||
int buffer_size_change (pframes_t nframes);
|
||||
int device_list_change ();
|
||||
int sample_rate_change (pframes_t nframes);
|
||||
void freewheel_callback (bool);
|
||||
void timebase_callback (TransportState state, pframes_t nframes, framepos_t pos, int new_position);
|
||||
|
|
@ -232,7 +232,6 @@ public:
|
|||
/// the number of frames processed since start() was called
|
||||
framecnt_t _processed_frames;
|
||||
Glib::Threads::Thread* m_meter_thread;
|
||||
Glib::Threads::Thread* m_hw_event_thread;
|
||||
ProcessThread* _main_thread;
|
||||
MTDM* _mtdm;
|
||||
bool _measuring_latency;
|
||||
|
|
@ -246,8 +245,17 @@ public:
|
|||
bool _started_for_latency;
|
||||
bool _in_destructor;
|
||||
|
||||
Glib::Threads::Thread* _hw_reset_event_thread;
|
||||
uint16_t _hw_reset_request_count;
|
||||
bool _stop_hw_reset_processing;
|
||||
Glib::Threads::Thread* _hw_devicelist_update_thread;
|
||||
uint16_t _hw_devicelist_update_count;
|
||||
bool _stop_hw_devicelist_processing;
|
||||
|
||||
void start_hw_event_processing();
|
||||
void stop_hw_event_processing();
|
||||
void do_reset_backend();
|
||||
void wait_hw_event_processing_complete();
|
||||
void do_devicelist_update();
|
||||
|
||||
void meter_thread ();
|
||||
void start_metering_thread ();
|
||||
|
|
|
|||
|
|
@ -80,8 +80,15 @@ AudioEngine::AudioEngine ()
|
|||
, _latency_signal_latency (0)
|
||||
, _stopped_for_latency (false)
|
||||
, _in_destructor (false)
|
||||
, _hw_reset_event_thread(0)
|
||||
, _hw_reset_request_count(0)
|
||||
, _stop_hw_reset_processing(false)
|
||||
, _hw_devicelist_update_thread(0)
|
||||
, _hw_devicelist_update_count(0)
|
||||
, _stop_hw_devicelist_processing(false)
|
||||
{
|
||||
g_atomic_int_set (&m_meter_exit, 0);
|
||||
start_hw_event_processing();
|
||||
discover_backends ();
|
||||
}
|
||||
|
||||
|
|
@ -89,7 +96,7 @@ AudioEngine::~AudioEngine ()
|
|||
{
|
||||
_in_destructor = true;
|
||||
stop_metering_thread ();
|
||||
wait_hw_event_processing_complete();
|
||||
stop_hw_event_processing();
|
||||
drop_backend ();
|
||||
}
|
||||
|
||||
|
|
@ -168,14 +175,6 @@ AudioEngine::buffer_size_change (pframes_t bufsiz)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
AudioEngine::device_list_change ()
|
||||
{
|
||||
DeviceListChanged (); /* EMIT SIGNAL */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Method called by our ::process_thread when there is work to be done.
|
||||
* @param nframes Number of frames to process.
|
||||
*/
|
||||
|
|
@ -366,37 +365,98 @@ AudioEngine::process_callback (pframes_t nframes)
|
|||
void
|
||||
AudioEngine::request_backend_reset()
|
||||
{
|
||||
if (m_hw_event_thread != 0) {
|
||||
m_hw_event_thread->join ();
|
||||
m_hw_event_thread = 0;
|
||||
}
|
||||
|
||||
m_hw_event_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::do_reset_backend, this));
|
||||
g_atomic_int_inc(&_hw_reset_request_count);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AudioEngine::do_reset_backend()
|
||||
{
|
||||
SessionEvent::create_per_thread_pool (X_("Backend reset processing thread"), 512);
|
||||
|
||||
if (_backend) {
|
||||
std::string name = _backend->device_name ();
|
||||
stop();
|
||||
_backend->drop_device();
|
||||
_backend->set_device_name(name);
|
||||
start();
|
||||
SampleRateChanged(_backend->sample_rate() );
|
||||
BufferSizeChanged(_backend->buffer_size() );
|
||||
}
|
||||
SessionEvent::create_per_thread_pool (X_("Backend reset processing thread"), 512);
|
||||
|
||||
while (!_stop_hw_reset_processing) {
|
||||
|
||||
if (_hw_reset_request_count && _backend) {
|
||||
|
||||
g_atomic_int_dec_and_test (&_hw_reset_request_count);
|
||||
|
||||
// backup the device name
|
||||
std::string name = _backend->device_name ();
|
||||
|
||||
stop();
|
||||
|
||||
// "hard reset" the device
|
||||
_backend->drop_device();
|
||||
_backend->set_device_name(name);
|
||||
|
||||
start();
|
||||
|
||||
// inform about possible changes
|
||||
SampleRateChanged(_backend->sample_rate() );
|
||||
BufferSizeChanged(_backend->buffer_size() );
|
||||
}
|
||||
|
||||
g_usleep(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AudioEngine::wait_hw_event_processing_complete()
|
||||
AudioEngine::request_device_list_update()
|
||||
{
|
||||
m_hw_event_thread->join ();
|
||||
m_hw_event_thread = 0;
|
||||
g_atomic_int_inc (&_hw_devicelist_update_count);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AudioEngine::do_devicelist_update()
|
||||
{
|
||||
SessionEvent::create_per_thread_pool (X_("Device list update processing thread"), 512);
|
||||
|
||||
while (!_stop_hw_devicelist_processing) {
|
||||
if (_hw_devicelist_update_count) {
|
||||
g_atomic_int_dec_and_test (&_hw_devicelist_update_count);
|
||||
DeviceListChanged (); /* EMIT SIGNAL */
|
||||
}
|
||||
g_usleep(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AudioEngine::start_hw_event_processing()
|
||||
{
|
||||
if (_hw_reset_event_thread == 0) {
|
||||
g_atomic_int_set(&_hw_reset_request_count, 0);
|
||||
g_atomic_int_set(&_stop_hw_reset_processing, 0);
|
||||
_hw_reset_event_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::do_reset_backend, this));
|
||||
}
|
||||
|
||||
if (_hw_devicelist_update_thread == 0) {
|
||||
g_atomic_int_set(&_hw_devicelist_update_count, 0);
|
||||
g_atomic_int_set(&_stop_hw_devicelist_processing, 0);
|
||||
_hw_devicelist_update_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::do_devicelist_update, this));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AudioEngine::stop_hw_event_processing()
|
||||
{
|
||||
if (_hw_reset_event_thread) {
|
||||
g_atomic_int_set(&_stop_hw_reset_processing, 1);
|
||||
g_atomic_int_set(&_hw_reset_request_count, 0);
|
||||
_hw_reset_event_thread->join ();
|
||||
_hw_reset_event_thread = 0;
|
||||
}
|
||||
|
||||
if (_hw_devicelist_update_thread) {
|
||||
g_atomic_int_set(&_stop_hw_devicelist_processing, 1);
|
||||
g_atomic_int_set(&_hw_devicelist_update_count, 0);
|
||||
_hw_devicelist_update_thread->join ();
|
||||
_hw_devicelist_update_thread = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -64,11 +64,11 @@ void WavesAudioBackend::AudioDeviceManagerNotification (NotificationReason reaso
|
|||
break;
|
||||
case WCMRAudioDeviceManagerClient::DeviceListChanged:
|
||||
std::cout << "------------------------------- WCMRAudioDeviceManagerClient::DeviceListChanged" << std::endl;
|
||||
_device_list_change();
|
||||
engine.request_device_list_update();
|
||||
break;
|
||||
case WCMRAudioDeviceManagerClient::IODeviceDisconnected:
|
||||
std::cout << "------------------------------- WCMRAudioDeviceManagerClient::DeviceListChanged" << std::endl;
|
||||
_device_list_change();
|
||||
engine.request_device_list_update();
|
||||
break;
|
||||
case WCMRAudioDeviceManagerClient::AudioCallback:
|
||||
if (parameter) {
|
||||
|
|
@ -585,14 +585,6 @@ WavesAudioBackend::_sample_rate_change (float new_sample_rate)
|
|||
}
|
||||
|
||||
|
||||
int
|
||||
WavesAudioBackend::_device_list_change ()
|
||||
{
|
||||
// requires GZ changes for device list update
|
||||
return engine.device_list_change ();
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
WavesAudioBackend::set_interleaved (bool yn)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -331,8 +331,6 @@ class WavesMidiPort;
|
|||
int _buffer_size_change(uint32_t new_buffer_size);
|
||||
int _sample_rate_change(float new_sample_rate);
|
||||
|
||||
int _device_list_change();
|
||||
|
||||
int _register_system_audio_ports ();
|
||||
int _register_system_midi_ports ();
|
||||
|
||||
|
|
|
|||
|
|
@ -1248,12 +1248,17 @@ WTErr WCMRCoreAudioDevice::EnableListeners()
|
|||
goto Exit;
|
||||
}
|
||||
|
||||
#if ENABLE_DEVICE_CHANGE_LISTNER
|
||||
#if ENABLE_DEVICE_CHANGE_LISTNER
|
||||
{
|
||||
//listner for device change...
|
||||
err = AudioDeviceAddPropertyListener(m_DeviceID, 0, 0, kAudioDevicePropertyDeviceHasChanged,
|
||||
StaticPropertyChangeProc, this);
|
||||
|
||||
err = AudioDeviceAddPropertyListener (m_DeviceID,
|
||||
kAudioPropertyWildcardChannel,
|
||||
true,
|
||||
kAudioDevicePropertyDeviceHasChanged,
|
||||
StaticPropertyChangeProc,
|
||||
this);
|
||||
|
||||
if (err)
|
||||
{
|
||||
DEBUG_MSG("Couldn't Setup device change Property Listner, error = " << err);
|
||||
|
|
@ -1309,14 +1314,18 @@ WTErr WCMRCoreAudioDevice::DisableListeners()
|
|||
|
||||
#if ENABLE_DEVICE_CHANGE_LISTNER
|
||||
{
|
||||
err = AudioDeviceRemovePropertyListener(m_DeviceID, 0, 0, kAudioDevicePropertyDeviceHasChanged,
|
||||
StaticPropertyChangeProc);
|
||||
|
||||
err = AudioDeviceRemovePropertyListener (m_DeviceID,
|
||||
kAudioPropertyWildcardChannel,
|
||||
true/* Input */,
|
||||
kAudioDevicePropertyDeviceHasChanged,
|
||||
StaticPropertyChangeProc);
|
||||
|
||||
if (err)
|
||||
{
|
||||
DEBUG_MSG("Couldn't Cleanup device change Property Listner, error = " << err);
|
||||
DEBUG_MSG("Couldn't Cleanup device input stream change Property Listner, error = " << err);
|
||||
//not sure if we need to report this...
|
||||
}
|
||||
|
||||
}
|
||||
#endif //ENABLE_DEVICE_CHANGE_LISTNER
|
||||
|
||||
|
|
@ -1385,15 +1394,19 @@ void WCMRCoreAudioDevice::PropertyChangeProc (AudioDevicePropertyID inPropertyID
|
|||
case kAudioDevicePropertyDeviceHasChanged:
|
||||
{
|
||||
m_ResetRequested++;
|
||||
m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::RequestReset);
|
||||
}
|
||||
break;
|
||||
#endif //ENABLE_DEVICE_CHANGE_LISTNER
|
||||
case kAudioDeviceProcessorOverload:
|
||||
{
|
||||
if (m_IgnoreThisDrop)
|
||||
m_IgnoreThisDrop = false; //We'll ignore once, just once!
|
||||
else
|
||||
m_DropsDetected++;
|
||||
m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::Dropout );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -1659,35 +1672,7 @@ WTErr WCMRCoreAudioDevice::SetupAUHAL()
|
|||
retVal = EnableListeners();
|
||||
if (retVal != eNoErr)
|
||||
goto Exit;
|
||||
|
||||
//also prepare the buffer list for input...
|
||||
if (!m_InputChannels.empty())
|
||||
{
|
||||
|
||||
//now setup the buffer list.
|
||||
memset (&m_InputAudioBufferList, 0, sizeof (m_InputAudioBufferList));
|
||||
m_InputAudioBufferList.mNumberBuffers = 1;
|
||||
m_InputAudioBufferList.mBuffers[0].mNumberChannels = m_InputChannels.size();
|
||||
m_InputAudioBufferList.mBuffers[0].mDataByteSize = m_InputAudioBufferList.mBuffers[0].mNumberChannels *
|
||||
m_CurrentBufferSize * sizeof(float);
|
||||
//allocate the data buffer...
|
||||
try
|
||||
{
|
||||
m_pInputData = new float[m_InputAudioBufferList.mBuffers[0].mNumberChannels * m_CurrentBufferSize];
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
retVal = eMemNewFailed;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
m_InputAudioBufferList.mBuffers[0].mData = m_pInputData;
|
||||
|
||||
//zero it out...
|
||||
memset (m_InputAudioBufferList.mBuffers[0].mData, 0, m_InputAudioBufferList.mBuffers[0].mDataByteSize);
|
||||
|
||||
}
|
||||
|
||||
//initialize the audio-unit now!
|
||||
err = AudioUnitInitialize(m_AUHALAudioUnit);
|
||||
if (err != kAudioHardwareNoError)
|
||||
|
|
@ -1727,8 +1712,6 @@ WTErr WCMRCoreAudioDevice::TearDownAUHAL()
|
|||
CloseComponent(m_AUHALAudioUnit);
|
||||
m_AUHALAudioUnit = NULL;
|
||||
}
|
||||
|
||||
safe_delete_array(m_pInputData);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
|
@ -1759,7 +1742,6 @@ WTErr WCMRCoreAudioDevice::SetActive (bool newState)
|
|||
|
||||
if (newState)
|
||||
{
|
||||
|
||||
m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::DeviceDebugInfo, (void *)"Setting up AUHAL.");
|
||||
retVal = SetupAUHAL();
|
||||
|
||||
|
|
@ -1907,7 +1889,6 @@ WTErr WCMRCoreAudioDevice::SetStreaming (bool newState)
|
|||
SetupToneGenerator ();
|
||||
#endif //WV_USE_TONE_GEN
|
||||
|
||||
m_StopRequested = false;
|
||||
m_SampleCountAtLastIdle = 0;
|
||||
m_StalledSampleCounter = 0;
|
||||
m_SampleCounter = 0;
|
||||
|
|
@ -1924,6 +1905,8 @@ WTErr WCMRCoreAudioDevice::SetStreaming (bool newState)
|
|||
|
||||
err = AudioOutputUnitStart (m_AUHALAudioUnit);
|
||||
|
||||
m_StopRequested = false;
|
||||
|
||||
if(err)
|
||||
{
|
||||
DEBUG_MSG( "Failed to start AudioUnit, err " << err );
|
||||
|
|
@ -1938,11 +1921,11 @@ WTErr WCMRCoreAudioDevice::SetStreaming (bool newState)
|
|||
err = AudioOutputUnitStop (m_AUHALAudioUnit);
|
||||
if (!err)
|
||||
{
|
||||
if (!m_InputChannels.empty());
|
||||
//if (!m_InputChannels.empty());
|
||||
{
|
||||
err = AudioUnitReset (m_AUHALAudioUnit, kAudioUnitScope_Global, AUHAL_INPUT_ELEMENT);
|
||||
}
|
||||
if (!m_OutputChannels.empty());
|
||||
//if (!m_OutputChannels.empty());
|
||||
{
|
||||
err = AudioUnitReset (m_AUHALAudioUnit, kAudioUnitScope_Global, AUHAL_OUTPUT_ELEMENT);
|
||||
}
|
||||
|
|
@ -1981,6 +1964,7 @@ Exit:
|
|||
//**********************************************************************************************
|
||||
WTErr WCMRCoreAudioDevice::DoIdle ()
|
||||
{
|
||||
/*
|
||||
if (m_BufferSizeChangeRequested != m_BufferSizeChangeReported)
|
||||
{
|
||||
m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::BufferSizeChanged);
|
||||
|
|
@ -2033,7 +2017,7 @@ WTErr WCMRCoreAudioDevice::DoIdle ()
|
|||
m_StalledSampleCounter = 0;
|
||||
m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::DeviceStoppedStreaming, (void *)currentSampleCount);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
return (eNoErr);
|
||||
|
|
@ -2198,19 +2182,38 @@ OSStatus WCMRCoreAudioDevice::AudioIOProc(AudioUnitRenderActionFlags * ioAction
|
|||
OSStatus retVal = 0;
|
||||
|
||||
if (m_StopRequested)
|
||||
goto Exit;
|
||||
return retVal;
|
||||
|
||||
if (m_IOProcThreadPort == 0)
|
||||
m_IOProcThreadPort = mach_thread_self ();
|
||||
|
||||
//cannot really deal with it unless the number of frames are the same as our buffer size!
|
||||
if (inNumberFrames != (UInt32)m_CurrentBufferSize)
|
||||
goto Exit;
|
||||
return retVal;
|
||||
|
||||
//Retrieve the input data...
|
||||
if (!m_InputChannels.empty())
|
||||
{
|
||||
retVal = AudioUnitRender(m_AUHALAudioUnit, ioActionFlags, inTimeStamp, AUHAL_INPUT_ELEMENT, inNumberFrames, &m_InputAudioBufferList);
|
||||
UInt32 expectedDataSize = m_InputChannels.size() * m_CurrentBufferSize * sizeof(float);
|
||||
AudioBufferList inputAudioBufferList;
|
||||
inputAudioBufferList.mNumberBuffers = 1;
|
||||
inputAudioBufferList.mBuffers[0].mNumberChannels = m_InputChannels.size();
|
||||
inputAudioBufferList.mBuffers[0].mDataByteSize = expectedDataSize*10;
|
||||
inputAudioBufferList.mBuffers[0].mData = NULL;//new float[expectedDataSize]; // we are going to get buffer from CoreAudio
|
||||
|
||||
retVal = AudioUnitRender(m_AUHALAudioUnit, ioActionFlags, inTimeStamp, AUHAL_INPUT_ELEMENT, inNumberFrames, &inputAudioBufferList);
|
||||
|
||||
if (retVal == kAudioHardwareNoError &&
|
||||
inputAudioBufferList.mBuffers[0].mNumberChannels == m_InputChannels.size() &&
|
||||
inputAudioBufferList.mBuffers[0].mDataByteSize == expectedDataSize )
|
||||
{
|
||||
m_pInputData = (float*)inputAudioBufferList.mBuffers[0].mData;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pInputData = NULL;
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
|
||||
//is this an input only device?
|
||||
|
|
@ -2219,7 +2222,6 @@ OSStatus WCMRCoreAudioDevice::AudioIOProc(AudioUnitRenderActionFlags * ioAction
|
|||
else if ((!m_OutputChannels.empty()) && (ioData->mBuffers[0].mNumberChannels == m_OutputChannels.size()))
|
||||
AudioCallback ((float *)ioData->mBuffers[0].mData, inNumberFrames, (uint32_t)inTimeStamp->mSampleTime, theStartTime);
|
||||
|
||||
Exit:
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
|
@ -2398,7 +2400,7 @@ WCMRCoreAudioDeviceManager::WCMRCoreAudioDeviceManager(WCMRAudioDeviceManagerCli
|
|||
}
|
||||
|
||||
//add a listener to find out when devices change...
|
||||
AudioHardwareAddPropertyListener (kAudioHardwarePropertyDevices, DevicePropertyChangeCallback, this);
|
||||
AudioHardwareAddPropertyListener (kAudioHardwarePropertyDevices, HardwarePropertyChangeCallback, this);
|
||||
|
||||
//Always add the None device first...
|
||||
m_NoneDevice = new WCMRNativeAudioNoneDevice(this);
|
||||
|
|
@ -2929,7 +2931,7 @@ WTErr WCMRCoreAudioDeviceManager::getDeviceBufferSizesImpl(const std::string & d
|
|||
}
|
||||
|
||||
|
||||
OSStatus WCMRCoreAudioDeviceManager::DevicePropertyChangeCallback (AudioHardwarePropertyID inPropertyID, void* inClientData)
|
||||
OSStatus WCMRCoreAudioDeviceManager::HardwarePropertyChangeCallback (AudioHardwarePropertyID inPropertyID, void* inClientData)
|
||||
{
|
||||
switch (inPropertyID)
|
||||
{
|
||||
|
|
@ -2940,9 +2942,10 @@ OSStatus WCMRCoreAudioDeviceManager::DevicePropertyChangeCallback (AudioHardware
|
|||
pManager->updateDeviceListImpl();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -81,7 +81,7 @@ protected:
|
|||
|
||||
AudioDeviceID m_DeviceID; ///< The CoreAudio device id
|
||||
bool m_StopRequested; ///< should be set to true when want to stop, set to false otherwise.
|
||||
float *m_pInputData; ///< This is what came in with the most recent callback.
|
||||
float *m_pInputData; ///< This is what came in with the most recent callback.
|
||||
int m_SampleCounter; ///< The current running sample counter, updated by the audio callback.
|
||||
int m_SampleCountAtLastIdle; ///< What was the sample count last time we checked...
|
||||
int m_StalledSampleCounter; ///< The number of idle calls with same sample count detected
|
||||
|
|
@ -93,9 +93,7 @@ protected:
|
|||
// int m_CyclesToAccumulate; ///< The number of cycles to accumulate the values for - maximum for last one second.
|
||||
// unsigned int m_CyclePeriod; ///< The number of host time units for a cycle period - determined by buffer size and sampling rate
|
||||
|
||||
|
||||
|
||||
AudioBufferList m_InputAudioBufferList; ///< The buffer list used to get AHHAL to render input to.
|
||||
|
||||
AudioUnit m_AUHALAudioUnit;///< The AUHAL AudioUnit
|
||||
|
||||
int m_BufferSizeChangeRequested;
|
||||
|
|
@ -152,6 +150,7 @@ protected:
|
|||
AudioDevicePropertyID inPropertyID, void *inClientData);
|
||||
void PropertyChangeProc (AudioDevicePropertyID inPropertyID);
|
||||
|
||||
void resetAudioDevice();
|
||||
private:
|
||||
|
||||
};
|
||||
|
|
@ -168,7 +167,7 @@ public:
|
|||
virtual ~WCMRCoreAudioDeviceManager(void); ///< Destructor
|
||||
|
||||
protected:
|
||||
static OSStatus DevicePropertyChangeCallback (AudioHardwarePropertyID inPropertyID, void* inClientData);
|
||||
static OSStatus HardwarePropertyChangeCallback (AudioHardwarePropertyID inPropertyID, void* inClientData);
|
||||
|
||||
virtual WCMRAudioDevice* initNewCurrentDeviceImpl(const std::string & deviceName);
|
||||
virtual void destroyCurrentDeviceImpl();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue