ALSA backend: device detection
This commit is contained in:
parent
d5fa80e01d
commit
b050f91323
@ -81,10 +81,12 @@ AlsaAudioBackend::enumerate_devices () const
|
|||||||
{
|
{
|
||||||
std::vector<AudioBackend::DeviceStatus> s;
|
std::vector<AudioBackend::DeviceStatus> s;
|
||||||
int cardnum = -1;
|
int cardnum = -1;
|
||||||
|
int device = -1;
|
||||||
snd_ctl_card_info_t *info;
|
snd_ctl_card_info_t *info;
|
||||||
snd_ctl_card_info_alloca (&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) {
|
while (snd_card_next (&cardnum) >= 0 && cardnum >= 0) {
|
||||||
snd_ctl_t *handle;
|
snd_ctl_t *handle;
|
||||||
|
|
||||||
@ -92,12 +94,32 @@ AlsaAudioBackend::enumerate_devices () const
|
|||||||
devname += PBD::to_string (cardnum, std::dec);
|
devname += PBD::to_string (cardnum, std::dec);
|
||||||
|
|
||||||
if (snd_ctl_open (&handle, devname.c_str(), 0) >= 0 && snd_ctl_card_info (handle, info) >= 0) {
|
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);
|
if (snd_ctl_card_info (handle, info) < 0) {
|
||||||
int device = -1;
|
continue;
|
||||||
if (snd_ctl_pcm_next_device (handle, &device) >= 0 && device >= 0) {
|
|
||||||
s.push_back (DeviceStatus (devname, true));
|
|
||||||
}
|
}
|
||||||
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;
|
return s;
|
||||||
@ -276,18 +298,82 @@ void
|
|||||||
AlsaAudioBackend::enumerate_midi_devices (std::vector<std::string> &m) const
|
AlsaAudioBackend::enumerate_midi_devices (std::vector<std::string> &m) const
|
||||||
{
|
{
|
||||||
int cardnum = -1;
|
int cardnum = -1;
|
||||||
|
snd_ctl_card_info_t *cinfo;
|
||||||
|
snd_ctl_card_info_alloca (&cinfo);
|
||||||
while (snd_card_next (&cardnum) >= 0 && cardnum >= 0) {
|
while (snd_card_next (&cardnum) >= 0 && cardnum >= 0) {
|
||||||
snd_ctl_t *handle;
|
snd_ctl_t *handle;
|
||||||
std::string devname = "hw:";
|
std::string devname = "hw:";
|
||||||
devname += PBD::to_string (cardnum, std::dec);
|
devname += PBD::to_string (cardnum, std::dec);
|
||||||
|
if (snd_ctl_open (&handle, devname.c_str (), 0) >= 0 && snd_ctl_card_info (handle, cinfo) >= 0) {
|
||||||
if (snd_ctl_open (&handle, devname.c_str(), 0) >= 0) {
|
|
||||||
int device = -1;
|
int device = -1;
|
||||||
// TODO iterate over sub-devices
|
while (snd_ctl_rawmidi_next_device (handle, &device) >= 0 && device >= 0) {
|
||||||
if (snd_ctl_rawmidi_next_device (handle, &device) >= 0 && device >= 0) {
|
snd_rawmidi_info_t *info;
|
||||||
m.push_back (devname);
|
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(_rmidi_out.size() == 0);
|
||||||
assert(_pcmi == 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 ()) {
|
if (_pcmi->state ()) {
|
||||||
|
// TODO get detailed error from _pcmi
|
||||||
PBD::error << _("AlsaAudioBackend: failed to open device (see stderr for details).") << endmsg;
|
PBD::error << _("AlsaAudioBackend: failed to open device (see stderr for details).") << endmsg;
|
||||||
delete _pcmi; _pcmi = 0;
|
delete _pcmi; _pcmi = 0;
|
||||||
return -1;
|
return -1;
|
||||||
@ -780,7 +868,8 @@ AlsaAudioBackend::register_system_midi_ports()
|
|||||||
else if (_midi_device == _("-All-")) {
|
else if (_midi_device == _("-All-")) {
|
||||||
enumerate_midi_devices(devices);
|
enumerate_midi_devices(devices);
|
||||||
} else {
|
} 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) {
|
for (std::vector<std::string>::const_iterator i = devices.begin (); i != devices.end (); ++i) {
|
||||||
|
Loading…
Reference in New Issue
Block a user