diff options
author | Greg Zharun <grygoriiz@wavesglobal.com> | 2015-02-28 18:38:45 +0200 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2015-03-31 17:29:41 -0400 |
commit | a2f82f8c5d46beead18d22a60c67c67e848d9561 (patch) | |
tree | 6c562159bcb62a5f8ad4c65d5c1099ee9034707d /libs/backends | |
parent | ce069da6827717d1428637fb2e9d4e9cbd40b30b (diff) |
[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
Diffstat (limited to 'libs/backends')
-rw-r--r-- | libs/backends/wavesaudio/waves_midi_device.cc | 69 | ||||
-rw-r--r-- | libs/backends/wavesaudio/wavesapi/devicemanager/WCMRPortAudioDeviceManager.cpp | 134 |
2 files changed, 96 insertions, 107 deletions
diff --git a/libs/backends/wavesaudio/waves_midi_device.cc b/libs/backends/wavesaudio/waves_midi_device.cc index 9e69633afd..31b6d019c1 100644 --- a/libs/backends/wavesaudio/waves_midi_device.cc +++ b/libs/backends/wavesaudio/waves_midi_device.cc @@ -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; - - 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() (?) + 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 (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; } - - Pm_QueueDestroy (_input_queue); - _input_queue = NULL; - _input_pm_stream = NULL; - _pm_input_id = pmNoDevice; - } - - - 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() (?) + + + if ( _output_pm_stream ) { + PmError err = Pm_Close (_output_pm_stream); + + 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() (?) + } + + 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 diff --git a/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRPortAudioDeviceManager.cpp b/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRPortAudioDeviceManager.cpp index 2d9081830c..b3469039f3 100644 --- a/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRPortAudioDeviceManager.cpp +++ b/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRPortAudioDeviceManager.cpp @@ -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()) - { - //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) + // Buffer size for ASIO devices can be changed from the control panel only + // We have driver driven logi here + if (m_CurrentBufferSize != newSize ) { - 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 |