ALSA backend: add support for half-duplex devices
This commit is contained in:
parent
acd95215a4
commit
dc2030cfd7
|
@ -39,7 +39,9 @@ using namespace ARDOUR;
|
||||||
static std::string s_instance_name;
|
static std::string s_instance_name;
|
||||||
size_t AlsaAudioBackend::_max_buffer_size = 8192;
|
size_t AlsaAudioBackend::_max_buffer_size = 8192;
|
||||||
std::vector<std::string> AlsaAudioBackend::_midi_options;
|
std::vector<std::string> AlsaAudioBackend::_midi_options;
|
||||||
std::vector<AudioBackend::DeviceStatus> AlsaAudioBackend::_audio_device_status;
|
std::vector<AudioBackend::DeviceStatus> AlsaAudioBackend::_input_audio_device_status;
|
||||||
|
std::vector<AudioBackend::DeviceStatus> AlsaAudioBackend::_output_audio_device_status;
|
||||||
|
std::vector<AudioBackend::DeviceStatus> AlsaAudioBackend::_duplex_audio_device_status;
|
||||||
std::vector<AudioBackend::DeviceStatus> AlsaAudioBackend::_midi_device_status;
|
std::vector<AudioBackend::DeviceStatus> AlsaAudioBackend::_midi_device_status;
|
||||||
|
|
||||||
AlsaAudioBackend::AlsaAudioBackend (AudioEngine& e, AudioBackendInfo& info)
|
AlsaAudioBackend::AlsaAudioBackend (AudioEngine& e, AudioBackendInfo& info)
|
||||||
|
@ -51,7 +53,8 @@ AlsaAudioBackend::AlsaAudioBackend (AudioEngine& e, AudioBackendInfo& info)
|
||||||
, _freewheeling (false)
|
, _freewheeling (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"))
|
||||||
, _device_reservation(0)
|
, _device_reservation(0)
|
||||||
, _samplerate (48000)
|
, _samplerate (48000)
|
||||||
|
@ -91,14 +94,43 @@ AlsaAudioBackend::is_realtime () const
|
||||||
std::vector<AudioBackend::DeviceStatus>
|
std::vector<AudioBackend::DeviceStatus>
|
||||||
AlsaAudioBackend::enumerate_devices () const
|
AlsaAudioBackend::enumerate_devices () const
|
||||||
{
|
{
|
||||||
_audio_device_status.clear();
|
_duplex_audio_device_status.clear();
|
||||||
std::map<std::string, std::string> devices;
|
std::map<std::string, std::string> devices;
|
||||||
get_alsa_audio_device_names(devices);
|
get_alsa_audio_device_names(devices);
|
||||||
for (std::map<std::string, std::string>::const_iterator i = devices.begin (); i != devices.end(); ++i) {
|
for (std::map<std::string, std::string>::const_iterator i = devices.begin (); i != devices.end(); ++i) {
|
||||||
if (_audio_device == "") _audio_device = i->first;
|
if (_input_audio_device == "") _input_audio_device = i->first;
|
||||||
_audio_device_status.push_back (DeviceStatus (i->first, true));
|
if (_output_audio_device == "") _output_audio_device = i->first;
|
||||||
|
_duplex_audio_device_status.push_back (DeviceStatus (i->first, true));
|
||||||
}
|
}
|
||||||
return _audio_device_status;
|
return _duplex_audio_device_status;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<AudioBackend::DeviceStatus>
|
||||||
|
AlsaAudioBackend::enumerate_input_devices () const
|
||||||
|
{
|
||||||
|
_input_audio_device_status.clear();
|
||||||
|
std::map<std::string, std::string> devices;
|
||||||
|
get_alsa_audio_device_names(devices, HalfDuplexIn);
|
||||||
|
_input_audio_device_status.push_back (DeviceStatus (_("None"), true));
|
||||||
|
for (std::map<std::string, std::string>::const_iterator i = devices.begin (); i != devices.end(); ++i) {
|
||||||
|
if (_input_audio_device == "") _input_audio_device = i->first;
|
||||||
|
_input_audio_device_status.push_back (DeviceStatus (i->first, true));
|
||||||
|
}
|
||||||
|
return _input_audio_device_status;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<AudioBackend::DeviceStatus>
|
||||||
|
AlsaAudioBackend::enumerate_output_devices () const
|
||||||
|
{
|
||||||
|
_output_audio_device_status.clear();
|
||||||
|
std::map<std::string, std::string> devices;
|
||||||
|
get_alsa_audio_device_names(devices, HalfDuplexOut);
|
||||||
|
_output_audio_device_status.push_back (DeviceStatus (_("None"), true));
|
||||||
|
for (std::map<std::string, std::string>::const_iterator i = devices.begin (); i != devices.end(); ++i) {
|
||||||
|
if (_output_audio_device == "") _output_audio_device = i->first;
|
||||||
|
_output_audio_device_status.push_back (DeviceStatus (i->first, true));
|
||||||
|
}
|
||||||
|
return _output_audio_device_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -234,11 +266,27 @@ AlsaAudioBackend::can_change_buffer_size_when_running () const
|
||||||
return false; // why not? :)
|
return false; // why not? :)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
AlsaAudioBackend::set_input_device_name (const std::string& d)
|
||||||
|
{
|
||||||
|
_input_audio_device = d;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
AlsaAudioBackend::set_output_device_name (const std::string& d)
|
||||||
|
{
|
||||||
|
_output_audio_device = d;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
AlsaAudioBackend::set_device_name (const std::string& d)
|
AlsaAudioBackend::set_device_name (const std::string& d)
|
||||||
{
|
{
|
||||||
_audio_device = d;
|
int rv = 0;
|
||||||
return 0;
|
rv |= set_input_device_name (d);
|
||||||
|
rv |= set_output_device_name (d);
|
||||||
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -321,7 +369,25 @@ AlsaAudioBackend::set_systemic_midi_output_latency (std::string const device, ui
|
||||||
std::string
|
std::string
|
||||||
AlsaAudioBackend::device_name () const
|
AlsaAudioBackend::device_name () const
|
||||||
{
|
{
|
||||||
return _audio_device;
|
if (_input_audio_device != _("None")) {
|
||||||
|
return _input_audio_device;
|
||||||
|
}
|
||||||
|
if (_output_audio_device != _("None")) {
|
||||||
|
return _output_audio_device;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
AlsaAudioBackend::input_device_name () const
|
||||||
|
{
|
||||||
|
return _input_audio_device;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
AlsaAudioBackend::output_device_name () const
|
||||||
|
{
|
||||||
|
return _output_audio_device;
|
||||||
}
|
}
|
||||||
|
|
||||||
float
|
float
|
||||||
|
@ -516,18 +582,52 @@ AlsaAudioBackend::_start (bool for_latency_measurement)
|
||||||
assert(_rmidi_out.size() == 0);
|
assert(_rmidi_out.size() == 0);
|
||||||
assert(_pcmi == 0);
|
assert(_pcmi == 0);
|
||||||
|
|
||||||
|
int duplex = 0;
|
||||||
|
std::string audio_device;
|
||||||
std::string alsa_device;
|
std::string alsa_device;
|
||||||
std::map<std::string, std::string> devices;
|
std::map<std::string, std::string> devices;
|
||||||
get_alsa_audio_device_names(devices);
|
|
||||||
|
if (_input_audio_device == _("None") && _output_audio_device == _("None")) {
|
||||||
|
PBD::error << _("AlsaAudioBackend: At least one of input or output device needs to be set.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_input_audio_device != _output_audio_device) {
|
||||||
|
if (_input_audio_device != _("None") && _output_audio_device != _("None")) {
|
||||||
|
PBD::error << _("AlsaAudioBackend: Cannot use two different devices.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (_input_audio_device != _("None")) {
|
||||||
|
get_alsa_audio_device_names(devices, HalfDuplexIn);
|
||||||
|
audio_device = _input_audio_device;
|
||||||
|
duplex = 1;
|
||||||
|
} else {
|
||||||
|
get_alsa_audio_device_names(devices, HalfDuplexOut);
|
||||||
|
audio_device = _output_audio_device;
|
||||||
|
duplex = 2;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
get_alsa_audio_device_names(devices);
|
||||||
|
audio_device = _input_audio_device;
|
||||||
|
duplex = 3;
|
||||||
|
}
|
||||||
|
|
||||||
for (std::map<std::string, std::string>::const_iterator i = devices.begin (); i != devices.end(); ++i) {
|
for (std::map<std::string, std::string>::const_iterator i = devices.begin (); i != devices.end(); ++i) {
|
||||||
if (i->first == _audio_device) {
|
if (i->first == audio_device) {
|
||||||
alsa_device = i->second;
|
alsa_device = i->second;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (alsa_device == "") {
|
||||||
|
PBD::error << _("AlsaAudioBackend: Cannot find configured device. Is it still connected?");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
acquire_device(alsa_device.c_str());
|
acquire_device(alsa_device.c_str());
|
||||||
_pcmi = new Alsa_pcmi (alsa_device.c_str(), alsa_device.c_str(), 0, _samplerate, _samples_per_period, _periods_per_cycle, 0);
|
_pcmi = new Alsa_pcmi (
|
||||||
|
(duplex & 2) ? alsa_device.c_str() : NULL,
|
||||||
|
(duplex & 1) ? alsa_device.c_str() : NULL,
|
||||||
|
0, _samplerate, _samples_per_period, _periods_per_cycle, 0);
|
||||||
switch (_pcmi->state ()) {
|
switch (_pcmi->state ()) {
|
||||||
case 0: /* OK */ break;
|
case 0: /* OK */ break;
|
||||||
case -1: PBD::error << _("AlsaAudioBackend: failed to open device.") << endmsg; break;
|
case -1: PBD::error << _("AlsaAudioBackend: failed to open device.") << endmsg; break;
|
||||||
|
|
|
@ -164,7 +164,10 @@ class AlsaAudioBackend : public AudioBackend {
|
||||||
std::string name () const;
|
std::string name () const;
|
||||||
bool is_realtime () 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_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 +177,8 @@ class AlsaAudioBackend : 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 +193,8 @@ class AlsaAudioBackend : 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;
|
||||||
|
@ -308,10 +315,13 @@ class AlsaAudioBackend : 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> _duplex_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 device reservation */
|
/* audio device reservation */
|
||||||
|
|
Loading…
Reference in New Issue
Block a user