second attempt at fixing the launchpad pro port name mess
It turns out that slightly older versions of ALSA create different "pretty" port names for USB MIDI devices than slightly newer ones. The new versions use names that match those seen on other platforms. This means that to do port matching on Linux now requires a regexp to match the possible alternatives. This matters much more for the LPP, which has 3 input ports and 3 output ports, than it does for most devices that have a single input and single output, and we can "find" the ports just using simple string searching
This commit is contained in:
parent
c90dc9a647
commit
1d6c2a946d
|
@ -16,6 +16,8 @@
|
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <regex>
|
||||
|
||||
#include "pbd/debug.h"
|
||||
#include "pbd/i18n.h"
|
||||
|
||||
|
@ -167,20 +169,79 @@ MIDISurface::port_registration_handler ()
|
|||
return;
|
||||
}
|
||||
|
||||
std::vector<std::string> in;
|
||||
std::vector<std::string> out;
|
||||
std::vector<std::string> midi_inputs;
|
||||
std::vector<std::string> midi_outputs;
|
||||
|
||||
AudioEngine::instance()->get_ports (string_compose (".*%1", input_port_name()), DataType::MIDI, PortFlags (IsPhysical|IsOutput), in);
|
||||
AudioEngine::instance()->get_ports (string_compose (".*%1", output_port_name()), DataType::MIDI, PortFlags (IsPhysical|IsInput), out);
|
||||
AudioEngine::instance()->get_ports ("", DataType::MIDI, PortFlags (IsPhysical|IsOutput), midi_inputs);
|
||||
AudioEngine::instance()->get_ports ("", DataType::MIDI, PortFlags (IsPhysical|IsInput), midi_outputs);
|
||||
|
||||
if (!in.empty() && !out.empty()) {
|
||||
if (!_async_in->connected()) {
|
||||
AudioEngine::instance()->connect (_async_in->name(), in.front());
|
||||
if (midi_inputs.empty() || midi_outputs.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Try to find the input & output ports, whose pretty name varies on
|
||||
* Linux depending on the version of ALSA, but is fairly consistent
|
||||
* across newer ALSA and other platforms.
|
||||
*/
|
||||
|
||||
/* See if the input port is available, and maybe connect that */
|
||||
|
||||
string ip = input_port_name ();
|
||||
|
||||
if (ip[0] == ':') {
|
||||
std::regex rx (ip.substr (1), std::regex::extended);
|
||||
|
||||
auto is_the_input = [&rx](string const &s) {
|
||||
std::string pn = AudioEngine::instance()->get_hardware_port_name_by_name(s);
|
||||
return std::regex_search (pn, rx);
|
||||
};
|
||||
|
||||
auto pi = std::find_if (midi_inputs.begin(), midi_inputs.end(), is_the_input);
|
||||
if (pi != midi_inputs.end()) {
|
||||
AudioEngine::instance()->connect (_async_in->name(), *pi);
|
||||
}
|
||||
if (!_async_out->connected()) {
|
||||
AudioEngine::instance()->connect (_async_out->name(), out.front());
|
||||
} else {
|
||||
/* regular partial string search */
|
||||
auto is_the_input = [&ip](string const &s) {
|
||||
std::string pn = AudioEngine::instance()->get_hardware_port_name_by_name(s);
|
||||
return pn.find (ip) != string::npos;
|
||||
};
|
||||
|
||||
auto pi = std::find_if (midi_inputs.begin(), midi_inputs.end(), is_the_input);
|
||||
if (pi != midi_inputs.end()) {
|
||||
AudioEngine::instance()->connect (_async_in->name(), *pi);
|
||||
}
|
||||
}
|
||||
|
||||
/* Now see if the output port is available, and maybe connect that */
|
||||
|
||||
string op = output_port_name ();
|
||||
|
||||
if (op[0] == ':') {
|
||||
std::regex rx (op.substr (1), std::regex::extended);
|
||||
|
||||
auto is_the_output = [&rx](string const &s) {
|
||||
std::string pn = AudioEngine::instance()->get_hardware_port_name_by_name(s);
|
||||
return std::regex_search (pn, rx);
|
||||
};
|
||||
|
||||
auto po = std::find_if (midi_outputs.begin(), midi_outputs.end(), is_the_output);
|
||||
if (po != midi_outputs.end()) {
|
||||
AudioEngine::instance()->connect (_async_in->name(), *po);
|
||||
}
|
||||
} else {
|
||||
/* regular partial string search */
|
||||
auto is_the_output = [&op](string const &s) {
|
||||
std::string pn = AudioEngine::instance()->get_hardware_port_name_by_name(s);
|
||||
return pn.find (op) != string::npos;
|
||||
};
|
||||
|
||||
auto po = std::find_if (midi_outputs.begin(), midi_outputs.end(), is_the_output);
|
||||
if (po != midi_outputs.end()) {
|
||||
AudioEngine::instance()->connect (_async_in->name(), *po);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -442,4 +503,3 @@ MIDISurface::bundles ()
|
|||
|
||||
return b;
|
||||
}
|
||||
|
||||
|
|
|
@ -58,6 +58,17 @@ class MIDISurface : public ARDOUR::ControlProtocol
|
|||
|
||||
ARDOUR::Session & get_session() { return *session; }
|
||||
|
||||
/* These two names are used in a port registration handler to try to
|
||||
automatically connect the device when it is discovered.
|
||||
|
||||
If the value returned by these methods begins with a colon, they
|
||||
will be assumed to be regular expressions, and passed (without the
|
||||
leading colon) into the constructor of a std::regex using
|
||||
std::regex::extended syntax.
|
||||
|
||||
Otherwise, they are assumed to be unique string identifiers, and are
|
||||
merely searched for in port names with std::string::find().
|
||||
*/
|
||||
virtual std::string input_port_name () const = 0;
|
||||
virtual std::string output_port_name () const = 0;
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <bitset>
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <regex>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
@ -110,15 +111,26 @@ LaunchPadPro::probe (std::string& i, std::string& o)
|
|||
{
|
||||
vector<string> midi_inputs;
|
||||
vector<string> midi_outputs;
|
||||
AudioEngine::instance()->get_ports (string_compose (".*%1", input_port_regex()), DataType::MIDI, PortFlags (IsOutput|IsTerminal), midi_inputs);
|
||||
AudioEngine::instance()->get_ports (string_compose (".*%1", output_port_regex()), DataType::MIDI, PortFlags (IsInput|IsTerminal), midi_outputs);
|
||||
|
||||
AudioEngine::instance()->get_ports ("", DataType::MIDI, PortFlags (IsOutput|IsTerminal), midi_inputs);
|
||||
AudioEngine::instance()->get_ports("", DataType::MIDI, PortFlags(IsInput | IsTerminal), midi_outputs);
|
||||
|
||||
if (midi_inputs.empty() || midi_outputs.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
i = midi_inputs.front();
|
||||
o = midi_inputs.front();
|
||||
std::regex rx (X_("Launchpad Pro MK3.*MIDI"));
|
||||
|
||||
auto has_lppro = [&rx](string const &s) {
|
||||
std::string pn = AudioEngine::instance()->get_hardware_port_name_by_name(s);
|
||||
return std::regex_search (pn, rx);
|
||||
};
|
||||
|
||||
auto pi = std::find_if (midi_inputs.begin(), midi_inputs.end(), has_lppro);
|
||||
auto po = std::find_if (midi_outputs.begin (), midi_outputs.end (), has_lppro);
|
||||
|
||||
i = *pi;
|
||||
o = *po;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -322,53 +334,13 @@ LaunchPadPro::set_state (const XMLNode & node, int version)
|
|||
std::string
|
||||
LaunchPadPro::input_port_name () const
|
||||
{
|
||||
return input_port_regex();
|
||||
}
|
||||
|
||||
std::string
|
||||
LaunchPadPro::input_port_regex ()
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
return X_("Launchpad Pro MK3.*MIDI In");
|
||||
#else
|
||||
return X_("Launchpad Pro MK3.*MIDI 1");
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string
|
||||
LaunchPadPro::input_daw_port_regex ()
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
return X_("Launchpad Pro MK3.*DAW");
|
||||
#else
|
||||
return X_("Launchpad Pro MK3.*MIDI 3");
|
||||
#endif
|
||||
return X_(":Launchpad Pro MK3.*MIDI (In|1)");
|
||||
}
|
||||
|
||||
std::string
|
||||
LaunchPadPro::output_port_name () const
|
||||
{
|
||||
return output_port_regex();
|
||||
}
|
||||
|
||||
std::string
|
||||
LaunchPadPro::output_port_regex()
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
return X_("Launchpad Pro MK3.*MIDI Out");
|
||||
#else
|
||||
return X_("Launchpad Pro MK3.*MIDI 1");
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string
|
||||
LaunchPadPro::output_daw_port_regex ()
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
return X_("Launchpad Pro MK3.*DAW");
|
||||
#else
|
||||
return X_("Launchpad Pro MK3.*MIDI 3");
|
||||
#endif
|
||||
return X_(":Launchpad Pro MK3.*MIDI (Out|1)");
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -856,21 +828,40 @@ LaunchPadPro::connect_daw_ports ()
|
|||
return;
|
||||
}
|
||||
|
||||
std::vector<std::string> in;
|
||||
std::vector<std::string> out;
|
||||
AudioEngine::instance()->get_ports (string_compose (".*%1", input_daw_port_regex()), DataType::MIDI, PortFlags (IsPhysical|IsOutput), in);
|
||||
AudioEngine::instance()->get_ports (string_compose (".*%1", output_daw_port_regex()), DataType::MIDI, PortFlags (IsPhysical|IsInput), out);
|
||||
std::vector<std::string> midi_inputs;
|
||||
std::vector<std::string> midi_outputs;
|
||||
|
||||
if (!in.empty() && !out.empty()) {
|
||||
/* get all MIDI Ports */
|
||||
|
||||
if (!_daw_in->connected()) {
|
||||
AudioEngine::instance()->connect (_daw_in->name(), in.front());
|
||||
}
|
||||
AudioEngine::instance()->get_ports ("", DataType::MIDI, PortFlags (IsOutput|IsTerminal), midi_inputs);
|
||||
AudioEngine::instance()->get_ports("", DataType::MIDI, PortFlags(IsInput | IsTerminal), midi_outputs);
|
||||
|
||||
if (!_daw_out->connected()) {
|
||||
AudioEngine::instance()->connect (_daw_out->name(), out.front());
|
||||
}
|
||||
if (midi_inputs.empty() || midi_outputs.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Try to find the DAW port, whose pretty name varies on Linux
|
||||
* depending on the version of ALSA, but is fairly consistent across
|
||||
* newer ALSA and other platforms.
|
||||
*/
|
||||
|
||||
std::regex rx (X_("Launchpad Pro MK3.*(DAW|MIDI 3)"), std::regex::extended);
|
||||
|
||||
auto is_dawport = [&rx](string const &s) {
|
||||
std::string pn = AudioEngine::instance()->get_hardware_port_name_by_name(s);
|
||||
return std::regex_search (pn, rx);
|
||||
};
|
||||
|
||||
auto pi = std::find_if (midi_inputs.begin(), midi_inputs.end(), is_dawport);
|
||||
auto po = std::find_if (midi_outputs.begin (), midi_outputs.end (), is_dawport);
|
||||
|
||||
if (!_daw_in->connected()) {
|
||||
AudioEngine::instance()->connect (_daw_in->name(), *pi);
|
||||
}
|
||||
|
||||
if (!_daw_out->connected()) {
|
||||
AudioEngine::instance()->connect (_daw_out->name(), *po);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -1074,7 +1065,7 @@ LaunchPadPro::stripable_selection_changed ()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -292,10 +292,6 @@ class LaunchPadPro : public MIDISurface
|
|||
void port_registration_handler ();
|
||||
int ports_acquire ();
|
||||
void ports_release ();
|
||||
static std::string input_port_regex ();
|
||||
static std::string output_port_regex ();
|
||||
static std::string input_daw_port_regex ();
|
||||
static std::string output_daw_port_regex ();
|
||||
void connect_daw_ports ();
|
||||
|
||||
void daw_write (const MidiByteArray&);
|
||||
|
|
Loading…
Reference in New Issue
Block a user