summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2014-09-30 20:35:31 -0400
committerPaul Davis <paul@linuxaudiosystems.com>2014-09-30 21:00:34 -0400
commit8d59afb0486e1816f5ef30526c2dc762b9f4eda8 (patch)
treede90977cedb059b8c9c3c911f5e2ffe2493971a4 /libs
parent38e975d6b1d6e8b1cd85e7896bc00a63643d4f1d (diff)
copy over current Waves version of their backend, along with minor changes in libs/ardour and libs/backend/jack to fit with API changes
Diffstat (limited to 'libs')
-rw-r--r--libs/ardour/ardour/audio_backend.h8
-rw-r--r--libs/ardour/ardour/audioengine.h40
-rw-r--r--libs/ardour/ardour/session.h1
-rw-r--r--libs/ardour/audioengine.cc165
-rw-r--r--libs/ardour/session.cc8
-rw-r--r--libs/backends/jack/jack_audiobackend.cc8
-rw-r--r--libs/backends/jack/jack_audiobackend.h2
-rw-r--r--libs/backends/wavesaudio/portmidi/src/porttime/ptwinmm.c2
-rw-r--r--libs/backends/wavesaudio/waves_audiobackend.cc156
-rw-r--r--libs/backends/wavesaudio/waves_audiobackend.h6
-rw-r--r--libs/backends/wavesaudio/waves_audiobackend.latency.cc2
-rw-r--r--libs/backends/wavesaudio/waves_audiobackend.midi.cc2
-rw-r--r--libs/backends/wavesaudio/waves_audiobackend.port_engine.cc25
-rw-r--r--libs/backends/wavesaudio/waves_audioport.cc2
-rw-r--r--libs/backends/wavesaudio/waves_dataport.cc2
-rw-r--r--libs/backends/wavesaudio/wavesapi/devicemanager/WCMRAudioDeviceManager.cpp29
-rw-r--r--libs/backends/wavesaudio/wavesapi/devicemanager/WCMRAudioDeviceManager.h4
-rw-r--r--libs/backends/wavesaudio/wavesapi/devicemanager/WCMRCoreAudioDeviceManager.cpp295
-rw-r--r--libs/backends/wavesaudio/wavesapi/devicemanager/WCMRCoreAudioDeviceManager.h10
-rw-r--r--libs/backends/wavesaudio/wavesapi/devicemanager/WCMRNativeAudio.cpp16
-rw-r--r--libs/backends/wavesaudio/wavesapi/devicemanager/WCMRNativeAudio.h4
-rw-r--r--libs/backends/wavesaudio/wavesapi/devicemanager/WCMRPortAudioDeviceManager.cpp436
-rw-r--r--libs/backends/wavesaudio/wavesapi/devicemanager/WCMRPortAudioDeviceManager.h1
-rw-r--r--libs/backends/wavesaudio/wavesapi/miscutils/pthread_utils.h38
-rw-r--r--[-rwxr-xr-x]libs/backends/wavesaudio/wscript6
25 files changed, 841 insertions, 427 deletions
diff --git a/libs/ardour/ardour/audio_backend.h b/libs/ardour/ardour/audio_backend.h
index bf860e9aeb..a61e5757de 100644
--- a/libs/ardour/ardour/audio_backend.h
+++ b/libs/ardour/ardour/audio_backend.h
@@ -225,7 +225,7 @@ class LIBARDOUR_API AudioBackend : public PortEngine {
virtual int set_device_name (const std::string&) = 0;
/** Deinitialize and destroy current device
*/
- virtual int drop_device() { return 0; };
+ virtual int drop_device() {return 0;};
/** Set the sample rate to be used
*/
virtual int set_sample_rate (float) = 0;
@@ -386,6 +386,12 @@ class LIBARDOUR_API AudioBackend : public PortEngine {
*/
virtual int stop () = 0;
+ /** Reset device.
+ *
+ * Return zero if successful, negative values on error
+ */
+ virtual int reset_device() = 0;
+
/** While remaining connected to the device, and without changing its
* configuration, start (or stop) calling the process_callback() of @param engine
* without waiting for the device. Once process_callback() has returned, it
diff --git a/libs/ardour/ardour/audioengine.h b/libs/ardour/ardour/audioengine.h
index 7eeae8f205..5679d375aa 100644
--- a/libs/ardour/ardour/audioengine.h
+++ b/libs/ardour/ardour/audioengine.h
@@ -108,9 +108,15 @@ public:
bool in_process_thread ();
uint32_t process_thread_count ();
+ void request_backend_reset();
+ void request_device_list_update();
+
bool is_realtime() const;
bool connected() const;
+ // for the user which hold state_lock to check if reset operation is pending
+ bool is_reset_requested() const { return g_atomic_int_get(const_cast<gint*>(&_hw_reset_request_count)); }
+
int set_device_name (const std::string&);
int set_sample_rate (float);
int set_buffer_size (uint32_t);
@@ -126,6 +132,7 @@ public:
bool running() const { return _running; }
Glib::Threads::Mutex& process_lock() { return _process_lock; }
+ Glib::Threads::RecMutex& state_lock() { return _state_lock; }
int request_buffer_size (pframes_t samples) {
return set_buffer_size (samples);
@@ -137,6 +144,8 @@ public:
void remove_session (); // not a replacement for SessionHandle::session_going_away()
Session* session() const { return _session; }
+ void reconnect_session_routes (bool reconnect_inputs = true, bool reconnect_outputs = true);
+
class NoBackendAvailable : public std::exception {
public:
virtual const char *what() const throw() { return "could not connect to engine backend"; }
@@ -159,6 +168,18 @@ public:
/* this signal is emitted if the sample rate changes */
PBD::Signal1<void, framecnt_t> SampleRateChanged;
+
+ /* this signal is emitted if the buffer size changes */
+
+ PBD::Signal1<void, pframes_t> BufferSizeChanged;
+
+ /* this signal is emitted if the device cannot operate properly */
+
+ PBD::Signal0<void> DeviceError;
+
+ /* this signal is emitted if the device list changed */
+
+ PBD::Signal0<void> DeviceListChanged;
/* this signal is sent if the backend ever disconnects us */
@@ -215,7 +236,8 @@ public:
static AudioEngine* _instance;
- Glib::Threads::Mutex _process_lock;
+ Glib::Threads::Mutex _process_lock;
+ Glib::Threads::RecMutex _state_lock;
Glib::Threads::Cond session_removed;
bool session_remove_pending;
frameoffset_t session_removal_countdown;
@@ -244,6 +266,22 @@ public:
bool _started_for_latency;
bool _in_destructor;
+ Glib::Threads::Thread* _hw_reset_event_thread;
+ gint _hw_reset_request_count;
+ Glib::Threads::Cond _hw_reset_condition;
+ Glib::Threads::Mutex _reset_request_lock;
+ gint _stop_hw_reset_processing;
+ Glib::Threads::Thread* _hw_devicelist_update_thread;
+ gint _hw_devicelist_update_count;
+ Glib::Threads::Cond _hw_devicelist_update_condition;
+ Glib::Threads::Mutex _devicelist_update_lock;
+ gint _stop_hw_devicelist_processing;
+
+ void start_hw_event_processing();
+ void stop_hw_event_processing();
+ void do_reset_backend();
+ void do_devicelist_update();
+
void meter_thread ();
void start_metering_thread ();
void stop_metering_thread ();
diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h
index 4c84ec7dfa..333911cb92 100644
--- a/libs/ardour/ardour/session.h
+++ b/libs/ardour/ardour/session.h
@@ -933,6 +933,7 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
friend class AudioEngine;
void set_block_size (pframes_t nframes);
void set_frame_rate (framecnt_t nframes);
+ void reconnect_existing_routes (bool withLock, bool reconnect_master = true, bool reconnect_inputs = true, bool reconnect_outputs = true);
protected:
friend class Route;
diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc
index ab99ccbda3..41224a10b7 100644
--- a/libs/ardour/audioengine.cc
+++ b/libs/ardour/audioengine.cc
@@ -82,8 +82,15 @@ AudioEngine::AudioEngine ()
, _latency_signal_latency (0)
, _stopped_for_latency (false)
, _in_destructor (false)
+ , _hw_reset_event_thread(0)
+ , _hw_reset_request_count(0)
+ , _stop_hw_reset_processing(0)
+ , _hw_devicelist_update_thread(0)
+ , _hw_devicelist_update_count(0)
+ , _stop_hw_devicelist_processing(0)
{
g_atomic_int_set (&m_meter_exit, 0);
+ start_hw_event_processing();
discover_backends ();
}
@@ -91,6 +98,7 @@ AudioEngine::~AudioEngine ()
{
_in_destructor = true;
stop_metering_thread ();
+ stop_hw_event_processing();
drop_backend ();
}
@@ -164,6 +172,8 @@ AudioEngine::buffer_size_change (pframes_t bufsiz)
last_monitor_check = 0;
}
+ BufferSizeChanged (bufsiz); /* EMIT SIGNAL */
+
return 0;
}
@@ -380,6 +390,139 @@ AudioEngine::process_callback (pframes_t nframes)
void
+AudioEngine::request_backend_reset()
+{
+ Glib::Threads::Mutex::Lock guard (_reset_request_lock);
+ g_atomic_int_inc (&_hw_reset_request_count);
+ _hw_reset_condition.signal ();
+}
+
+
+void
+AudioEngine::do_reset_backend()
+{
+ SessionEvent::create_per_thread_pool (X_("Backend reset processing thread"), 512);
+
+ Glib::Threads::Mutex::Lock guard (_reset_request_lock);
+
+ while (!_stop_hw_reset_processing) {
+
+ if (_hw_reset_request_count && _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;
+
+ // backup the device name
+ std::string name = _backend->device_name ();
+
+ std::cout << "AudioEngine::RESET::Stoping engine..." << std::endl;
+ stop();
+
+ std::cout << "AudioEngine::RESET::Reseting device..." << std::endl;
+ if ( 0 == _backend->reset_device () ) {
+
+ std::cout << "AudioEngine::RESET::Starting engine..." << std::endl;
+ start ();
+
+ // inform about possible changes
+ BufferSizeChanged (_backend->buffer_size() );
+ } else {
+ DeviceError();
+ }
+
+ std::cout << "AudioEngine::RESET::Done." << std::endl;
+
+ _reset_request_lock.lock();
+
+ } else {
+
+ _hw_reset_condition.wait (_reset_request_lock);
+
+ }
+ }
+}
+
+
+void
+AudioEngine::request_device_list_update()
+{
+ Glib::Threads::Mutex::Lock guard (_devicelist_update_lock);
+ g_atomic_int_inc (&_hw_devicelist_update_count);
+ _hw_devicelist_update_condition.signal ();
+}
+
+
+void
+AudioEngine::do_devicelist_update()
+{
+ SessionEvent::create_per_thread_pool (X_("Device list update processing thread"), 512);
+
+ Glib::Threads::Mutex::Lock guard (_devicelist_update_lock);
+
+ while (!_stop_hw_devicelist_processing) {
+
+ if (_hw_devicelist_update_count) {
+
+ _devicelist_update_lock.unlock();
+
+ g_atomic_int_dec_and_test (&_hw_devicelist_update_count);
+ DeviceListChanged (); /* EMIT SIGNAL */
+
+ _devicelist_update_lock.lock();
+
+ } else {
+ _hw_devicelist_update_condition.wait (_devicelist_update_lock);
+ }
+ }
+}
+
+
+void
+AudioEngine::start_hw_event_processing()
+{
+ if (_hw_reset_event_thread == 0) {
+ g_atomic_int_set(&_hw_reset_request_count, 0);
+ g_atomic_int_set(&_stop_hw_reset_processing, 0);
+ _hw_reset_event_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::do_reset_backend, this));
+ }
+
+ if (_hw_devicelist_update_thread == 0) {
+ g_atomic_int_set(&_hw_devicelist_update_count, 0);
+ g_atomic_int_set(&_stop_hw_devicelist_processing, 0);
+ _hw_devicelist_update_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::do_devicelist_update, this));
+ }
+}
+
+
+void
+AudioEngine::stop_hw_event_processing()
+{
+ if (_hw_reset_event_thread) {
+ g_atomic_int_set(&_stop_hw_reset_processing, 1);
+ g_atomic_int_set(&_hw_reset_request_count, 0);
+ _hw_reset_condition.signal ();
+ _hw_reset_event_thread->join ();
+ _hw_reset_event_thread = 0;
+ }
+
+ if (_hw_devicelist_update_thread) {
+ g_atomic_int_set(&_stop_hw_devicelist_processing, 1);
+ g_atomic_int_set(&_hw_devicelist_update_count, 0);
+ _hw_devicelist_update_condition.signal ();
+ _hw_devicelist_update_thread->join ();
+ _hw_devicelist_update_thread = 0;
+ }
+
+}
+
+
+
+void
AudioEngine::stop_metering_thread ()
{
if (m_meter_thread) {
@@ -460,13 +603,22 @@ AudioEngine::remove_session ()
void
+AudioEngine::reconnect_session_routes (bool reconnect_inputs, bool reconnect_outputs)
+{
+ if (_session) {
+ _session->reconnect_existing_routes(true, true, reconnect_inputs, reconnect_outputs);
+ }
+}
+
+
+void
AudioEngine::died ()
{
/* called from a signal handler for SIGPIPE */
stop_metering_thread ();
- _running = false;
+ _running = false;
}
int
@@ -591,7 +743,7 @@ AudioEngine::drop_backend ()
{
if (_backend) {
_backend->stop ();
- _backend->drop_device();
+ _backend->drop_device ();
_backend.reset ();
_running = false;
}
@@ -661,6 +813,7 @@ AudioEngine::start (bool for_latency)
if (_session->config.get_jack_time_master()) {
_backend->set_time_master (true);
}
+
}
start_metering_thread ();
@@ -679,6 +832,12 @@ AudioEngine::stop (bool for_latency)
return 0;
}
+ if (_session && _running) {
+ // it's not a halt, but should be handled the same way:
+ // disable record, stop transport and I/O processign but save the data.
+ _session->engine_halted ();
+ }
+
Glib::Threads::Mutex::Lock lm (_process_lock);
if (_backend->stop ()) {
@@ -1031,7 +1190,7 @@ AudioEngine::halted_callback (const char* why)
return;
}
- stop_metering_thread ();
+ stop_metering_thread ();
_running = false;
Port::PortDrop (); /* EMIT SIGNAL */
diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc
index fca74ee4a5..09d69d5738 100644
--- a/libs/ardour/session.cc
+++ b/libs/ardour/session.cc
@@ -2072,6 +2072,14 @@ Session::auto_connect_route (boost::shared_ptr<Route> route, ChanCount& existing
}
}
+void
+Session::reconnect_existing_routes (bool withLock, bool reconnect_master, bool reconnect_inputs, bool reconnect_outputs)
+{
+ /* TRX does stuff here, ardour does not (but probably should). This is called after an engine reset (in particular).
+ */
+}
+
+
/** Caller must not hold process lock
* @param name_template string to use for the start of the name, or "" to use "Audio".
*/
diff --git a/libs/backends/jack/jack_audiobackend.cc b/libs/backends/jack/jack_audiobackend.cc
index b60d2418c9..428d3f3c18 100644
--- a/libs/backends/jack/jack_audiobackend.cc
+++ b/libs/backends/jack/jack_audiobackend.cc
@@ -1158,3 +1158,11 @@ JACKAudioBackend::speed_and_position (double& speed, framepos_t& position)
position = pos.frame;
return starting;
}
+
+int
+JACKAudioBackend::reset_device ()
+{
+ /* XXX need to figure out what this means for JACK
+ */
+ return 0;
+}
diff --git a/libs/backends/jack/jack_audiobackend.h b/libs/backends/jack/jack_audiobackend.h
index 000a348161..5a5aaaff63 100644
--- a/libs/backends/jack/jack_audiobackend.h
+++ b/libs/backends/jack/jack_audiobackend.h
@@ -76,6 +76,8 @@ class JACKAudioBackend : public AudioBackend {
int set_systemic_midi_input_latency (std::string const, uint32_t) { return 0; }
int set_systemic_midi_output_latency (std::string const, uint32_t) { return 0; }
+ int reset_device ();
+
std::string device_name () const;
float sample_rate () const;
uint32_t buffer_size () const;
diff --git a/libs/backends/wavesaudio/portmidi/src/porttime/ptwinmm.c b/libs/backends/wavesaudio/portmidi/src/porttime/ptwinmm.c
index b0607ca332..af4034c7cc 100644
--- a/libs/backends/wavesaudio/portmidi/src/porttime/ptwinmm.c
+++ b/libs/backends/wavesaudio/portmidi/src/porttime/ptwinmm.c
@@ -2,11 +2,11 @@
#include "porttime.h"
+
#include <windows.h>
#include <mmsystem.h>
#include <time.h>
-
TIMECAPS caps;
static long time_offset = 0;
diff --git a/libs/backends/wavesaudio/waves_audiobackend.cc b/libs/backends/wavesaudio/waves_audiobackend.cc
index aa1fbf47b2..e231dc698d 100644
--- a/libs/backends/wavesaudio/waves_audiobackend.cc
+++ b/libs/backends/wavesaudio/waves_audiobackend.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2013 Valeriy Kamyshniy
+ Copyright (C) 2014 Waves Audio Ltd.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -38,13 +38,14 @@ void WavesAudioBackend::AudioDeviceManagerNotification (NotificationReason reaso
switch (reason) {
case WCMRAudioDeviceManagerClient::DeviceDebugInfo:
std::cout << "------------------------------- WCMRAudioDeviceManagerClient::DeviceDebugInfo -- " << (char*)parameter << std::endl;
- break;
+ break;
case WCMRAudioDeviceManagerClient::BufferSizeChanged:
std::cout << "------------------------------- WCMRAudioDeviceManagerClient::BufferSizeChanged: " << *(uint32_t*)parameter << std::endl;
_buffer_size_change(*(uint32_t*)parameter);
- break;
+ break;
case WCMRAudioDeviceManagerClient::RequestReset:
std::cout << "------------------------------- WCMRAudioDeviceManagerClient::RequestReset" << std::endl;
+ engine.request_backend_reset();
break;
case WCMRAudioDeviceManagerClient::RequestResync:
std::cout << "------------------------------- WCMRAudioDeviceManagerClient::RequestResync" << std::endl;
@@ -53,6 +54,9 @@ void WavesAudioBackend::AudioDeviceManagerNotification (NotificationReason reaso
std::cout << "------------------------------- WCMRAudioDeviceManagerClient::SamplingRateChanged: " << *(float*)parameter << std::endl;
set_sample_rate(*(float*)parameter);
break;
+ case WCMRAudioDeviceManagerClient::Dropout:
+ std::cout << "------------------------------- WCMRAudioDeviceManagerClient::Dropout: " << std::endl;
+ break;
case WCMRAudioDeviceManagerClient::DeviceDroppedSamples:
std::cout << "------------------------------- WCMRAudioDeviceManagerClient::DeviceDroppedSamples" << std::endl;
break;
@@ -68,11 +72,11 @@ void WavesAudioBackend::AudioDeviceManagerNotification (NotificationReason reaso
break;
case WCMRAudioDeviceManagerClient::DeviceListChanged:
std::cout << "------------------------------- WCMRAudioDeviceManagerClient::DeviceListChanged" << std::endl;
- _device_list_change();
+ engine.request_device_list_update();
break;
case WCMRAudioDeviceManagerClient::IODeviceDisconnected:
std::cout << "------------------------------- WCMRAudioDeviceManagerClient::DeviceListChanged" << std::endl;
- _device_list_change();
+ engine.request_device_list_update();
break;
case WCMRAudioDeviceManagerClient::AudioCallback:
if (parameter) {
@@ -192,17 +196,18 @@ WavesAudioBackend::available_sample_rates (const std::string& device_name) const
{
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::available_sample_rates (): [" << device_name << "]" << std::endl;
- DeviceInfo devInfo;
- WTErr err = _audio_device_manager.GetDeviceInfoByName(device_name, devInfo);
+ std::vector<int> sr;
- if (eNoErr != err) {
+ WTErr retVal = _audio_device_manager.GetDeviceSampleRates(device_name, sr);
+
+ if (eNoErr != retVal) {
std::cerr << "WavesAudioBackend::available_sample_rates (): Failed to find device [" << device_name << "]" << std::endl;
return std::vector<float> ();
}
// COMMENTED DBG LOGS */ std::cout << "\tFound " << devInfo.m_AvailableSampleRates.size () << " sample rates for " << device_name << ":";
- std::vector<float> sample_rates (devInfo.m_AvailableSampleRates.begin (), devInfo.m_AvailableSampleRates.end ());
+ std::vector<float> sample_rates (sr.begin (), sr.end ());
// COMMENTED DBG LOGS */ for (std::vector<float>::iterator i = sample_rates.begin (); i != sample_rates.end (); ++i) std::cout << " " << *i; std::cout << std::endl;
@@ -224,8 +229,7 @@ WavesAudioBackend::available_buffer_sizes (const std::string& device_name) const
std::vector<int> bs;
- WTErr retVal;
- retVal = _audio_device_manager.GetDeviceBufferSizes(device_name, bs);
+ WTErr retVal = _audio_device_manager.GetDeviceBufferSizes(device_name, bs);
if (retVal != eNoErr) {
std::cerr << "WavesAudioBackend::available_buffer_sizes (): Failed to get buffer size for device [" << device_name << "]" << std::endl;
@@ -442,6 +446,10 @@ WavesAudioBackend::set_buffer_size (uint32_t buffer_size)
return -1;
}
+ // if call to set buffer is successful but device buffer size differs from the value we tried to set
+ // this means we are driven by device for buffer size
+ buffer_size = _device->CurrentBufferSize ();
+
_buffer_size_change(buffer_size);
if (device_needs_restart) {
@@ -468,9 +476,9 @@ WavesAudioBackend::set_sample_format (SampleFormat sample_format)
}
int
-WavesAudioBackend::_reset_device (uint32_t buffer_size, float sample_rate)
+WavesAudioBackend::reset_device ()
{
- // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::_reset_device (" << buffer_size <<", " << sample_rate << "):" << std::endl;
+ // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::_reset_device ():" << std::endl;
WTErr retVal = eNoErr;
@@ -479,95 +487,7 @@ WavesAudioBackend::_reset_device (uint32_t buffer_size, float sample_rate)
return -1;
}
- bool device_needs_restart = _device->Streaming ();
-
- if (device_needs_restart) {
- retVal = _device->SetStreaming (false);
- // COMMENTED DBG LOGS */ std::cout << "\t\t[" << _device->DeviceName() << "]->SetStreaming (false);"<< std::endl;
- if (retVal != eNoErr) {
- std::cerr << "WavesAudioBackend::_reset_device (): [" << _device->DeviceName () << "]->SetStreaming (false) failed (" << retVal << ") !" << std::endl;
- return -1;
- }
- retVal = _device->SetActive (false);
- // COMMENTED DBG LOGS */ std::cout << "\t\t[" << _device->DeviceName() << "]->SetActive (false);"<< std::endl;
- if (retVal != eNoErr) {
- std::cerr << "WavesAudioBackend::_reset_device (): [" << _device->DeviceName () << "]->SetActive (false) failed (" << retVal << ") !" << std::endl;
- return -1;
- }
- }
-
- retVal = _device->UpdateDeviceInfo ();
- if (retVal != eNoErr) {
- std::cerr << "WavesAudioBackend::_reset_device (): [" << _device->DeviceName() << "]->UpdateDeviceInfo () failed (" << retVal << ") !" << std::endl;
- return -1;
- }
-
- if (buffer_size != 0)
- {
- retVal = _device->SetCurrentBufferSize (buffer_size);
-
- if (retVal != eNoErr) {
- std::cerr << "WavesAudioBackend::_reset_device (): [" << _device->DeviceName() << "]->SetCurrentBufferSize (" << buffer_size << ") failed (" << retVal << ") !" << std::endl;
- return -1;
- }
-
- _buffer_size = buffer_size;
- }
- else
- {
- uint32_t current_buffer_size = _device->CurrentBufferSize();
- // COMMENTED DBG LOGS */ std::cout << "\t\tcurrent_buffer_size: " << current_buffer_size << std::endl;
- // COMMENTED DBG LOGS */ std::cout << "\t\t _buffer_size: " << _buffer_size << std::endl;
- if(_buffer_size != current_buffer_size)
- {
- _buffer_size = current_buffer_size;
- engine.buffer_size_change (_buffer_size);
- // COMMENTED DBG LOGS */ std::cout << "\t\tengine.buffer_size_change (" << buffer_size <<")" << std::endl;
- }
- }
-
- if(sample_rate > 0.0)
- {
- retVal = _device->SetCurrentSamplingRate ((int)sample_rate);
-
- if (retVal != eNoErr) {
- std::cerr << "WavesAudioBackend::set_sample_rate (): [" << _device->DeviceName() << "]->SetCurrentSamplingRate ((int)" << sample_rate << ") failed (" << retVal << ") !" << std::endl;
- return -1;
- }
- _sample_rate = sample_rate;
- }
- else
- {
- float current_sample_rate = _device->CurrentSamplingRate();
- // COMMENTED DBG LOGS */ std::cout << "\t\tcurrent_sample_rate: " << current_sample_rate << std::endl;
- // COMMENTED DBG LOGS */ std::cout << "\t\t _sample_rate: " << _sample_rate << std::endl;
- if(_sample_rate != current_sample_rate)
- {
- _sample_rate = current_sample_rate;
- engine.sample_rate_change (_sample_rate);
- // COMMENTED DBG LOGS */ std::cout << "\t\tengine.sample_rate_change (" << _sample_rate <<")" << std::endl;
- }
- }
-
- _init_dsp_load_history();
-
- if (device_needs_restart) {
- // COMMENTED DBG LOGS */ std::cout << "\t\t[" << _device->DeviceName() << "]->SetActive (true);"<< std::endl;
- retVal = _device->SetActive (true);
- if (retVal != eNoErr) {
- std::cerr << "WavesAudioBackend::_reset_device (): [" << _device->DeviceName () << "]->SetActive (true) failed (" << retVal << ") !" << std::endl;
- return -1;
- }
- // COMMENTED DBG LOGS */ std::cout << "\t\t[" << _device->DeviceName() << "]->SetStreaming (true);"<< std::endl;
- _call_thread_init_callback = true;
- retVal = _device->SetStreaming (true);
- if (retVal != eNoErr) {
- std::cerr << "WavesAudioBackend::_reset_device (): [" << _device->DeviceName () << "]->SetStreaming (true) failed (" << retVal << ") !" << std::endl;
- return -1;
- }
- }
-
- return 0;
+ return _device->ResetDevice();
}
@@ -589,15 +509,6 @@ WavesAudioBackend::_sample_rate_change (float new_sample_rate)
}
-int
-WavesAudioBackend::_device_list_change ()
-{
- // requires GZ changes for device list update
- // return engine.device_list_change ();
- return 0;
-}
-
-
int
WavesAudioBackend::set_interleaved (bool yn)
{
@@ -750,22 +661,26 @@ WavesAudioBackend::_start (bool for_latency_measurement)
if (!_device) {
std::cerr << "WavesAudioBackend::_start (): No device is set!" << std::endl;
- return -1;
+ stop();
+ return -1;
}
if (_register_system_audio_ports () != 0) {
std::cerr << "WavesAudioBackend::_start (): _register_system_audio_ports () failed!" << std::endl;
- return -1;
+ stop();
+ return -1;
}
if (_use_midi) {
if (_midi_device_manager.start () != 0) {
std::cerr << "WavesAudioBackend::_start (): _midi_device_manager.start () failed!" << std::endl;
- return -1;
+ stop();
+ return -1;
}
if (_register_system_midi_ports () != 0) {
std::cerr << "WavesAudioBackend::_start (): _register_system_midi_ports () failed!" << std::endl;
- return -1;
+ stop();
+ return -1;
}
}
@@ -779,13 +694,15 @@ WavesAudioBackend::_start (bool for_latency_measurement)
WTErr retVal = _device->SetStreaming (true);
if (retVal != eNoErr) {
std::cerr << "WavesAudioBackend::_start (): [" << _device->DeviceName () << "]->SetStreaming () failed!" << std::endl;
+ stop();
return -1;
}
if (_use_midi) {
if (_midi_device_manager.stream (true)) {
std::cerr << "WavesAudioBackend::_start (): _midi_device_manager.stream (true) failed!" << std::endl;
- return -1;
+ stop();
+ return -1;
}
}
@@ -827,7 +744,7 @@ WavesAudioBackend::_audio_device_callback (const float* input_buffer,
uint64_t dsp_end_time_nanos = __get_time_nanos();
_dsp_load_accumulator -= *_dsp_load_history.begin();
- _dsp_load_history.pop_front();
+ _dsp_load_history.pop_front();
uint64_t dsp_load_nanos = dsp_end_time_nanos - dsp_start_time_nanos;
_dsp_load_accumulator += dsp_load_nanos;
_dsp_load_history.push_back(dsp_load_nanos);
@@ -1217,7 +1134,7 @@ WavesAudioBackend::_read_audio_data_from_device (const float* input_buffer, pfra
{
#if defined(PLATFORM_WINDOWS)
const float **buffer = (const float**)input_buffer;
- size_t copied_bytes = nframes*sizeof(float*);
+ size_t copied_bytes = nframes*sizeof(float);
for(std::vector<WavesAudioPort*>::iterator it = _physical_audio_inputs.begin ();
it != _physical_audio_inputs.end();
@@ -1284,7 +1201,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, __backend_info));
+ __instance.reset (new WavesAudioBackend (e, *(descriptor())));
}
return __instance;
}
@@ -1375,3 +1292,4 @@ AudioBackendInfo WavesAudioBackend::__backend_info = {
WavesAudioBackend::__already_configured,
};
+
diff --git a/libs/backends/wavesaudio/waves_audiobackend.h b/libs/backends/wavesaudio/waves_audiobackend.h
index 6c027824c4..a97bd957bd 100644
--- a/libs/backends/wavesaudio/waves_audiobackend.h
+++ b/libs/backends/wavesaudio/waves_audiobackend.h
@@ -122,9 +122,10 @@ class WavesMidiPort;
virtual int set_systemic_output_latency (uint32_t);
int set_systemic_midi_input_latency (std::string const, uint32_t) { return 0; }
-
int set_systemic_midi_output_latency (std::string const, uint32_t) { return 0; }
+ virtual int reset_device ();
+
virtual std::string device_name () const;
virtual float sample_rate () const;
@@ -345,15 +346,12 @@ class WavesMidiPort;
pframes_t sample_time,
uint64_t cycle_start_time_nanos);
- int _reset_device (uint32_t buffer_size, float sample_rate);
void _changed_midi_devices ();
// DO change sample rate and buffer size
int _buffer_size_change(uint32_t new_buffer_size);
int _sample_rate_change(float new_sample_rate);
- int _device_list_change();
-
int _register_system_audio_ports ();
int _register_system_midi_ports ();
diff --git a/libs/backends/wavesaudio/waves_audiobackend.latency.cc b/libs/backends/wavesaudio/waves_audiobackend.latency.cc
index e1869cbf1f..17f0e9609e 100644
--- a/libs/backends/wavesaudio/waves_audiobackend.latency.cc
+++ b/libs/backends/wavesaudio/waves_audiobackend.latency.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2013 Valeriy Kamyshniy
+ Copyright (C) 2014 Waves Audio Ltd.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/libs/backends/wavesaudio/waves_audiobackend.midi.cc b/libs/backends/wavesaudio/waves_audiobackend.midi.cc
index 9ebcd1cc54..f77a288624 100644
--- a/libs/backends/wavesaudio/waves_audiobackend.midi.cc
+++ b/libs/backends/wavesaudio/waves_audiobackend.midi.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2013 Valeriy Kamyshniy
+ Copyright (C) 2014 Waves Audio Ltd.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/libs/backends/wavesaudio/waves_audiobackend.port_engine.cc b/libs/backends/wavesaudio/waves_audiobackend.port_engine.cc
index f798ff4c14..ffde29e03b 100644
--- a/libs/backends/wavesaudio/waves_audiobackend.port_engine.cc
+++ b/libs/backends/wavesaudio/waves_audiobackend.port_engine.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2013 Valeriy Kamyshniy
+ Copyright (C) 2014 Waves Audio Ltd.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -425,7 +425,7 @@ WavesAudioBackend::physically_connected (PortHandle port_handle, bool process_ca
int
WavesAudioBackend::get_connections (PortHandle port_handle, std::vector<std::string>& names, bool process_callback_safe)
{
- // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::get_connections ()" << std::endl;
+ // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::get_connections ()" << std::endl;
if (!_registered (port_handle)) {
std::cerr << "WavesAudioBackend::get_connections (): Failed to find port [" << std::hex << port_handle << std::dec << "]!" << std::endl;
@@ -487,6 +487,8 @@ WavesAudioBackend::port_is_physical (PortHandle port_handle) const
void
WavesAudioBackend::get_physical_outputs (DataType type, std::vector<std::string>& names)
{
+ names.clear();
+
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::get_physical_outputs ():" << std::endl << "\tdatatype = " << type << std::endl;
switch (type) {
@@ -511,6 +513,8 @@ WavesAudioBackend::get_physical_outputs (DataType type, std::vector<std::string>
void
WavesAudioBackend::get_physical_inputs (DataType type, std::vector<std::string>& names)
{
+ names.clear();
+
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::get_physical_inputs ():" << std::endl << "\tdatatype = " << type << std::endl;
switch (type) {
case ARDOUR::DataType::AUDIO: {
@@ -594,10 +598,11 @@ WavesAudioBackend::_register_system_audio_ports ()
for (std::vector<std::string>::iterator it = input_channels.begin ();
(port_number < channels) && (it != input_channels.end ());
++it) {
- std::ostringstream port_name;
- port_name << "capture_" << ++port_number;
-
- WavesDataPort* port = _register_port ("system:" + port_name.str (), DataType::AUDIO , static_cast<PortFlags> (IsOutput | IsPhysical | IsTerminal));
+
+ std::ostringstream port_name(*it);
+ WavesDataPort* port = _register_port ("system:capture:" + port_name.str (), DataType::AUDIO ,
+ static_cast<PortFlags> (IsOutput | IsPhysical | IsTerminal));
+
if (port == NULL) {
std::cerr << "WavesAudioBackend::_create_system_audio_ports (): Failed registering port [" << port_name << "] for [" << _device->DeviceName () << "]" << std::endl;
return-1;
@@ -616,9 +621,11 @@ WavesAudioBackend::_register_system_audio_ports ()
for (std::vector<std::string>::iterator it = output_channels.begin ();
(port_number < channels) && (it != output_channels.end ());
++it) {
- std::ostringstream port_name;
- port_name << "playback_" << ++port_number;
- WavesDataPort* port = _register_port ("system:" + port_name.str (), DataType::AUDIO , static_cast<PortFlags> (IsInput| IsPhysical | IsTerminal));
+
+ std::ostringstream port_name(*it);
+ WavesDataPort* port = _register_port ("system:playback:" + port_name.str (), DataType::AUDIO ,
+ static_cast<PortFlags> (IsInput| IsPhysical | IsTerminal));
+
if (port == NULL) {
std::cerr << "WavesAudioBackend::_create_system_audio_ports (): Failed registering port ]" << port_name << "] for [" << _device->DeviceName () << "]" << std::endl;
return-1;
diff --git a/libs/backends/wavesaudio/waves_audioport.cc b/libs/backends/wavesaudio/waves_audioport.cc
index 600066b83c..4ded37d906 100644
--- a/libs/backends/wavesaudio/waves_audioport.cc
+++ b/libs/backends/wavesaudio/waves_audioport.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2013 Valeriy Kamyshniy
+ Copyright (C) 2014 Waves Audio Ltd.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/libs/backends/wavesaudio/waves_dataport.cc b/libs/backends/wavesaudio/waves_dataport.cc
index 9e68dd1a9b..d1dacc90eb 100644
--- a/libs/backends/wavesaudio/waves_dataport.cc
+++ b/libs/backends/wavesaudio/waves_dataport.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2013 Valeriy Kamyshniy
+ Copyright (C) 2014 Waves Audio Ltd.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRAudioDeviceManager.cpp b/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRAudioDeviceManager.cpp
index 256dc6b4cf..cddc218df6 100644
--- a/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRAudioDeviceManager.cpp
+++ b/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRAudioDeviceManager.cpp
@@ -345,6 +345,28 @@ WTErr WCMRAudioDevice::SetStreaming (bool newState)
return (eNoErr);
}
+
+WTErr WCMRAudioDevice::ResetDevice ()
+{
+ // Keep device sates
+ bool wasStreaming = Streaming();
+ bool wasActive = Active();
+
+ WTErr err = SetStreaming(false);
+
+ if (err == eNoErr)
+ SetActive(false);
+
+ if (err == eNoErr && wasActive)
+ SetActive(true);
+
+ if (err == eNoErr && wasStreaming)
+ SetStreaming(true);
+
+ return err;
+}
+
+
///////////////////////////////////////////////////////////////////////////////////////////////////////
// IsProcessActive - returns true if process code is running.
// A normal audio device should return the Streaming() value
@@ -632,6 +654,13 @@ WTErr WCMRAudioDeviceManager::GetDeviceInfoByName(const std::string & nameToMatc
}
+WTErr WCMRAudioDeviceManager::GetDeviceSampleRates(const std::string & nameToMatch, std::vector<int>& sampleRates) const
+{
+ return getDeviceSampleRatesImpl(nameToMatch, sampleRates);
+}
+
+
+
WTErr WCMRAudioDeviceManager::GetDeviceBufferSizes(const std::string & nameToMatch, std::vector<int>& bufferSizes) const
{
return getDeviceBufferSizesImpl(nameToMatch, bufferSizes);
diff --git a/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRAudioDeviceManager.h b/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRAudioDeviceManager.h
index a3b1baa784..7466544d44 100644
--- a/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRAudioDeviceManager.h
+++ b/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRAudioDeviceManager.h
@@ -151,6 +151,8 @@ public:
virtual bool Streaming();///<Streaming Status?
virtual WTErr SetStreaming (bool newState);///<Start/Stop Streaming - should reconnect connections when streaming starts!
+ virtual WTErr ResetDevice ();
+
virtual bool IsProcessActive();
virtual WTErr DoIdle();///<Do Idle Processing
@@ -218,6 +220,7 @@ public://< Public functions for the class.
void DestroyCurrentDevice();
const DeviceInfoVec DeviceInfoList () const;
WTErr GetDeviceInfoByName(const std::string & nameToMatch, DeviceInfo & devInfo) const;
+ WTErr GetDeviceSampleRates(const std::string & nameToMatch, std::vector<int>& sampleRates) const;
WTErr GetDeviceBufferSizes(const std::string & nameToMatch, std::vector<int>& bufferSizes) const;
//virtual void EnableVerboseLogging(bool /*bEnable*/, const std::string& /*logFilePath*/) { };
@@ -238,6 +241,7 @@ private:
// made private to avoid pure virtual function call
virtual WCMRAudioDevice* initNewCurrentDeviceImpl(const std::string & deviceName) = 0;
virtual void destroyCurrentDeviceImpl() = 0;
+ virtual WTErr getDeviceSampleRatesImpl(const std::string & deviceName, std::vector<int>& sampleRates) const = 0;
virtual WTErr getDeviceBufferSizesImpl(const std::string & deviceName, std::vector<int>& bufferSizes) const = 0;
virtual WTErr generateDeviceListImpl() = 0;
virtual WTErr updateDeviceListImpl() = 0;
diff --git a/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRCoreAudioDeviceManager.cpp b/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRCoreAudioDeviceManager.cpp
index 8e8ee466dc..5c1ceac63e 100644
--- a/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRCoreAudioDeviceManager.cpp
+++ b/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRCoreAudioDeviceManager.cpp
@@ -25,7 +25,7 @@ using namespace wvNS;
///< Supported Sample rates
static const double gAllSampleRates[] =
{
- 44100.0, 48000.0, 88200.0, 96000.0, -1 /* negative terminated list */
+ 44100.0, 48000.0, 88200.0, 96000.0, 176400.0, 192000.0, -1 /* negative terminated list */
};
@@ -356,7 +356,7 @@ WTErr WCMRCoreAudioDevice::UpdateDeviceInputs()
memset (pStreamBuffers, 0, propSize);
// Get the Input channels
- err = AudioDeviceGetProperty (m_DeviceID, 0, 1/* Input */, kAudioDevicePropertyStreamConfiguration, &propSize, pStreamBuffers);
+ err = AudioDeviceGetProperty (m_DeviceID, 0, true/* Input */, kAudioDevicePropertyStreamConfiguration, &propSize, pStreamBuffers);
if (err == kAudioHardwareNoError)
{
// Calculate the number of input channels
@@ -387,12 +387,54 @@ WTErr WCMRCoreAudioDevice::UpdateDeviceInputs()
// Update input channels
m_InputChannels.clear();
+
for (int channel = 0; channel < maxInputChannels; channel++)
{
+ CFStringRef cfName;
std::stringstream chNameStream;
- //A better implementation would be to retrieve the names from ASIO or CoreAudio interfaces
- chNameStream << "Input " << (channel+1);
+ UInt32 nameSize = 0;
+ OSStatus error = kAudioHardwareNoError;
+
+ error = AudioDeviceGetPropertyInfo (m_DeviceID,
+ channel + 1,
+ true /* Input */,
+ kAudioDevicePropertyChannelNameCFString,
+ &nameSize,
+ NULL);
+
+ if (error == kAudioHardwareNoError)
+ {
+ error = AudioDeviceGetProperty (m_DeviceID,
+ channel + 1,
+ true /* Input */,
+ kAudioDevicePropertyChannelNameCFString,
+ &nameSize,
+ &cfName);
+ }
+
+ bool decoded = false;
+ char* cstr_name = 0;
+ if (error == kAudioHardwareNoError)
+ {
+ CFIndex length = CFStringGetLength(cfName);
+ CFIndex maxSize = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8);
+ cstr_name = new char[maxSize];
+ decoded = CFStringGetCString(cfName, cstr_name, maxSize, kCFStringEncodingUTF8);
+ }
+
+ chNameStream << (channel+1) << " - ";
+
+ if (cstr_name && decoded && (0 != std::strlen(cstr_name) ) ) {
+ chNameStream << cstr_name;
+ }
+ else
+ {
+ chNameStream << "Input " << (channel+1);
+ }
+
m_InputChannels.push_back (chNameStream.str());
+
+ delete [] cstr_name;
}
return retVal;
@@ -470,10 +512,51 @@ WTErr WCMRCoreAudioDevice::UpdateDeviceOutputs()
m_OutputChannels.clear();
for (int channel = 0; channel < maxOutputChannels; channel++)
{
+ CFStringRef cfName;
std::stringstream chNameStream;
- //A better implementation would be to retrieve the names from ASIO or CoreAudio interfaces
- chNameStream << "Output " << (channel+1);
+ UInt32 nameSize = 0;
+ OSStatus error = kAudioHardwareNoError;
+
+ error = AudioDeviceGetPropertyInfo (m_DeviceID,
+ channel + 1,
+ false /* Output */,
+ kAudioDevicePropertyChannelNameCFString,
+ &nameSize,
+ NULL);
+
+ if (error == kAudioHardwareNoError)
+ {
+ error = AudioDeviceGetProperty (m_DeviceID,
+ channel + 1,
+ false /* Output */,
+ kAudioDevicePropertyChannelNameCFString,
+ &nameSize,
+ &cfName);
+ }
+
+ bool decoded = false;
+ char* cstr_name = 0;
+ if (error == kAudioHardwareNoError )
+ {
+ CFIndex length = CFStringGetLength(cfName);
+ CFIndex maxSize = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8);
+ cstr_name = new char[maxSize];
+ decoded = CFStringGetCString(cfName, cstr_name, maxSize, kCFStringEncodingUTF8);
+ }
+
+ chNameStream << (channel+1) << " - ";
+
+ if (cstr_name && decoded && (0 != std::strlen(cstr_name) ) ) {
+ chNameStream << cstr_name;
+ }
+ else
+ {
+ chNameStream << "Output " << (channel+1);
+ }
+
m_OutputChannels.push_back (chNameStream.str());
+
+ delete [] cstr_name;
}
return retVal;
@@ -1178,12 +1261,17 @@ WTErr WCMRCoreAudioDevice::EnableListeners()
goto Exit;
}
-#if ENABLE_DEVICE_CHANGE_LISTNER
+#if ENABLE_DEVICE_CHANGE_LISTNER
{
//listner for device change...
- err = AudioDeviceAddPropertyListener(m_DeviceID, 0, 0, kAudioDevicePropertyDeviceHasChanged,
- StaticPropertyChangeProc, this);
+ err = AudioDeviceAddPropertyListener (m_DeviceID,
+ kAudioPropertyWildcardChannel,
+ true,
+ kAudioDevicePropertyDeviceHasChanged,
+ StaticPropertyChangeProc,
+ this);
+
if (err)
{
DEBUG_MSG("Couldn't Setup device change Property Listner, error = " << err);
@@ -1239,14 +1327,18 @@ WTErr WCMRCoreAudioDevice::DisableListeners()
#if ENABLE_DEVICE_CHANGE_LISTNER
{
- err = AudioDeviceRemovePropertyListener(m_DeviceID, 0, 0, kAudioDevicePropertyDeviceHasChanged,
- StaticPropertyChangeProc);
-
+ err = AudioDeviceRemovePropertyListener (m_DeviceID,
+ kAudioPropertyWildcardChannel,
+ true/* Input */,
+ kAudioDevicePropertyDeviceHasChanged,
+ StaticPropertyChangeProc);
+
if (err)
{
- DEBUG_MSG("Couldn't Cleanup device change Property Listner, error = " << err);
+ DEBUG_MSG("Couldn't Cleanup device input stream change Property Listner, error = " << err);
//not sure if we need to report this...
}
+
}
#endif //ENABLE_DEVICE_CHANGE_LISTNER
@@ -1315,15 +1407,19 @@ void WCMRCoreAudioDevice::PropertyChangeProc (AudioDevicePropertyID inPropertyID
case kAudioDevicePropertyDeviceHasChanged:
{
m_ResetRequested++;
+ m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::RequestReset);
}
break;
#endif //ENABLE_DEVICE_CHANGE_LISTNER
case kAudioDeviceProcessorOverload:
+ {
if (m_IgnoreThisDrop)
m_IgnoreThisDrop = false; //We'll ignore once, just once!
else
m_DropsDetected++;
+ m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::Dropout );
break;
+ }
default:
break;
}
@@ -1589,35 +1685,7 @@ WTErr WCMRCoreAudioDevice::SetupAUHAL()
retVal = EnableListeners();
if (retVal != eNoErr)
goto Exit;
-
- //also prepare the buffer list for input...
- if (!m_InputChannels.empty())
- {
-
- //now setup the buffer list.
- memset (&m_InputAudioBufferList, 0, sizeof (m_InputAudioBufferList));
- m_InputAudioBufferList.mNumberBuffers = 1;
- m_InputAudioBufferList.mBuffers[0].mNumberChannels = m_InputChannels.size();
- m_InputAudioBufferList.mBuffers[0].mDataByteSize = m_InputAudioBufferList.mBuffers[0].mNumberChannels *
- m_CurrentBufferSize * sizeof(float);
- //allocate the data buffer...
- try
- {
- m_pInputData = new float[m_InputAudioBufferList.mBuffers[0].mNumberChannels * m_CurrentBufferSize];
- }
- catch (...)
- {
- retVal = eMemNewFailed;
- goto Exit;
- }
-
- m_InputAudioBufferList.mBuffers[0].mData = m_pInputData;
-
- //zero it out...
- memset (m_InputAudioBufferList.mBuffers[0].mData, 0, m_InputAudioBufferList.mBuffers[0].mDataByteSize);
- }
-
//initialize the audio-unit now!
err = AudioUnitInitialize(m_AUHALAudioUnit);
if (err != kAudioHardwareNoError)
@@ -1657,8 +1725,6 @@ WTErr WCMRCoreAudioDevice::TearDownAUHAL()
CloseComponent(m_AUHALAudioUnit);
m_AUHALAudioUnit = NULL;
}
-
- safe_delete_array(m_pInputData);
return retVal;
}
@@ -1689,7 +1755,6 @@ WTErr WCMRCoreAudioDevice::SetActive (bool newState)
if (newState)
{
-
m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::DeviceDebugInfo, (void *)"Setting up AUHAL.");
retVal = SetupAUHAL();
@@ -1837,7 +1902,6 @@ WTErr WCMRCoreAudioDevice::SetStreaming (bool newState)
SetupToneGenerator ();
#endif //WV_USE_TONE_GEN
- m_StopRequested = false;
m_SampleCountAtLastIdle = 0;
m_StalledSampleCounter = 0;
m_SampleCounter = 0;
@@ -1854,6 +1918,8 @@ WTErr WCMRCoreAudioDevice::SetStreaming (bool newState)
err = AudioOutputUnitStart (m_AUHALAudioUnit);
+ m_StopRequested = false;
+
if(err)
{
DEBUG_MSG( "Failed to start AudioUnit, err " << err );
@@ -1868,11 +1934,11 @@ WTErr WCMRCoreAudioDevice::SetStreaming (bool newState)
err = AudioOutputUnitStop (m_AUHALAudioUnit);
if (!err)
{
- if (!m_InputChannels.empty());
+ //if (!m_InputChannels.empty());
{
err = AudioUnitReset (m_AUHALAudioUnit, kAudioUnitScope_Global, AUHAL_INPUT_ELEMENT);
}
- if (!m_OutputChannels.empty());
+ //if (!m_OutputChannels.empty());
{
err = AudioUnitReset (m_AUHALAudioUnit, kAudioUnitScope_Global, AUHAL_OUTPUT_ELEMENT);
}
@@ -1911,6 +1977,7 @@ Exit:
//**********************************************************************************************
WTErr WCMRCoreAudioDevice::DoIdle ()
{
+ /*
if (m_BufferSizeChangeRequested != m_BufferSizeChangeReported)
{
m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::BufferSizeChanged);
@@ -1963,7 +2030,7 @@ WTErr WCMRCoreAudioDevice::DoIdle ()
m_StalledSampleCounter = 0;
m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::DeviceStoppedStreaming, (void *)currentSampleCount);
}
- }
+ }*/
return (eNoErr);
@@ -2055,6 +2122,18 @@ WTErr WCMRCoreAudioDevice::ShowConfigPanel (void */*pParam*/)
{
LSOpenFSRef(&theAppFSRef, NULL);
}
+ else
+ {
+ // open default AudioMIDISetup if device app is not found
+ CFStringRef audiMidiSetupApp = CFStringCreateWithCString(kCFAllocatorDefault, "com.apple.audio.AudioMIDISetup", kCFStringEncodingMacRoman);
+ theError = LSFindApplicationForInfo(kLSUnknownCreator, audiMidiSetupApp, NULL, &theAppFSRef, NULL);
+
+ if (!theError)
+ {
+ LSOpenFSRef(&theAppFSRef, NULL);
+ }
+ }
+
CFRelease (configAP);
}
@@ -2116,19 +2195,38 @@ OSStatus WCMRCoreAudioDevice::AudioIOProc(AudioUnitRenderActionFlags * ioAction
OSStatus retVal = 0;
if (m_StopRequested)
- goto Exit;
+ return retVal;
if (m_IOProcThreadPort == 0)
m_IOProcThreadPort = mach_thread_self ();
//cannot really deal with it unless the number of frames are the same as our buffer size!
if (inNumberFrames != (UInt32)m_CurrentBufferSize)
- goto Exit;
+ return retVal;
//Retrieve the input data...
if (!m_InputChannels.empty())
{
- retVal = AudioUnitRender(m_AUHALAudioUnit, ioActionFlags, inTimeStamp, AUHAL_INPUT_ELEMENT, inNumberFrames, &m_InputAudioBufferList);
+ UInt32 expectedDataSize = m_InputChannels.size() * m_CurrentBufferSize * sizeof(float);
+ AudioBufferList inputAudioBufferList;
+ inputAudioBufferList.mNumberBuffers = 1;
+ inputAudioBufferList.mBuffers[0].mNumberChannels = m_InputChannels.size();
+ inputAudioBufferList.mBuffers[0].mDataByteSize = expectedDataSize;
+ inputAudioBufferList.mBuffers[0].mData = NULL;//new float[expectedDataSize]; // we are going to get buffer from CoreAudio
+
+ retVal = AudioUnitRender(m_AUHALAudioUnit, ioActionFlags, inTimeStamp, AUHAL_INPUT_ELEMENT, inNumberFrames, &inputAudioBufferList);
+
+ if (retVal == kAudioHardwareNoError &&
+ inputAudioBufferList.mBuffers[0].mNumberChannels == m_InputChannels.size() &&
+ inputAudioBufferList.mBuffers[0].mDataByteSize == expectedDataSize )
+ {
+ m_pInputData = (float*)inputAudioBufferList.mBuffers[0].mData;
+ }
+ else
+ {
+ m_pInputData = NULL;
+ return retVal;
+ }
}
//is this an input only device?
@@ -2137,7 +2235,6 @@ OSStatus WCMRCoreAudioDevice::AudioIOProc(AudioUnitRenderActionFlags * ioAction
else if ((!m_OutputChannels.empty()) && (ioData->mBuffers[0].mNumberChannels == m_OutputChannels.size()))
AudioCallback ((float *)ioData->mBuffers[0].mData, inNumberFrames, (uint32_t)inTimeStamp->mSampleTime, theStartTime);
-Exit:
return retVal;
}
@@ -2316,7 +2413,7 @@ WCMRCoreAudioDeviceManager::WCMRCoreAudioDeviceManager(WCMRAudioDeviceManagerCli
}
//add a listener to find out when devices change...
- AudioHardwareAddPropertyListener (kAudioHardwarePropertyDevices, DevicePropertyChangeCallback, this);
+ AudioHardwareAddPropertyListener (kAudioHardwarePropertyDevices, HardwarePropertyChangeCallback, this);
//Always add the None device first...
m_NoneDevice = new WCMRNativeAudioNoneDevice(this);
@@ -2415,7 +2512,7 @@ WTErr WCMRCoreAudioDeviceManager::getDeviceAvailableSampleRates(DeviceID deviceI
{
//! 2. Get property: cannels output.
- // Allocate size accrding to the number of audio values
+ // Allocate size according to the number of audio values
int numRates = propSize / sizeof(AudioValueRange);
AudioValueRange* supportedRates = new AudioValueRange[numRates];
@@ -2465,7 +2562,7 @@ WTErr WCMRCoreAudioDeviceManager::getDeviceMaxInputChannels(DeviceID deviceId, u
OSStatus err = kAudioHardwareNoError;
UInt32 propSize = 0;
inputChannels = 0;
-
+
// 1. Get property cannels input size.
err = AudioDeviceGetPropertyInfo (deviceId, 0, 1/* Input */, kAudioDevicePropertyStreamConfiguration, &propSize, NULL);
if (err == kAudioHardwareNoError)
@@ -2521,7 +2618,7 @@ WTErr WCMRCoreAudioDeviceManager::getDeviceMaxOutputChannels(DeviceID deviceId,
OSStatus err = kAudioHardwareNoError;
UInt32 propSize = 0;
outputChannels = 0;
-
+
//! 1. Get property cannels output size.
err = AudioDeviceGetPropertyInfo (deviceId, 0, 0/* Output */, kAudioDevicePropertyStreamConfiguration, &propSize, NULL);
if (err == kAudioHardwareNoError)
@@ -2786,6 +2883,84 @@ WTErr WCMRCoreAudioDeviceManager::updateDeviceListImpl()
}
+WTErr WCMRCoreAudioDeviceManager::getDeviceSampleRatesImpl(const std::string & deviceName, std::vector<int>& sampleRates) const
+{
+ AUTO_FUNC_DEBUG;
+
+ WTErr retVal = eNoErr;
+ OSStatus err = kAudioHardwareNoError;
+ UInt32 propSize = 0;
+
+ sampleRates.clear();
+
+ //first check if the request has been made for None device
+ if (deviceName == m_NoneDevice->DeviceName() )
+ {
+ sampleRates = m_NoneDevice->SamplingRates();
+ return retVal;
+ }
+
+ if (m_CurrentDevice && m_CurrentDevice->DeviceName () == deviceName) {
+ sampleRates.assign(m_CurrentDevice->SamplingRates().begin(), m_CurrentDevice->SamplingRates().end() );
+ return retVal;
+ }
+
+ DeviceInfo devInfo;
+ retVal = GetDeviceInfoByName(deviceName, devInfo);
+
+ //! 1. Get sample rate property size.
+ err = AudioDeviceGetPropertyInfo(devInfo.m_DeviceId, 0, 0, kAudioDevicePropertyAvailableNominalSampleRates, &propSize, NULL);
+
+ if (err == kAudioHardwareNoError)
+ {
+ //! 2. Get property: cannels output.
+
+ // Allocate size accrding to the number of audio values
+ int numRates = propSize / sizeof(AudioValueRange);
+ AudioValueRange* supportedRates = new AudioValueRange[numRates];
+
+ // Get sampling rates from Audio device
+ err = AudioDeviceGetProperty(devInfo.m_DeviceId, 0, 0, kAudioDevicePropertyAvailableNominalSampleRates, &propSize, supportedRates);
+
+ if (err == kAudioHardwareNoError)
+ {
+ //! 3. Update sample rates
+
+ // now iterate through our standard SRs
+ for(int ourSR=0; gAllSampleRates[ourSR] > 0; ourSR++)
+ {
+ //check to see if our SR is in the supported rates...
+ for (int deviceSR = 0; deviceSR < numRates; deviceSR++)
+ {
+ if ((supportedRates[deviceSR].mMinimum <= gAllSampleRates[ourSR]) &&
+ (supportedRates[deviceSR].mMaximum >= gAllSampleRates[ourSR]))
+ {
+ sampleRates.push_back ((int)gAllSampleRates[ourSR]);
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ retVal = eCoreAudioFailed;
+ DEBUG_MSG("Failed to get device Sample rates. Device Name: " << m_DeviceName.c_str());
+ }
+
+ delete [] supportedRates;
+ }
+ else
+ {
+ retVal = eCoreAudioFailed;
+ DEBUG_MSG("Failed to get device Sample rates property size. Device Name: " << m_DeviceName.c_str());
+ }
+
+ devInfo.m_AvailableSampleRates.assign(sampleRates.begin(), sampleRates.end() );
+
+ return retVal;
+}
+
+
WTErr WCMRCoreAudioDeviceManager::getDeviceBufferSizesImpl(const std::string & deviceName, std::vector<int>& bufferSizes) const
{
AUTO_FUNC_DEBUG;
@@ -2803,6 +2978,11 @@ WTErr WCMRCoreAudioDeviceManager::getDeviceBufferSizesImpl(const std::string & d
return retVal;
}
+ if (m_CurrentDevice && m_CurrentDevice->DeviceName () == deviceName) {
+ bufferSizes.assign(m_CurrentDevice->BufferSizes().begin(), m_CurrentDevice->BufferSizes().end() );
+ return retVal;
+ }
+
DeviceInfo devInfo;
retVal = GetDeviceInfoByName(deviceName, devInfo);
@@ -2847,7 +3027,7 @@ WTErr WCMRCoreAudioDeviceManager::getDeviceBufferSizesImpl(const std::string & d
}
-OSStatus WCMRCoreAudioDeviceManager::DevicePropertyChangeCallback (AudioHardwarePropertyID inPropertyID, void* inClientData)
+OSStatus WCMRCoreAudioDeviceManager::HardwarePropertyChangeCallback (AudioHardwarePropertyID inPropertyID, void* inClientData)
{
switch (inPropertyID)
{
@@ -2858,6 +3038,7 @@ OSStatus WCMRCoreAudioDeviceManager::DevicePropertyChangeCallback (AudioHardware
pManager->updateDeviceListImpl();
}
break;
+
default:
break;
}
diff --git a/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRCoreAudioDeviceManager.h b/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRCoreAudioDeviceManager.h
index 5cfbedb9c9..913b4af5cb 100644
--- a/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRCoreAudioDeviceManager.h
+++ b/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRCoreAudioDeviceManager.h
@@ -81,7 +81,7 @@ protected:
AudioDeviceID m_DeviceID; ///< The CoreAudio device id
bool m_StopRequested; ///< should be set to true when want to stop, set to false otherwise.
- float *m_pInputData; ///< This is what came in with the most recent callback.
+ float *m_pInputData; ///< This is what came in with the most recent callback.
int m_SampleCounter; ///< The current running sample counter, updated by the audio callback.
int m_SampleCountAtLastIdle; ///< What was the sample count last time we checked...
int m_StalledSampleCounter; ///< The number of idle calls with same sample count detected
@@ -93,9 +93,7 @@ protected:
// int m_CyclesToAccumulate; ///< The number of cycles to accumulate the values for - maximum for last one second.
// unsigned int m_CyclePeriod; ///< The number of host time units for a cycle period - determined by buffer size and sampling rate
-
-
- AudioBufferList m_InputAudioBufferList; ///< The buffer list used to get AHHAL to render input to.
+
AudioUnit m_AUHALAudioUnit;///< The AUHAL AudioUnit
int m_BufferSizeChangeRequested;
@@ -152,6 +150,7 @@ protected:
AudioDevicePropertyID inPropertyID, void *inClientData);
void PropertyChangeProc (AudioDevicePropertyID inPropertyID);
+ void resetAudioDevice();
private:
};
@@ -168,12 +167,13 @@ public:
virtual ~WCMRCoreAudioDeviceManager(void); ///< Destructor
protected:
- static OSStatus DevicePropertyChangeCallback (AudioHardwarePropertyID inPropertyID, void* inClientData);
+ static OSStatus HardwarePropertyChangeCallback (AudioHardwarePropertyID inPropertyID, void* inClientData);
virtual WCMRAudioDevice* initNewCurrentDeviceImpl(const std::string & deviceName);
virtual void destroyCurrentDeviceImpl();
virtual WTErr generateDeviceListImpl();
virtual WTErr updateDeviceListImpl();
+ virtual WTErr getDeviceSampleRatesImpl(const std::string & deviceName, std::vector<int>& sampleRates) const;
virtual WTErr getDeviceBufferSizesImpl(const std::string & deviceName, std::vector<int>& bufferSizes) const;
bool m_UseMultithreading; ///< Flag indicates whether to use multi-threading for audio processing.
diff --git a/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRNativeAudio.cpp b/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRNativeAudio.cpp
index 889defe0ad..2bb52ddcb1 100644
--- a/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRNativeAudio.cpp
+++ b/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRNativeAudio.cpp
@@ -12,7 +12,6 @@
#endif
#include "WCMRNativeAudio.h"
-#include "MiscUtils/pthread_utils.h"
#include "MiscUtils/safe_delete.h"
#include <iostream>
#include <sstream>
@@ -35,15 +34,14 @@
//**********************************************************************************************
WCMRNativeAudioNoneDevice::WCMRNativeAudioNoneDevice (WCMRAudioDeviceManager *pManager)
: WCMRNativeAudioDevice (pManager, false /*useMultiThreading*/)
+ , m_SilenceThread(0)
#if defined (PLATFORM_WINDOWS)
, _waitableTimerForUsleep (CreateWaitableTimer(NULL, TRUE, NULL))
#endif
{
- mark_pthread_inactive (m_SilenceThread);
-
m_DeviceName = NONE_DEVICE_NAME;
- m_SamplingRates = boost::assign::list_of (m_CurrentSamplingRate=44100)(48000)(88200)(96000);
+ m_SamplingRates = boost::assign::list_of (m_CurrentSamplingRate=44100)(48000)(88200)(96000)(176400)(192000);
m_BufferSizes = boost::assign::list_of (32)(64)(128)(m_CurrentBufferSize=256)(512)(1024);
@@ -139,7 +137,7 @@ WTErr WCMRNativeAudioNoneDevice::SetStreaming (bool newState)
if (Streaming())
{
- if (is_pthread_active (m_SilenceThread))
+ if (m_SilenceThread)
std::cerr << "\t\t\t\t\t !!!!!!!!!!!!!!! Warning: the inactive NONE-DEVICE was streaming!" << std::endl;
pthread_attr_t attributes;
@@ -158,19 +156,19 @@ WTErr WCMRNativeAudioNoneDevice::SetStreaming (bool newState)
}
if (pthread_create (&m_SilenceThread, &attributes, __SilenceThread, this)) {
- mark_pthread_inactive (m_SilenceThread);
+ m_SilenceThread = 0;
std::cerr << "WCMRNativeAudioNoneDevice::SetStreaming (): pthread_create () failed!" << std::endl;
return eGenericErr;
}
}
else
{
- if (!is_pthread_active (m_SilenceThread))
+ if (!m_SilenceThread)
{
std::cerr << "\t\t\t\t\t !!!!!!!!!!!!!!! Warning: the active NONE-DEVICE was NOT streaming!" << std::endl;
}
- while (is_pthread_active (m_SilenceThread))
+ while (m_SilenceThread)
{
_usleep(1); //now wait for ended thread;
}
@@ -222,7 +220,7 @@ void WCMRNativeAudioNoneDevice::_SilenceThread()
}
audioCallbackData.acdCycleStartTimeNanos = cycleEndTimeNanos+1;
}
- mark_pthread_inactive (m_SilenceThread);
+ m_SilenceThread = 0;
}
void* WCMRNativeAudioNoneDevice::__SilenceThread(void *This)
diff --git a/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRNativeAudio.h b/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRNativeAudio.h
index f9f42cdc9f..138703ccb8 100644
--- a/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRNativeAudio.h
+++ b/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRNativeAudio.h
@@ -17,6 +17,10 @@
#include "WCRefManager.h"
#include "WCMRAudioDeviceManager.h"
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_9
+#include <unistd.h>
+#endif
+
class WCMRNativeAudioDevice; //forward
diff --git a/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRPortAudioDeviceManager.cpp b/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRPortAudioDeviceManager.cpp
index 1e2b700fb3..1c7149f78a 100644
--- a/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRPortAudioDeviceManager.cpp
+++ b/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRPortAudioDeviceManager.cpp
@@ -13,16 +13,22 @@
#include <iostream>
#include <sstream>
#include <algorithm>
+#include <list>
using namespace wvNS;
#include "IncludeWindows.h"
#include <MMSystem.h>
#include "pa_asio.h"
#include "asio.h"
+#define PROPERTY_CHANGE_SLEEP_TIME_MILLISECONDS 200
+#define DEVICE_INFO_UPDATE_SLEEP_TIME_MILLISECONDS 500
+#define PROPERTY_CHANGE_TIMEOUT_SECONDS 2
+#define PROPERTY_CHANGE_RETRIES 3
+
///< Supported Sample rates
static const double gAllSampleRates[] =
{
- 44100.0, 48000.0, 88200.0, 96000.0, -1 /* negative terminated list */
+ 44100.0, 48000.0, 88200.0, 96000.0, 176400.0, 192000.0 -1 /* negative terminated list */
};
@@ -305,14 +311,12 @@ void WCMRPortAudioDevice::updateDeviceInfo (bool callerIsWaiting/*=false*/)
//update name.
m_DeviceName = pDeviceInfo->name;
- std::cout << "API::Device " << m_DeviceName << " Getting device info " << std::endl;
-
//following parameters are needed opening test stream and for sample rates validation
PaStreamParameters inputParameters, outputParameters;
PaStreamParameters *pInS = NULL, *pOutS = NULL;
inputParameters.device = m_DeviceID;
- inputParameters.channelCount = std::min<int>(2, pDeviceInfo->maxInputChannels);
+ inputParameters.channelCount = pDeviceInfo->maxInputChannels;
inputParameters.sampleFormat = paFloat32 | paNonInterleaved;
inputParameters.suggestedLatency = 0; /* ignored by Pa_IsFormatSupported() */
inputParameters.hostApiSpecificStreamInfo = 0;
@@ -321,7 +325,7 @@ void WCMRPortAudioDevice::updateDeviceInfo (bool callerIsWaiting/*=false*/)
pInS = &inputParameters;
outputParameters.device = m_DeviceID;
- outputParameters.channelCount = std::min<int>(2, pDeviceInfo->maxOutputChannels);
+ outputParameters.channelCount = pDeviceInfo->maxOutputChannels;
outputParameters.sampleFormat = paFloat32;
outputParameters.suggestedLatency = 0; /* ignored by Pa_IsFormatSupported() */
outputParameters.hostApiSpecificStreamInfo = 0;
@@ -329,7 +333,6 @@ void WCMRPortAudioDevice::updateDeviceInfo (bool callerIsWaiting/*=false*/)
if (outputParameters.channelCount)
pOutS = &outputParameters;
- std::cout << "API::Device" << m_DeviceName << " Updating sample rates " << std::endl;
////////////////////////////////////////////////////////////////////////////////////
//update list of supported SRs...
m_SamplingRates.clear();
@@ -345,54 +348,27 @@ void WCMRPortAudioDevice::updateDeviceInfo (bool callerIsWaiting/*=false*/)
}
}
- std::cout << "API::Device" << m_DeviceName << " Updating buffer sizes" << std::endl;
///////////////////////////////////////////////////////////////////////////////////
//update buffer sizes
m_BufferSizes.clear();
bool useDefaultBuffers = true;
- PaError paErr = paNoError;
-
- //sometimes devices change buffer size if sample rate changes
- //it updates buffer size during stream opening
- //we need to find out how device would behave with current sample rate
- //try opening test stream to load device driver for current sample rate and buffer size
- //(skip this step if the device is Active)
- if ( !Active() )
- {
- if (paNoError != testStateValidness(m_CurrentSamplingRate, m_CurrentBufferSize) )
- {
- //buffer size did change
- Pa_Terminate();
- Pa_Initialize();
-
- // test validness with current sample rate and device prefered buffer size
- paErr = testStateValidness(m_CurrentSamplingRate, 0);
- }
- }
- if (paErr == paNoError)
- {
- // In ASIO Windows, the buffer size is set from the sound device manufacturer's control panel
- long minSize, maxSize, preferredSize, granularity;
- paErr = PaAsio_GetAvailableBufferSizes(m_DeviceID, &minSize, &maxSize, &preferredSize, &granularity);
+ // In ASIO Windows, the buffer size is set from the sound device manufacturer's control panel
+ long minSize, maxSize, preferredSize, granularity;
+ PaError err = PaAsio_GetAvailableBufferSizes(m_DeviceID, &minSize, &maxSize, &preferredSize, &granularity);
- if (paErr == paNoError)
- {
- std::cout << "API::Device " << m_DeviceName << " Buffers: " << minSize << " " << maxSize << " " << preferredSize << std::endl;
+ if (err == paNoError)
+ {
+ std::cout << "API::Device " << m_DeviceName << " Buffers: " << minSize << " " << maxSize << " " << preferredSize << std::endl;
- m_BufferSizes.push_back (preferredSize);
- useDefaultBuffers = false;
- }
- else
- {
- std::cout << "API::Device" << m_DeviceName << " Preffered buffer size is not supported" << std::endl;
- }
+ m_BufferSizes.push_back (preferredSize);
+ useDefaultBuffers = false;
}
else
{
- std::cout << "API::Device" << m_DeviceName << " Device does not start with sample rate: "<< m_CurrentSamplingRate << " and default buffer size" << std::endl;
+ std::cout << "API::Device" << m_DeviceName << " Preffered buffer size is not supported" << std::endl;
}
-
+
if (useDefaultBuffers)
{
std::cout << "API::Device" << m_DeviceName << " Using default buffer sizes " <<std::endl;
@@ -410,9 +386,22 @@ void WCMRPortAudioDevice::updateDeviceInfo (bool callerIsWaiting/*=false*/)
m_InputChannels.clear();
for (int channel = 0; channel < maxInputChannels; channel++)
{
+ const char* channelName[32]; // 32 is max leth declared by PortAudio for this operation
std::stringstream chNameStream;
- //A better implementation would be to retrieve the names from ASIO or CoreAudio interfaces
- chNameStream << "Input " << (channel+1);
+
+ PaError error = PaAsio_GetInputChannelName(m_DeviceID, channel, channelName);
+
+ chNameStream << (channel+1) << " - ";
+
+ if (error == paNoError)
+ {
+ chNameStream << *channelName;
+ }
+ else
+ {
+ chNameStream << "Input " << (channel+1);
+ }
+
m_InputChannels.push_back (chNameStream.str());
}
@@ -421,9 +410,22 @@ void WCMRPortAudioDevice::updateDeviceInfo (bool callerIsWaiting/*=false*/)
m_OutputChannels.clear();
for (int channel = 0; channel < maxOutputChannels; channel++)
{
+ const char* channelName[32]; // 32 is max leth declared by PortAudio for this operation
std::stringstream chNameStream;
- //A better implementation would be to retrieve the names from ASIO or CoreAudio interfaces
- chNameStream << "Output " << (channel+1);
+
+ PaError error = PaAsio_GetOutputChannelName(m_DeviceID, channel, channelName);
+
+ chNameStream << (channel+1) << " - ";
+
+ if (error == paNoError)
+ {
+ chNameStream << *channelName;
+ }
+ else
+ {
+ chNameStream << "Output " << (channel+1);
+ }
+
m_OutputChannels.push_back (chNameStream.str());
}
}
@@ -447,18 +449,18 @@ PaError WCMRPortAudioDevice::testStateValidness(int sampleRate, int bufferSize)
PaStreamParameters *pInS = NULL, *pOutS = NULL;
inputParameters.device = m_DeviceID;
- inputParameters.channelCount = std::min<int>(2, pDeviceInfo->maxInputChannels);
+ inputParameters.channelCount = pDeviceInfo->maxInputChannels;
inputParameters.sampleFormat = paFloat32 | paNonInterleaved;
- inputParameters.suggestedLatency = 0; /* ignored by Pa_IsFormatSupported() */
+ inputParameters.suggestedLatency = 0;
inputParameters.hostApiSpecificStreamInfo = 0;
if (inputParameters.channelCount)
pInS = &inputParameters;
outputParameters.device = m_DeviceID;
- outputParameters.channelCount = std::min<int>(2, pDeviceInfo->maxOutputChannels);
+ outputParameters.channelCount = pDeviceInfo->maxOutputChannels;
outputParameters.sampleFormat = paFloat32;
- outputParameters.suggestedLatency = 0; /* ignored by Pa_IsFormatSupported() */
+ outputParameters.suggestedLatency = 0;
outputParameters.hostApiSpecificStreamInfo = 0;
if (outputParameters.channelCount)
@@ -470,7 +472,7 @@ PaError WCMRPortAudioDevice::testStateValidness(int sampleRate, int bufferSize)
//it updates buffer size during stream opening
//we need to find out how device would behave with current sample rate
//try opening test stream to load device driver for current sample rate and buffer size
- paErr = Pa_OpenStream (&portAudioStream, pInS, pOutS, m_CurrentSamplingRate, m_CurrentBufferSize, paDitherOff, NULL, NULL);
+ paErr = Pa_OpenStream (&portAudioStream, pInS, pOutS, sampleRate, bufferSize, paDitherOff, NULL, NULL);
if (portAudioStream)
{
@@ -599,35 +601,18 @@ WTErr WCMRPortAudioDevice::SetCurrentSamplingRate (int newRate)
return (retVal);
}
- if (oldActive)
- {
- //Deactivate it for the change...
- SetActive (false);
- }
-
//make the change...
m_CurrentSamplingRate = newRate;
+ PaError paErr = PaAsio_SetStreamSampleRate (m_PortAudioStream, m_CurrentSamplingRate);
+ Pa_Sleep(PROPERTY_CHANGE_SLEEP_TIME_MILLISECONDS); // sleep some time to make sure the change has place
- // Before reactivating the device: opening stream we should try getting buffer size update from the device
- // because for new sampling rate some devices may change buffer size as well
- int oldBufferSize = m_CurrentBufferSize;
-
- retVal = ResetDevice();
-
- //reactivate it.
- if (oldActive && retVal == eNoErr)
+ if (paErr != paNoError)
{
- retVal = SetActive (true);
- }
+ std::cout << "Sample rate change failed: " << Pa_GetErrorText (paErr) << std::endl;
+ if (paErr == paUnanticipatedHostError)
+ std::cout << "Details: "<< Pa_GetLastHostErrorInfo ()->errorText << "; code: " << Pa_GetLastHostErrorInfo ()->errorCode << std::endl;
- if (retVal != eNoErr)
- {
- //revert changes if the device was not activated
- m_CurrentSamplingRate = oldRate;
- m_CurrentBufferSize = oldBufferSize;
- int bufferSize = m_CurrentBufferSize;
- m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::BufferSizeChanged, (void *)&bufferSize);
- retVal = eCommandLineParameter;
+ retVal = eWrongObjectState;
}
return (retVal);
@@ -676,21 +661,37 @@ WTErr WCMRPortAudioDevice::SetCurrentBufferSize (int newSize)
if (oldSize == newSize)
return (retVal);
- //see if this is one of our supported rates...
- intIter = find(m_BufferSizes.begin(), m_BufferSizes.end(), newSize);
- if (intIter == m_BufferSizes.end())
- {
- //Can't change, perhaps use an "invalid param" type of error
- retVal = eCommandLineParameter;
- return (retVal);
- }
-
if (Streaming())
{
//Can't change, perhaps use an "in use" type of error
retVal = eGenericErr;
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)
{
@@ -748,6 +749,17 @@ 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;
@@ -771,20 +783,46 @@ void WCMRPortAudioDevice::activateDevice (bool callerIsWaiting/*=false*/)
if (outputParameters.channelCount)
pOutS = &outputParameters;
-
- 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);
+
+ // 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);
+
+ if(paErr == paNoError)
+ {
+ break;
+ }
+
+ std::cout << "Cannot open streamm with buffer: "<< *bufferIter << " Error: " << Pa_GetErrorText (paErr) << std::endl;
+
+ if (paErr == paUnanticipatedHostError)
+ std::cout << "Error details: "<< Pa_GetLastHostErrorInfo ()->errorText << "; code: " << Pa_GetLastHostErrorInfo ()->errorCode << std::endl;
+ }
if(paErr == paNoError)
{
+ long minSize, maxSize, preferredSize, granularity;
+ PaError paErr = PaAsio_GetAvailableBufferSizes(m_DeviceID, &minSize, &maxSize, &preferredSize, &granularity);
+
+ if (paErr == paNoError && m_CurrentBufferSize != preferredSize)
+ {
+ m_CurrentBufferSize = preferredSize;
+ m_BufferSizes.clear();
+ m_BufferSizes.push_back(preferredSize);
+ m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::BufferSizeChanged, (void *)&preferredSize);
+ }
+
m_DropsDetected = 0;
m_DropsReported = 0;
m_IgnoreThisDrop = true;
@@ -806,8 +844,8 @@ void WCMRPortAudioDevice::activateDevice (bool callerIsWaiting/*=false*/)
else
{
//failed, do not update device state
- std::cout << "Failed to open pa stream stream " << paErr << std::endl;
- DEBUG_MSG( "Failed to open pa stream stream " << paErr );
+ std::cout << "Failed to open pa stream: " << Pa_GetErrorText (paErr) << std::endl;
+ DEBUG_MSG( "Failed to open pa stream: " << Pa_GetErrorText (paErr) );
m_ConnectionStatus = DeviceErrors;
m_lastErr = eAsioFailed;
}
@@ -867,8 +905,8 @@ void WCMRPortAudioDevice::deactivateDevice (bool callerIsWaiting/*=false*/)
else
{
//failed, do not update device state
- std::cout << "Failed to close pa stream stream " << paErr << std::endl;
- DEBUG_MSG( "Failed to open pa stream stream " << paErr );
+ std::cout << "Failed to close pa stream stream " << Pa_GetErrorText (paErr) << std::endl;
+ DEBUG_MSG( "Failed to open pa stream stream " << Pa_GetErrorText (paErr) );
m_ConnectionStatus = DeviceErrors;
m_lastErr = eAsioFailed;
}
@@ -899,17 +937,25 @@ void WCMRPortAudioDevice::startStreaming (bool callerIsWaiting/*=false*/)
m_SampleCounter = 0;
std::cout << "API::Device" << m_DeviceName << " Starting device stream" << std::endl;
+
+ //get device info
+ const PaDeviceInfo *pDeviceInfo = Pa_GetDeviceInfo(m_DeviceID);
+
+ unsigned int inChannelCount = pDeviceInfo->maxInputChannels;
+ unsigned int outChannelCount = pDeviceInfo->maxOutputChannels;
+
paErr = Pa_StartStream( m_PortAudioStream );
if(paErr == paNoError)
{
// if the stream was started successfully
m_IsStreaming = true;
+ std::cout << "API::Device" << m_DeviceName << " Device is streaming" << std::endl;
}
else
{
- std::cout << "Failed to start PA stream: " << paErr << std::endl;
- DEBUG_MSG( "Failed to start PA stream: " << paErr );
+ std::cout << "Failed to start PA stream: " << Pa_GetErrorText (paErr) << std::endl;
+ DEBUG_MSG( "Failed to start PA stream: " << Pa_GetErrorText (paErr) );
m_lastErr = eGenericErr;
}
}
@@ -947,8 +993,8 @@ void WCMRPortAudioDevice::stopStreaming (bool callerIsWaiting/*=false*/)
}
else
{
- std::cout << "Failed to stop PA stream: " << paErr << std::endl;
- DEBUG_MSG( "Failed to stop PA stream " << paErr );
+ 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;
}
}
@@ -973,60 +1019,82 @@ void WCMRPortAudioDevice::resetDevice (bool callerIsWaiting /*=false*/ )
{
std::cout << "API::Device" << m_DeviceName << "Reseting device" << std::endl;
+ PaError paErr = paNoError;
+
// Keep device sates
bool wasStreaming = Streaming();
bool wasActive = Active();
- // Notify the Application about reset
- m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::RequestReset);
-
// Reset the device
stopStreaming();
deactivateDevice();
- // Reinitialize PA
- Pa_Terminate();
- Pa_Initialize();
-
- updateDeviceInfo();
-
// Cache device buffer size as it might be changed during reset
int oldBufferSize = m_CurrentBufferSize;
- // In ASIO Windows, the buffer size is set from the sound device manufacturer's control panel
- // Backend should always use preffered buffer size value in this case
- long minSize, maxSize, preferredSize, granularity;
- PaError paErr = PaAsio_GetAvailableBufferSizes(m_DeviceID, &minSize, &maxSize, &preferredSize, &granularity);
-
- if (paErr == paNoError)
+ // Now, validate the state and update device info if required
+ unsigned int retry = PROPERTY_CHANGE_RETRIES;
+ while (retry-- )
{
+ // Reinitialize PA
+ Pa_Terminate();
+ Pa_Initialize();
+
+ std::cout << "Updating device state... " << std::endl;
+ // update device info
+ updateDeviceInfo();
+
+ // take up buffers
+ long minSize, maxSize, preferredSize, granularity;
+ PaError paErr = PaAsio_GetAvailableBufferSizes(m_DeviceID, &minSize, &maxSize, &preferredSize, &granularity);
+
+ if (paErr != paNoError)
+ {
+ continue;
+ }
m_CurrentBufferSize = preferredSize;
- }
- else
- {
- // if we can't get device buffer sizes, use the first one among supported
- if (m_BufferSizes.size() != 0)
- m_CurrentBufferSize = m_BufferSizes.front();
+
+ paErr = testStateValidness(m_CurrentSamplingRate, m_CurrentBufferSize);
+ if (paNoError == paErr)
+ {
+ std::cout << "Device state is valid" << std::endl;
+ break;
+ }
+
+ std::cout << "Cannot start with current state: sr: " << m_CurrentSamplingRate << " bs:" << m_CurrentBufferSize \
+ << "\nReason: " << Pa_GetErrorText (paErr) << std::endl;
+ if (paErr == paUnanticipatedHostError)
+ std::cout << "Details: "<< Pa_GetLastHostErrorInfo ()->errorText << "; code: " << Pa_GetLastHostErrorInfo ()->errorCode << std::endl;
+
+ std::cout << "Will try again in " << DEVICE_INFO_UPDATE_SLEEP_TIME_MILLISECONDS << "msec" << std::endl;
+
+ Pa_Sleep(DEVICE_INFO_UPDATE_SLEEP_TIME_MILLISECONDS);
}
- // Notify the Application about device setting changes
- if (oldBufferSize != m_CurrentBufferSize)
+ if (paErr == paNoError)
{
- std::cout << "API::Device" << m_DeviceName << " buffer size changed" << std::endl;
- int bufferSize = m_CurrentBufferSize;
- m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::BufferSizeChanged, (void *)&bufferSize);
- }
+ // Notify the Application about device setting changes
+ if (oldBufferSize != m_CurrentBufferSize)
+ {
+ std::cout << "API::Device" << m_DeviceName << " buffer size changed" << std::endl;
+ int bufferSize = m_CurrentBufferSize;
+ m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::BufferSizeChanged, (void *)&bufferSize);
+ }
- // Activate the device if it was active before
- if (wasActive)
- activateDevice();
+ // Activate the device if it was active before
+ if (wasActive)
+ activateDevice();
- // Resume streaming if the device was streaming before
- if(wasStreaming)
- {
- // Notify the Application to prepare for the stream start
- m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::DeviceStartsStreaming);
- startStreaming();
+ // Resume streaming if the device was streaming before
+ if(wasStreaming && m_lastErr == eNoErr && m_ConnectionStatus == DeviceAvailable)
+ {
+ // Notify the Application to prepare for the stream start
+ m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::DeviceStartsStreaming);
+ startStreaming();
+ }
+ } else {
+ m_ConnectionStatus = DeviceErrors;
+ m_lastErr = eWrongObjectState;
}
if (callerIsWaiting)
@@ -1050,32 +1118,34 @@ long WCMRPortAudioDevice::ASIOMessageHook (long selector, long WCUNUSEDPARAM(val
{
switch(selector)
{
+ case kAsioResyncRequest:
+ m_ResyncRequested++;
+ std::cout << "\t\t\tWCMRPortAudioDevice::ASIOMessageHook -- kAsioResyncRequest" << std::endl;
+ m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::RequestReset);
+ break;
+
+ case kAsioLatenciesChanged:
+ m_BufferSizeChangeRequested++;
+ std::cout << "\t\t\tWCMRPortAudioDevice::ASIOMessageHook -- kAsioLatenciesChanged" << std::endl;
+ m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::RequestReset);
+ break;
+
case kAsioBufferSizeChange:
m_BufferSizeChangeRequested++;
std::cout << "\t\t\tWCMRPortAudioDevice::ASIOMessageHook -- m_BufferSizeChangeRequested" << std::endl;
- SetEvent(m_hBufferSizeChangedEvent);
+ m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::RequestReset);
break;
case kAsioResetRequest:
m_ResetRequested++;
std::cout << "\t\t\tWCMRPortAudioDevice::ASIOMessageHook -- kAsioResetRequest" << std::endl;
- SetEvent(m_hResetFromDevRequestedEvent);
- break;
-
- case kAsioResyncRequest:
- std::cout << "\t\t\tWCMRPortAudioDevice::ASIOMessageHook -- kAsioResyncRequest" << std::endl;
- m_ResyncRequested++;
- break;
-
- case kAsioLatenciesChanged:
- std::cout << "\t\t\tWCMRPortAudioDevice::ASIOMessageHook -- kAsioLatenciesChanged" << std::endl;
- SetEvent(m_hBufferSizeChangedEvent);
- m_BufferSizeChangeRequested++;
+ m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::RequestReset);
break;
case kAsioOverload:
+ m_DropsDetected++;
std::cout << "\t\t\tWCMRPortAudioDevice::ASIOMessageHook -- kAsioOverload" << std::endl;
- m_DropsDetected++;
+ m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::Dropout);
break;
}
return 0;
@@ -1642,33 +1712,55 @@ WTErr WCMRPortAudioDeviceManager::generateDeviceListImpl()
}
+WTErr WCMRPortAudioDeviceManager::getDeviceSampleRatesImpl(const std::string & deviceName, std::vector<int>& sampleRates) const
+{
+ sampleRates.clear ();
+
+ WTErr retVal = eNoErr;
+
+ if (m_CurrentDevice && deviceName == m_CurrentDevice->DeviceName() )
+ {
+ sampleRates.assign(m_CurrentDevice->SamplingRates().begin(), m_CurrentDevice->SamplingRates().end() );
+ return retVal;
+ }
+
+ DeviceInfo devInfo;
+ retVal = GetDeviceInfoByName(deviceName, devInfo);
+
+ if (eNoErr == retVal)
+ {
+ sampleRates.assign(devInfo.m_AvailableSampleRates.begin(), devInfo.m_AvailableSampleRates.end() );
+ }
+ else
+ {
+ std::cout << "API::PortAudioDeviceManager::GetSampleRates: Device not found: "<< deviceName << std::endl;
+ }
+
+ return retVal;
+}
+
+
WTErr WCMRPortAudioDeviceManager::getDeviceBufferSizesImpl(const std::string & deviceName, std::vector<int>& buffers) const
{
WTErr retVal = eNoErr;
- std::cout << "API::PortAudioDeviceManager::GetBufferSizes: getting buffer size for device: "<< deviceName << std::endl;
+
+ buffers.clear();
+
//first check if the request has been made for None device
if (deviceName == m_NoneDevice->DeviceName() )
{
- buffers = m_NoneDevice->BufferSizes();
+ buffers.assign(m_NoneDevice->BufferSizes().begin(), m_NoneDevice->BufferSizes().end() );
return retVal;
}
-
- //if we have current device initialized and it's PA device, reset it
- //this procedure will reset PA corrently and update info for all PA devices as well
- bool paLocalInit = false;
- WCMRPortAudioDevice* portaudioDevice = dynamic_cast<WCMRPortAudioDevice*>(m_CurrentDevice);
- if (portaudioDevice)
- {
- portaudioDevice->ResetDevice();
- }
- else
+ if (m_CurrentDevice && deviceName == m_CurrentDevice->DeviceName() )
{
- //initialize PA to get buffers for the device
- Pa_Initialize();
- paLocalInit = true;
+ buffers.assign(m_CurrentDevice->BufferSizes().begin(), m_CurrentDevice->BufferSizes().end() );
+ return retVal;
}
+ Pa_Initialize();
+
DeviceInfo devInfo;
retVal = GetDeviceInfoByName(deviceName, devInfo);
@@ -1686,7 +1778,7 @@ WTErr WCMRPortAudioDeviceManager::getDeviceBufferSizesImpl(const std::string & d
else
{
retVal = eAsioFailed;
- std::cout << "API::PortAudioDeviceManager::GetBufferSizes: error: " << paErr << " getting buffer size fo device: "<< deviceName << std::endl;
+ std::cout << "API::PortAudioDeviceManager::GetBufferSizes: error: " << Pa_GetErrorText (paErr) << " getting buffer sizes for device: "<< deviceName << std::endl;
}
}
else
@@ -1694,9 +1786,7 @@ WTErr WCMRPortAudioDeviceManager::getDeviceBufferSizesImpl(const std::string & d
std::cout << "API::PortAudioDeviceManager::GetBufferSizes: Device not found: "<< deviceName << std::endl;
}
- //deinitialize PA now
- if (paLocalInit)
- Pa_Terminate();
+ Pa_Terminate();
return retVal;
}
diff --git a/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRPortAudioDeviceManager.h b/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRPortAudioDeviceManager.h
index 2ee3e6d55b..2efe7a3da3 100644
--- a/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRPortAudioDeviceManager.h
+++ b/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRPortAudioDeviceManager.h
@@ -146,6 +146,7 @@ protected:
virtual WTErr generateDeviceListImpl(); // use this in derived class to fill device list
virtual WTErr updateDeviceListImpl() {return eNoErr; } // not supported
virtual WTErr getDeviceBufferSizesImpl(const std::string & deviceName, std::vector<int>& buffers) const;
+ virtual WTErr getDeviceSampleRatesImpl(const std::string & deviceName, std::vector<int>& sampleRates) const;
bool m_UseMultithreading; ///< Flag indicates whether to use multi-threading for audio processing.
bool m_bNoCopyAudioBuffer;
diff --git a/libs/backends/wavesaudio/wavesapi/miscutils/pthread_utils.h b/libs/backends/wavesaudio/wavesapi/miscutils/pthread_utils.h
deleted file mode 100644
index e5202ece7e..0000000000
--- a/libs/backends/wavesaudio/wavesapi/miscutils/pthread_utils.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- Copyright (C) 2014 John Emmas
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#ifndef __waves_pthread_utils__
-#define __waves_pthread_utils__
-
-/* Accommodate thread setting (and testing) for both
- * 'libpthread' and 'libpthread_win32' (whose implementations
- * of 'pthread_t' are subtlely different)
- */
-#ifndef PTHREAD_MACROS_DEFINED
-#define PTHREAD_MACROS_DEFINED
-#ifdef PTW32_VERSION /* pthread_win32 */
-#define mark_pthread_inactive(threadID) threadID.p=0
-#define is_pthread_active(threadID) threadID.p!=0
-#else /* normal pthread */
-#define mark_pthread_inactive(threadID) threadID=0
-#define is_pthread_active(threadID) threadID!=0
-#endif /* PTW32_VERSION */
-
-#endif /* PTHREAD_MACROS_DEFINED */
-#endif /* __waves_pthread_utils__ */
diff --git a/libs/backends/wavesaudio/wscript b/libs/backends/wavesaudio/wscript
index 6905f07bc7..c1ff717d10 100755..100644
--- a/libs/backends/wavesaudio/wscript
+++ b/libs/backends/wavesaudio/wscript
@@ -29,8 +29,8 @@ def build(bld):
if bld.env['build_target'] == 'mingw':
obj = bld(features = 'cxx cxxshlib')
else:
- obj = bld(features = 'c cxx cxxshlib')
-
+ obj = bld(features = 'c cxx cxxshlib')
+
if sys.platform == 'darwin':
if bld.env['build_target'] not in [ 'lion' ]:
obj.framework = 'CoreMidi'
@@ -89,7 +89,7 @@ def build(bld):
]
obj.cxxflags = [ '-fPIC' ]
- obj.cflags = [ '-fPIC', '-fms-extensions' ]
+ obj.cflags = [ '-fPIC', '-fms-extensions' ]
obj.name = 'waves_audiobackend'
obj.target = 'waves_audiobackend'
obj.use = 'libardour libpbd'