[Summary] Backend Improvements

[Details] Fixed error handling
Fixed switching to None device when something goes wrong with the current device
Backend now takes care when device ID changes - Sound Grid does this when the amount of channel changes and it's not going to change in the neared future.
Fixed sample rate changes notification from device to DAW - Some devices can respond with such updates, we must correctly process them.
This commit is contained in:
GZharun 2015-02-12 11:39:13 +02:00
parent 8da1ad9fcf
commit cb9f19baca
6 changed files with 124 additions and 30 deletions

View file

@ -420,19 +420,17 @@ AudioEngine::do_reset_backend()
// backup the device name // backup the device name
std::string name = _backend->device_name (); std::string name = _backend->device_name ();
std::cout << "AudioEngine::RESET::Stoping engine..." << std::endl;
stop();
std::cout << "AudioEngine::RESET::Reseting device..." << std::endl; std::cout << "AudioEngine::RESET::Reseting device..." << std::endl;
if ( 0 == _backend->reset_device () ) { if ( ( 0 == stop () ) &&
( 0 == _backend->reset_device () ) &&
( 0 == start () ) ) {
std::cout << "AudioEngine::RESET::Engine started..." << std::endl;
std::cout << "AudioEngine::RESET::Starting engine..." << std::endl;
start ();
// inform about possible changes // inform about possible changes
BufferSizeChanged (_backend->buffer_size() ); BufferSizeChanged (_backend->buffer_size() );
} else { } else {
DeviceError(); DeviceError();
} }
@ -471,9 +469,11 @@ AudioEngine::do_devicelist_update()
_devicelist_update_lock.unlock(); _devicelist_update_lock.unlock();
Glib::Threads::RecMutex::Lock pl (_state_lock);
g_atomic_int_dec_and_test (&_hw_devicelist_update_count); g_atomic_int_dec_and_test (&_hw_devicelist_update_count);
DeviceListChanged (); /* EMIT SIGNAL */ DeviceListChanged (); /* EMIT SIGNAL */
_devicelist_update_lock.lock(); _devicelist_update_lock.lock();
} else { } else {

View file

@ -802,8 +802,6 @@ EngineStateController::set_new_sample_rate_in_controller(framecnt_t sample_rate)
} }
bool bool
EngineStateController::set_new_buffer_size_in_controller(pframes_t buffer_size) EngineStateController::set_new_buffer_size_in_controller(pframes_t buffer_size)
{ {
@ -1350,11 +1348,10 @@ EngineStateController::_on_sample_rate_change(framecnt_t new_sample_rate)
framecnt_t sample_rate_to_set = new_sample_rate; framecnt_t sample_rate_to_set = new_sample_rate;
if (AudioEngine::instance()->session() ) { if (AudioEngine::instance()->session() ) {
// and we have current session we should restore it back to the one tracks uses // and we have current session we should restore it back to the one tracks uses
sample_rate_to_set = _current_state->sample_rate; sample_rate_to_set = AudioEngine::instance()->session()->frame_rate ();
} }
if ( set_new_sample_rate_in_controller (sample_rate_to_set) ) { if ( set_new_sample_rate_in_controller (sample_rate_to_set) ) {
push_current_state_to_backend(false);
SampleRateChanged(); // emit a signal SampleRateChanged(); // emit a signal
} else { } else {
// if sample rate can't be set // if sample rate can't be set
@ -1412,7 +1409,7 @@ EngineStateController::_on_device_list_change()
_states.push_front(_current_state); _states.push_front(_current_state);
} }
push_current_state_to_backend(false); push_current_state_to_backend(true);
current_device_disconnected = true; current_device_disconnected = true;
} }
} else { } else {

View file

@ -42,6 +42,7 @@ void WavesAudioBackend::AudioDeviceManagerNotification (NotificationReason reaso
case WCMRAudioDeviceManagerClient::BufferSizeChanged: case WCMRAudioDeviceManagerClient::BufferSizeChanged:
std::cout << "------------------------------- WCMRAudioDeviceManagerClient::BufferSizeChanged: " << *(uint32_t*)parameter << std::endl; std::cout << "------------------------------- WCMRAudioDeviceManagerClient::BufferSizeChanged: " << *(uint32_t*)parameter << std::endl;
_buffer_size_change(*(uint32_t*)parameter); _buffer_size_change(*(uint32_t*)parameter);
_buffer_size_change(*(int*)parameter);
break; break;
case WCMRAudioDeviceManagerClient::RequestReset: case WCMRAudioDeviceManagerClient::RequestReset:
std::cout << "------------------------------- WCMRAudioDeviceManagerClient::RequestReset" << std::endl; std::cout << "------------------------------- WCMRAudioDeviceManagerClient::RequestReset" << std::endl;
@ -51,8 +52,8 @@ void WavesAudioBackend::AudioDeviceManagerNotification (NotificationReason reaso
std::cout << "------------------------------- WCMRAudioDeviceManagerClient::RequestResync" << std::endl; std::cout << "------------------------------- WCMRAudioDeviceManagerClient::RequestResync" << std::endl;
break; break;
case WCMRAudioDeviceManagerClient::SamplingRateChanged: case WCMRAudioDeviceManagerClient::SamplingRateChanged:
std::cout << "------------------------------- WCMRAudioDeviceManagerClient::SamplingRateChanged: " << *(float*)parameter << std::endl; std::cout << "------------------------------- WCMRAudioDeviceManagerClient::SamplingRateChanged: " << *(int*)parameter << std::endl;
set_sample_rate(*(float*)parameter); _sample_rate_change(*(float*)parameter);
break; break;
case WCMRAudioDeviceManagerClient::Dropout: case WCMRAudioDeviceManagerClient::Dropout:
std::cout << "------------------------------- WCMRAudioDeviceManagerClient::Dropout: " << std::endl; std::cout << "------------------------------- WCMRAudioDeviceManagerClient::Dropout: " << std::endl;
@ -401,7 +402,11 @@ WavesAudioBackend::set_sample_rate (float sample_rate)
return -1; return -1;
} }
_sample_rate_change(sample_rate); // if call to set sample rate is successful
// but device sample rate differs from the value we tried to set
// this means we are driven by device for buffer size
sample_rate = _device->CurrentSamplingRate ();
_sample_rate_change(sample_rate);
if (device_needs_restart) { if (device_needs_restart) {
// COMMENTED DBG LOGS */ std::cout << "\t\t[" << _device->DeviceName() << "]->SetStreaming (true);"<< std::endl; // COMMENTED DBG LOGS */ std::cout << "\t\t[" << _device->DeviceName() << "]->SetStreaming (true);"<< std::endl;

View file

@ -359,10 +359,10 @@ WTErr WCMRAudioDevice::ResetDevice ()
WTErr err = SetStreaming(false); WTErr err = SetStreaming(false);
if (err == eNoErr) if (err == eNoErr)
SetActive(false); err = SetActive(false);
if (err == eNoErr && wasActive) if (err == eNoErr && wasActive)
SetActive(true); err = SetActive(true);
if (err == eNoErr && wasStreaming) { if (err == eNoErr && wasStreaming) {
err = SetStreaming(true); err = SetStreaming(true);

View file

@ -247,6 +247,9 @@ WTErr WCMRCoreAudioDevice::UpdateDeviceInfo ()
WTErr retVal = eNoErr; WTErr retVal = eNoErr;
// Some devices change the ID during restart
WTErr errId = UpdateDeviceId();
// Update all devices parts regardless of errors // Update all devices parts regardless of errors
WTErr errName = UpdateDeviceName(); WTErr errName = UpdateDeviceName();
WTErr errIn = UpdateDeviceInputs(); WTErr errIn = UpdateDeviceInputs();
@ -257,7 +260,7 @@ WTErr WCMRCoreAudioDevice::UpdateDeviceInfo ()
errSR = UpdateDeviceSampleRates(); errSR = UpdateDeviceSampleRates();
errBS = UpdateDeviceBufferSizes(); errBS = UpdateDeviceBufferSizes();
if(errName != eNoErr || errIn != eNoErr || errOut != eNoErr || errSR != eNoErr || errBS != eNoErr) if(errId != eNoErr || errName != eNoErr || errIn != eNoErr || errOut != eNoErr || errSR != eNoErr || errBS != eNoErr)
{ {
retVal = eCoreAudioFailed; retVal = eCoreAudioFailed;
} }
@ -265,6 +268,69 @@ WTErr WCMRCoreAudioDevice::UpdateDeviceInfo ()
return retVal; return retVal;
} }
WTErr WCMRCoreAudioDevice::UpdateDeviceId()
{
//Get device count...
UInt32 propSize = 0;
WTErr retVal = eNoErr;
OSStatus osErr = AudioHardwareGetPropertyInfo (kAudioHardwarePropertyDevices, &propSize, NULL);
ASSERT_ERROR(osErr, "AudioHardwareGetProperty 1");
if (WUIsError(osErr))
throw osErr;
size_t numDevices = propSize / sizeof (AudioDeviceID);
AudioDeviceID* deviceIDs = new AudioDeviceID[numDevices];
//retrieve the device IDs
propSize = numDevices * sizeof (AudioDeviceID);
osErr = AudioHardwareGetProperty (kAudioHardwarePropertyDevices, &propSize, deviceIDs);
ASSERT_ERROR(osErr, "Error while getting audio devices: AudioHardwareGetProperty 2");
if (WUIsError(osErr))
throw osErr;
//now add the ones that are not there...
for (size_t deviceIndex = 0; deviceIndex < numDevices; deviceIndex++)
{
DeviceInfo* pDevInfo = 0;
//Get device name and create new DeviceInfo entry
//Get property name size.
osErr = AudioDeviceGetPropertyInfo(deviceIDs[deviceIndex], 0, 0, kAudioDevicePropertyDeviceName, &propSize, NULL);
if (osErr == kAudioHardwareNoError)
{
//Get property: name.
char* deviceName = new char[propSize];
osErr = AudioDeviceGetProperty(deviceIDs[deviceIndex], 0, 0, kAudioDevicePropertyDeviceName, &propSize, deviceName);
if (osErr == kAudioHardwareNoError)
{
if ( (m_DeviceName == deviceName) &&
(m_DeviceID != deviceIDs[deviceIndex]) ) {
m_DeviceID = deviceIDs[deviceIndex];
m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::DeviceDebugInfo, (void *)"Current device has changed it's id.");
}
}
else
{
retVal = eCoreAudioFailed;
DEBUG_MSG("Failed to get device name. Device ID: " << m_DeviceID);
}
delete [] deviceName;
}
else
{
retVal = eCoreAudioFailed;
DEBUG_MSG("Failed to get device name prop Info. Device ID: " << m_DeviceID);
}
}
delete [] deviceIDs;
}
//********************************************************************************************** //**********************************************************************************************
// WCMRCoreAudioDevice::UpdateDeviceName // WCMRCoreAudioDevice::UpdateDeviceName
// //
@ -875,13 +941,26 @@ WTErr WCMRCoreAudioDevice::SetAndCheckCurrentSamplingRate (int newRate)
OSStatus err = kAudioHardwareNoError; OSStatus err = kAudioHardwareNoError;
UInt32 propSize = 0; UInt32 propSize = 0;
// Check current sample rate
/*
propSize = sizeof (Float64);
Float64 currentSamplingRate = 0.0;
err = AudioDeviceGetProperty(m_DeviceID, 0, 0, kAudioDevicePropertyNominalSampleRate, &propSize, &currentSamplingRate);
if (err == kAudioHardwareNoError)
{
if (currentSamplingRate == newRate)
{
// nothing to do
return (retVal);
}
}*/
// 1. Set new sampling rate // 1. Set new sampling rate
Float64 newNominalRate = newRate; Float64 newNominalRate = newRate;
propSize = sizeof (Float64); propSize = sizeof (Float64);
err = AudioDeviceSetProperty(m_DeviceID, NULL, 0, 0, kAudioDevicePropertyNominalSampleRate, propSize, &newNominalRate); err = AudioDeviceSetProperty(m_DeviceID, NULL, 0, 0, kAudioDevicePropertyNominalSampleRate, propSize, &newNominalRate);
m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::DeviceDebugInfo, (void *)"Changed the Sampling Rate.");
if (err != kAudioHardwareNoError) if (err != kAudioHardwareNoError)
{ {
retVal = eCoreAudioFailed; retVal = eCoreAudioFailed;
@ -925,6 +1004,8 @@ WTErr WCMRCoreAudioDevice::SetAndCheckCurrentSamplingRate (int newRate)
// If sample rate actually changed // If sample rate actually changed
if (tryAgain != 0) if (tryAgain != 0)
{ {
m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::DeviceDebugInfo, (void *)"Changed the Sampling Rate.");
// Update member with new rate // Update member with new rate
m_CurrentSamplingRate = newRate; m_CurrentSamplingRate = newRate;
@ -941,6 +1022,9 @@ WTErr WCMRCoreAudioDevice::SetAndCheckCurrentSamplingRate (int newRate)
char debugMsg[128]; char debugMsg[128];
snprintf (debugMsg, sizeof(debugMsg), "Unable to change SR, even after waiting for %d milliseconds", actualWait * PROPERTY_CHANGE_SLEEP_TIME_MILLISECONDS); snprintf (debugMsg, sizeof(debugMsg), "Unable to change SR, even after waiting for %d milliseconds", actualWait * PROPERTY_CHANGE_SLEEP_TIME_MILLISECONDS);
m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::DeviceDebugInfo, (void *)debugMsg); m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::DeviceDebugInfo, (void *)debugMsg);
float sample_rate_update = actualSamplingRate;
m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::SamplingRateChanged, (void *)&sample_rate_update);
} }
} }
@ -1471,8 +1555,8 @@ WTErr WCMRCoreAudioDevice::SetupAUHAL()
} }
//gains access to the services provided by the component //gains access to the services provided by the component
OpenAComponent(comp, &m_AUHALAudioUnit); OpenAComponent(comp, &m_AUHALAudioUnit);
retVal = EnableAudioUnitIO(); retVal = EnableAudioUnitIO();
if (retVal != eNoErr) if (retVal != eNoErr)
@ -1730,7 +1814,6 @@ WTErr WCMRCoreAudioDevice::TearDownAUHAL()
} }
//********************************************************************************************** //**********************************************************************************************
// WCMRCoreAudioDevice::SetActive // WCMRCoreAudioDevice::SetActive
// //
@ -1796,9 +1879,8 @@ WTErr WCMRCoreAudioDevice::SetActive (bool newState)
m_DropsDetected = 0; m_DropsDetected = 0;
m_DropsReported = 0; m_DropsReported = 0;
m_IgnoreThisDrop = true; m_IgnoreThisDrop = true;
UpdateDeviceInfo(); UpdateDeviceInfo();
} }
m_IsActive = newState; m_IsActive = newState;
@ -1926,6 +2008,7 @@ WTErr WCMRCoreAudioDevice::SetStreaming (bool newState)
if(err) if(err)
{ {
DEBUG_MSG( "Failed to start AudioUnit, err " << err ); DEBUG_MSG( "Failed to start AudioUnit, err " << err );
m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::DeviceDebugInfo, (void *)"Failed to start AudioUnit.");
retVal = eGenericErr; retVal = eGenericErr;
goto Exit; goto Exit;
} }
@ -2556,7 +2639,7 @@ WTErr WCMRCoreAudioDeviceManager::getDeviceAvailableSampleRates(DeviceID deviceI
return retVal; return retVal;
} }
WTErr WCMRCoreAudioDeviceManager::getDeviceMaxInputChannels(DeviceID deviceId, unsigned int& inputChannels) WTErr WCMRCoreAudioDeviceManager::getDeviceMaxInputChannels(DeviceID deviceId, unsigned int& inputChannels)
{ {
@ -2878,6 +2961,15 @@ WTErr WCMRCoreAudioDeviceManager::updateDeviceListImpl()
NotifyClient (WCMRAudioDeviceManagerClient::IODeviceDisconnected); NotifyClient (WCMRAudioDeviceManagerClient::IODeviceDisconnected);
return err; return err;
} }
WCMRCoreAudioDevice* current_device = dynamic_cast<WCMRCoreAudioDevice*>(m_CurrentDevice);
if ( current_device &&
(current_device->DeviceID() != devInfo.m_DeviceId ) )
{
NotifyClient (WCMRAudioDeviceManagerClient::RequestReset);
return err;
}
} }
NotifyClient (WCMRAudioDeviceManagerClient::DeviceListChanged); NotifyClient (WCMRAudioDeviceManagerClient::DeviceListChanged);

View file

@ -138,6 +138,7 @@ protected:
#endif //WV_USE_TONE_GEN #endif //WV_USE_TONE_GEN
WTErr UpdateDeviceInfo (); WTErr UpdateDeviceInfo ();
WTErr UpdateDeviceId ();
WTErr UpdateDeviceName(); WTErr UpdateDeviceName();
WTErr UpdateDeviceInputs(); WTErr UpdateDeviceInputs();
WTErr UpdateDeviceOutputs(); WTErr UpdateDeviceOutputs();
@ -167,8 +168,7 @@ protected:
static OSStatus StaticPropertyChangeProc (AudioDeviceID inDevice, UInt32 inChannel, Boolean isInput, static OSStatus StaticPropertyChangeProc (AudioDeviceID inDevice, UInt32 inChannel, Boolean isInput,
AudioDevicePropertyID inPropertyID, void *inClientData); AudioDevicePropertyID inPropertyID, void *inClientData);
void PropertyChangeProc (AudioDevicePropertyID inPropertyID); void PropertyChangeProc (AudioDevicePropertyID inPropertyID);
void resetAudioDevice();
private: private:
}; };