[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:
parent
ce069da682
commit
a2f82f8c5d
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user