summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2014-06-03 00:50:26 +0200
committerRobin Gareus <robin@gareus.org>2014-06-03 00:50:26 +0200
commitb050f913235eb83edc1b0cdef7bd61312381162f (patch)
treea721a63bfdaabc8bc905ec73d39e5fe958110077 /libs
parentd5fa80e01de69ba7449a1b2f8d38514734f3211e (diff)
ALSA backend: device detection
Diffstat (limited to 'libs')
-rw-r--r--libs/backends/alsa/alsa_audiobackend.cc117
1 files changed, 103 insertions, 14 deletions
diff --git a/libs/backends/alsa/alsa_audiobackend.cc b/libs/backends/alsa/alsa_audiobackend.cc
index ca4fd25c28..7ce83ddc40 100644
--- a/libs/backends/alsa/alsa_audiobackend.cc
+++ b/libs/backends/alsa/alsa_audiobackend.cc
@@ -81,10 +81,12 @@ AlsaAudioBackend::enumerate_devices () const
{
std::vector<AudioBackend::DeviceStatus> s;
int cardnum = -1;
+ int device = -1;
snd_ctl_card_info_t *info;
snd_ctl_card_info_alloca (&info);
+ snd_pcm_info_t *pcminfo;
+ snd_pcm_info_alloca (&pcminfo);
- // TODO re-use code from libs/backends/jack/jack_utils.cc
while (snd_card_next (&cardnum) >= 0 && cardnum >= 0) {
snd_ctl_t *handle;
@@ -92,12 +94,32 @@ AlsaAudioBackend::enumerate_devices () const
devname += PBD::to_string (cardnum, std::dec);
if (snd_ctl_open (&handle, devname.c_str(), 0) >= 0 && snd_ctl_card_info (handle, info) >= 0) {
- //string card_name = snd_ctl_card_info_get_name (info);
- int device = -1;
- if (snd_ctl_pcm_next_device (handle, &device) >= 0 && device >= 0) {
- s.push_back (DeviceStatus (devname, true));
+ if (snd_ctl_card_info (handle, info) < 0) {
+ continue;
}
- snd_ctl_close(handle);
+
+ std::string card_name = snd_ctl_card_info_get_name (info);
+ devname = "hw:";
+ devname += snd_ctl_card_info_get_id (info);
+
+ while (snd_ctl_pcm_next_device (handle, &device) >= 0 && device >= 0) {
+ snd_pcm_info_set_device (pcminfo, device);
+ snd_pcm_info_set_subdevice (pcminfo, 0);
+ snd_pcm_info_set_stream (pcminfo, SND_PCM_STREAM_CAPTURE);
+ if (snd_ctl_pcm_info (handle, pcminfo) < 0) {
+ continue;
+ }
+ snd_pcm_info_set_device (pcminfo, device);
+ snd_pcm_info_set_subdevice (pcminfo, 0);
+ snd_pcm_info_set_stream (pcminfo, SND_PCM_STREAM_PLAYBACK);
+ if (snd_ctl_pcm_info (handle, pcminfo) < 0) {
+ continue;
+ }
+ devname += ',';
+ devname += PBD::to_string (device, std::dec);
+ s.push_back (DeviceStatus (devname + " " + card_name, true));
+ }
+ snd_ctl_close (handle);
}
}
return s;
@@ -276,18 +298,82 @@ void
AlsaAudioBackend::enumerate_midi_devices (std::vector<std::string> &m) const
{
int cardnum = -1;
+ snd_ctl_card_info_t *cinfo;
+ snd_ctl_card_info_alloca (&cinfo);
while (snd_card_next (&cardnum) >= 0 && cardnum >= 0) {
snd_ctl_t *handle;
std::string devname = "hw:";
devname += PBD::to_string (cardnum, std::dec);
-
- if (snd_ctl_open (&handle, devname.c_str(), 0) >= 0) {
+ if (snd_ctl_open (&handle, devname.c_str (), 0) >= 0 && snd_ctl_card_info (handle, cinfo) >= 0) {
int device = -1;
- // TODO iterate over sub-devices
- if (snd_ctl_rawmidi_next_device (handle, &device) >= 0 && device >= 0) {
- m.push_back (devname);
+ while (snd_ctl_rawmidi_next_device (handle, &device) >= 0 && device >= 0) {
+ snd_rawmidi_info_t *info;
+ snd_rawmidi_info_alloca (&info);
+ snd_rawmidi_info_set_device (info, device);
+
+ int subs_in, subs_out;
+
+ snd_rawmidi_info_set_stream (info, SND_RAWMIDI_STREAM_INPUT);
+ if (snd_ctl_rawmidi_info (handle, info) >= 0) {
+ subs_in = snd_rawmidi_info_get_subdevices_count (info);
+ } else {
+ subs_in = 0;
+ }
+
+ snd_rawmidi_info_set_stream (info, SND_RAWMIDI_STREAM_OUTPUT);
+ if (snd_ctl_rawmidi_info (handle, info) >= 0) {
+ subs_out = snd_rawmidi_info_get_subdevices_count (info);
+ } else {
+ subs_out = 0;
+ }
+
+ const int subs = subs_in > subs_out ? subs_in : subs_out;
+ if (!subs) {
+ continue;
+ }
+
+ for (int sub = 0; sub < subs; ++sub) {
+ snd_rawmidi_info_set_stream (info, sub < subs_in ?
+ SND_RAWMIDI_STREAM_INPUT :
+ SND_RAWMIDI_STREAM_OUTPUT);
+
+ snd_rawmidi_info_set_subdevice (info, sub);
+ if (snd_ctl_rawmidi_info (handle, info) < 0) {
+ continue;
+ }
+
+ const char *sub_name = snd_rawmidi_info_get_subdevice_name (info);
+ if (sub == 0 && sub_name[0] == '\0') {
+ devname = "hw:";
+ devname += snd_ctl_card_info_get_id (cinfo);
+ devname += ",";
+ devname += PBD::to_string (device, std::dec);
+ devname += " ";
+ devname += snd_rawmidi_info_get_name (info);
+ devname += " (";
+ if (sub < subs_in) devname += "I";
+ if (sub < subs_out) devname += "O";
+ devname += ")";
+ m.push_back (devname);
+ break;
+ } else {
+ devname = "hw:";
+ devname += snd_ctl_card_info_get_id (cinfo);
+ devname += ",";
+ devname += PBD::to_string (device, std::dec);
+ devname += ",";
+ devname += PBD::to_string (sub, std::dec);
+ devname += " ";
+ devname += sub_name;
+ devname += " (";
+ if (sub < subs_in) devname += "I";
+ if (sub < subs_out) devname += "O";
+ devname += ")";
+ m.push_back (devname);
+ }
+ }
}
- snd_ctl_close(handle);
+ snd_ctl_close (handle);
}
}
}
@@ -348,8 +434,10 @@ AlsaAudioBackend::_start (bool for_latency_measurement)
assert(_rmidi_out.size() == 0);
assert(_pcmi == 0);
- _pcmi = new Alsa_pcmi (_capture_device.c_str(), _playback_device.c_str(), 0, _samplerate, _samples_per_period, _periods_per_cycle, 0);
+ unsigned int pos = _capture_device.find(" ");
+ _pcmi = new Alsa_pcmi (_capture_device.substr(0, pos).c_str(), _playback_device.substr(0, pos).c_str(), 0, _samplerate, _samples_per_period, _periods_per_cycle, 0);
if (_pcmi->state ()) {
+ // TODO get detailed error from _pcmi
PBD::error << _("AlsaAudioBackend: failed to open device (see stderr for details).") << endmsg;
delete _pcmi; _pcmi = 0;
return -1;
@@ -780,7 +868,8 @@ AlsaAudioBackend::register_system_midi_ports()
else if (_midi_device == _("-All-")) {
enumerate_midi_devices(devices);
} else {
- devices.push_back(_midi_device);
+ unsigned int pos = _midi_device.find(" ");
+ devices.push_back(_midi_device.substr(0, pos));
}
for (std::vector<std::string>::const_iterator i = devices.begin (); i != devices.end (); ++i) {