From f7802325dcf07b6dec4061d0bd413ed6f09a4e8c Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Thu, 7 Mar 2019 12:00:51 -0700 Subject: redesign naming and reload of MIDI port information (library edition) --- libs/ardour/ardour/port_manager.h | 11 +++- libs/ardour/port_manager.cc | 131 +++++++++++++++++++++++++------------- 2 files changed, 94 insertions(+), 48 deletions(-) (limited to 'libs/ardour') diff --git a/libs/ardour/ardour/port_manager.h b/libs/ardour/ardour/port_manager.h index e2a932e0d9..268c166b13 100644 --- a/libs/ardour/ardour/port_manager.h +++ b/libs/ardour/ardour/port_manager.h @@ -101,6 +101,8 @@ class LIBARDOUR_API PortManager int get_ports (const std::string& port_name_pattern, DataType type, PortFlags flags, std::vector&); int get_ports (DataType, PortList&); + void set_port_pretty_name (std::string const&, std::string const&); + void remove_all_ports (); void clear_pending_port_deletions (); virtual void add_pending_port_deletion (Port*) = 0; @@ -134,11 +136,17 @@ class LIBARDOUR_API PortManager bool port_remove_in_progress() const { return _port_remove_in_progress; } struct MidiPortInformation { + std::string canonical_name; std::string pretty_name; bool input; MidiPortFlags properties; + bool exists; - MidiPortInformation () : input (false) , properties (MidiPortFlags (0)) {} + MidiPortInformation (std::string const & canonical, bool input, MidiPortFlags flags, bool xists) + : canonical_name (canonical) + , input (input) + , properties (flags) + , exists (xists) {} }; void fill_midi_port_info (); @@ -148,7 +156,6 @@ class LIBARDOUR_API PortManager void get_midi_selection_ports (std::vector&); void add_midi_port_flags (std::string const&, MidiPortFlags); void remove_midi_port_flags (std::string const&, MidiPortFlags); - void set_midi_port_pretty_name (std::string const&, std::string const&); /** Emitted if the list of ports to be used for MIDI selection tracking changes */ PBD::Signal0 MidiSelectionPortsChanged; diff --git a/libs/ardour/port_manager.cc b/libs/ardour/port_manager.cc index 85aa9819d6..ae0dd5d838 100644 --- a/libs/ardour/port_manager.cc +++ b/libs/ardour/port_manager.cc @@ -17,6 +17,8 @@ */ +#include + #ifdef COMPILER_MSVC #include // Microsoft's nearest equivalent to #include @@ -28,6 +30,7 @@ #include #include "pbd/error.h" +#include "pbd/strsplit.h" #include "ardour/async_midi_port.h" #include "ardour/audio_backend.h" @@ -49,6 +52,8 @@ using namespace PBD; using std::string; using std::vector; +#define MIDI_PORT_INFO_SEPARATOR_CHAR '!' + PortManager::PortManager () : ports (new Ports) , _port_remove_in_progress (false) @@ -143,17 +148,16 @@ std::string PortManager::get_pretty_name_by_name(const std::string& portname) const { PortEngine::PortHandle ph = _backend->get_port_by_name (portname); + if (ph) { std::string value; std::string type; - if (0 == _backend->get_port_property (ph, - "http://jackaudio.org/metadata/pretty-name", - value, type)) - { + if (0 == _backend->get_port_property (ph, "http://jackaudio.org/metadata/pretty-name", value, type)) { return value; } } - return ""; + + return string(); } bool @@ -1010,7 +1014,7 @@ PortManager::midi_port_information (std::string const & name) return x->second; } - return MidiPortInformation (); + return MidiPortInformation (string(), false, MidiPortFlags(0), false); } void @@ -1040,8 +1044,9 @@ PortManager::get_midi_selection_ports (vector& copy) } void -PortManager::set_midi_port_pretty_name (string const & port, string const & pretty) +PortManager::set_port_pretty_name (string const & port, string const & pretty) { + bool emit = false; { Glib::Threads::Mutex::Lock lm (midi_port_info_mutex); @@ -1052,6 +1057,7 @@ PortManager::set_midi_port_pretty_name (string const & port, string const & pret return; } x->second.pretty_name = pretty; + emit = true; } /* push into back end */ @@ -1062,7 +1068,9 @@ PortManager::set_midi_port_pretty_name (string const & port, string const & pret _backend->set_port_property (ph, "http://jackaudio.org/metadata/pretty-name", pretty, string()); } - MidiPortInfoChanged (); /* EMIT SIGNAL*/ + if (emit) { + MidiPortInfoChanged (); /* EMIT SIGNAL*/ + } } void @@ -1153,6 +1161,7 @@ PortManager::save_midi_port_info () for (MidiPortInfo::iterator i = midi_port_info.begin(); i != midi_port_info.end(); ++i) { XMLNode* node = new XMLNode (X_("port")); node->set_property (X_("name"), i->first); + node->set_property (X_("canonical-name"), i->second.canonical_name); node->set_property (X_("input"), i->second.input); node->set_property (X_("properties"), i->second.properties); root->add_child_nocopy (*node); @@ -1186,15 +1195,21 @@ PortManager::load_midi_port_info () midi_port_info.clear (); for (XMLNodeConstIterator i = tree.root()->children().begin(); i != tree.root()->children().end(); ++i) { - MidiPortInformation mpi; string name; + string canonical; + bool input; + MidiPortFlags properties; + if (!(*i)->get_property (X_("name"), name) || - !(*i)->get_property (X_("input"), mpi.input) || - !(*i)->get_property (X_("properties"), mpi.properties)) { + !(*i)->get_property (X_("canonical-name"), canonical) || + !(*i)->get_property (X_("input"), input) || + !(*i)->get_property (X_("properties"), properties)) { continue; } + MidiPortInformation mpi (canonical, input, properties, false); + midi_port_info.insert (make_pair (name, mpi)); } } @@ -1202,8 +1217,12 @@ PortManager::load_midi_port_info () void PortManager::fill_midi_port_info () { - Glib::Threads::Mutex::Lock lm (midi_port_info_mutex); - fill_midi_port_info_locked (); + { + Glib::Threads::Mutex::Lock lm (midi_port_info_mutex); + fill_midi_port_info_locked (); + } + + save_midi_port_info (); } void @@ -1211,7 +1230,7 @@ PortManager::fill_midi_port_info_locked () { /* MIDI info mutex MUST be held */ - if (!midi_info_dirty) { + if (!midi_info_dirty || !_backend) { return; } @@ -1226,17 +1245,20 @@ PortManager::fill_midi_port_info_locked () } if (midi_port_info.find (*p) == midi_port_info.end()) { - MidiPortInformation mpi; - mpi.pretty_name = *p; - mpi.input = true; + + MidiPortFlags flags (MidiPortFlags (0)); if (port_is_control_only (*p)) { - mpi.properties = MidiPortFlags (mpi.properties | MidiPortControl); + flags = MidiPortControl; } + + MidiPortInformation mpi (string_compose ("%1%4%2%4%3", _backend->name(), _backend->device_name(), *p, MIDI_PORT_INFO_SEPARATOR_CHAR), + true, + flags, + true); + #ifdef LINUX - if ((*p.find (X_("Midi Through")) != string::npos || - (*p).find (X_("Midi-Through")) != string::npos)) - { + if ((*p.find (X_("Midi Through")) != string::npos || (*p).find (X_("Midi-Through")) != string::npos)) { mpi.properties = MidiPortFlags (mpi.properties | MidiPortVirtual); } #endif @@ -1253,17 +1275,20 @@ PortManager::fill_midi_port_info_locked () } if (midi_port_info.find (*p) == midi_port_info.end()) { - MidiPortInformation mpi; - mpi.pretty_name = *p; - mpi.input = false; + + MidiPortFlags flags (MidiPortFlags (0)); if (port_is_control_only (*p)) { - mpi.properties = MidiPortFlags (mpi.properties | MidiPortControl); + flags = MidiPortControl; } + + MidiPortInformation mpi (string_compose ("%1%4%2%4%3", _backend->name(), _backend->device_name(), *p, MIDI_PORT_INFO_SEPARATOR_CHAR), + false, + flags, + true); + #ifdef LINUX - if ((*p.find (X_("Midi Through")) != string::npos || - (*p).find (X_("Midi-Through")) != string::npos)) - { + if ((*p.find (X_("Midi Through")) != string::npos || (*p).find (X_("Midi-Through")) != string::npos)) { mpi.properties = MidiPortFlags (mpi.properties | MidiPortVirtual); } #endif @@ -1271,35 +1296,49 @@ PortManager::fill_midi_port_info_locked () } } - /* now push/pull pretty name information between backend and the - * PortManager + /* now check with backend about which ports are present and pull + * pretty-name if it exists */ - // rg: I don't understand what this attempts to solve - // - // Naming ports should be left to the backend: - // Ardour cannot associate numeric IDs with corresponding hardware. - // (see also 7dde6c3b) - for (MidiPortInfo::iterator x = midi_port_info.begin(); x != midi_port_info.end(); ++x) { - PortEngine::PortHandle ph = _backend->get_port_by_name (x->first); + + vector parts; + + /*PBD::*/split (x->second.canonical_name, parts, MIDI_PORT_INFO_SEPARATOR_CHAR); + assert (parts.size() == 3); + + if (parts[0] != _backend->name()) { + x->second.exists = false; + continue; + } + + if (parts[1] != _backend->device_name()) { + x->second.exists = false; + continue; + } + + PortEngine::PortHandle ph = _backend->get_port_by_name (parts[2]); if (!ph) { /* port info saved from some condition where this port * existed, but no longer does (i.e. device unplugged * at present). We don't remove it from midi_port_info. */ - continue; - } + x->second.exists = false; - /* check with backend for pre-existing pretty name */ - string value; - string type; + } else { + x->second.exists = true; + /* check with backend for pre-existing pretty name */ + + string value; + + value = AudioEngine::instance()->get_pretty_name_by_name (x->first); - if (0 == _backend->get_port_property (ph, - "http://jackaudio.org/metadata/pretty-name", - value, type)) { - x->second.pretty_name = value; + if (!value.empty()) { + x->second.pretty_name = value; + } else { + x->second.pretty_name = parts[2]; + } } } -- cgit v1.2.3