13
0

[Summary] Added actions to handle abnormal behavior during stream stop for MIDI and Audio devices.

Made correct error handling for cases we didn't see before.
Removed redundant and experimental code I forgot to remove months ago.
Added debug output which will help in future testing

Conflicts:
	libs/ardour/ardour/audioengine.h
	libs/ardour/engine_state_controller.cc
	libs/backends/wavesaudio/waves_midi_device.cc
This commit is contained in:
Greg Zharun 2015-02-28 18:38:45 +02:00 committed by Paul Davis
parent ce069da682
commit a2f82f8c5d
4 changed files with 99 additions and 105 deletions

View File

@ -104,6 +104,7 @@ class LIBARDOUR_API AudioEngine : public SessionHandlePtr, public PortManager
bool in_process_thread ();
uint32_t process_thread_count ();
int backend_reset_requested();
void request_backend_reset();
void request_device_list_update();
void launch_device_control_app();

View File

@ -394,6 +394,11 @@ AudioEngine::request_backend_reset()
_hw_reset_condition.signal ();
}
int
AudioEngine::backend_reset_requested()
{
return g_atomic_int_get (&_hw_reset_request_count);
}
void
AudioEngine::do_reset_backend()
@ -409,7 +414,6 @@ AudioEngine::do_reset_backend()
_reset_request_lock.unlock();
Glib::Threads::RecMutex::Lock pl (_state_lock);
g_atomic_int_dec_and_test (&_hw_reset_request_count);
std::cout << "AudioEngine::RESET::Reset request processing" << std::endl;

View File

@ -124,32 +124,53 @@ WavesMidiDevice::open (PmTimeProcPtr time_proc, void* time_info)
void
WavesMidiDevice::close ()
{
// COMMENTED DBG LOGS */ std::cout << "WavesMidiDevice::close ():" << name () << std::endl;
WavesMidiEvent *waves_midi_event;
DEBUG_TRACE (DEBUG::WavesMIDI, string_compose ("WavesMidiDevice::close (): %1\n", name ()));
WavesMidiEvent *waves_midi_event;
if (_input_pm_stream) {
PmError err = Pm_Close (_input_pm_stream);
if (_input_pm_stream) {
Pm_Close (_input_pm_stream);
while (1 == Pm_Dequeue (_input_queue, &waves_midi_event)) {
delete waves_midi_event; // XXX possible dup free in ~WavesMidiBuffer() (?)
if (err != pmNoError) {
std::cerr << "WavesMidiDevice::close (): Pm_Close () failed for " << _pm_input_id << "-[" << name () << "]!" << std::endl;
char* err_msg = new char[256];
Pm_GetHostErrorText(err_msg, 256);
std::cerr << "Error: " << err_msg << std::endl;
std::cerr << "Aborting!" << std::endl;
Pm_Abort (_input_pm_stream);
}
while (1 == Pm_Dequeue (_input_queue, &waves_midi_event)) {
delete waves_midi_event; // XXX possible dup free in ~WavesMidiBuffer() (?)
}
Pm_QueueDestroy (_input_queue);
_input_queue = NULL;
_input_pm_stream = NULL;
_pm_input_id = pmNoDevice;
}
if ( _output_pm_stream ) {
PmError err = Pm_Close (_output_pm_stream);
Pm_QueueDestroy (_input_queue);
_input_queue = NULL;
_input_pm_stream = NULL;
_pm_input_id = pmNoDevice;
}
if (err != pmNoError) {
std::cerr << "WavesMidiDevice::close (): Pm_Close () failed for " << _pm_output_id << "-[" << name () << "]!" << std::endl;
char* err_msg = new char[256];
Pm_GetHostErrorText(err_msg, 256);
std::cerr << "Error: " << err_msg << std::endl;
std::cerr << "Aborting!" << std::endl;
Pm_Abort (_output_pm_stream);
}
while (1 == Pm_Dequeue (_output_queue, &waves_midi_event)) {
delete waves_midi_event; // XXX possible dup free in ~WavesMidiBuffer() (?)
}
if ( _output_pm_stream ) {
Pm_Close (_output_pm_stream);
while (1 == Pm_Dequeue (_output_queue, &waves_midi_event)) {
delete waves_midi_event; // XXX possible dup free in ~WavesMidiBuffer() (?)
Pm_QueueDestroy (_output_queue);
_output_queue = NULL;
_output_pm_stream = NULL;
_pm_output_id = pmNoDevice;
}
Pm_QueueDestroy (_output_queue);
_output_queue = NULL;
_output_pm_stream = NULL;
_pm_output_id = pmNoDevice;
}
}
void

View File

@ -605,7 +605,8 @@ WTErr WCMRPortAudioDevice::SetCurrentSamplingRate (int newRate)
//make the change...
m_CurrentSamplingRate = newRate;
PaError paErr = PaAsio_SetStreamSampleRate (m_PortAudioStream, m_CurrentSamplingRate);
PaError paErr = PaAsio_SetStreamSampleRate (m_PortAudioStream, m_CurrentSamplingRate);
std::cout << "Sleeping after sample rate change " << std::endl;
Pa_Sleep(PROPERTY_CHANGE_SLEEP_TIME_MILLISECONDS); // sleep some time to make sure the change has place
if (paErr != paNoError)
@ -655,14 +656,6 @@ WTErr WCMRPortAudioDevice::SetCurrentBufferSize (int newSize)
WTErr retVal = eNoErr;
std::vector<int>::iterator intIter;
//changes the status.
int oldSize = CurrentBufferSize();
bool oldActive = Active();
//same size, nothing to do.
if (oldSize == newSize)
return (retVal);
if (Streaming())
{
//Can't change, perhaps use an "in use" type of error
@ -670,44 +663,17 @@ WTErr WCMRPortAudioDevice::SetCurrentBufferSize (int newSize)
return (retVal);
}
std::cout << "Setting buffer: " << newSize << std::endl;
//see if this is one of our supported rates...
intIter = find(m_BufferSizes.begin(), m_BufferSizes.end(), newSize);
if (intIter == m_BufferSizes.end())
// Buffer size for ASIO devices can be changed from the control panel only
// We have driver driven logi here
if (m_CurrentBufferSize != newSize )
{
//Sample rate proposed by client is not supported any more
if (m_BufferSizes.size() == 1)
{
// we have only one aloved buffer size which is preffered by PA
// this is the only value which could be set
newSize = m_BufferSizes[0];
int bufferSize = newSize;
// notify client to update sample rate after us
m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::BufferSizeChanged, (void *)&bufferSize);
return retVal;
} else {
// more then one buffer size value is available
//Can't change, perhaps use an "invalid param" type of error
retVal = eCommandLineParameter;
return (retVal);
}
}
if (oldActive)
{
//Deactivate it for the change...
SetActive (false);
}
//make the change...
m_CurrentBufferSize = newSize;
//reactivate it.
if (oldActive)
{
retVal = SetActive (true);
// we have only one aloved buffer size which is preffered by PA
// this is the only value which could be set
newSize = m_BufferSizes[0];
int bufferSize = newSize;
// notify client to update buffer size
m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::BufferSizeChanged, (void *)&bufferSize);
return retVal;
}
return (retVal);
@ -751,17 +717,6 @@ void WCMRPortAudioDevice::activateDevice (bool callerIsWaiting/*=false*/)
// if device is not active activate it
if (!Active() )
{
std::list<long> buffersSizes;
buffersSizes.push_back(m_CurrentBufferSize);
long minSize, maxSize, preferredSize, granularity;
PaError paErr = PaAsio_GetAvailableBufferSizes(m_DeviceID, &minSize, &maxSize, &preferredSize, &granularity);
if (paErr == paNoError)
{
buffersSizes.push_front(preferredSize);
}
PaStreamParameters inputParameters, outputParameters;
PaStreamParameters *pInS = NULL, *pOutS = NULL;
@ -786,27 +741,20 @@ void WCMRPortAudioDevice::activateDevice (bool callerIsWaiting/*=false*/)
if (outputParameters.channelCount)
pOutS = &outputParameters;
// try opening stream with current buffer and the rest if not successful
std::list<long>::const_iterator bufferIter = buffersSizes.begin();
for (; bufferIter != buffersSizes.end(); ++bufferIter) {
std::cout << "API::Device" << m_DeviceName << " Opening device stream " << std::endl;
std::cout << "Sample rate: " << m_CurrentSamplingRate << " buffer size: " << *bufferIter << std::endl;
paErr = Pa_OpenStream(&m_PortAudioStream,
pInS,
pOutS,
m_CurrentSamplingRate,
m_CurrentBufferSize,
paDitherOff,
WCMRPortAudioDevice::TheCallback,
this);
std::cout << "API::Device " << m_DeviceName << " Opening device stream " << std::endl;
std::cout << "Sample rate: " << m_CurrentSamplingRate << " buffer size: " << m_CurrentBufferSize << std::endl;
paErr = Pa_OpenStream(&m_PortAudioStream,
pInS,
pOutS,
m_CurrentSamplingRate,
m_CurrentBufferSize,
paDitherOff,
WCMRPortAudioDevice::TheCallback,
this);
if(paErr == paNoError)
{
break;
}
std::cout << "Cannot open streamm with buffer: "<< *bufferIter << " Error: " << Pa_GetErrorText (paErr) << std::endl;
if(paErr != paNoError)
{
std::cout << "Cannot open streamm with buffer: "<< m_CurrentBufferSize << " Error: " << Pa_GetErrorText (paErr) << std::endl;
if (paErr == paUnanticipatedHostError)
std::cout << "Error details: "<< Pa_GetLastHostErrorInfo ()->errorText << "; code: " << Pa_GetLastHostErrorInfo ()->errorCode << std::endl;
@ -814,11 +762,16 @@ void WCMRPortAudioDevice::activateDevice (bool callerIsWaiting/*=false*/)
if(paErr == paNoError)
{
std::cout << "Stream has been opened! "<< std::endl;
// check for possible changes
long minSize, maxSize, preferredSize, granularity;
PaError paErr = PaAsio_GetAvailableBufferSizes(m_DeviceID, &minSize, &maxSize, &preferredSize, &granularity);
std::cout << "Checked if buffer size changed "<< std::endl;
if (paErr == paNoError && m_CurrentBufferSize != preferredSize)
{
std::cout << "Buffer size has changed "<< std::endl;
m_CurrentBufferSize = preferredSize;
m_BufferSizes.clear();
m_BufferSizes.push_back(preferredSize);
@ -837,6 +790,7 @@ void WCMRPortAudioDevice::activateDevice (bool callerIsWaiting/*=false*/)
m_ResetReported = 0;
m_ResyncRequested = 0;
m_ResyncReported = 0;
std::cout << "Installing new mesage hook "<< std::endl;
PaAsio_SetMessageHook (StaticASIOMessageHook, this);
}
m_IsActive = true;
@ -855,6 +809,8 @@ void WCMRPortAudioDevice::activateDevice (bool callerIsWaiting/*=false*/)
}
std::cout << "Activation is DONE "<< std::endl;
if (callerIsWaiting)
SetEvent(m_hActivationDone);
}
@ -987,7 +943,7 @@ void WCMRPortAudioDevice::stopStreaming (bool callerIsWaiting/*=false*/)
std::cout << "API::Device " << m_DeviceName << " Stopping device stream" << std::endl;
paErr = Pa_StopStream( m_PortAudioStream );
if(paErr == paNoError)
if(paErr == paNoError || paErr == paStreamIsStopped)
{
// if the stream was stopped successfully
m_IsStreaming = false;
@ -995,9 +951,23 @@ void WCMRPortAudioDevice::stopStreaming (bool callerIsWaiting/*=false*/)
}
else
{
std::cout << "Failed to stop PA stream: " << Pa_GetErrorText (paErr) << std::endl;
DEBUG_MSG( "Failed to stop PA stream " << Pa_GetErrorText (paErr) );
m_lastErr = eGenericErr;
std::cout << "Failed to stop PA stream normaly! Aborting the stream. Error:" << Pa_GetErrorText (paErr) << std::endl;
DEBUG_MSG( "Failed to stop PA stream normaly! Aborting the stream. Error:" << Pa_GetErrorText (paErr) );
Pa_Sleep(PROPERTY_CHANGE_SLEEP_TIME_MILLISECONDS); // sleep some time to make sure the change has place
PaError abortionError = Pa_AbortStream( m_PortAudioStream );
if(abortionError == paNoError || abortionError == paStreamIsStopped)
{
// if the stream was stopped successfully
m_IsStreaming = false;
m_pInputData = NULL;
}
else
{
std::cout << "Failed to stop PA stream: " << Pa_GetErrorText (paErr) << std::endl;
DEBUG_MSG( "Failed to stop PA stream " << Pa_GetErrorText (paErr) );
m_lastErr = eGenericErr;
}
}
}
@ -1019,8 +989,6 @@ void WCMRPortAudioDevice::stopStreaming (bool callerIsWaiting/*=false*/)
//**********************************************************************************************
void WCMRPortAudioDevice::resetDevice (bool callerIsWaiting /*=false*/ )
{
std::cout << "API::Device" << m_DeviceName << "Reseting device" << std::endl;
PaError paErr = paNoError;
// Keep device sates