mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-11 00:56:33 +01:00
copy over current Waves version of their backend, along with minor changes in libs/ardour and libs/backend/jack to fit with API changes
This commit is contained in:
parent
38e975d6b1
commit
8d59afb048
25 changed files with 844 additions and 430 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"; }
|
||||
|
|
@ -160,6 +169,18 @@ public:
|
|||
|
||||
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 */
|
||||
|
||||
PBD::Signal1<void,const char*> Halted;
|
||||
|
|
@ -216,6 +237,7 @@ public:
|
|||
static AudioEngine* _instance;
|
||||
|
||||
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 ();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -379,6 +389,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 ()
|
||||
{
|
||||
|
|
@ -459,6 +602,15 @@ 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 ()
|
||||
{
|
||||
|
|
@ -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 ()) {
|
||||
|
|
|
|||
|
|
@ -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".
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@
|
|||
|
||||
|
||||
#include "porttime.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <mmsystem.h>
|
||||
#include <time.h>
|
||||
|
||||
|
||||
TIMECAPS caps;
|
||||
|
||||
static long time_offset = 0;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -45,6 +45,7 @@ void WavesAudioBackend::AudioDeviceManagerNotification (NotificationReason reaso
|
|||
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,21 +661,25 @@ WavesAudioBackend::_start (bool for_latency_measurement)
|
|||
|
||||
if (!_device) {
|
||||
std::cerr << "WavesAudioBackend::_start (): No device is set!" << std::endl;
|
||||
stop();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (_register_system_audio_ports () != 0) {
|
||||
std::cerr << "WavesAudioBackend::_start (): _register_system_audio_ports () failed!" << std::endl;
|
||||
stop();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (_use_midi) {
|
||||
if (_midi_device_manager.start () != 0) {
|
||||
std::cerr << "WavesAudioBackend::_start (): _midi_device_manager.start () failed!" << std::endl;
|
||||
stop();
|
||||
return -1;
|
||||
}
|
||||
if (_register_system_midi_ports () != 0) {
|
||||
std::cerr << "WavesAudioBackend::_start (): _register_system_midi_ports () failed!" << std::endl;
|
||||
stop();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
|
@ -779,12 +694,14 @@ 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;
|
||||
stop();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
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
|
||||
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;
|
||||
|
|
@ -1181,8 +1264,13 @@ WTErr WCMRCoreAudioDevice::EnableListeners()
|
|||
#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)
|
||||
{
|
||||
|
|
@ -1239,14 +1327,18 @@ WTErr WCMRCoreAudioDevice::DisableListeners()
|
|||
|
||||
#if ENABLE_DEVICE_CHANGE_LISTNER
|
||||
{
|
||||
err = AudioDeviceRemovePropertyListener(m_DeviceID, 0, 0, kAudioDevicePropertyDeviceHasChanged,
|
||||
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;
|
||||
}
|
||||
|
|
@ -1590,34 +1686,6 @@ WTErr WCMRCoreAudioDevice::SetupAUHAL()
|
|||
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)
|
||||
|
|
@ -1658,8 +1726,6 @@ WTErr WCMRCoreAudioDevice::TearDownAUHAL()
|
|||
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];
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,8 +94,6 @@ protected:
|
|||
// 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.
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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,38 +348,16 @@ 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);
|
||||
PaError err = PaAsio_GetAvailableBufferSizes(m_DeviceID, &minSize, &maxSize, &preferredSize, &granularity);
|
||||
|
||||
if (paErr == paNoError)
|
||||
if (err == paNoError)
|
||||
{
|
||||
std::cout << "API::Device " << m_DeviceName << " Buffers: " << minSize << " " << maxSize << " " << preferredSize << std::endl;
|
||||
|
||||
|
|
@ -387,11 +368,6 @@ void WCMRPortAudioDevice::updateDeviceInfo (bool callerIsWaiting/*=false*/)
|
|||
{
|
||||
std::cout << "API::Device" << m_DeviceName << " Preffered buffer size is not supported" << std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "API::Device" << m_DeviceName << " Device does not start with sample rate: "<< m_CurrentSamplingRate << " and default buffer size" << std::endl;
|
||||
}
|
||||
|
||||
if (useDefaultBuffers)
|
||||
{
|
||||
|
|
@ -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
|
||||
|
||||
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
|
||||
|
||||
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,15 +661,6 @@ 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
|
||||
|
|
@ -692,6 +668,31 @@ WTErr WCMRPortAudioDevice::SetCurrentBufferSize (int newSize)
|
|||
return (retVal);
|
||||
}
|
||||
|
||||
std::cout << "Setting buffer: " << newSize << std::endl;
|
||||
|
||||
//see if this is one of our supported rates...
|
||||
intIter = find(m_BufferSizes.begin(), m_BufferSizes.end(), newSize);
|
||||
if (intIter == m_BufferSizes.end())
|
||||
{
|
||||
//Sample rate proposed by client is not supported any more
|
||||
if (m_BufferSizes.size() == 1)
|
||||
{
|
||||
// we have only one aloved buffer size which is preffered by PA
|
||||
// this is the only value which could be set
|
||||
newSize = m_BufferSizes[0];
|
||||
int bufferSize = newSize;
|
||||
// notify client to update sample rate after us
|
||||
m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::BufferSizeChanged, (void *)&bufferSize);
|
||||
return retVal;
|
||||
|
||||
} else {
|
||||
// more then one buffer size value is available
|
||||
//Can't change, perhaps use an "invalid param" type of error
|
||||
retVal = eCommandLineParameter;
|
||||
return (retVal);
|
||||
}
|
||||
}
|
||||
|
||||
if (oldActive)
|
||||
{
|
||||
//Deactivate it for the change...
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
@ -772,8 +784,12 @@ void WCMRPortAudioDevice::activateDevice (bool callerIsWaiting/*=false*/)
|
|||
if (outputParameters.channelCount)
|
||||
pOutS = &outputParameters;
|
||||
|
||||
// try opening stream with current buffer and the rest if not successful
|
||||
std::list<long>::const_iterator bufferIter = buffersSizes.begin();
|
||||
for (; bufferIter != buffersSizes.end(); ++bufferIter) {
|
||||
|
||||
std::cout << "API::Device" << m_DeviceName << " Opening device stream " << std::endl;
|
||||
std::cout << "Sample rate: " << m_CurrentSamplingRate << " buffer size: " << m_CurrentBufferSize << std::endl;
|
||||
std::cout << "Sample rate: " << m_CurrentSamplingRate << " buffer size: " << *bufferIter << std::endl;
|
||||
paErr = Pa_OpenStream(&m_PortAudioStream,
|
||||
pInS,
|
||||
pOutS,
|
||||
|
|
@ -785,6 +801,28 @@ void WCMRPortAudioDevice::activateDevice (bool callerIsWaiting/*=false*/)
|
|||
|
||||
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,42 +1019,60 @@ 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();
|
||||
|
||||
// Cache device buffer size as it might be changed during reset
|
||||
int oldBufferSize = m_CurrentBufferSize;
|
||||
|
||||
// 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();
|
||||
|
||||
// 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
|
||||
// take up buffers
|
||||
long minSize, maxSize, preferredSize, granularity;
|
||||
PaError paErr = PaAsio_GetAvailableBufferSizes(m_DeviceID, &minSize, &maxSize, &preferredSize, &granularity);
|
||||
|
||||
if (paErr == paNoError)
|
||||
if (paErr != paNoError)
|
||||
{
|
||||
m_CurrentBufferSize = preferredSize;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
m_CurrentBufferSize = preferredSize;
|
||||
|
||||
paErr = testStateValidness(m_CurrentSamplingRate, m_CurrentBufferSize);
|
||||
if (paNoError == paErr)
|
||||
{
|
||||
// if we can't get device buffer sizes, use the first one among supported
|
||||
if (m_BufferSizes.size() != 0)
|
||||
m_CurrentBufferSize = m_BufferSizes.front();
|
||||
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);
|
||||
}
|
||||
|
||||
if (paErr == paNoError)
|
||||
{
|
||||
// Notify the Application about device setting changes
|
||||
if (oldBufferSize != m_CurrentBufferSize)
|
||||
{
|
||||
|
|
@ -1022,12 +1086,16 @@ void WCMRPortAudioDevice::resetDevice (bool callerIsWaiting /*=false*/ )
|
|||
activateDevice();
|
||||
|
||||
// Resume streaming if the device was streaming before
|
||||
if(wasStreaming)
|
||||
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)
|
||||
SetEvent(m_hResetDone);
|
||||
|
|
@ -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:
|
||||
std::cout << "\t\t\tWCMRPortAudioDevice::ASIOMessageHook -- kAsioOverload" << std::endl;
|
||||
m_DropsDetected++;
|
||||
std::cout << "\t\t\tWCMRPortAudioDevice::ASIOMessageHook -- kAsioOverload" << std::endl;
|
||||
m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::Dropout);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
|
|
@ -1642,33 +1712,55 @@ WTErr WCMRPortAudioDeviceManager::generateDeviceListImpl()
|
|||
}
|
||||
|
||||
|
||||
WTErr WCMRPortAudioDeviceManager::getDeviceBufferSizesImpl(const std::string & deviceName, std::vector<int>& buffers) const
|
||||
WTErr WCMRPortAudioDeviceManager::getDeviceSampleRatesImpl(const std::string & deviceName, std::vector<int>& sampleRates) const
|
||||
{
|
||||
sampleRates.clear ();
|
||||
|
||||
WTErr retVal = eNoErr;
|
||||
std::cout << "API::PortAudioDeviceManager::GetBufferSizes: getting buffer size for device: "<< deviceName << std::endl;
|
||||
//first check if the request has been made for None device
|
||||
if (deviceName == m_NoneDevice->DeviceName() )
|
||||
|
||||
if (m_CurrentDevice && deviceName == m_CurrentDevice->DeviceName() )
|
||||
{
|
||||
buffers = m_NoneDevice->BufferSizes();
|
||||
sampleRates.assign(m_CurrentDevice->SamplingRates().begin(), m_CurrentDevice->SamplingRates().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
|
||||
DeviceInfo devInfo;
|
||||
retVal = GetDeviceInfoByName(deviceName, devInfo);
|
||||
|
||||
bool paLocalInit = false;
|
||||
WCMRPortAudioDevice* portaudioDevice = dynamic_cast<WCMRPortAudioDevice*>(m_CurrentDevice);
|
||||
if (portaudioDevice)
|
||||
if (eNoErr == retVal)
|
||||
{
|
||||
portaudioDevice->ResetDevice();
|
||||
sampleRates.assign(devInfo.m_AvailableSampleRates.begin(), devInfo.m_AvailableSampleRates.end() );
|
||||
}
|
||||
else
|
||||
{
|
||||
//initialize PA to get buffers for the device
|
||||
Pa_Initialize();
|
||||
paLocalInit = true;
|
||||
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;
|
||||
|
||||
buffers.clear();
|
||||
|
||||
//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() );
|
||||
return retVal;
|
||||
}
|
||||
|
||||
if (m_CurrentDevice && deviceName == m_CurrentDevice->DeviceName() )
|
||||
{
|
||||
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,8 +1786,6 @@ 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();
|
||||
|
||||
return retVal;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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__ */
|
||||
0
libs/backends/wavesaudio/wscript
Executable file → Normal file
0
libs/backends/wavesaudio/wscript
Executable file → Normal file
Loading…
Add table
Add a link
Reference in a new issue