summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2015-12-04 22:19:47 +0100
committerRobin Gareus <robin@gareus.org>2015-12-04 22:19:47 +0100
commitbfd2cbaa3f3d03dbca4c9ad424eab6a2ce4b6e99 (patch)
tree1f3a727b4b86ccbe0da7c650d0be2c6edcd2250c
parentac075560bd8034a549bc017391fae92cfb5d7eef (diff)
ALSA: allow to dynamically add/remove midi devices & update their latency.
-rw-r--r--libs/backends/alsa/alsa_audiobackend.cc81
-rw-r--r--libs/backends/alsa/alsa_audiobackend.h5
-rw-r--r--libs/backends/alsa/alsa_midi.h5
-rw-r--r--libs/backends/alsa/alsa_rawmidi.cc11
-rw-r--r--libs/backends/alsa/alsa_rawmidi.h6
-rw-r--r--libs/backends/alsa/alsa_sequencer.cc11
-rw-r--r--libs/backends/alsa/alsa_sequencer.h6
7 files changed, 92 insertions, 33 deletions
diff --git a/libs/backends/alsa/alsa_audiobackend.cc b/libs/backends/alsa/alsa_audiobackend.cc
index 25a5e3f127..8a25f548d7 100644
--- a/libs/backends/alsa/alsa_audiobackend.cc
+++ b/libs/backends/alsa/alsa_audiobackend.cc
@@ -70,6 +70,8 @@ AlsaAudioBackend::AlsaAudioBackend (AudioEngine& e, AudioBackendInfo& info)
, _dsp_load (0)
, _processed_samples (0)
, _port_change_flag (false)
+ , _midi_ins (0)
+ , _midi_outs (0)
{
_instance_name = s_instance_name;
pthread_mutex_init (&_port_callback_mutex, 0);
@@ -544,19 +546,27 @@ AlsaAudioBackend::update_systemic_audio_latencies ()
void
AlsaAudioBackend::update_systemic_midi_latencies ()
{
-#if 0
- // TODO, need a way to associate the port with the corresponding AlsaMidiDeviceInfo
- for (std::vector<AlsaPort*>::iterator it = _system_midi_out.begin (); it != _system_midi_out.end (); ++it) {
+ uint32_t i = 0;
+ for (std::vector<AlsaPort*>::iterator it = _system_midi_out.begin (); it != _system_midi_out.end (); ++it, ++i) {
+ assert (_rmidi_out.size() > i);
+ AlsaMidiOut *rm = _rmidi_out.at(i);
+ struct AlsaMidiDeviceInfo * nfo = midi_device_info (rm->name());
+ assert (nfo);
LatencyRange lr;
lr.min = lr.max = (_measure_latency ? 0 : nfo->systemic_output_latency);
set_latency_range (*it, false, lr);
}
- for (std::vector<AlsaPort*>::const_iterator it = _system_midi_in.begin (); it != _system_midi_in.end (); ++it) {
+
+ i = 0;
+ for (std::vector<AlsaPort*>::const_iterator it = _system_midi_in.begin (); it != _system_midi_in.end (); ++it, ++i) {
+ assert (_rmidi_in.size() > i);
+ AlsaMidiIO *rm = _rmidi_in.at(i);
+ struct AlsaMidiDeviceInfo * nfo = midi_device_info (rm->name());
+ assert (nfo);
LatencyRange lr;
lr.min = lr.max = (_measure_latency ? 0 : nfo->systemic_input_latency);
set_latency_range (*it, true, lr);
}
-#endif
update_latencies ();
}
@@ -712,6 +722,9 @@ AlsaAudioBackend::set_midi_option (const std::string& opt)
if (opt != get_standard_device_name(DeviceNone) && opt != _("ALSA raw devices") && opt != _("ALSA sequencer")) {
return -1;
}
+ if (_run && _midi_driver_option != opt) {
+ return -1;
+ }
_midi_driver_option = opt;
return 0;
}
@@ -727,8 +740,41 @@ AlsaAudioBackend::set_midi_device_enabled (std::string const device, bool enable
{
struct AlsaMidiDeviceInfo * nfo = midi_device_info(device);
if (!nfo) return -1;
+ const bool prev_enabled = nfo->enabled;
nfo->enabled = enable;
- // TODO - trigger update when already running
+
+ if (_run && prev_enabled != enable) {
+ if (enable) {
+ // add ports for the given device
+ register_system_midi_ports(device);
+ } else {
+ // remove all ports provided by the given device
+ uint32_t i = 0;
+ for (std::vector<AlsaPort*>::iterator it = _system_midi_out.begin (); it != _system_midi_out.end ();) {
+ assert (_rmidi_out.size() > i);
+ AlsaMidiOut *rm = _rmidi_out.at(i);
+ if (rm->name () != device) { ++it; ++i; continue; }
+ it = _system_midi_out.erase (it);
+ unregister_port (*it);
+ rm->stop();
+ _rmidi_out.erase (_rmidi_out.begin() + i);
+ delete rm;
+ }
+
+ i = 0;
+ for (std::vector<AlsaPort*>::iterator it = _system_midi_in.begin (); it != _system_midi_in.end ();) {
+ assert (_rmidi_in.size() > i);
+ AlsaMidiIn *rm = _rmidi_in.at(i);
+ if (rm->name () != device) { ++it; ++i; continue; }
+ it = _system_midi_in.erase (it);
+ unregister_port (*it);
+ rm->stop();
+ _rmidi_in.erase (_rmidi_in.begin() + i);
+ delete rm;
+ }
+ }
+ update_systemic_midi_latencies ();
+ }
return 0;
}
@@ -909,6 +955,7 @@ AlsaAudioBackend::_start (bool for_latency_measurement)
_measure_latency = for_latency_measurement;
+ _midi_ins = _midi_outs = 0;
register_system_midi_ports();
if (register_system_audio_ports()) {
@@ -990,6 +1037,7 @@ AlsaAudioBackend::stop ()
unregister_ports();
delete _pcmi; _pcmi = 0;
+ _midi_ins = _midi_outs = 0;
release_device();
return (_active == false) ? 0 : -1;
@@ -1312,11 +1360,11 @@ AlsaAudioBackend::register_system_audio_ports()
}
int
-AlsaAudioBackend::register_system_midi_ports()
+AlsaAudioBackend::register_system_midi_ports(const std::string device)
{
std::map<std::string, std::string> devices;
- int midi_ins = 0;
- int midi_outs = 0;
+
+ // TODO use consistent numbering when re-adding devices: _midi_ins, _midi_outs
if (_midi_driver_option == get_standard_device_name(DeviceNone)) {
return 0;
@@ -1327,15 +1375,18 @@ AlsaAudioBackend::register_system_midi_ports()
}
for (std::map<std::string, std::string>::const_iterator i = devices.begin (); i != devices.end(); ++i) {
+ if (!device.empty() && device != i->first) {
+ continue;
+ }
struct AlsaMidiDeviceInfo * nfo = midi_device_info(i->first);
if (!nfo) continue;
if (!nfo->enabled) continue;
AlsaMidiOut *mout;
if (_midi_driver_option == _("ALSA raw devices")) {
- mout = new AlsaRawMidiOut (i->second.c_str());
+ mout = new AlsaRawMidiOut (i->first, i->second.c_str());
} else {
- mout = new AlsaSeqMidiOut (i->second.c_str());
+ mout = new AlsaSeqMidiOut (i->first, i->second.c_str());
}
if (mout->state ()) {
@@ -1353,7 +1404,7 @@ AlsaAudioBackend::register_system_midi_ports()
delete mout;
} else {
char tmp[64];
- snprintf(tmp, sizeof(tmp), "system:midi_playback_%d", ++midi_ins);
+ snprintf(tmp, sizeof(tmp), "system:midi_playback_%d", ++_midi_ins);
PortHandle p = add_port(std::string(tmp), DataType::MIDI, static_cast<PortFlags>(IsInput | IsPhysical | IsTerminal));
if (!p) {
mout->stop();
@@ -1370,9 +1421,9 @@ AlsaAudioBackend::register_system_midi_ports()
AlsaMidiIn *midin;
if (_midi_driver_option == _("ALSA raw devices")) {
- midin = new AlsaRawMidiIn (i->second.c_str());
+ midin = new AlsaRawMidiIn (i->first, i->second.c_str());
} else {
- midin = new AlsaSeqMidiIn (i->second.c_str());
+ midin = new AlsaSeqMidiIn (i->first, i->second.c_str());
}
if (midin->state ()) {
@@ -1390,7 +1441,7 @@ AlsaAudioBackend::register_system_midi_ports()
delete midin;
} else {
char tmp[64];
- snprintf(tmp, sizeof(tmp), "system:midi_capture_%d", ++midi_outs);
+ snprintf(tmp, sizeof(tmp), "system:midi_capture_%d", ++_midi_outs);
PortHandle p = add_port(std::string(tmp), DataType::MIDI, static_cast<PortFlags>(IsOutput | IsPhysical | IsTerminal));
if (!p) {
midin->stop();
diff --git a/libs/backends/alsa/alsa_audiobackend.h b/libs/backends/alsa/alsa_audiobackend.h
index a661aa2979..2233c9be9e 100644
--- a/libs/backends/alsa/alsa_audiobackend.h
+++ b/libs/backends/alsa/alsa_audiobackend.h
@@ -395,7 +395,7 @@ class AlsaAudioBackend : public AudioBackend {
/* port engine */
PortHandle add_port (const std::string& shortname, ARDOUR::DataType, ARDOUR::PortFlags);
int register_system_audio_ports ();
- int register_system_midi_ports ();
+ int register_system_midi_ports (const std::string device = "");
void unregister_ports (bool system_only = false);
std::vector<AlsaPort *> _ports;
@@ -407,6 +407,9 @@ class AlsaAudioBackend : public AudioBackend {
std::vector<AlsaMidiOut *> _rmidi_out;
std::vector<AlsaMidiIn *> _rmidi_in;
+ unsigned _midi_ins;
+ unsigned _midi_outs;
+
struct PortConnectData {
std::string a;
std::string b;
diff --git a/libs/backends/alsa/alsa_midi.h b/libs/backends/alsa/alsa_midi.h
index 7da991d66e..254835591f 100644
--- a/libs/backends/alsa/alsa_midi.h
+++ b/libs/backends/alsa/alsa_midi.h
@@ -42,6 +42,8 @@ public:
virtual void* main_process_thread () = 0;
+ const std::string & name () const { return _name; }
+
protected:
pthread_t _main_thread;
pthread_mutex_t _notify_mutex;
@@ -68,7 +70,8 @@ protected:
RingBuffer<uint8_t>* _rb;
-protected:
+ std::string _name;
+
virtual void init (const char *device_name, const bool input) = 0;
};
diff --git a/libs/backends/alsa/alsa_rawmidi.cc b/libs/backends/alsa/alsa_rawmidi.cc
index e4678ba269..303649b9e7 100644
--- a/libs/backends/alsa/alsa_rawmidi.cc
+++ b/libs/backends/alsa/alsa_rawmidi.cc
@@ -38,10 +38,11 @@ using namespace ARDOUR;
#define _DEBUGPRINT(STR) ;
#endif
-AlsaRawMidiIO::AlsaRawMidiIO (const char *device, const bool input)
+AlsaRawMidiIO::AlsaRawMidiIO (const std::string &name, const char *device, const bool input)
: AlsaMidiIO()
, _device (0)
{
+ _name = name;
init (device, input);
}
@@ -107,8 +108,8 @@ initerr:
///////////////////////////////////////////////////////////////////////////////
-AlsaRawMidiOut::AlsaRawMidiOut (const char *device)
- : AlsaRawMidiIO (device, false)
+AlsaRawMidiOut::AlsaRawMidiOut (const std::string &name, const char *device)
+ : AlsaRawMidiIO (name, device, false)
, AlsaMidiOut ()
{
}
@@ -223,8 +224,8 @@ retry:
///////////////////////////////////////////////////////////////////////////////
-AlsaRawMidiIn::AlsaRawMidiIn (const char *device)
- : AlsaRawMidiIO (device, true)
+AlsaRawMidiIn::AlsaRawMidiIn (const std::string &name, const char *device)
+ : AlsaRawMidiIO (name, device, true)
, AlsaMidiIn ()
, _event(0,0)
, _first_time(true)
diff --git a/libs/backends/alsa/alsa_rawmidi.h b/libs/backends/alsa/alsa_rawmidi.h
index 5d9a86c8db..654f084c4e 100644
--- a/libs/backends/alsa/alsa_rawmidi.h
+++ b/libs/backends/alsa/alsa_rawmidi.h
@@ -33,7 +33,7 @@ namespace ARDOUR {
class AlsaRawMidiIO : virtual public AlsaMidiIO {
public:
- AlsaRawMidiIO (const char *device, const bool input);
+ AlsaRawMidiIO (const std::string &name, const char *device, const bool input);
virtual ~AlsaRawMidiIO ();
protected:
@@ -46,14 +46,14 @@ private:
class AlsaRawMidiOut : public AlsaRawMidiIO, public AlsaMidiOut
{
public:
- AlsaRawMidiOut (const char *device);
+ AlsaRawMidiOut (const std::string &name, const char *device);
void* main_process_thread ();
};
class AlsaRawMidiIn : public AlsaRawMidiIO, public AlsaMidiIn
{
public:
- AlsaRawMidiIn (const char *device);
+ AlsaRawMidiIn (const std::string &name, const char *device);
void* main_process_thread ();
diff --git a/libs/backends/alsa/alsa_sequencer.cc b/libs/backends/alsa/alsa_sequencer.cc
index aa0aac09fa..cb77c3c48d 100644
--- a/libs/backends/alsa/alsa_sequencer.cc
+++ b/libs/backends/alsa/alsa_sequencer.cc
@@ -37,10 +37,11 @@ using namespace ARDOUR;
#define _DEBUGPRINT(STR) ;
#endif
-AlsaSeqMidiIO::AlsaSeqMidiIO (const char *device, const bool input)
+AlsaSeqMidiIO::AlsaSeqMidiIO (const std::string &name, const char *device, const bool input)
: AlsaMidiIO()
, _seq (0)
{
+ _name = name;
init (device, input);
}
@@ -117,8 +118,8 @@ initerr:
///////////////////////////////////////////////////////////////////////////////
-AlsaSeqMidiOut::AlsaSeqMidiOut (const char *device)
- : AlsaSeqMidiIO (device, false)
+AlsaSeqMidiOut::AlsaSeqMidiOut (const std::string &name, const char *device)
+ : AlsaSeqMidiIO (name, device, false)
, AlsaMidiOut ()
{
}
@@ -227,8 +228,8 @@ retry:
///////////////////////////////////////////////////////////////////////////////
-AlsaSeqMidiIn::AlsaSeqMidiIn (const char *device)
- : AlsaSeqMidiIO (device, true)
+AlsaSeqMidiIn::AlsaSeqMidiIn (const std::string &name, const char *device)
+ : AlsaSeqMidiIO (name, device, true)
, AlsaMidiIn ()
{
}
diff --git a/libs/backends/alsa/alsa_sequencer.h b/libs/backends/alsa/alsa_sequencer.h
index bc00751acf..2c27778c97 100644
--- a/libs/backends/alsa/alsa_sequencer.h
+++ b/libs/backends/alsa/alsa_sequencer.h
@@ -33,7 +33,7 @@ namespace ARDOUR {
class AlsaSeqMidiIO : virtual public AlsaMidiIO {
public:
- AlsaSeqMidiIO (const char *port_name, const bool input);
+ AlsaSeqMidiIO (const std::string &name, const char *port_name, const bool input);
virtual ~AlsaSeqMidiIO ();
protected:
@@ -47,14 +47,14 @@ private:
class AlsaSeqMidiOut : public AlsaSeqMidiIO, public AlsaMidiOut
{
public:
- AlsaSeqMidiOut (const char *port_name);
+ AlsaSeqMidiOut (const std::string &name, const char *port_name);
void* main_process_thread ();
};
class AlsaSeqMidiIn : public AlsaSeqMidiIO, public AlsaMidiIn
{
public:
- AlsaSeqMidiIn (const char *port_name);
+ AlsaSeqMidiIn (const std::string &name, const char *port_name);
void* main_process_thread ();
};