mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-13 18:16:35 +01:00
[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:
parent
8da1ad9fcf
commit
cb9f19baca
6 changed files with 124 additions and 30 deletions
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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, ¤tSamplingRate);
|
||||||
|
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);
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue