mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-16 11:46:25 +01:00
Support selecting separate input and output devices in portaudio backend
This commit is contained in:
parent
ff1d4d5c67
commit
6b7875de1e
4 changed files with 137 additions and 42 deletions
|
|
@ -41,7 +41,8 @@ using namespace ARDOUR;
|
||||||
static std::string s_instance_name;
|
static std::string s_instance_name;
|
||||||
size_t PortAudioBackend::_max_buffer_size = 8192;
|
size_t PortAudioBackend::_max_buffer_size = 8192;
|
||||||
std::vector<std::string> PortAudioBackend::_midi_options;
|
std::vector<std::string> PortAudioBackend::_midi_options;
|
||||||
std::vector<AudioBackend::DeviceStatus> PortAudioBackend::_audio_device_status;
|
std::vector<AudioBackend::DeviceStatus> PortAudioBackend::_input_audio_device_status;
|
||||||
|
std::vector<AudioBackend::DeviceStatus> PortAudioBackend::_output_audio_device_status;
|
||||||
|
|
||||||
PortAudioBackend::PortAudioBackend (AudioEngine& e, AudioBackendInfo& info)
|
PortAudioBackend::PortAudioBackend (AudioEngine& e, AudioBackendInfo& info)
|
||||||
: AudioBackend (e, info)
|
: AudioBackend (e, info)
|
||||||
|
|
@ -51,7 +52,8 @@ PortAudioBackend::PortAudioBackend (AudioEngine& e, AudioBackendInfo& info)
|
||||||
, _freewheel (false)
|
, _freewheel (false)
|
||||||
, _measure_latency (false)
|
, _measure_latency (false)
|
||||||
, _last_process_start (0)
|
, _last_process_start (0)
|
||||||
, _audio_device("")
|
, _input_audio_device("")
|
||||||
|
, _output_audio_device("")
|
||||||
, _midi_driver_option(_("None"))
|
, _midi_driver_option(_("None"))
|
||||||
, _samplerate (48000)
|
, _samplerate (48000)
|
||||||
, _samples_per_period (1024)
|
, _samples_per_period (1024)
|
||||||
|
|
@ -116,26 +118,53 @@ PortAudioBackend::set_driver (const std::string& name)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
PortAudioBackend::use_separate_input_and_output_devices () const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<AudioBackend::DeviceStatus>
|
std::vector<AudioBackend::DeviceStatus>
|
||||||
PortAudioBackend::enumerate_devices () const
|
PortAudioBackend::enumerate_devices () const
|
||||||
{
|
{
|
||||||
_pcmio->discover();
|
return std::vector<AudioBackend::DeviceStatus>();
|
||||||
_audio_device_status.clear();
|
|
||||||
std::map<int, std::string> devices;
|
|
||||||
_pcmio->device_list(devices);
|
|
||||||
|
|
||||||
for (std::map<int, 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));
|
|
||||||
}
|
}
|
||||||
return _audio_device_status;
|
|
||||||
|
std::vector<AudioBackend::DeviceStatus>
|
||||||
|
PortAudioBackend::enumerate_input_devices () const
|
||||||
|
{
|
||||||
|
_pcmio->discover();
|
||||||
|
_input_audio_device_status.clear();
|
||||||
|
std::map<int, std::string> input_devices;
|
||||||
|
_pcmio->input_device_list(input_devices);
|
||||||
|
|
||||||
|
for (std::map<int, std::string>::const_iterator i = input_devices.begin (); i != input_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>
|
||||||
|
PortAudioBackend::enumerate_output_devices () const
|
||||||
|
{
|
||||||
|
_pcmio->discover();
|
||||||
|
_output_audio_device_status.clear();
|
||||||
|
std::map<int, std::string> output_devices;
|
||||||
|
_pcmio->output_device_list(output_devices);
|
||||||
|
|
||||||
|
for (std::map<int, std::string>::const_iterator i = output_devices.begin (); i != output_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>
|
std::vector<float>
|
||||||
PortAudioBackend::available_sample_rates (const std::string&) const
|
PortAudioBackend::available_sample_rates (const std::string&) const
|
||||||
{
|
{
|
||||||
std::vector<float> sr;
|
std::vector<float> sr;
|
||||||
_pcmio->available_sample_rates(name_to_id(_audio_device), sr);
|
_pcmio->available_sample_rates(name_to_id(_input_audio_device), sr);
|
||||||
return sr;
|
return sr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -143,7 +172,7 @@ std::vector<uint32_t>
|
||||||
PortAudioBackend::available_buffer_sizes (const std::string&) const
|
PortAudioBackend::available_buffer_sizes (const std::string&) const
|
||||||
{
|
{
|
||||||
std::vector<uint32_t> bs;
|
std::vector<uint32_t> bs;
|
||||||
_pcmio->available_buffer_sizes(name_to_id(_audio_device), bs);
|
_pcmio->available_buffer_sizes(name_to_id(_input_audio_device), bs);
|
||||||
return bs;
|
return bs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -174,7 +203,20 @@ PortAudioBackend::can_change_buffer_size_when_running () const
|
||||||
int
|
int
|
||||||
PortAudioBackend::set_device_name (const std::string& d)
|
PortAudioBackend::set_device_name (const std::string& d)
|
||||||
{
|
{
|
||||||
_audio_device = d;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
PortAudioBackend::set_input_device_name (const std::string& d)
|
||||||
|
{
|
||||||
|
_input_audio_device = d;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
PortAudioBackend::set_output_device_name (const std::string& d)
|
||||||
|
{
|
||||||
|
_output_audio_device = d;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -238,7 +280,19 @@ PortAudioBackend::set_systemic_output_latency (uint32_t sl)
|
||||||
std::string
|
std::string
|
||||||
PortAudioBackend::device_name () const
|
PortAudioBackend::device_name () const
|
||||||
{
|
{
|
||||||
return _audio_device;
|
return "Unused";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
PortAudioBackend::input_device_name () const
|
||||||
|
{
|
||||||
|
return _input_audio_device;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
PortAudioBackend::output_device_name () const
|
||||||
|
{
|
||||||
|
return _output_audio_device;
|
||||||
}
|
}
|
||||||
|
|
||||||
float
|
float
|
||||||
|
|
@ -349,7 +403,7 @@ PortAudioBackend::_start (bool for_latency_measurement)
|
||||||
_freewheel = false;
|
_freewheel = false;
|
||||||
_last_process_start = 0;
|
_last_process_start = 0;
|
||||||
|
|
||||||
_pcmio->pcm_setup (name_to_id(_audio_device), name_to_id(_audio_device), _samplerate, _samples_per_period);
|
_pcmio->pcm_setup (name_to_id(_input_audio_device), name_to_id(_output_audio_device), _samplerate, _samples_per_period);
|
||||||
|
|
||||||
switch (_pcmio->state ()) {
|
switch (_pcmio->state ()) {
|
||||||
case 0: /* OK */ break;
|
case 0: /* OK */ break;
|
||||||
|
|
@ -515,7 +569,8 @@ int
|
||||||
PortAudioBackend::name_to_id(std::string device_name) const {
|
PortAudioBackend::name_to_id(std::string device_name) const {
|
||||||
uint32_t device_id = UINT32_MAX;
|
uint32_t device_id = UINT32_MAX;
|
||||||
std::map<int, std::string> devices;
|
std::map<int, std::string> devices;
|
||||||
_pcmio->device_list(devices);
|
_pcmio->input_device_list(devices);
|
||||||
|
_pcmio->output_device_list(devices);
|
||||||
|
|
||||||
for (std::map<int, std::string>::const_iterator i = devices.begin (); i != devices.end(); ++i) {
|
for (std::map<int, std::string>::const_iterator i = devices.begin (); i != devices.end(); ++i) {
|
||||||
if (i->second == device_name) {
|
if (i->second == device_name) {
|
||||||
|
|
|
||||||
|
|
@ -164,7 +164,11 @@ class PortAudioBackend : public AudioBackend {
|
||||||
std::vector<std::string> enumerate_drivers () const;
|
std::vector<std::string> enumerate_drivers () const;
|
||||||
int set_driver (const std::string&);
|
int set_driver (const std::string&);
|
||||||
|
|
||||||
|
bool use_separate_input_and_output_devices () const;
|
||||||
std::vector<DeviceStatus> enumerate_devices () const;
|
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<float> available_sample_rates (const std::string& device) const;
|
||||||
std::vector<uint32_t> available_buffer_sizes (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;
|
uint32_t available_input_channel_count (const std::string& device) const;
|
||||||
|
|
@ -174,6 +178,8 @@ class PortAudioBackend : public AudioBackend {
|
||||||
bool can_change_buffer_size_when_running () const;
|
bool can_change_buffer_size_when_running () const;
|
||||||
|
|
||||||
int set_device_name (const std::string&);
|
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_sample_rate (float);
|
||||||
int set_buffer_size (uint32_t);
|
int set_buffer_size (uint32_t);
|
||||||
int set_interleaved (bool yn);
|
int set_interleaved (bool yn);
|
||||||
|
|
@ -188,6 +194,8 @@ class PortAudioBackend : public AudioBackend {
|
||||||
|
|
||||||
/* Retrieving parameters */
|
/* Retrieving parameters */
|
||||||
std::string device_name () const;
|
std::string device_name () const;
|
||||||
|
std::string input_device_name () const;
|
||||||
|
std::string output_device_name () const;
|
||||||
float sample_rate () const;
|
float sample_rate () const;
|
||||||
uint32_t buffer_size () const;
|
uint32_t buffer_size () const;
|
||||||
bool interleaved () const;
|
bool interleaved () const;
|
||||||
|
|
@ -314,10 +322,12 @@ class PortAudioBackend : public AudioBackend {
|
||||||
uint64_t _last_process_start;
|
uint64_t _last_process_start;
|
||||||
|
|
||||||
static std::vector<std::string> _midi_options;
|
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> _midi_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;
|
std::string _midi_driver_option;
|
||||||
|
|
||||||
/* audio settings */
|
/* audio settings */
|
||||||
|
|
|
||||||
|
|
@ -51,10 +51,7 @@ PortAudioIO::~PortAudioIO ()
|
||||||
Pa_Terminate();
|
Pa_Terminate();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (std::map<int, paDevice*>::const_iterator i = _devices.begin (); i != _devices.end(); ++i) {
|
clear_device_lists ();
|
||||||
delete i->second;
|
|
||||||
}
|
|
||||||
_devices.clear();
|
|
||||||
|
|
||||||
free (_input_buffer); _input_buffer = NULL;
|
free (_input_buffer); _input_buffer = NULL;
|
||||||
free (_output_buffer); _output_buffer = NULL;
|
free (_output_buffer); _output_buffer = NULL;
|
||||||
|
|
@ -126,9 +123,21 @@ PortAudioIO::available_buffer_sizes(int device_id, std::vector<uint32_t>& buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
PortAudioIO::device_list (std::map<int, std::string> &devices) const {
|
PortAudioIO::input_device_list(std::map<int, std::string> &devices) const
|
||||||
devices.clear();
|
{
|
||||||
for (std::map<int, paDevice*>::const_iterator i = _devices.begin (); i != _devices.end(); ++i) {
|
for (std::map<int, paDevice*>::const_iterator i = _input_devices.begin ();
|
||||||
|
i != _input_devices.end ();
|
||||||
|
++i) {
|
||||||
|
devices.insert (std::pair<int, std::string>(i->first, Glib::locale_to_utf8(i->second->name)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PortAudioIO::output_device_list(std::map<int, std::string> &devices) const
|
||||||
|
{
|
||||||
|
for (std::map<int, paDevice*>::const_iterator i = _output_devices.begin ();
|
||||||
|
i != _output_devices.end ();
|
||||||
|
++i) {
|
||||||
devices.insert (std::pair<int, std::string>(i->first, Glib::locale_to_utf8(i->second->name)));
|
devices.insert (std::pair<int, std::string>(i->first, Glib::locale_to_utf8(i->second->name)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -211,16 +220,21 @@ PortAudioIO::get_default_output_device ()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
PortAudioIO::clear_device_list ()
|
PortAudioIO::clear_device_lists ()
|
||||||
{
|
{
|
||||||
for (std::map<int, paDevice*>::const_iterator i = _devices.begin (); i != _devices.end(); ++i) {
|
for (std::map<int, paDevice*>::const_iterator i = _input_devices.begin (); i != _input_devices.end(); ++i) {
|
||||||
delete i->second;
|
delete i->second;
|
||||||
}
|
}
|
||||||
_devices.clear();
|
_input_devices.clear();
|
||||||
|
|
||||||
|
for (std::map<int, paDevice*>::const_iterator i = _output_devices.begin (); i != _output_devices.end(); ++i) {
|
||||||
|
delete i->second;
|
||||||
|
}
|
||||||
|
_output_devices.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
PortAudioIO::add_default_device ()
|
PortAudioIO::add_default_devices ()
|
||||||
{
|
{
|
||||||
const PaHostApiInfo* info = Pa_GetHostApiInfo (_host_api_index);
|
const PaHostApiInfo* info = Pa_GetHostApiInfo (_host_api_index);
|
||||||
if (info == NULL) return;
|
if (info == NULL) return;
|
||||||
|
|
@ -228,7 +242,12 @@ PortAudioIO::add_default_device ()
|
||||||
const PaDeviceInfo* nfo_i = Pa_GetDeviceInfo(get_default_input_device());
|
const PaDeviceInfo* nfo_i = Pa_GetDeviceInfo(get_default_input_device());
|
||||||
const PaDeviceInfo* nfo_o = Pa_GetDeviceInfo(get_default_output_device());
|
const PaDeviceInfo* nfo_o = Pa_GetDeviceInfo(get_default_output_device());
|
||||||
if (nfo_i && nfo_o) {
|
if (nfo_i && nfo_o) {
|
||||||
_devices.insert (std::pair<int, paDevice*> (-1,
|
_input_devices.insert (std::pair<int, paDevice*> (-1,
|
||||||
|
new paDevice("Default",
|
||||||
|
nfo_i->maxInputChannels,
|
||||||
|
nfo_o->maxOutputChannels
|
||||||
|
)));
|
||||||
|
_output_devices.insert (std::pair<int, paDevice*> (-1,
|
||||||
new paDevice("Default",
|
new paDevice("Default",
|
||||||
nfo_i->maxInputChannels,
|
nfo_i->maxInputChannels,
|
||||||
nfo_o->maxOutputChannels
|
nfo_o->maxOutputChannels
|
||||||
|
|
@ -267,12 +286,21 @@ PortAudioIO::add_devices ()
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
_devices.insert (std::pair<int, paDevice*> (i, new paDevice(
|
if (nfo->maxInputChannels > 0) {
|
||||||
|
_input_devices.insert (std::pair<int, paDevice*> (i, new paDevice(
|
||||||
nfo->name,
|
nfo->name,
|
||||||
nfo->maxInputChannels,
|
nfo->maxInputChannels,
|
||||||
nfo->maxOutputChannels
|
nfo->maxOutputChannels
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
if (nfo->maxOutputChannels > 0) {
|
||||||
|
_output_devices.insert (std::pair<int, paDevice*> (i, new paDevice(
|
||||||
|
nfo->name,
|
||||||
|
nfo->maxInputChannels,
|
||||||
|
nfo->maxOutputChannels
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -280,8 +308,8 @@ PortAudioIO::discover()
|
||||||
{
|
{
|
||||||
if (!initialize_pa()) return;
|
if (!initialize_pa()) return;
|
||||||
|
|
||||||
clear_device_list ();
|
clear_device_lists ();
|
||||||
add_default_device ();
|
add_default_devices ();
|
||||||
add_devices ();
|
add_devices ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,8 @@ public:
|
||||||
PaDeviceIndex get_default_output_device ();
|
PaDeviceIndex get_default_output_device ();
|
||||||
|
|
||||||
void discover();
|
void discover();
|
||||||
void device_list (std::map<int, std::string> &devices) const;
|
void input_device_list (std::map<int, std::string> &devices) const;
|
||||||
|
void output_device_list (std::map<int, std::string> &devices) const;
|
||||||
|
|
||||||
int available_sample_rates (int device_id, std::vector<float>& sampleRates);
|
int available_sample_rates (int device_id, std::vector<float>& sampleRates);
|
||||||
int available_buffer_sizes (int device_id, std::vector<uint32_t>& sampleRates);
|
int available_buffer_sizes (int device_id, std::vector<uint32_t>& sampleRates);
|
||||||
|
|
@ -77,8 +78,8 @@ public:
|
||||||
|
|
||||||
private: // Methods
|
private: // Methods
|
||||||
|
|
||||||
void clear_device_list ();
|
void clear_device_lists ();
|
||||||
void add_default_device ();
|
void add_default_devices ();
|
||||||
void add_devices ();
|
void add_devices ();
|
||||||
|
|
||||||
private: // Data
|
private: // Data
|
||||||
|
|
@ -109,7 +110,8 @@ private: // Data
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::map<int, paDevice *> _devices;
|
std::map<int, paDevice *> _input_devices;
|
||||||
|
std::map<int, paDevice *> _output_devices;
|
||||||
|
|
||||||
PaHostApiIndex _host_api_index;
|
PaHostApiIndex _host_api_index;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue