summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGreg Zharun <grygoriiz@wavesglobal.com>2015-02-28 18:38:45 +0200
committerPaul Davis <paul@linuxaudiosystems.com>2015-03-31 17:29:41 -0400
commita2f82f8c5d46beead18d22a60c67c67e848d9561 (patch)
tree6c562159bcb62a5f8ad4c65d5c1099ee9034707d
parentce069da6827717d1428637fb2e9d4e9cbd40b30b (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
-rw-r--r--libs/ardour/ardour/audioengine.h1
-rw-r--r--libs/ardour/audioengine.cc6
-rw-r--r--libs/backends/wavesaudio/waves_midi_device.cc69
-rw-r--r--libs/backends/wavesaudio/wavesapi/devicemanager/WCMRPortAudioDeviceManager.cpp134
4 files changed, 102 insertions, 108 deletions
diff --git a/libs/ardour/ardour/audioengine.h b/libs/ardour/ardour/audioengine.h
index ed1ddb8609..b1e059e76a 100644
--- a/libs/ardour/ardour/audioengine.h
+++ b/libs/ardour/ardour/audioengine.h
@@ -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();
diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc
index 160a2b36df..6d854a80a5 100644
--- a/libs/ardour/audioengine.cc
+++ b/libs/ardour/audioengine.cc
@@ -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;
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