diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2015-05-13 19:11:27 -0400 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2015-06-29 14:18:14 -0400 |
commit | 237f255fb51d02bf312c04900ecd9a37579ff9f8 (patch) | |
tree | bb58b63d398de97f327656981f6a2201058cc0b9 /libs | |
parent | 0fca07fa9df93d9bcbf516be2824247b39a1aeff (diff) |
meld-driven unification of current ardour-ish WavesAudio backend and current tracks WavesAudio backend.
May be incomplete, and may not compile (testing to follow)
Diffstat (limited to 'libs')
14 files changed, 487 insertions, 250 deletions
diff --git a/libs/backends/wavesaudio/waves_audiobackend.cc b/libs/backends/wavesaudio/waves_audiobackend.cc index 7fd6da2f39..2a5ddba991 100644 --- a/libs/backends/wavesaudio/waves_audiobackend.cc +++ b/libs/backends/wavesaudio/waves_audiobackend.cc @@ -99,8 +99,8 @@ void WavesAudioBackend::AudioDeviceManagerNotification (NotificationReason reaso } -WavesAudioBackend::WavesAudioBackend (AudioEngine& e) - : AudioBackend (e, __backend_info) +WavesAudioBackend::WavesAudioBackend (AudioEngine& e, AudioBackendInfo& info) + : AudioBackend (e, info) , _audio_device_manager (this) , _midi_device_manager (*this) , _device (NULL) @@ -420,7 +420,11 @@ WavesAudioBackend::set_sample_rate (float sample_rate) 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) { // COMMENTED DBG LOGS */ std::cout << "\t\t[" << _device->DeviceName() << "]->SetStreaming (true);"<< std::endl; @@ -499,8 +503,6 @@ WavesAudioBackend::reset_device () { // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::_reset_device ():" << std::endl; - WTErr retVal = eNoErr; - if (!_device) { std::cerr << "WavesAudioBackend::set_buffer_size (): No device is set!" << std::endl; return -1; @@ -829,11 +831,23 @@ WavesAudioBackend::freewheel (bool start_stop) } _call_thread_init_callback = true; _freewheel_thread (); - engine.freewheel_callback (start_stop); + + while (!engine.freewheeling()) { + sleep(0); + } + + // freewheel thread was not activated successfully + if (_freewheel_thread_active == false) { + engine.freewheel_callback(false); + } } else { _freewheel_thread_active = false; // stop _freewheel_thread () - engine.freewheel_callback (start_stop); + + while (engine.freewheeling()) { + sleep(0); + } + _call_thread_init_callback = true; WTErr retval = _device->SetStreaming (true); if (retval != eNoErr) { @@ -873,6 +887,10 @@ WavesAudioBackend::_freewheel_thread () _freewheel_thread_active = true; if ((pthread_create (&thread_id, &attributes, __start_process_thread, thread_data))) { _freewheel_thread_active = false; + + // release invoking thread + engine.freewheel_callback(true); + std::cerr << "WavesAudioBackend::freewheel_thread (): pthread_create () failed!" << std::endl; return; } @@ -881,6 +899,9 @@ WavesAudioBackend::_freewheel_thread () return; } + // notify angine that freewheeling is started + engine.freewheel_callback(true); + if (_call_thread_init_callback) { _call_thread_init_callback = false; AudioEngine::thread_init_callback (this); @@ -889,6 +910,10 @@ WavesAudioBackend::_freewheel_thread () while (_freewheel_thread_active) { engine.process_callback (_buffer_size); } + + // notify angine that freewheeling is stopped + engine.freewheel_callback(false); + // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::_freewheel_thread (): FINISHED" << std::endl; return; } @@ -1238,7 +1263,7 @@ WavesAudioBackend::__waves_backend_factory (AudioEngine& e) { // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::__waves_backend_factory ():" << std::endl; if (!__instance) { - __instance.reset (new WavesAudioBackend (e)); + __instance.reset (new WavesAudioBackend (e, *(descriptor()))); } return __instance; } @@ -1260,7 +1285,6 @@ WavesAudioBackend::__instantiate (const std::string& arg1, const std::string& ar LARGE_INTEGER Frequency; QueryPerformanceFrequency(&Frequency); __performance_counter_frequency = Frequency.QuadPart; - std::cout << "__performance_counter_frequency:" << __performance_counter_frequency << std::endl; #endif return 0; diff --git a/libs/backends/wavesaudio/waves_audiobackend.h b/libs/backends/wavesaudio/waves_audiobackend.h index ad40d094df..68af4b2a04 100644 --- a/libs/backends/wavesaudio/waves_audiobackend.h +++ b/libs/backends/wavesaudio/waves_audiobackend.h @@ -70,7 +70,7 @@ class WavesMidiPort; class WavesAudioBackend : public AudioBackend, WCMRAudioDeviceManagerClient { public: - WavesAudioBackend (AudioEngine& e); + WavesAudioBackend (AudioEngine& e, AudioBackendInfo&); virtual ~WavesAudioBackend (); /* AUDIOBACKEND API */ diff --git a/libs/backends/wavesaudio/waves_audioport.cc b/libs/backends/wavesaudio/waves_audioport.cc index 1249f4d31e..8f967f0a57 100644 --- a/libs/backends/wavesaudio/waves_audioport.cc +++ b/libs/backends/wavesaudio/waves_audioport.cc @@ -18,13 +18,21 @@ */ #include "waves_audioport.h" +#include "ardour/runtime_functions.h" +#include "pbd/malign.h" using namespace ARDOUR; WavesAudioPort::WavesAudioPort (const std::string& port_name, PortFlags flags) : WavesDataPort (port_name, flags) { - memset (_buffer, 0, sizeof (_buffer)); + aligned_malloc ((void**)&_buffer, MAX_BUFFER_SIZE_BYTES, 32 /*32 byte alignment*/); + memset (_buffer, 0, MAX_BUFFER_SIZE_BYTES); +} + +WavesAudioPort::~WavesAudioPort () +{ + aligned_free (_buffer); } @@ -35,24 +43,25 @@ void* WavesAudioPort::get_buffer (pframes_t nframes) std::vector<WavesDataPort*>::const_iterator it = get_connections ().begin (); if (it != get_connections ().end ()) { - /* In fact, the static casting to (const WavesAudioPort*) is not that safe. - * However, mixing the buffers is assumed in the time critical conditions. - * Base class WavesDataPort takes is supposed to provide enough consistentcy - * of the connections. - */ - // get first buffer data - // use optimized function to fill the buffer intialy - ARDOUR::copy_vector (_buffer, ((const WavesAudioPort*)*it)->const_buffer (), nframes); - ++it; - - // mix the rest - for (; it != get_connections ().end (); ++it) { - Sample* tgt = buffer (); - const Sample* src = ((const WavesAudioPort*)*it)->const_buffer (); - for (uint32_t frame = 0; frame < nframes; ++frame, ++tgt, ++src) { - *tgt += *src; - } - } + /* In fact, the static casting to (const WavesAudioPort*) is not that safe. + * However, mixing the buffers is assumed in the time critical conditions. + * Base class WavesDataPort takes is supposed to provide enough consistentcy + * of the connections. + */ + + // get first buffer data + // use optimized function to fill the buffer intialy + ARDOUR::copy_vector (_buffer, ((const WavesAudioPort*)*it)->const_buffer (), nframes); + ++it; + + // mix the rest + for (; it != get_connections ().end (); ++it) { + Sample* tgt = buffer (); + const Sample* src = ((const WavesAudioPort*)*it)->const_buffer (); + + // use otimized function to mix the buffers + ARDOUR::mix_buffers_no_gain (tgt, src, nframes); + } } } return _buffer; diff --git a/libs/backends/wavesaudio/waves_audioport.h b/libs/backends/wavesaudio/waves_audioport.h index 5b4ab52449..d658dba868 100644 --- a/libs/backends/wavesaudio/waves_audioport.h +++ b/libs/backends/wavesaudio/waves_audioport.h @@ -35,7 +35,7 @@ public: WavesAudioPort (const std::string& port_name, PortFlags flags); - virtual ~WavesAudioPort () { }; + virtual ~WavesAudioPort (); virtual DataType type () const { return DataType::AUDIO; }; @@ -49,7 +49,7 @@ protected: private: - Sample _buffer[MAX_BUFFER_SIZE_SAMPLES]; + Sample *_buffer; }; } // namespace diff --git a/libs/backends/wavesaudio/waves_dataport.cc b/libs/backends/wavesaudio/waves_dataport.cc index d1dacc90eb..ffdc9865f3 100644 --- a/libs/backends/wavesaudio/waves_dataport.cc +++ b/libs/backends/wavesaudio/waves_dataport.cc @@ -67,7 +67,7 @@ int WavesDataPort::connect (WavesDataPort *port) } if (is_connected (port)) { - std::cerr << "WavesDataPort::connect (): the ports are already connected!" << std::endl; + // std::cerr << "WavesDataPort::connect (): the ports are already connected!" << std::endl; return -1; } @@ -115,8 +115,7 @@ void WavesDataPort::_disconnect (WavesDataPort *port, bool api_call) port->_disconnect (this, false); } - if (is_input() && _connections.empty()) - { + if (is_input() && _connections.empty()) { _wipe_buffer(); } } @@ -124,13 +123,21 @@ void WavesDataPort::_disconnect (WavesDataPort *port, bool api_call) void WavesDataPort::disconnect_all () { + _disconnect_all (); + + if (is_input()) { + _wipe_buffer(); + } +} + +void WavesDataPort::_disconnect_all () +{ while (!_connections.empty ()) { _connections.back ()->_disconnect (this, false); _connections.pop_back (); } } - bool WavesDataPort::is_physically_connected () const { for (std::vector<WavesDataPort*>::const_iterator it = _connections.begin (); it != _connections.end (); ++it) { diff --git a/libs/backends/wavesaudio/waves_dataport.h b/libs/backends/wavesaudio/waves_dataport.h index 1b2f26f3f1..a5b8243bbe 100644 --- a/libs/backends/wavesaudio/waves_dataport.h +++ b/libs/backends/wavesaudio/waves_dataport.h @@ -106,6 +106,7 @@ private: std::vector<WavesDataPort*> _connections; void _connect (WavesDataPort* port, bool api_call); + void _disconnect_all (); void _disconnect (WavesDataPort* port, bool api_call); }; diff --git a/libs/backends/wavesaudio/waves_midi_device.cc b/libs/backends/wavesaudio/waves_midi_device.cc index 25d06da481..9bb6661136 100644 --- a/libs/backends/wavesaudio/waves_midi_device.cc +++ b/libs/backends/wavesaudio/waves_midi_device.cc @@ -18,6 +18,12 @@ */ #include <iostream> + +#include "pbd/error.h" +#include "pbd/debug.h" +#include "pbd/compose.h" +#include "pbd/stacktrace.h" + #include "waves_midi_device.h" #include "waves_midi_event.h" @@ -27,6 +33,7 @@ #define QUEUE_LENGTH 1024 using namespace ARDOUR; +using namespace PBD; WavesMidiDevice::WavesMidiDevice (const std::string& device_name) : _pm_input_id (pmNoDevice) @@ -61,14 +68,16 @@ WavesMidiDevice::WavesMidiDevice (const std::string& device_name) WavesMidiDevice::~WavesMidiDevice () { - // COMMENTED DBG LOGS */ std::cout << "WavesMidiDevice::~WavesMidiDevice ():" << name () << std::endl; - close (); + DEBUG_TRACE (DEBUG::WavesMIDI, string_compose ("WavesMidiDevice::~WavesMidiDevice (): %1\n", name())); + close (); } int WavesMidiDevice::open (PmTimeProcPtr time_proc, void* time_info) { - if (is_input () ) { + DEBUG_TRACE (DEBUG::WavesMIDI, string_compose ("WavesMidiDevice::open (): %1", name ())); + + if (is_input () ) { // COMMENTED DBG LOGS */ std::cout << "WavesMidiDevice::open (): INPUT" << _pm_input_id << "-[" << name () << "]" << std::endl; if (!_input_pm_stream) { @@ -78,26 +87,26 @@ WavesMidiDevice::open (PmTimeProcPtr time_proc, void* time_info) _input_queue = Pm_QueueCreate (QUEUE_LENGTH, sizeof (const WavesMidiEvent*)); // COMMENTED DBG LOGS */ std::cout << " DONE : " << std::endl; if (NULL == _input_queue) { - std::cerr << "WavesMidiDevice::open (): _input_queue = Pm_QueueCreate () failed for " << _pm_input_id << "-[" << name () << "]!" << std::endl; - return -1; + std::cerr << "WavesMidiDevice::open (): _input_queue = Pm_QueueCreate () failed for " << _pm_input_id << "-[" << name () << "]!" << std::endl; + return -1; } } // create stream // COMMENTED DBG LOGS */ std::cout << " going to Pm_OpenInput : " << std::endl; - if (pmNoError != Pm_OpenInput (&_input_pm_stream, - _pm_input_id, - NULL, - 1024, - time_proc, - time_info)) { - // COMMENTED DBG LOGS */ std::cout << " DONE : " << std::endl; - char* err_msg = new char[256]; - Pm_GetHostErrorText(err_msg, 256); - std::cerr << "WavesMidiDevice::open (): Pm_OpenInput () failed for " << _pm_input_id << "-[" << name () << "]!" << std::endl; - std::cerr << " Port Midi Host Error: " << err_msg << std::endl; - close (); - return -1; - } + if (pmNoError != Pm_OpenInput (&_input_pm_stream, + _pm_input_id, + NULL, + 1024, + time_proc, + time_info)) { + // COMMENTED DBG LOGS */ std::cout << " DONE : " << std::endl; + char* err_msg = new char[256]; + Pm_GetHostErrorText(err_msg, 256); + std::cerr << "WavesMidiDevice::open (): Pm_OpenInput () failed for " << _pm_input_id << "-[" << name () << "]!" << std::endl; + std::cerr << " Port Midi Host Error: " << err_msg << std::endl; + close (); + return -1; + } // COMMENTED DBG LOGS */ std::cout << " DONE : " << std::endl; } } @@ -142,6 +151,7 @@ WavesMidiDevice::open (PmTimeProcPtr time_proc, void* time_info) void WavesMidiDevice::close () { + DEBUG_TRACE (DEBUG::WavesMIDI, string_compose ("WavesMidiDevice::close (): %1\n", name ())); WavesMidiEvent *waves_midi_event; // save _input_pm_stream and _output_pm_stream to local buf @@ -197,114 +207,123 @@ WavesMidiDevice::close () void WavesMidiDevice::do_io () { - read_midi (); - write_midi (); + read_midi (); + write_midi (); } void WavesMidiDevice::read_midi () { - if (NULL == _input_pm_stream) { - return; - } - - // COMMENTED DBG LOGS */ std::cout << "WavesMidiDevice::_read_midi (): " << _pm_device_id << "-[" << name () << "]" << std::endl; - - while (Pm_Poll (_input_pm_stream) > 0) { - PmEvent pm_event; // just one message at a time - int result = Pm_Read (_input_pm_stream, &pm_event, 1); - if (result < 0) { - std::cerr << "WavesMidiDevice::_read_midi (): Pm_Read () failed (" << result << ") for [" << name () << "]!" << std::endl; - break; - } - // COMMENTED DBG LOGS */ std::cout << "WavesMidiDevice::_read_midi (): " << _pm_device_id << "-[" << name () << "] evt-tm:" << pm_event.timestamp << std::endl; - if (_incomplete_waves_midi_event == NULL ) { - // COMMENTED DBG LOGS */ std::cout << "WavesMidiDevice::_read_midi (): " << _pm_device_id << "-[" << name () << "] : new _incomplete_waves_midi_event" << std::endl; - _incomplete_waves_midi_event = new WavesMidiEvent (pm_event.timestamp); + if (NULL == _input_pm_stream) { + return; } - WavesMidiEvent *nested_pm_event = _incomplete_waves_midi_event->append_data (pm_event); - if (nested_pm_event) { - Pm_Enqueue (_input_queue, &nested_pm_event); - // COMMENTED DBG LOGS */ std::cout << "WavesMidiDevice::_read_midi (): " << _pm_device_id << "-[" << name () << "] : Pm_Enqueue (_input_queue, nested_pm_event)" << std::endl; + while (Pm_Poll (_input_pm_stream) > 0) { + + PmEvent pm_event; // just one message at a time + int result = Pm_Read (_input_pm_stream, &pm_event, 1); + + if (result < 0) { + DEBUG_TRACE (DEBUG::WavesMIDI, string_compose ("Pm_Read failed for (): [%1]\n", name())); + break; + } + + DEBUG_TRACE (DEBUG::WavesMIDI, string_compose ("WavesMidiDevice::_read_midi (): [%1] evt-tm: %2\n", name(), pm_event.timestamp)); + + if (_incomplete_waves_midi_event == NULL ) { + DEBUG_TRACE (DEBUG::WavesMIDI, string_compose ("WavesMidiDevice::_read_midi (): [%1] new incomplete_waves_midi_event\n", name())); + _incomplete_waves_midi_event = new WavesMidiEvent (pm_event.timestamp); + } + + WavesMidiEvent *nested_pm_event = _incomplete_waves_midi_event->append_data (pm_event); + + if (nested_pm_event) { + Pm_Enqueue (_input_queue, &nested_pm_event); + DEBUG_TRACE (DEBUG::WavesMIDI, string_compose ("WavesMidiDevice::_read_midi (): [%1] : Pm_Enqueue (_input_queue, nested_pm_event)\n", name())); + } + + switch ( _incomplete_waves_midi_event->state ()) { + case WavesMidiEvent::BROKEN: + delete _incomplete_waves_midi_event; + _incomplete_waves_midi_event = NULL; + DEBUG_TRACE (DEBUG::WavesMIDI, string_compose ("WavesMidiDevice::_read_midi (): [%1] : case WavesMidiEvent::BROKEN:\n", name())); + break; + case WavesMidiEvent::COMPLETE: + DEBUG_TRACE (DEBUG::WavesMIDI, string_compose ("WavesMidiDevice::_read_midi (): [%1] : Pm_Enqueue (_input_queue, _incomplete_waves_midi_event); %3\n", name (), _incomplete_waves_midi_event)); + + if (pmNoError != Pm_Enqueue (_input_queue, &_incomplete_waves_midi_event) ) { + char* err_msg = new char[256]; + Pm_GetHostErrorText(err_msg, 256); + std::cerr << "WavesMidiDevice::read_midi (): Pm_Enqueue () failed for [" << name () << "]!" << std::endl; + std::cerr << "Error: " << err_msg << std::endl; + } + + _incomplete_waves_midi_event = NULL; + break; + default: + break; + } } - switch ( _incomplete_waves_midi_event->state ()) { - case WavesMidiEvent::BROKEN: - delete _incomplete_waves_midi_event; - _incomplete_waves_midi_event = NULL; - // COMMENTED DBG LOGS */ std::cout << "WavesMidiDevice::_read_midi (): " << _pm_device_id << "-[" << name () << "] : case WavesMidiEvent::BROKEN:" << std::endl; - break; - case WavesMidiEvent::COMPLETE: - // COMMENTED DBG LOGS */ std::cout << "WavesMidiDevice::_read_midi (): " << _pm_device_id << "-[" << name () << "] : Pm_Enqueue (_input_queue, _incomplete_waves_midi_event); " << std::hex << (void*)_incomplete_waves_midi_event << std::dec << std::endl; - Pm_Enqueue (_input_queue, &_incomplete_waves_midi_event); - _incomplete_waves_midi_event = NULL; - break; - default: - break; - } - } } - void WavesMidiDevice::write_midi () { - if (NULL == _output_pm_stream) { - return; - } - // COMMENTED DBG LOGS */ std::cout << "WavesMidiDevice::_write_midi (): " << _pm_device_id << "-[" << name () << "]" << std::endl; - - PmError err; - WavesMidiEvent *waves_midi_event; - - while (1 == Pm_Dequeue (_output_queue, &waves_midi_event)) { - if (waves_midi_event->sysex ()) { - // LATENCY compensation - err = Pm_WriteSysEx (_output_pm_stream, waves_midi_event->timestamp () - LATENCY, waves_midi_event->data ()); - if (0 > err) { - std::cout << "WavesMidiDevice::write_event_to_device (): [" << name () << "] Pm_WriteSysEx () failed (" << err << ")!" << std::endl; - }; - // COMMENTED DBG LOGS */ std::cout << "WavesMidiDevice::_write_midi (): SYSEX used, ev->tm:" << waves_midi_event->timestamp () - LATENCY << std::endl; + if (NULL == _output_pm_stream) { + return; } - else - { - err = Pm_WriteShort (_output_pm_stream, waves_midi_event->timestamp () - LATENCY, * (PmMessage*)waves_midi_event->data ()); - if (0 > err) { - std::cout << "WavesMidiDevice::write_event_to_device (): [" << name () << "] Pm_WriteShort () failed (" << err << ")!" << std::endl; - } - // COMMENTED DBG LOGS */ std::cout << "WavesMidiDevice::_write_midi (): SHORTMSG used, ev->tm:" << waves_midi_event->timestamp () - LATENCY << std::endl; + + PmError err; + WavesMidiEvent *waves_midi_event; + + while (1 == Pm_Dequeue (_output_queue, &waves_midi_event)) { + if (waves_midi_event->sysex ()) { + // LATENCY compensation + err = Pm_WriteSysEx (_output_pm_stream, waves_midi_event->timestamp () - LATENCY, waves_midi_event->data ()); + if (0 > err) { + std::cerr << "WavesMidiDevice::write_event_to_device (): [" << name () << "] Pm_WriteSysEx () failed (" << err << ")!" << std::endl; + }; + DEBUG_TRACE (DEBUG::WavesMIDI, string_compose ("WavesMidiDevice::_write_midi (): SYSEX used, ev->tm: %1", waves_midi_event->timestamp () - LATENCY)); + } + else + { + err = Pm_WriteShort (_output_pm_stream, waves_midi_event->timestamp () - LATENCY, * (PmMessage*)waves_midi_event->data ()); + if (0 > err) { + error << "WavesMidiDevice::write_event_to_device (): [" << name () << "] Pm_WriteShort () failed (" << err << ")!" << endmsg; + } + DEBUG_TRACE (DEBUG::WavesMIDI, string_compose ("WavesMidiDevice::_write_midi (): SHORTMSG used, ev->tm: %1\n", waves_midi_event->timestamp () - LATENCY)); + } } - } - return; -} + return; +} + int WavesMidiDevice::enqueue_output_waves_midi_event (const WavesMidiEvent* waves_midi_event) { - // COMMENTED DBG LOGS */ std::cout << "WavesMidiDevice::enqueue_output_waves_midi_event (): " << _pm_device_id << "-[" << name () << "]" << std::endl; - - if (waves_midi_event == NULL) { - std::cerr << "WavesMidiDevice::put_event_to_callback (): 'waves_midi_event' is NULL!" << std::endl; - return -1; - } - - PmError err = Pm_Enqueue (_output_queue, &waves_midi_event); - - if (0 > err) { - std::cerr << "WavesMidiDevice::put_event_to_callback (): Pm_Enqueue () failed (" << err << ")!" << std::endl; - return -1; - }; - - return 0; + DEBUG_TRACE (DEBUG::WavesMIDI, string_compose ("WavesMidiDevice::enqueue_output_waves_midi_event () [%1]\n", name())); + + if (waves_midi_event == NULL) { + error << "WavesMidiDevice::put_event_to_callback (): 'waves_midi_event' is NULL!" << endmsg; + return -1; + } + + PmError err = Pm_Enqueue (_output_queue, &waves_midi_event); + + if (0 > err) { + error << "WavesMidiDevice::put_event_to_callback (): Pm_Enqueue () failed (" << err << ")!" << endmsg; + return -1; + }; + + return 0; } WavesMidiEvent* WavesMidiDevice::dequeue_input_waves_midi_event () { - WavesMidiEvent* waves_midi_event; - if (Pm_Dequeue (_input_queue, &waves_midi_event) == 1) { - return waves_midi_event; - } - return NULL; + WavesMidiEvent* waves_midi_event; + if (Pm_Dequeue (_input_queue, &waves_midi_event) == 1) { + return waves_midi_event; + } + return NULL; } - diff --git a/libs/backends/wavesaudio/waves_midi_device_manager.cc b/libs/backends/wavesaudio/waves_midi_device_manager.cc index dcc5fa0f03..317f1ec257 100644 --- a/libs/backends/wavesaudio/waves_midi_device_manager.cc +++ b/libs/backends/wavesaudio/waves_midi_device_manager.cc @@ -195,7 +195,17 @@ WavesMidiDeviceManager::_create_devices () for (int i = 0; i < count; i++) { const PmDeviceInfo* pm_device_info = Pm_GetDeviceInfo (i); - + // COMMENTED DBG LOGS */ std::cout << " interf : " << pm_device_info->interf << std::endl; + // COMMENTED DBG LOGS */ std::cout << " name : " << pm_device_info->name << std::endl; + // COMMENTED DBG LOGS */ std::cout << " input : " << pm_device_info->input << std::endl; + // COMMENTED DBG LOGS */ std::cout << " output : " << pm_device_info->output << std::endl; + // COMMENTED DBG LOGS */ std::cout << " opened : " << pm_device_info->opened << std::endl; +#if defined (PLATFORM_WINDOWS) + if (strncmp (pm_device_info->name, "Microsoft", strlen ("Microsoft")) == 0) { + // COMMENTED DBG LOGS */ std::cout << " skipping anything from Microsoft :" << pm_device_info->name << std::endl; + continue; + } +#endif if (pm_device_info == NULL) { std::cerr << "WavesMidiDeviceManager::_create_devices (): Pm_GetDeviceInfo (" << i << ") failed!" << std::endl; continue; diff --git a/libs/backends/wavesaudio/waves_midi_event.cc b/libs/backends/wavesaudio/waves_midi_event.cc index 7960cb4871..0afe168c92 100644 --- a/libs/backends/wavesaudio/waves_midi_event.cc +++ b/libs/backends/wavesaudio/waves_midi_event.cc @@ -16,10 +16,15 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "pbd/debug.h" +#include "pbd/compose.h" + #include "memory.h" #include "waves_midi_event.h" using namespace ARDOUR; +using namespace PBD; WavesMidiEvent::WavesMidiEvent (PmTimestamp timestamp) : _size (0) @@ -37,13 +42,27 @@ WavesMidiEvent::WavesMidiEvent (PmTimestamp timestamp, const uint8_t* data, size , _data (data && datalen ? new uint8_t[ (datalen < sizeof (PmMessage)) ? sizeof (PmMessage) : datalen] : NULL) , _state (data && datalen ? COMPLETE : BROKEN) { - // COMMENTED DBG LOGS */ std::cout << "WavesMidiEvent::WavesMidiEvent (const WavesMidiEvent& source) : Size=" << _size << "---" << datalen << std::endl; - if (_state == COMPLETE) { - // COMMENTED DBG LOGS */ std::cout << "\t\t\t Allocated Size=" << ((datalen < sizeof (PmMessage)) ? sizeof (PmMessage) : datalen) << std::endl; - memcpy (_data, data, datalen); - } -} + DEBUG_TRACE (DEBUG::WavesMIDI, string_compose ( "WavesMidiEvent::WavesMidiEvent (const WavesMidiEvent& source) : Size=%1---%2\n", _size, datalen)); + if (_state == COMPLETE) { + DEBUG_TRACE (DEBUG::WavesMIDI, string_compose ( "\t\t\t Allocated Size=%1\n", ((datalen < sizeof (PmMessage)) ? sizeof (PmMessage) : datalen))); + memcpy (_data, data, datalen); + +#ifndef NDEBUG + if (DEBUG::WavesMIDI & PBD::debug_bits) { + DEBUG_STR_DECL(a); + for (size_t i=0; i < datalen; ++i) { + DEBUG_STR_APPEND(a,std::hex); + DEBUG_STR_APPEND(a,"0x"); + DEBUG_STR_APPEND(a,(int)data[i]); + DEBUG_STR_APPEND(a,' '); + } + DEBUG_STR_APPEND(a,'\n'); + DEBUG_TRACE (DEBUG::WavesMIDI, DEBUG_STR(a).str()); + } +#endif + } +} WavesMidiEvent::WavesMidiEvent (const WavesMidiEvent& source) : _size (source.size ()) @@ -51,11 +70,25 @@ WavesMidiEvent::WavesMidiEvent (const WavesMidiEvent& source) , _data ((source.size () && source.const_data ()) ? new uint8_t[ (source.size () < sizeof (PmMessage)) ? sizeof (PmMessage) : source.size ()] : NULL) , _state (source.state () ) { - // COMMENTED DBG LOGS */ std::cout << "WavesMidiEvent::WavesMidiEvent (const WavesMidiEvent& source) : Size=" << _size << "---" << source.size () << std::endl; - // COMMENTED DBG LOGS */ std::cout << "\t\t\t Allocated Size=" << ((source.size () < sizeof (PmMessage)) ? sizeof (PmMessage) : source.size ()) << std::endl; - if (_data && source.const_data ()) { - memcpy (_data, source.const_data (), source.size ()); - } + DEBUG_TRACE (DEBUG::WavesMIDI, string_compose ( "WavesMidiEvent::WavesMidiEvent (const WavesMidiEvent& source) : Size=%1---%2\n", _size, source.size ())); + DEBUG_TRACE (DEBUG::WavesMIDI, string_compose ( "\t\t\t Allocated Size=%1\n", ((source.size () < sizeof (PmMessage)) ? sizeof (PmMessage) : source.size ()))); + if (_data && source.const_data ()) { + memcpy (_data, source.const_data (), source.size ()); + +#ifndef NDEBUG + if (DEBUG::WavesMIDI & PBD::debug_bits) { + DEBUG_STR_DECL(a); + for (size_t i=0; i < source.size(); ++i) { + DEBUG_STR_APPEND(a,std::hex); + DEBUG_STR_APPEND(a,"0x"); + DEBUG_STR_APPEND(a,(int)source.const_data()[i]); + DEBUG_STR_APPEND(a,' '); + } + DEBUG_STR_APPEND(a,'\n'); + DEBUG_TRACE (DEBUG::WavesMIDI, DEBUG_STR(a).str()); + } +#endif + } } @@ -67,74 +100,78 @@ WavesMidiEvent::~WavesMidiEvent () WavesMidiEvent *WavesMidiEvent::append_data (const PmEvent &midi_event) { - switch ( _state ) { + switch ( _state ) { case INCOMPLETE: - break; - default: - // COMMENTED DBG LOGS */ std::cout << "WavesMidiEvent::append_data (): NO case INCOMPLETE" << std::endl; - _state = BROKEN; - return NULL; - } - - size_t message_size = _midi_message_size (midi_event.message); - uint8_t message_status = Pm_MessageStatus (midi_event.message); - - if (_data == NULL) { // This is a first event to add - bool sysex = (message_status == SYSEX); - _data = new unsigned char [sysex ? PM_DEFAULT_SYSEX_BUFFER_SIZE : sizeof (PmMessage)]; - if (!sysex) - { - // COMMENTED DBG LOGS */ std::cout << "WavesMidiEvent::append_data (): SHORT MSG" << std::endl; - * (PmMessage*)_data = 0; - switch (message_size) { - case 1: - case 3: - _size = message_size; - // COMMENTED DBG LOGS */ std::cout << "WavesMidiEvent::append_data (): size = " << _size << std::endl; break; - default: - // COMMENTED DBG LOGS */ std::cout << "WavesMidiEvent::append_data (): WRONG MESSAGE SIZE (" << message_size << ") in the message: "; - // COMMENTED DBG LOGS */ std::cout << std::hex << (int) ((unsigned char*)&midi_event)[0] << " " << (int) ((unsigned char*)&midi_event)[1] << " " << (int) ((unsigned char*)&midi_event)[2] << " " << (int) ((unsigned char*)&midi_event)[3] << std::dec << std::endl; - _state = BROKEN; + default: + DEBUG_TRACE (DEBUG::WavesMIDI, "WavesMidiEvent::append_data (): NO case INCOMPLETE\n"); + _state = BROKEN; return NULL; - } - // COMMENTED DBG LOGS */ std::cout << "\t size = " << _size << std::endl; - memcpy (_data, &midi_event.message, _size); - // COMMENTED DBG LOGS */ std::cout << "\t\t size = " << _size << std::endl; - _state = COMPLETE; - // COMMENTED DBG LOGS */ std::cout << "\t\t\t size = " << _size << std::endl; - return NULL; } - } - - // Now let's parse to sysex msg - if (message_status >= REAL_TIME_FIRST) { // Nested Real Time MIDI event - WavesMidiEvent *waves_midi_message = new WavesMidiEvent (midi_event.timestamp); - waves_midi_message->append_data (midi_event); - return waves_midi_message; - } - - if (message_status >= STATUS_FIRST && (message_status != EOX) && _size) { // Certainly it's a broken SYSEX case - WavesMidiEvent *waves_midi_message = new WavesMidiEvent (midi_event.timestamp); - waves_midi_message->append_data (midi_event); - return waves_midi_message; - } + + size_t message_size = _midi_message_size (midi_event.message); + uint8_t message_status = Pm_MessageStatus (midi_event.message); + + if (_data == NULL) { // This is a first event to add + bool sysex = (message_status == SYSEX); + _data = new unsigned char [sysex ? PM_DEFAULT_SYSEX_BUFFER_SIZE : sizeof (PmMessage)]; + if (!sysex) + { + DEBUG_TRACE (DEBUG::WavesMIDI, "WavesMidiEvent::append_data (): SHORT MSG\n"); + * (PmMessage*)_data = 0; + switch (message_size) { + case 1: + case 2: + case 3: + _size = message_size; + DEBUG_TRACE (DEBUG::WavesMIDI, string_compose ( "WavesMidiEvent::append_data (): size = %1\n", _size)); + break; + default: + DEBUG_TRACE (DEBUG::WavesMIDI, string_compose ( "WavesMidiEvent::append_data (): WRONG MESSAGE SIZE (%1 not %2) %3 [%4 %5 %6 %7] %8\n", + message_size, + std::hex, + (int) ((unsigned char*)&midi_event)[0], + (int) ((unsigned char*)&midi_event)[1], + (int) ((unsigned char*)&midi_event)[2], + (int) ((unsigned char*)&midi_event)[3], + std::dec)); + _state = BROKEN; + return NULL; + } + memcpy (_data, &midi_event.message, _size); + _state = COMPLETE; + DEBUG_TRACE (DEBUG::WavesMIDI, string_compose ( "\t\t\t size = %1\n", _size)); + return NULL; + } + } + + // Now let's parse to sysex msg + if (message_status >= REAL_TIME_FIRST) { // Nested Real Time MIDI event + WavesMidiEvent *waves_midi_message = new WavesMidiEvent (midi_event.timestamp); + waves_midi_message->append_data (midi_event); + return waves_midi_message; + } + + if (message_status >= STATUS_FIRST && (message_status != EOX) && _size) { // Certainly it's a broken SYSEX case + WavesMidiEvent *waves_midi_message = new WavesMidiEvent (midi_event.timestamp); + waves_midi_message->append_data (midi_event); + return waves_midi_message; + } - const uint8_t* source_data ((uint8_t*)&midi_event.message); - - for (size_t i = 0; i < sizeof (midi_event.message); ++i) { - _data[_size] = source_data[i]; - _size++; + const uint8_t* source_data ((uint8_t*)&midi_event.message); - if (source_data[i] == EOX) { // Ended SYSEX message - _state = COMPLETE; - return NULL; + for (size_t i = 0; i < sizeof (midi_event.message); ++i) { + _data[_size] = source_data[i]; + _size++; + + if (source_data[i] == EOX) { // Ended SYSEX message + _state = COMPLETE; + return NULL; + } } - } - return NULL; + return NULL; } - size_t WavesMidiEvent::_midi_message_size (PmMessage midi_message) { static int high_lengths[] = { diff --git a/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRAudioDeviceManager.cpp b/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRAudioDeviceManager.cpp index ee8dba5028..1b18fc3cfa 100644 --- a/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRAudioDeviceManager.cpp +++ b/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRAudioDeviceManager.cpp @@ -361,13 +361,14 @@ WTErr WCMRAudioDevice::ResetDevice () WTErr err = SetStreaming(false); if (err == eNoErr) - SetActive(false); + err = SetActive(false); if (err == eNoErr && wasActive) - SetActive(true); + err = SetActive(true); - if (err == eNoErr && wasStreaming) - SetStreaming(true); + if (err == eNoErr && wasStreaming) { + err = SetStreaming(true); + } return err; } diff --git a/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRCoreAudioDeviceManager.cpp b/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRCoreAudioDeviceManager.cpp index 8cfa096c2a..9c97e6181a 100644 --- a/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRCoreAudioDeviceManager.cpp +++ b/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRCoreAudioDeviceManager.cpp @@ -248,6 +248,9 @@ WTErr WCMRCoreAudioDevice::UpdateDeviceInfo () WTErr retVal = eNoErr; + // Some devices change the ID during restart + WTErr errId = UpdateDeviceId(); + // Update all devices parts regardless of errors WTErr errName = UpdateDeviceName(); WTErr errIn = UpdateDeviceInputs(); @@ -258,7 +261,7 @@ WTErr WCMRCoreAudioDevice::UpdateDeviceInfo () errSR = UpdateDeviceSampleRates(); 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; } @@ -266,6 +269,70 @@ WTErr WCMRCoreAudioDevice::UpdateDeviceInfo () 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; + return retVal; +} + + //********************************************************************************************** // WCMRCoreAudioDevice::UpdateDeviceName // @@ -881,8 +948,6 @@ WTErr WCMRCoreAudioDevice::SetAndCheckCurrentSamplingRate (int newRate) propSize = sizeof (Float64); err = AudioDeviceSetProperty(m_DeviceID, NULL, 0, 0, kAudioDevicePropertyNominalSampleRate, propSize, &newNominalRate); - m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::DeviceDebugInfo, (void *)"Changed the Sampling Rate."); - if (err != kAudioHardwareNoError) { retVal = eCoreAudioFailed; @@ -926,6 +991,8 @@ WTErr WCMRCoreAudioDevice::SetAndCheckCurrentSamplingRate (int newRate) // If sample rate actually changed if (tryAgain != 0) { + m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::DeviceDebugInfo, (void *)"Changed the Sampling Rate."); + // Update member with new rate m_CurrentSamplingRate = newRate; @@ -936,12 +1003,28 @@ WTErr WCMRCoreAudioDevice::SetAndCheckCurrentSamplingRate (int newRate) // If sample rate did not change after time out else { - // Update member with last read value - m_CurrentSamplingRate = static_cast<int>(actualSamplingRate); + // Check if current device sample rate is supported + bool found = false; + for(int i = 0; gAllSampleRates[i] > 0; i++) + { + if (fabs(gAllSampleRates[i] - actualSamplingRate) < 0.01) { + found = true; + } + } - char debugMsg[128]; - 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); + if (found) { + // Update member with last read value + m_CurrentSamplingRate = static_cast<int>(actualSamplingRate); + + char debugMsg[128]; + 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); + + float sample_rate_update = actualSamplingRate; + m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::SamplingRateChanged, (void *)&sample_rate_update); + } else { + retVal = eGenericErr; + } } } @@ -1731,7 +1814,6 @@ WTErr WCMRCoreAudioDevice::TearDownAUHAL() } - //********************************************************************************************** // WCMRCoreAudioDevice::SetActive // @@ -1799,7 +1881,6 @@ WTErr WCMRCoreAudioDevice::SetActive (bool newState) m_IgnoreThisDrop = true; UpdateDeviceInfo(); - } m_IsActive = newState; @@ -1909,6 +1990,9 @@ WTErr WCMRCoreAudioDevice::SetStreaming (bool newState) m_IOProcThreadPort = 0; m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::DeviceDebugInfo, (void *)"Starting AUHAL."); + // Prepare for streaming - tell Engine to do the initialization for process callback + m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::DeviceStartsStreaming); + if (m_UseMultithreading) { //set thread constraints... @@ -1924,6 +2008,7 @@ WTErr WCMRCoreAudioDevice::SetStreaming (bool newState) if(err) { DEBUG_MSG( "Failed to start AudioUnit, err " << err ); + m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::DeviceDebugInfo, (void *)"Failed to start AudioUnit."); retVal = eGenericErr; goto Exit; } @@ -2554,7 +2639,7 @@ WTErr WCMRCoreAudioDeviceManager::getDeviceAvailableSampleRates(DeviceID deviceI return retVal; } - + WTErr WCMRCoreAudioDeviceManager::getDeviceMaxInputChannels(DeviceID deviceId, unsigned int& inputChannels) { @@ -2876,6 +2961,15 @@ WTErr WCMRCoreAudioDeviceManager::updateDeviceListImpl() NotifyClient (WCMRAudioDeviceManagerClient::IODeviceDisconnected); 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); diff --git a/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRCoreAudioDeviceManager.h b/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRCoreAudioDeviceManager.h index a3269f63fb..cd4797a000 100644 --- a/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRCoreAudioDeviceManager.h +++ b/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRCoreAudioDeviceManager.h @@ -138,6 +138,7 @@ protected: #endif //WV_USE_TONE_GEN WTErr UpdateDeviceInfo (); + WTErr UpdateDeviceId (); WTErr UpdateDeviceName(); WTErr UpdateDeviceInputs(); WTErr UpdateDeviceOutputs(); diff --git a/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRPortAudioDeviceManager.cpp b/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRPortAudioDeviceManager.cpp index 7816fcb470..67c170d565 100644 --- a/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRPortAudioDeviceManager.cpp +++ b/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRPortAudioDeviceManager.cpp @@ -901,6 +901,9 @@ void WCMRPortAudioDevice::startStreaming (bool callerIsWaiting/*=false*/) unsigned int inChannelCount = pDeviceInfo->maxInputChannels; unsigned int outChannelCount = pDeviceInfo->maxOutputChannels; + // Prepare for streaming - tell Engine to do the initialization for process callback + m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::DeviceStartsStreaming); + paErr = Pa_StartStream( m_PortAudioStream ); if(paErr == paNoError) @@ -1082,13 +1085,19 @@ long WCMRPortAudioDevice::ASIOMessageHook (long selector, long WCUNUSEDPARAM(val case kAsioLatenciesChanged: m_BufferSizeChangeRequested++; std::cout << "\t\t\tWCMRPortAudioDevice::ASIOMessageHook -- kAsioLatenciesChanged" << std::endl; - m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::RequestReset); + if (m_ResetRequested == 0) { + m_ResetRequested++; + m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::RequestReset); + } break; case kAsioBufferSizeChange: m_BufferSizeChangeRequested++; std::cout << "\t\t\tWCMRPortAudioDevice::ASIOMessageHook -- m_BufferSizeChangeRequested" << std::endl; - m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::RequestReset); + if (m_ResetRequested == 0) { + m_ResetRequested++; + m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::RequestReset); + } break; case kAsioResetRequest: @@ -1540,6 +1549,32 @@ WTErr WCMRPortAudioDeviceManager::getDeviceAvailableSampleRates(DeviceID deviceI } +WTErr WCMRPortAudioDeviceManager::getDeviceAvailableBufferSizes(DeviceID deviceId, std::vector<int>& buffers) +{ + WTErr retVal = eNoErr; + + buffers.clear(); + + //make PA request to get actual device buffer sizes + long minSize, maxSize, preferredSize, granularity; + + PaError paErr = PaAsio_GetAvailableBufferSizes(deviceId, &minSize, &maxSize, &preferredSize, &granularity); + + //for Windows ASIO devices we always use prefferes buffer size ONLY + if (paNoError == paErr ) + { + buffers.push_back(preferredSize); + } + else + { + retVal = eAsioFailed; + std::cout << "API::PortAudioDeviceManager::GetBufferSizes: error: " << Pa_GetErrorText (paErr) << " getting buffer sizes for device: "<< deviceId << std::endl; + } + + return retVal; +} + + WTErr WCMRPortAudioDeviceManager::generateDeviceListImpl() { std::cout << "API::PortAudioDeviceManager::Generating device list" << std::endl; @@ -1586,6 +1621,7 @@ WTErr WCMRPortAudioDeviceManager::generateDeviceListImpl() DeviceInfo *pDevInfo = new DeviceInfo(thisDeviceID, pPaDeviceInfo->name); if (pDevInfo) { + //Get available sample rates std::vector<int> availableSampleRates; WTErr wErr = WCMRPortAudioDeviceManager::getDeviceAvailableSampleRates(thisDeviceID, availableSampleRates); @@ -1600,6 +1636,19 @@ WTErr WCMRPortAudioDeviceManager::generateDeviceListImpl() pDevInfo->m_MaxInputChannels = pPaDeviceInfo->maxInputChannels; pDevInfo->m_MaxOutputChannels = pPaDeviceInfo->maxOutputChannels; + //Get available buffer sizes + std::vector<int> availableBuffers; + wErr = getDeviceAvailableBufferSizes(thisDeviceID, availableBuffers); + + if (wErr != eNoErr) + { + DEBUG_MSG ("Failed to get device available buffer sizes. Device ID: " << m_DeviceID); + delete pDevInfo; + continue; //proceed to the next device + } + + pDevInfo->m_AvailableBufferSizes = availableBuffers; + //Now check if this device is acceptable according to current input/output settings bool bRejectDevice = false; switch(m_eAudioDeviceFilter) @@ -1681,7 +1730,7 @@ WTErr WCMRPortAudioDeviceManager::getDeviceSampleRatesImpl(const std::string & d if (m_CurrentDevice && deviceName == m_CurrentDevice->DeviceName() ) { - sampleRates.assign(m_CurrentDevice->SamplingRates().begin(), m_CurrentDevice->SamplingRates().end() ); + sampleRates=m_CurrentDevice->SamplingRates(); return retVal; } @@ -1690,7 +1739,7 @@ WTErr WCMRPortAudioDeviceManager::getDeviceSampleRatesImpl(const std::string & d if (eNoErr == retVal) { - sampleRates.assign(devInfo.m_AvailableSampleRates.begin(), devInfo.m_AvailableSampleRates.end() ); + sampleRates=devInfo.m_AvailableSampleRates; } else { @@ -1710,44 +1759,28 @@ WTErr WCMRPortAudioDeviceManager::getDeviceBufferSizesImpl(const std::string & d //first check if the request has been made for None device if (deviceName == m_NoneDevice->DeviceName() ) { - buffers.assign(m_NoneDevice->BufferSizes().begin(), m_NoneDevice->BufferSizes().end() ); + buffers=m_NoneDevice->BufferSizes(); return retVal; } if (m_CurrentDevice && deviceName == m_CurrentDevice->DeviceName() ) { - buffers.assign(m_CurrentDevice->BufferSizes().begin(), m_CurrentDevice->BufferSizes().end() ); + buffers=m_CurrentDevice->BufferSizes(); return retVal; } - Pa_Initialize(); - DeviceInfo devInfo; retVal = GetDeviceInfoByName(deviceName, devInfo); if (eNoErr == retVal) { - //make PA request to get actual device buffer sizes - long minSize, maxSize, preferredSize, granularity; - PaError paErr = PaAsio_GetAvailableBufferSizes(devInfo.m_DeviceId, &minSize, &maxSize, &preferredSize, &granularity); - - //for Windows ASIO devices we always use prefferes buffer size ONLY - if (paNoError == paErr ) - { - buffers.push_back(preferredSize); - } - else - { - retVal = eAsioFailed; - std::cout << "API::PortAudioDeviceManager::GetBufferSizes: error: " << Pa_GetErrorText (paErr) << " getting buffer sizes for device: "<< deviceName << std::endl; - } + std::cout << "API::PortAudioDeviceManager::GetBufferSizes: got buffer :"<< devInfo.m_AvailableBufferSizes.front() << std::endl; + buffers = devInfo.m_AvailableBufferSizes; } else { std::cout << "API::PortAudioDeviceManager::GetBufferSizes: Device not found: "<< deviceName << std::endl; } - Pa_Terminate(); - return retVal; } diff --git a/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRPortAudioDeviceManager.h b/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRPortAudioDeviceManager.h index 8f099ec9b5..da2027466e 100644 --- a/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRPortAudioDeviceManager.h +++ b/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRPortAudioDeviceManager.h @@ -172,6 +172,7 @@ protected: private: // helper functions for this class only WTErr getDeviceAvailableSampleRates(DeviceID deviceId, std::vector<int>& sampleRates); + WTErr getDeviceAvailableBufferSizes(DeviceID deviceId, std::vector<int>& buffers); WCMRAudioDevice* m_NoneDevice; }; |