From 0f8bd14d3487c35280c33bbfd133dd9e37c8f07e Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sat, 28 Nov 2020 15:58:38 +0100 Subject: Index clients and ports by ID --- src/AlsaDriver.cpp | 10 ++++--- src/ClientID.hpp | 18 ++++++++++++ src/JackDbusDriver.cpp | 80 +++++++++++++++++++++++++++----------------------- src/JackDbusDriver.hpp | 2 +- src/JackDriver.cpp | 38 +++++++++++++++--------- src/PatchageCanvas.cpp | 58 ++++++++++-------------------------- src/PatchageCanvas.hpp | 11 +++---- src/PatchageEvent.cpp | 2 +- src/PatchageEvent.hpp | 4 +-- src/PatchageModule.cpp | 4 +-- src/PatchageModule.hpp | 4 ++- src/PortID.hpp | 42 ++++++++++++++++++++++++++ 12 files changed, 162 insertions(+), 111 deletions(-) diff --git a/src/AlsaDriver.cpp b/src/AlsaDriver.cpp index 3ef466d..702cc00 100644 --- a/src/AlsaDriver.cpp +++ b/src/AlsaDriver.cpp @@ -234,7 +234,7 @@ AlsaDriver::find_or_create_module(Patchage* patchage, m = new PatchageModule( patchage, client_name, type, ClientID::alsa(client_id)); m->load_location(); - _app->canvas()->add_module(client_name, m); + _app->canvas()->add_module(ClientID::alsa(client_id), m); _modules.insert(std::make_pair(client_id, m)); } return m; @@ -292,10 +292,12 @@ AlsaDriver::create_port_view_internal(snd_seq_addr_t addr, split = _app->conf()->get_module_split(client_name, !is_application); } + const auto port_id = PortID::alsa(addr.client, addr.port, is_input); + if (!split) { parent = find_or_create_module( _app, addr.client, client_name, ModuleType::input_output); - if (!parent->get_port(port_name)) { + if (!parent->get_port(port_id)) { port = create_port(*parent, port_name, is_input, addr); port->show(); } @@ -307,7 +309,7 @@ AlsaDriver::create_port_view_internal(snd_seq_addr_t addr, parent = find_or_create_module( _app, addr.client, client_name, module_type); - if (!parent->get_port(port_name)) { + if (!parent->get_port(port_id)) { port = create_port(*parent, port_name, is_input, addr); port->show(); } @@ -318,7 +320,7 @@ AlsaDriver::create_port_view_internal(snd_seq_addr_t addr, ((!is_input) ? ModuleType::input : ModuleType::output); parent = find_or_create_module( _app, addr.client, client_name, flipped_module_type); - if (!parent->get_port(port_name)) { + if (!parent->get_port(port_id)) { port = create_port(*parent, port_name, !is_input, addr); port->show(); } diff --git a/src/ClientID.hpp b/src/ClientID.hpp index 43b56ec..639cbbf 100644 --- a/src/ClientID.hpp +++ b/src/ClientID.hpp @@ -85,6 +85,24 @@ operator<<(std::ostream& os, const ClientID& id) return os; } +static inline bool +operator==(const ClientID& lhs, const ClientID& rhs) +{ + if (lhs.type() != rhs.type()) { + return false; + } + + switch (lhs.type()) { + case ClientID::Type::jack: + return lhs.jack_name() == rhs.jack_name(); + case ClientID::Type::alsa: + return lhs.alsa_id() == rhs.alsa_id(); + } + + assert(false); + return false; +} + static inline bool operator<(const ClientID& lhs, const ClientID& rhs) { diff --git a/src/JackDbusDriver.cpp b/src/JackDbusDriver.cpp index 25ba144..211b6ae 100644 --- a/src/JackDbusDriver.cpp +++ b/src/JackDbusDriver.cpp @@ -28,6 +28,7 @@ PATCHAGE_DISABLE_FMT_WARNINGS #include +#include PATCHAGE_RESTORE_WARNINGS #include @@ -598,22 +599,24 @@ JackDriver::is_attached() const void JackDriver::add_port(PatchageModule* module, PortType type, - PortID id, + const PortID& id, const std::string& name, bool is_input) { - if (module->get_port(name)) { + if (module->get_port(id)) { return; } - new PatchagePort(*module, - type, - std::move(id), - name, - "", // TODO: pretty name - is_input, - _app->conf()->get_port_color(type), - _app->show_human_names()); + auto* port = new PatchagePort(*module, + type, + id, + name, + "", // TODO: pretty name + is_input, + _app->conf()->get_port_color(type), + _app->show_human_names()); + + _app->canvas()->index_port(id, port); } void @@ -663,8 +666,8 @@ JackDriver::remove_port(dbus_uint64_t /*client_id*/, dbus_uint64_t /*port_id*/, const char* port_name) { - PatchagePort* port = - _app->canvas()->find_port_by_name(client_name, port_name); + const auto port_id = PortID::jack(client_name, port_name); + PatchagePort* const port = _app->canvas()->find_port(port_id); if (!port) { error_msg("Unable to remove unknown port"); return; @@ -691,12 +694,13 @@ JackDriver::remove_port(dbus_uint64_t /*client_id*/, PatchageModule* JackDriver::find_or_create_module(ModuleType type, const std::string& name) { - PatchageModule* module = _app->canvas()->find_module(name, type); + const auto id = ClientID::jack(name); + PatchageModule* module = _app->canvas()->find_module(id, type); if (!module) { - module = new PatchageModule(_app, name, type, ClientID::jack(name)); + module = new PatchageModule(_app, name, type, id); module->load_location(); - _app->canvas()->add_module(name, module); + _app->canvas()->add_module(id, module); } return module; @@ -713,23 +717,24 @@ JackDriver::connect_ports(dbus_uint64_t /*connection_id*/, dbus_uint64_t /*port2_id*/, const char* port2_name) { - PatchagePort* port1 = - _app->canvas()->find_port_by_name(client1_name, port1_name); - if (!port1) { - error_msg(std::string{"Unable to connect unknown port '"} + port1_name + - "' of client '" + client1_name + "'"); + const auto tail_id = PortID::jack(client1_name, port1_name); + const auto head_id = PortID::jack(client2_name, port2_name); + + PatchagePort* const tail = _app->canvas()->find_port(tail_id); + if (!tail) { + error_msg( + fmt::format("Unable to connect unknown port \"{}\"", tail_id)); return; } - PatchagePort* port2 = - _app->canvas()->find_port_by_name(client2_name, port2_name); - if (!port2) { - error_msg(std::string{"Unable to connect unknown port '"} + port2_name + - "' of client '" + client2_name + "'"); + PatchagePort* const head = _app->canvas()->find_port(head_id); + if (!head) { + error_msg( + fmt::format("Unable to connect unknown port \"{}\"", head_id)); return; } - _app->canvas()->make_connection(port1, port2); + _app->canvas()->make_connection(tail, head); } void @@ -743,23 +748,24 @@ JackDriver::disconnect_ports(dbus_uint64_t /*connection_id*/, dbus_uint64_t /*port2_id*/, const char* port2_name) { - PatchagePort* port1 = - _app->canvas()->find_port_by_name(client1_name, port1_name); - if (!port1) { - error_msg(std::string{"Unable to disconnect unknown port '"} + - port1_name + "' of client '" + client1_name + "'"); + const auto tail_id = PortID::jack(client1_name, port1_name); + const auto head_id = PortID::jack(client2_name, port2_name); + + PatchagePort* const tail = _app->canvas()->find_port(tail_id); + if (!tail) { + error_msg( + fmt::format("Unable to disconnect unknown port \"{}\"", tail_id)); return; } - PatchagePort* port2 = - _app->canvas()->find_port_by_name(client2_name, port2_name); - if (!port2) { - error_msg(std::string{"Unable to disconnect unknown port '"} + - port2_name + "' of client '" + client2_name + "'"); + PatchagePort* const head = _app->canvas()->find_port(head_id); + if (!head) { + error_msg( + fmt::format("Unable to disconnect unknown port \"{}\"", head_id)); return; } - _app->canvas()->remove_edge_between(port1, port2); + _app->canvas()->remove_edge_between(tail, head); } void diff --git a/src/JackDbusDriver.hpp b/src/JackDbusDriver.hpp index c28c1d5..a92e553 100644 --- a/src/JackDbusDriver.hpp +++ b/src/JackDbusDriver.hpp @@ -81,7 +81,7 @@ private: void add_port(PatchageModule* module, PortType type, - PortID id, + const PortID& id, const std::string& name, bool is_input); diff --git a/src/JackDriver.cpp b/src/JackDriver.cpp index 0d8c2b9..36dfa47 100644 --- a/src/JackDriver.cpp +++ b/src/JackDriver.cpp @@ -137,6 +137,8 @@ JackDriver::create_port_view(Patchage* patchage, const PortID& id) { assert(id.type() == PortID::Type::jack); + const auto client_id = id.client(); + jack_port_t* const jack_port = jack_port_by_name(_client, id.jack_name().c_str()); if (!jack_port) { @@ -161,15 +163,15 @@ JackDriver::create_port_view(Patchage* patchage, const PortID& id) } } - PatchageModule* parent = _app->canvas()->find_module(module_name, type); + PatchageModule* parent = _app->canvas()->find_module(client_id, type); if (!parent) { parent = new PatchageModule( patchage, module_name, type, ClientID::jack(module_name)); parent->load_location(); - patchage->canvas()->add_module(module_name, parent); + patchage->canvas()->add_module(client_id, parent); } - if (parent->get_port(port_name)) { + if (parent->get_port(id)) { _log.error(fmt::format("[JACK] Module \"{}\" already has port \"{}\"", module_name, port_name)); @@ -315,16 +317,18 @@ JackDriver::refresh() } } - PatchageModule* m = _app->canvas()->find_module(client1_name, type); + const auto port1_id = PortID::jack(ports[i]); + const auto client1_id = ClientID::jack(client1_name); + + PatchageModule* m = _app->canvas()->find_module(client1_id, type); if (!m) { - m = new PatchageModule( - _app, client1_name, type, ClientID::jack(client1_name)); + m = new PatchageModule(_app, client1_name, type, client1_id); m->load_location(); - _app->canvas()->add_module(client1_name, m); + _app->canvas()->add_module(client1_id, m); } - if (!m->get_port(jack_port_short_name(port))) { + if (!m->get_port(port1_id)) { create_port(*m, port, PortID::jack(ports[i])); } } @@ -344,8 +348,11 @@ JackDriver::refresh() ? ModuleType::input : ModuleType::output; + const auto port1_id = PortID::jack(ports[i]); + const auto client1_id = ClientID::jack(client1_name); + PatchageModule* client1_module = - _app->canvas()->find_module(client1_name, port1_type); + _app->canvas()->find_module(client1_id, port1_type); if (connected_ports) { for (int j = 0; connected_ports[j]; ++j) { @@ -355,15 +362,18 @@ JackDriver::refresh() port2_name = client2_name.substr(colon + 1); client2_name = client2_name.substr(0, colon); + const auto port2_id = PortID::jack(connected_ports[j]); + const auto client2_id = ClientID::jack(client2_name); + const ModuleType port2_type = (port1_type == ModuleType::input) ? ModuleType::output : ModuleType::input; PatchageModule* client2_module = - _app->canvas()->find_module(client2_name, port2_type); + _app->canvas()->find_module(client2_id, port2_type); - Ganv::Port* port1 = client1_module->get_port(port1_name); - Ganv::Port* port2 = client2_module->get_port(port2_name); + Ganv::Port* port1 = client1_module->get_port(port1_id); + Ganv::Port* port2 = client2_module->get_port(port2_id); if (!port1 || !port2) { continue; @@ -474,9 +484,9 @@ JackDriver::jack_client_registration_cb(const char* name, assert(me->_client); if (registered) { - me->_events.emplace(ClientCreationEvent{name}); + me->_events.emplace(ClientCreationEvent{ClientID::jack(name)}); } else { - me->_events.emplace(ClientDestructionEvent{name}); + me->_events.emplace(ClientDestructionEvent{ClientID::jack(name)}); } } diff --git a/src/PatchageCanvas.cpp b/src/PatchageCanvas.cpp index 167df2b..f31c2f9 100644 --- a/src/PatchageCanvas.cpp +++ b/src/PatchageCanvas.cpp @@ -40,23 +40,18 @@ PatchageCanvas::PatchageCanvas(Connector& connector, int width, int height) } PatchageModule* -PatchageCanvas::find_module(const std::string& name, ModuleType type) +PatchageCanvas::find_module(const ClientID& id, const ModuleType type) { - const ModuleIndex::const_iterator i = _module_index.find(name); - if (i == _module_index.end()) { - return nullptr; - } + auto i = _module_index.find(id); PatchageModule* io_module = nullptr; - for (ModuleIndex::const_iterator j = i; - j != _module_index.end() && j->first == name; - ++j) { - if (j->second->type() == type) { - return j->second; + for (; i != _module_index.end() && i->first == id; ++i) { + if (i->second->type() == type) { + return i->second; } - if (j->second->type() == ModuleType::input_output) { - io_module = j->second; + if (i->second->type() == ModuleType::input_output) { + io_module = i->second; } } @@ -65,13 +60,13 @@ PatchageCanvas::find_module(const std::string& name, ModuleType type) } void -PatchageCanvas::remove_module(const std::string& name) +PatchageCanvas::remove_module(const ClientID& id) { - auto i = _module_index.find(name); + auto i = _module_index.find(id); while (i != _module_index.end()) { PatchageModule* mod = i->second; _module_index.erase(i); - i = _module_index.find(name); + i = _module_index.find(id); delete mod; } } @@ -161,27 +156,6 @@ PatchageCanvas::remove_ports(bool (*pred)(const PatchagePort*)) } } -PatchagePort* -PatchageCanvas::find_port_by_name(const std::string& client_name, - const std::string& port_name) -{ - const ModuleIndex::const_iterator i = _module_index.find(client_name); - if (i == _module_index.end()) { - return nullptr; - } - - for (ModuleIndex::const_iterator j = i; - j != _module_index.end() && j->first == client_name; - ++j) { - PatchagePort* port = j->second->get_port(port_name); - if (port) { - return port; - } - } - - return nullptr; -} - void PatchageCanvas::on_connect(Ganv::Node* port1, Ganv::Node* port2) { @@ -213,18 +187,18 @@ PatchageCanvas::on_disconnect(Ganv::Node* port1, Ganv::Node* port2) } void -PatchageCanvas::add_module(const std::string& name, PatchageModule* module) +PatchageCanvas::add_module(const ClientID& id, PatchageModule* module) { - _module_index.insert(std::make_pair(name, module)); + _module_index.emplace(id, module); // Join partners, if applicable PatchageModule* in_module = nullptr; PatchageModule* out_module = nullptr; if (module->type() == ModuleType::input) { in_module = module; - out_module = find_module(name, ModuleType::output); + out_module = find_module(id, ModuleType::output); } else if (module->type() == ModuleType::output) { - in_module = find_module(name, ModuleType::output); + in_module = find_module(id, ModuleType::output); out_module = module; } @@ -264,8 +238,8 @@ void PatchageCanvas::remove_module(PatchageModule* module) { // Remove module from cache - for (auto i = _module_index.find(module->get_label()); - i != _module_index.end() && i->first == module->get_label(); + for (auto i = _module_index.find(module->id()); + i != _module_index.end() && i->first == module->id(); ++i) { if (i->second == module) { _module_index.erase(i); diff --git a/src/PatchageCanvas.hpp b/src/PatchageCanvas.hpp index 349512b..7f68b9c 100644 --- a/src/PatchageCanvas.hpp +++ b/src/PatchageCanvas.hpp @@ -45,15 +45,12 @@ class PatchageCanvas : public Ganv::Canvas public: PatchageCanvas(Connector& connector, int width, int height); - PatchageModule* find_module(const std::string& name, ModuleType type); + PatchageModule* find_module(const ClientID& id, ModuleType type); PatchagePort* find_port(const PortID& id); - void remove_module(const std::string& name); + void remove_module(const ClientID& id); void remove_module(PatchageModule* module); - PatchagePort* find_port_by_name(const std::string& client_name, - const std::string& port_name); - void index_port(const PortID& id, PatchagePort* port) { _port_index.insert(std::make_pair(id, port)); @@ -61,7 +58,7 @@ public: void remove_ports(bool (*pred)(const PatchagePort*)); - void add_module(const std::string& name, PatchageModule* module); + void add_module(const ClientID& id, PatchageModule* module); bool make_connection(Ganv::Node* tail, Ganv::Node* head); @@ -71,7 +68,7 @@ public: private: using PortIndex = std::map; - using ModuleIndex = std::multimap; + using ModuleIndex = std::multimap; friend void disconnect_edge(GanvEdge*, void*); diff --git a/src/PatchageEvent.cpp b/src/PatchageEvent.cpp index 353bb16..0896b49 100644 --- a/src/PatchageEvent.cpp +++ b/src/PatchageEvent.cpp @@ -57,7 +57,7 @@ public: void operator()(const ClientDestructionEvent& event) { - _patchage.canvas()->remove_module(event.name); + _patchage.canvas()->remove_module(event.id); } void operator()(const PortCreationEvent& event) diff --git a/src/PatchageEvent.hpp b/src/PatchageEvent.hpp index b4aa640..f2fa99d 100644 --- a/src/PatchageEvent.hpp +++ b/src/PatchageEvent.hpp @@ -32,12 +32,12 @@ struct NoopEvent struct ClientCreationEvent { - std::string name; + ClientID id; }; struct ClientDestructionEvent { - std::string name; + ClientID id; }; struct PortCreationEvent diff --git a/src/PatchageModule.cpp b/src/PatchageModule.cpp index 574757f..63a268c 100644 --- a/src/PatchageModule.cpp +++ b/src/PatchageModule.cpp @@ -147,11 +147,11 @@ PatchageModule::menu_disconnect_all() } PatchagePort* -PatchageModule::get_port(const std::string& name) +PatchageModule::get_port(const PortID& id) { for (Ganv::Port* p : *this) { auto* pport = dynamic_cast(p); - if (pport && pport->name() == name) { + if (pport && pport->id() == id) { return pport; } } diff --git a/src/PatchageModule.hpp b/src/PatchageModule.hpp index e5abe43..6953124 100644 --- a/src/PatchageModule.hpp +++ b/src/PatchageModule.hpp @@ -30,6 +30,8 @@ PATCHAGE_RESTORE_WARNINGS #include +struct PortID; + class Patchage; class PatchagePort; @@ -57,7 +59,7 @@ public: bool show_menu(GdkEventButton* ev); void update_menu(); - PatchagePort* get_port(const std::string& name); + PatchagePort* get_port(const PortID& id); void load_location(); void menu_disconnect_all(); diff --git a/src/PortID.hpp b/src/PortID.hpp index 4887a27..e399220 100644 --- a/src/PortID.hpp +++ b/src/PortID.hpp @@ -17,6 +17,7 @@ #ifndef PATCHAGE_PORTID_HPP #define PATCHAGE_PORTID_HPP +#include "ClientID.hpp" #include "ClientType.hpp" #include @@ -44,6 +45,13 @@ struct PortID return PortID{Type::jack, std::move(name)}; } + /// Return an ID for a JACK port by separate client and port name + static PortID + jack(const std::string& client_name, const std::string& port_name) + { + return PortID{Type::jack, client_name + ":" + port_name}; + } + /// Return an ID for an ALSA Sequencer port by ID static PortID alsa(const uint8_t client_id, const uint8_t port, const bool is_input) @@ -51,6 +59,17 @@ struct PortID return PortID{Type::alsa, client_id, port, is_input}; } + /// Return the ID of the client that hosts this port + ClientID client() const + { + switch (_type) { + case Type::jack: + return ClientID::jack(_jack_name.substr(0, _jack_name.find(':'))); + case Type::alsa: + return ClientID::alsa(_alsa_client); + } + } + Type type() const { return _type; } const std::string& jack_name() const { return _jack_name; } uint8_t alsa_client() const { return _alsa_client; } @@ -64,6 +83,8 @@ private: { assert(_type == Type::jack); assert(_jack_name.find(':') != std::string::npos); + assert(_jack_name.find(':') > 0); + assert(_jack_name.find(':') < _jack_name.length() - 1); } PortID(const Type type, @@ -101,6 +122,27 @@ operator<<(std::ostream& os, const PortID& id) return os; } +static inline bool +operator==(const PortID& lhs, const PortID& rhs) +{ + if (lhs.type() != rhs.type()) { + return false; + } + + switch (lhs.type()) { + case PortID::Type::jack: + return lhs.jack_name() == rhs.jack_name(); + case PortID::Type::alsa: + return std::make_tuple( + lhs.alsa_client(), lhs.alsa_port(), lhs.alsa_is_input()) == + std::make_tuple( + rhs.alsa_client(), rhs.alsa_port(), rhs.alsa_is_input()); + } + + assert(false); + return false; +} + static inline bool operator<(const PortID& lhs, const PortID& rhs) { -- cgit v1.2.1