summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2015-05-05 17:28:31 +0200
committerRobin Gareus <robin@gareus.org>2015-06-01 01:02:38 +0200
commit1fe738a36eb826594194498ab88dcfa9891030d2 (patch)
treeb5a639f2a69db404356849d8d75f0be26e59cb9c /libs
parent4d2bc612f236e51473d75c9dbc50b5968b27e1bc (diff)
coreaudio support for multiple devices
Diffstat (limited to 'libs')
-rw-r--r--libs/backends/coreaudio/coreaudio_backend.cc114
-rw-r--r--libs/backends/coreaudio/coreaudio_backend.h15
-rw-r--r--libs/backends/coreaudio/coreaudio_pcmio.cc21
-rw-r--r--libs/backends/coreaudio/coreaudio_pcmio.h7
4 files changed, 134 insertions, 23 deletions
diff --git a/libs/backends/coreaudio/coreaudio_backend.cc b/libs/backends/coreaudio/coreaudio_backend.cc
index d22d067e38..6cc2adf833 100644
--- a/libs/backends/coreaudio/coreaudio_backend.cc
+++ b/libs/backends/coreaudio/coreaudio_backend.cc
@@ -38,7 +38,9 @@ using namespace ARDOUR;
static std::string s_instance_name;
size_t CoreAudioBackend::_max_buffer_size = 8192;
std::vector<std::string> CoreAudioBackend::_midi_options;
-std::vector<AudioBackend::DeviceStatus> CoreAudioBackend::_audio_device_status;
+std::vector<AudioBackend::DeviceStatus> CoreAudioBackend::_duplex_audio_device_status;
+std::vector<AudioBackend::DeviceStatus> CoreAudioBackend::_input_audio_device_status;
+std::vector<AudioBackend::DeviceStatus> CoreAudioBackend::_output_audio_device_status;
/* static class instance access */
@@ -90,7 +92,8 @@ CoreAudioBackend::CoreAudioBackend (AudioEngine& e, AudioBackendInfo& info)
, _reinit_thread_callback (false)
, _measure_latency (false)
, _last_process_start (0)
- , _audio_device("")
+ , _input_audio_device("")
+ , _output_audio_device("")
, _midi_driver_option(_("None"))
, _samplerate (48000)
, _samples_per_period (1024)
@@ -142,30 +145,67 @@ CoreAudioBackend::is_realtime () const
std::vector<AudioBackend::DeviceStatus>
CoreAudioBackend::enumerate_devices () const
{
- _audio_device_status.clear();
+ _duplex_audio_device_status.clear();
std::map<size_t, std::string> devices;
- _pcmio->device_list(devices);
+ _pcmio->duplex_device_list(devices);
for (std::map<size_t, std::string>::const_iterator i = devices.begin (); i != devices.end(); ++i) {
- if (_audio_device == "") _audio_device = i->second;
- _audio_device_status.push_back (DeviceStatus (i->second, true));
+ if (_input_audio_device == "") _input_audio_device = i->second;
+ if (_output_audio_device == "") _output_audio_device = i->second;
+ _duplex_audio_device_status.push_back (DeviceStatus (i->second, true));
}
- return _audio_device_status;
+ return _duplex_audio_device_status;
+}
+
+std::vector<AudioBackend::DeviceStatus>
+CoreAudioBackend::enumerate_input_devices () const
+{
+ _input_audio_device_status.clear();
+ std::map<size_t, std::string> devices;
+ _pcmio->input_device_list(devices);
+
+ for (std::map<size_t, std::string>::const_iterator i = devices.begin (); i != devices.end(); ++i) {
+ if (_input_audio_device == "") _input_audio_device = i->second;
+ _input_audio_device_status.push_back (DeviceStatus (i->second, true));
+ }
+ return _input_audio_device_status;
+}
+
+
+std::vector<AudioBackend::DeviceStatus>
+CoreAudioBackend::enumerate_output_devices () const
+{
+ _output_audio_device_status.clear();
+ std::map<size_t, std::string> devices;
+ _pcmio->output_device_list(devices);
+
+ for (std::map<size_t, std::string>::const_iterator i = devices.begin (); i != devices.end(); ++i) {
+ if (_output_audio_device == "") _output_audio_device = i->second;
+ _output_audio_device_status.push_back (DeviceStatus (i->second, true));
+ }
+ return _output_audio_device_status;
}
std::vector<float>
CoreAudioBackend::available_sample_rates (const std::string&) const
{
std::vector<float> sr;
- _pcmio->available_sample_rates(name_to_id(_audio_device), sr);
+ std::vector<float> sr_in;
+ std::vector<float> sr_out;
+
+ _pcmio->available_sample_rates(name_to_id(_input_audio_device), sr_in);
+ _pcmio->available_sample_rates(name_to_id(_output_audio_device), sr_out);
+
+ // TODO allow to use different SR per device, tweak aggregate
+ std::set_intersection(sr_in.begin(), sr_in.end(), sr_out.begin(), sr_out.end(), std::back_inserter(sr));
return sr;
}
std::vector<uint32_t>
-CoreAudioBackend::available_buffer_sizes (const std::string&) const
+CoreAudioBackend::available_buffer_sizes (const std::string& device) const
{
std::vector<uint32_t> bs;
- _pcmio->available_buffer_sizes(name_to_id(_audio_device), bs);
+ _pcmio->available_buffer_sizes(name_to_id(device), bs);
return bs;
}
@@ -196,8 +236,27 @@ CoreAudioBackend::can_change_buffer_size_when_running () const
int
CoreAudioBackend::set_device_name (const std::string& d)
{
- _audio_device = d;
- const float sr = _pcmio->current_sample_rate(name_to_id(_audio_device));
+ int rv = 0;
+ rv |= set_input_device_name (d);
+ rv |= set_output_device_name (d);
+ return rv;
+}
+
+int
+CoreAudioBackend::set_input_device_name (const std::string& d)
+{
+ _input_audio_device = d;
+ const float sr = _pcmio->current_sample_rate(name_to_id(_input_audio_device));
+ if (sr > 0) { set_sample_rate(sr); }
+ return 0;
+}
+
+int
+CoreAudioBackend::set_output_device_name (const std::string& d)
+{
+ _output_audio_device = d;
+ // TODO check SR.
+ const float sr = _pcmio->current_sample_rate(name_to_id(_output_audio_device));
if (sr > 0) { set_sample_rate(sr); }
return 0;
}
@@ -205,8 +264,10 @@ CoreAudioBackend::set_device_name (const std::string& d)
int
CoreAudioBackend::set_sample_rate (float sr)
{
- if (sr <= 0) { return -1; }
- // TODO check if it's in the list of valid SR
+ std::vector<float> srs = available_sample_rates (/* really ignored */_input_audio_device);
+ if (std::find(srs.begin(), srs.end(), sr) == srs.end()) {
+ return -1;
+ }
_samplerate = sr;
engine.sample_rate_change (sr);
return 0;
@@ -263,7 +324,19 @@ CoreAudioBackend::set_systemic_output_latency (uint32_t sl)
std::string
CoreAudioBackend::device_name () const
{
- return _audio_device;
+ return "";
+}
+
+std::string
+CoreAudioBackend::input_device_name () const
+{
+ return _input_audio_device;
+}
+
+std::string
+CoreAudioBackend::output_device_name () const
+{
+ return _output_audio_device;
}
float
@@ -339,7 +412,7 @@ CoreAudioBackend::midi_option () const
void
CoreAudioBackend::launch_control_app ()
{
- _pcmio->launch_control_app(name_to_id(_audio_device));
+ _pcmio->launch_control_app(name_to_id(_input_audio_device));
}
/* State Control */
@@ -380,8 +453,8 @@ CoreAudioBackend::_start (bool for_latency_measurement)
_ports.clear();
}
- uint32_t device1 = name_to_id(_audio_device); // usually input, but in an aggregate, 1st defines the clock
- uint32_t device2 = name_to_id(_audio_device); // usually output
+ uint32_t device1 = name_to_id(_input_audio_device);
+ uint32_t device2 = name_to_id(_output_audio_device);
assert(_active_ca == false);
assert(_active_fw == false);
@@ -395,6 +468,7 @@ CoreAudioBackend::_start (bool for_latency_measurement)
_pcmio->set_sample_rate_callback (sample_rate_callback_ptr, this);
_pcmio->pcm_start (device1, device2, _samplerate, _samples_per_period, process_callback_ptr, this);
+ printf("STATE: %d\n", _pcmio->state ());
switch (_pcmio->state ()) {
case 0: /* OK */ break;
@@ -867,8 +941,8 @@ CoreAudioBackend::register_system_audio_ports()
const uint32_t a_ins = _n_inputs;
const uint32_t a_out = _n_outputs;
- const uint32_t coreaudio_reported_input_latency = _pcmio->get_latency(name_to_id(_audio_device), true);
- const uint32_t coreaudio_reported_output_latency = _pcmio->get_latency(name_to_id(_audio_device), false);
+ const uint32_t coreaudio_reported_input_latency = _pcmio->get_latency(name_to_id(_input_audio_device), true);
+ const uint32_t coreaudio_reported_output_latency = _pcmio->get_latency(name_to_id(_output_audio_device), false);
#ifndef NDEBUG
printf("COREAUDIO LATENCY: i:%d, o:%d\n",
diff --git a/libs/backends/coreaudio/coreaudio_backend.h b/libs/backends/coreaudio/coreaudio_backend.h
index 7ac8e1c6e1..3300fc4216 100644
--- a/libs/backends/coreaudio/coreaudio_backend.h
+++ b/libs/backends/coreaudio/coreaudio_backend.h
@@ -165,7 +165,11 @@ class CoreAudioBackend : public AudioBackend {
std::string name () const;
bool is_realtime () const;
+ bool use_separate_input_and_output_devices () const { return true; }
std::vector<DeviceStatus> enumerate_devices () const;
+ std::vector<DeviceStatus> enumerate_input_devices () const;
+ std::vector<DeviceStatus> enumerate_output_devices () const;
+
std::vector<float> available_sample_rates (const std::string& device) const;
std::vector<uint32_t> available_buffer_sizes (const std::string& device) const;
uint32_t available_input_channel_count (const std::string& device) const;
@@ -175,6 +179,8 @@ class CoreAudioBackend : public AudioBackend {
bool can_change_buffer_size_when_running () const;
int set_device_name (const std::string&);
+ int set_input_device_name (const std::string&);
+ int set_output_device_name (const std::string&);
int set_sample_rate (float);
int set_buffer_size (uint32_t);
int set_interleaved (bool yn);
@@ -189,6 +195,8 @@ class CoreAudioBackend : public AudioBackend {
/* Retrieving parameters */
std::string device_name () const;
+ std::string input_device_name () const;
+ std::string output_device_name () const;
float sample_rate () const;
uint32_t buffer_size () const;
bool interleaved () const;
@@ -336,10 +344,13 @@ class CoreAudioBackend : public AudioBackend {
pthread_cond_t _freewheel_signal;
static std::vector<std::string> _midi_options;
- static std::vector<AudioBackend::DeviceStatus> _audio_device_status;
+ static std::vector<AudioBackend::DeviceStatus> _input_audio_device_status;
+ static std::vector<AudioBackend::DeviceStatus> _output_audio_device_status;
+ static std::vector<AudioBackend::DeviceStatus> _duplex_audio_device_status;
static std::vector<AudioBackend::DeviceStatus> _midi_device_status;
- mutable std::string _audio_device;
+ mutable std::string _input_audio_device;
+ mutable std::string _output_audio_device;
std::string _midi_driver_option;
/* audio settings */
diff --git a/libs/backends/coreaudio/coreaudio_pcmio.cc b/libs/backends/coreaudio/coreaudio_pcmio.cc
index 0b31a9a3ff..fb1d8caeff 100644
--- a/libs/backends/coreaudio/coreaudio_pcmio.cc
+++ b/libs/backends/coreaudio/coreaudio_pcmio.cc
@@ -480,6 +480,15 @@ CoreAudioPCM::get_latency(uint32_t device_id, bool input)
}
uint32_t
+CoreAudioPCM::get_latency(bool input)
+{
+ if (_active_device_id == 0) {
+ return 0;
+ }
+ return get_latency (_active_device_id, input);
+}
+
+uint32_t
CoreAudioPCM::current_buffer_size_id(AudioDeviceID id) {
UInt32 buffer_size;
UInt32 size = sizeof(UInt32);
@@ -629,6 +638,15 @@ CoreAudioPCM::discover()
if (outputChannelCount > 0 || inputChannelCount > 0) {
_devices.insert (std::pair<size_t, std::string> (idx, dn));
}
+ if (inputChannelCount > 0) {
+ _input_devices.insert (std::pair<size_t, std::string> (idx, dn));
+ }
+ if (outputChannelCount > 0) {
+ _output_devices.insert (std::pair<size_t, std::string> (idx, dn));
+ }
+ if (outputChannelCount > 0 && inputChannelCount > 0) {
+ _duplex_devices.insert (std::pair<size_t, std::string> (idx, dn));
+ }
}
}
pthread_mutex_unlock (&_discovery_lock);
@@ -695,6 +713,7 @@ CoreAudioPCM::pcm_stop ()
}
if (_aggregate_plugin_id) {
destroy_aggregate_device();
+ discover();
}
AudioUnitUninitialize(_auhal);
@@ -811,7 +830,7 @@ CoreAudioPCM::pcm_start (
err = AudioUnitInitialize(_auhal);
if (err != noErr) { errorMsg="AudioUnitInitialize"; goto error; }
- // explicitly change samplerate of the device
+ // explicitly change samplerate of the devices, TODO allow separate rates with aggregates
if (set_device_sample_rate(device_id_in, sample_rate, true)) {
errorMsg="Failed to set SampleRate, Capture Device"; goto error;
}
diff --git a/libs/backends/coreaudio/coreaudio_pcmio.h b/libs/backends/coreaudio/coreaudio_pcmio.h
index 76b5e76e1b..5f9778e845 100644
--- a/libs/backends/coreaudio/coreaudio_pcmio.h
+++ b/libs/backends/coreaudio/coreaudio_pcmio.h
@@ -48,12 +48,16 @@ public:
void discover();
void device_list (std::map<size_t, std::string> &devices) const { devices = _devices;}
+ void input_device_list (std::map<size_t, std::string> &devices) const { devices = _input_devices;}
+ void output_device_list (std::map<size_t, std::string> &devices) const { devices = _output_devices;}
+ void duplex_device_list (std::map<size_t, std::string> &devices) const { devices = _duplex_devices;}
int available_sample_rates (uint32_t device_id, std::vector<float>& sampleRates);
int available_buffer_sizes (uint32_t device_id, std::vector<uint32_t>& sampleRates);
uint32_t available_channels (uint32_t device_id, bool input);
float current_sample_rate (uint32_t device_id, bool input = false);
uint32_t get_latency (uint32_t device_id, bool input);
+ uint32_t get_latency (bool input);
std::string cached_port_name (uint32_t portnum, bool input) const;
@@ -186,6 +190,9 @@ private:
// TODO proper device info struct
std::map<size_t, std::string> _devices;
+ std::map<size_t, std::string> _input_devices;
+ std::map<size_t, std::string> _output_devices;
+ std::map<size_t, std::string> _duplex_devices;
uint32_t * _device_ins;
uint32_t * _device_outs;
std::vector<std::string> _input_names;