summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2015-08-11 19:01:52 +0200
committerRobin Gareus <robin@gareus.org>2015-08-11 19:01:52 +0200
commita226c4ce380bc61fd113521a695da9e6123b28c0 (patch)
tree6a67b2f7a64d14ab72c5b85031e7868bcdf72bb2
parent40661f7d1ff7ce75ef84d115241d841d9849b195 (diff)
ALSA backend: query and cache available device-parameters
-rw-r--r--libs/backends/alsa/alsa_audiobackend.cc172
-rw-r--r--libs/backends/alsa/alsa_audiobackend.h6
2 files changed, 154 insertions, 24 deletions
diff --git a/libs/backends/alsa/alsa_audiobackend.cc b/libs/backends/alsa/alsa_audiobackend.cc
index ab6c029c59..1e9ebd7764 100644
--- a/libs/backends/alsa/alsa_audiobackend.cc
+++ b/libs/backends/alsa/alsa_audiobackend.cc
@@ -44,6 +44,9 @@ std::vector<AudioBackend::DeviceStatus> AlsaAudioBackend::_output_audio_device_s
std::vector<AudioBackend::DeviceStatus> AlsaAudioBackend::_duplex_audio_device_status;
std::vector<AudioBackend::DeviceStatus> AlsaAudioBackend::_midi_device_status;
+ALSADeviceInfo AlsaAudioBackend::_input_audio_device_info;
+ALSADeviceInfo AlsaAudioBackend::_output_audio_device_info;
+
AlsaAudioBackend::AlsaAudioBackend (AudioEngine& e, AudioBackendInfo& info)
: AudioBackend (e, info)
, _pcmi (0)
@@ -70,6 +73,8 @@ AlsaAudioBackend::AlsaAudioBackend (AudioEngine& e, AudioBackendInfo& info)
{
_instance_name = s_instance_name;
pthread_mutex_init (&_port_callback_mutex, 0);
+ _input_audio_device_info.valid = false;
+ _output_audio_device_info.valid = false;
}
AlsaAudioBackend::~AlsaAudioBackend ()
@@ -211,47 +216,118 @@ AlsaAudioBackend::acquire_device(const char* device_name)
}
std::vector<float>
-AlsaAudioBackend::available_sample_rates (const std::string&) const
+AlsaAudioBackend::available_sample_rates (const std::string& input_device, const std::string& output_device) const
{
std::vector<float> sr;
- sr.push_back (8000.0);
- sr.push_back (22050.0);
- sr.push_back (24000.0);
- sr.push_back (44100.0);
- sr.push_back (48000.0);
- sr.push_back (88200.0);
- sr.push_back (96000.0);
- sr.push_back (176400.0);
- sr.push_back (192000.0);
+ if (input_device == _("None") && output_device == _("None")) {
+ return sr;
+ }
+ else if (input_device == _("None")) {
+ sr = available_sample_rates (output_device);
+ }
+ else if (output_device == _("None")) {
+ sr = available_sample_rates (input_device);
+ } else {
+ std::vector<float> sr_in = available_sample_rates (input_device);
+ std::vector<float> sr_out = available_sample_rates (output_device);
+ std::set_intersection (sr_in.begin(), sr_in.end(), sr_out.begin(), sr_out.end(), std::back_inserter(sr));
+ }
+ return sr;
+}
+
+std::vector<float>
+AlsaAudioBackend::available_sample_rates (const std::string& device) const
+{
+ ALSADeviceInfo *nfo = NULL;
+ std::vector<float> sr;
+ if (device == _("None")) {
+ return sr;
+ }
+ if (device == _input_audio_device && _input_audio_device_info.valid) {
+ nfo = &_input_audio_device_info;
+ }
+ else if (device == _output_audio_device && _output_audio_device_info.valid) {
+ nfo = &_output_audio_device_info;
+ }
+
+ static const float avail_rates [] = { 8000, 22050.0, 24000.0, 44100.0, 48000.0, 88200.0, 96000.0, 176400.0, 192000.0 };
+
+ for (size_t i = 0 ; i < sizeof(avail_rates) / sizeof(float); ++i) {
+ if (!nfo || (avail_rates[i] >= nfo->min_rate && avail_rates[i] <= nfo->max_rate)) {
+ sr.push_back (avail_rates[i]);
+ }
+ }
+
return sr;
}
std::vector<uint32_t>
-AlsaAudioBackend::available_buffer_sizes (const std::string&) const
+AlsaAudioBackend::available_buffer_sizes (const std::string& input_device, const std::string& output_device) const
{
std::vector<uint32_t> bs;
- bs.push_back (32);
- bs.push_back (64);
- bs.push_back (128);
- bs.push_back (256);
- bs.push_back (512);
- bs.push_back (1024);
- bs.push_back (2048);
- bs.push_back (4096);
- bs.push_back (8192);
+ if (input_device == _("None") && output_device == _("None")) {
+ return bs;
+ }
+ else if (input_device == _("None")) {
+ bs = available_buffer_sizes (output_device);
+ }
+ else if (output_device == _("None")) {
+ bs = available_buffer_sizes (input_device);
+ } else {
+ std::vector<uint32_t> bs_in = available_buffer_sizes (input_device);
+ std::vector<uint32_t> bs_out = available_buffer_sizes (output_device);
+ std::set_intersection (bs_in.begin(), bs_in.end(), bs_out.begin(), bs_out.end(), std::back_inserter(bs));
+ }
+ return bs;
+}
+
+std::vector<uint32_t>
+AlsaAudioBackend::available_buffer_sizes (const std::string& device) const
+{
+ ALSADeviceInfo *nfo = NULL;
+ std::vector<uint32_t> bs;
+ if (device == _("None")) {
+ return bs;
+ }
+ if (device == _input_audio_device && _input_audio_device_info.valid) {
+ nfo = &_input_audio_device_info;
+ }
+ else if (device == _output_audio_device && _output_audio_device_info.valid) {
+ nfo = &_output_audio_device_info;
+ }
+
+ static const unsigned long avail_sizes [] = { 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192 };
+
+ for (size_t i = 0 ; i < sizeof(avail_sizes) / sizeof(unsigned long); ++i) {
+ if (!nfo || (avail_sizes[i] >= nfo->min_size && avail_sizes[i] <= nfo->max_size)) {
+ bs.push_back (avail_sizes[i]);
+ }
+ }
return bs;
}
uint32_t
-AlsaAudioBackend::available_input_channel_count (const std::string&) const
+AlsaAudioBackend::available_input_channel_count (const std::string& device) const
{
- return 128; // TODO query current device
+ if (device == _("None")) {
+ return 0;
+ }
+ if (device == _input_audio_device && _input_audio_device_info.valid) {
+ return _input_audio_device_info.max_channels;
+ }
+ return 128;
}
uint32_t
-AlsaAudioBackend::available_output_channel_count (const std::string&) const
+AlsaAudioBackend::available_output_channel_count (const std::string& device) const
{
- return 128; // TODO query current device
+ if (device == _("None")) {
+ return 0;
+ }
+ if (device == _output_audio_device && _output_audio_device_info.valid) {
+ return _output_audio_device_info.max_channels;
+ }
+ return 128;
}
bool
@@ -269,14 +345,62 @@ AlsaAudioBackend::can_change_buffer_size_when_running () const
int
AlsaAudioBackend::set_input_device_name (const std::string& d)
{
+ if (_input_audio_device == d) {
+ return 0;
+ }
_input_audio_device = d;
+
+ if (d == _("None")) {
+ _input_audio_device_info.valid = false;
+ return 0;
+ }
+ std::string alsa_device;
+ std::map<std::string, std::string> devices;
+
+ get_alsa_audio_device_names(devices, HalfDuplexIn);
+ for (std::map<std::string, std::string>::const_iterator i = devices.begin (); i != devices.end(); ++i) {
+ if (i->first == d) {
+ alsa_device = i->second;
+ break;
+ }
+ }
+ if (alsa_device == "") {
+ _input_audio_device_info.valid = false;
+ return 1;
+ }
+ /* device will be busy once used, hence cache the parameters */
+ /* return */ get_alsa_device_parameters (alsa_device.c_str(), true, &_input_audio_device_info);
return 0;
}
int
AlsaAudioBackend::set_output_device_name (const std::string& d)
{
+ if (_output_audio_device == d) {
+ return 0;
+ }
+
_output_audio_device = d;
+
+ if (d == _("None")) {
+ _output_audio_device_info.valid = false;
+ return 0;
+ }
+ std::string alsa_device;
+ std::map<std::string, std::string> devices;
+
+ get_alsa_audio_device_names(devices, HalfDuplexOut);
+ for (std::map<std::string, std::string>::const_iterator i = devices.begin (); i != devices.end(); ++i) {
+ if (i->first == d) {
+ alsa_device = i->second;
+ break;
+ }
+ }
+ if (alsa_device == "") {
+ _output_audio_device_info.valid = false;
+ return 1;
+ }
+ /* return */ get_alsa_device_parameters (alsa_device.c_str(), true, &_output_audio_device_info);
return 0;
}
diff --git a/libs/backends/alsa/alsa_audiobackend.h b/libs/backends/alsa/alsa_audiobackend.h
index 49066e360b..73eddaaf4e 100644
--- a/libs/backends/alsa/alsa_audiobackend.h
+++ b/libs/backends/alsa/alsa_audiobackend.h
@@ -34,6 +34,8 @@
#include "ardour/system_exec.h"
#include "ardour/types.h"
+#include "ardouralsautil/deviceinfo.h"
+
#include "zita-alsa-pcmi.h"
#include "alsa_rawmidi.h"
#include "alsa_sequencer.h"
@@ -169,7 +171,9 @@ class AlsaAudioBackend : public AudioBackend {
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&, const std::string&) const;
std::vector<uint32_t> available_buffer_sizes (const std::string& device) const;
+ std::vector<uint32_t> available_buffer_sizes (const std::string&, const std::string&) const;
uint32_t available_input_channel_count (const std::string& device) const;
uint32_t available_output_channel_count (const std::string& device) const;
@@ -319,6 +323,8 @@ class AlsaAudioBackend : public AudioBackend {
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 ARDOUR::ALSADeviceInfo _input_audio_device_info;
+ static ARDOUR::ALSADeviceInfo _output_audio_device_info;
mutable std::string _input_audio_device;
mutable std::string _output_audio_device;