diff options
-rw-r--r-- | src/AlsaDriver.cpp | 71 | ||||
-rw-r--r-- | src/ClientID.hpp | 4 | ||||
-rw-r--r-- | src/JackDbusDriver.cpp | 16 | ||||
-rw-r--r-- | src/JackDriver.cpp | 50 | ||||
-rw-r--r-- | src/PatchageCanvas.cpp | 33 | ||||
-rw-r--r-- | src/PatchageEvent.cpp | 4 | ||||
-rw-r--r-- | src/PatchageEvent.hpp | 29 | ||||
-rw-r--r-- | src/PatchagePort.hpp | 2 | ||||
-rw-r--r-- | src/PortID.hpp | 153 |
9 files changed, 176 insertions, 186 deletions
diff --git a/src/AlsaDriver.cpp b/src/AlsaDriver.cpp index 7cd4f8d..b8dcdc6 100644 --- a/src/AlsaDriver.cpp +++ b/src/AlsaDriver.cpp @@ -31,6 +31,16 @@ PATCHAGE_RESTORE_WARNINGS #include <string> #include <utility> +namespace { + +inline PortID +addr_to_id(const snd_seq_addr_t& addr, bool is_input) +{ + return PortID::alsa(addr.client, addr.port, is_input); +} + +} // namespace + AlsaDriver::AlsaDriver(Patchage* app, ILog& log) : _app(app) , _log(log) @@ -153,8 +163,8 @@ AlsaDriver::refresh() continue; } - PatchagePort* port1 = - _app->canvas()->find_port(PortID(*addr, false)); + PatchagePort* const port1 = _app->canvas()->find_port( + PortID::alsa(addr->client, addr->port, false)); if (!port1) { continue; } @@ -167,7 +177,8 @@ AlsaDriver::refresh() const snd_seq_addr_t* addr2 = snd_seq_query_subscribe_get_addr(subsinfo); if (addr2) { - const PortID id2(*addr2, true); + const PortID id2 = + PortID::alsa(addr2->client, addr2->port, true); PatchagePort* port2 = _app->canvas()->find_port(id2); if (port2 && !_app->canvas()->get_edge(port1, port2)) { _app->canvas()->make_connection(port1, port2); @@ -186,7 +197,8 @@ AlsaDriver::create_port_view(Patchage*, const PortID& id) { PatchageModule* parent = nullptr; PatchagePort* port = nullptr; - create_port_view_internal(id.id.alsa_addr, parent, port); + create_port_view_internal({id.alsa_client(), id.alsa_port()}, parent, port); + return port; } @@ -324,7 +336,7 @@ AlsaDriver::create_port(PatchageModule& parent, bool is_input, snd_seq_addr_t addr) { - const PortID id{addr, is_input}; + const PortID id = PortID::alsa(addr.client, addr.port, is_input); auto* ret = new PatchagePort(parent, @@ -401,14 +413,18 @@ AlsaDriver::connect(const PortID tail_id, const std::string& head_client_name, const std::string& head_port_name) { - if (tail_id.type != PortID::Type::alsa_addr || - head_id.type != PortID::Type::alsa_addr) { + if (tail_id.type() != PortID::Type::alsa || + head_id.type() != PortID::Type::alsa) { _log.error("[ALSA] Attempt to connect non-ALSA ports"); return false; } - const auto& tail_addr = tail_id.id.alsa_addr; - const auto& head_addr = head_id.id.alsa_addr; + const snd_seq_addr_t tail_addr = {tail_id.alsa_client(), + tail_id.alsa_port()}; + + const snd_seq_addr_t head_addr = {head_id.alsa_client(), + head_id.alsa_port()}; + if (tail_addr.client == head_addr.client && tail_addr.port == head_addr.port) { _log.warning("[ALSA] Refusing to connect port to itself"); @@ -467,14 +483,17 @@ AlsaDriver::disconnect(const PortID tail_id, const std::string& head_client_name, const std::string& head_port_name) { - if (tail_id.type != PortID::Type::alsa_addr || - head_id.type != PortID::Type::alsa_addr) { + if (tail_id.type() != PortID::Type::alsa || + head_id.type() != PortID::Type::alsa) { _log.error("[ALSA] Attempt to disconnect non-ALSA ports"); return false; } - const auto& tail_addr = tail_id.id.alsa_addr; - const auto& head_addr = head_id.id.alsa_addr; + const snd_seq_addr_t tail_addr = {tail_id.alsa_client(), + tail_id.alsa_port()}; + + const snd_seq_addr_t head_addr = {head_id.alsa_client(), + head_id.alsa_port()}; snd_seq_port_subscribe_t* subs = nullptr; snd_seq_port_subscribe_malloc(&subs); @@ -581,17 +600,19 @@ AlsaDriver::_refresh_main() case SND_SEQ_EVENT_PORT_SUBSCRIBED: if (!ignore(ev->data.connect.sender) && !ignore(ev->data.connect.dest)) { - _events.push(PatchageEvent(PatchageEvent::Type::connection, - ev->data.connect.sender, - ev->data.connect.dest)); + _events.push( + PatchageEvent(PatchageEvent::Type::connection, + addr_to_id(ev->data.connect.sender, false), + addr_to_id(ev->data.connect.dest, true))); } break; case SND_SEQ_EVENT_PORT_UNSUBSCRIBED: if (!ignore(ev->data.connect.sender) && !ignore(ev->data.connect.dest)) { - _events.push(PatchageEvent(PatchageEvent::Type::disconnection, - ev->data.connect.sender, - ev->data.connect.dest)); + _events.push( + PatchageEvent(PatchageEvent::Type::disconnection, + addr_to_id(ev->data.connect.sender, false), + addr_to_id(ev->data.connect.dest, true))); } break; case SND_SEQ_EVENT_PORT_START: @@ -603,7 +624,7 @@ AlsaDriver::_refresh_main() if (!ignore(ev->data.addr)) { _events.push(PatchageEvent( PatchageEvent::Type::port_creation, - PortID(ev->data.addr, (caps & SND_SEQ_PORT_CAP_READ)))); + addr_to_id(ev->data.addr, (caps & SND_SEQ_PORT_CAP_READ)))); } break; case SND_SEQ_EVENT_PORT_EXIT: @@ -612,15 +633,15 @@ AlsaDriver::_refresh_main() // Delete both inputs and outputs (to handle duplex ports) _events.push( PatchageEvent(PatchageEvent::Type::port_destruction, - PortID(ev->data.addr, true))); + addr_to_id(ev->data.addr, true))); _events.push( PatchageEvent(PatchageEvent::Type::port_destruction, - PortID(ev->data.addr, false))); + addr_to_id(ev->data.addr, false))); + _port_addrs.erase(_app->canvas()->find_port( + addr_to_id(ev->data.addr, false))); _port_addrs.erase( - _app->canvas()->find_port(PortID(ev->data.addr, false))); - _port_addrs.erase( - _app->canvas()->find_port(PortID(ev->data.addr, true))); + _app->canvas()->find_port(addr_to_id(ev->data.addr, true))); } break; case SND_SEQ_EVENT_CLIENT_CHANGE: diff --git a/src/ClientID.hpp b/src/ClientID.hpp index 665c237..d58c5ee 100644 --- a/src/ClientID.hpp +++ b/src/ClientID.hpp @@ -61,14 +61,14 @@ private: assert(_type == Type::jack); } - ClientID(const Type type, uint8_t alsa_id) + ClientID(const Type type, const uint8_t alsa_id) : _type{type} , _alsa_id{alsa_id} { assert(_type == Type::alsa); } - Type _type; ///< Type that determines which field is active + Type _type; ///< Determines which field is active std::string _jack_name{}; ///< Client name for Type::jack uint8_t _alsa_id{}; ///< Client ID for Type::alsa }; diff --git a/src/JackDbusDriver.cpp b/src/JackDbusDriver.cpp index 2ec3dd1..7d3a532 100644 --- a/src/JackDbusDriver.cpp +++ b/src/JackDbusDriver.cpp @@ -54,6 +54,16 @@ PATCHAGE_RESTORE_WARNINGS //#define USE_FULL_REFRESH +namespace { + +std::string +full_name(const std::string& client_name, const std::string& port_name) +{ + return client_name + ":" + port_name; +} + +} // namespace + JackDriver::JackDriver(Patchage* app, ILog& log) : _app(app) , _log(log) @@ -600,7 +610,7 @@ JackDriver::add_port(PatchageModule* module, new PatchagePort(*module, type, - id, + std::move(id), name, "", // TODO: pretty name is_input, @@ -611,7 +621,7 @@ JackDriver::add_port(PatchageModule* module, void JackDriver::add_port(dbus_uint64_t /*client_id*/, const char* client_name, - dbus_uint64_t port_id, + dbus_uint64_t /*port_id*/, const char* port_name, dbus_uint32_t port_flags, dbus_uint32_t port_type) @@ -644,7 +654,7 @@ JackDriver::add_port(dbus_uint64_t /*client_id*/, add_port(module, local_port_type, - PortID{static_cast<jack_port_id_t>(port_id), false}, + PortID::jack(full_name(client_name, port_name)), port_name, port_flags & JACKDBUS_PORT_FLAG_INPUT); } diff --git a/src/JackDriver.cpp b/src/JackDriver.cpp index e20613c..e0b01ff 100644 --- a/src/JackDriver.cpp +++ b/src/JackDriver.cpp @@ -138,12 +138,13 @@ JackDriver::destroy_all() PatchagePort* JackDriver::create_port_view(Patchage* patchage, const PortID& id) { - assert(id.type == PortID::Type::jack_id); + assert(id.type() == PortID::Type::jack); - jack_port_t* jack_port = jack_port_by_id(_client, id.id.jack_id); + jack_port_t* const jack_port = + jack_port_by_name(_client, id.jack_name().c_str()); if (!jack_port) { - _log.error(fmt::format("[JACK] Failed to find port with ID \"{}\"", - id.id.jack_id)); + _log.error(fmt::format("[JACK] Failed to find port with name \"{}\"", + id.jack_name())); return nullptr; } @@ -261,7 +262,7 @@ JackDriver::create_port(PatchageModule& parent, _app->show_human_names(), order); - if (id.type != PortID::Type::nothing) { + if (id.type() != PortID::Type::nothing) { dynamic_cast<PatchageCanvas*>(parent.canvas())->index_port(id, ret); } @@ -280,8 +281,7 @@ JackDriver::shutdown() void JackDriver::refresh() { - const char** ports = nullptr; - jack_port_t* port = nullptr; + jack_port_t* port = nullptr; // Jack can take _client away from us at any time throughout here :/ // Shortest locks possible is the best solution I can figure out @@ -293,8 +293,8 @@ JackDriver::refresh() return; } - ports = - jack_get_ports(_client, nullptr, nullptr, 0); // get all existing ports + // Get all existing ports + const char** ports = jack_get_ports(_client, nullptr, nullptr, 0); if (!ports) { return; @@ -333,7 +333,7 @@ JackDriver::refresh() } if (!m->get_port(jack_port_short_name(port))) { - create_port(*m, port, PortID()); + create_port(*m, port, PortID::jack(ports[i])); } } @@ -407,8 +407,8 @@ JackDriver::port_names(const PortID& id, { jack_port_t* jack_port = nullptr; - if (id.type == PortID::Type::jack_id) { - jack_port = jack_port_by_id(_client, id.id.jack_id); + if (id.type() == PortID::Type::jack) { + jack_port = jack_port_by_name(_client, id.jack_name().c_str()); } if (!jack_port) { @@ -522,12 +522,15 @@ JackDriver::jack_port_registration_cb(jack_port_id_t port_id, auto* me = static_cast<JackDriver*>(jack_driver); assert(me->_client); + jack_port_t* const port = jack_port_by_id(me->_client, port_id); + const char* const name = jack_port_name(port); + if (registered) { - me->_events.push( - PatchageEvent(PatchageEvent::Type::port_creation, port_id)); + me->_events.push(PatchageEvent(PatchageEvent::Type::port_creation, + PortID::jack(name))); } else { - me->_events.push( - PatchageEvent(PatchageEvent::Type::port_destruction, port_id)); + me->_events.push(PatchageEvent(PatchageEvent::Type::port_destruction, + PortID::jack(name))); } } @@ -540,12 +543,19 @@ JackDriver::jack_port_connect_cb(jack_port_id_t src, auto* me = static_cast<JackDriver*>(jack_driver); assert(me->_client); + jack_port_t* const src_port = jack_port_by_id(me->_client, src); + jack_port_t* const dst_port = jack_port_by_id(me->_client, dst); + const char* const src_name = jack_port_name(src_port); + const char* const dst_name = jack_port_name(dst_port); + if (connect) { - me->_events.push( - PatchageEvent(PatchageEvent::Type::connection, src, dst)); + me->_events.push(PatchageEvent(PatchageEvent::Type::connection, + PortID::jack(src_name), + PortID::jack(dst_name))); } else { - me->_events.push( - PatchageEvent(PatchageEvent::Type::disconnection, src, dst)); + me->_events.push(PatchageEvent(PatchageEvent::Type::disconnection, + PortID::jack(src_name), + PortID::jack(dst_name))); } } diff --git a/src/PatchageCanvas.cpp b/src/PatchageCanvas.cpp index 16a85ef..1433244 100644 --- a/src/PatchageCanvas.cpp +++ b/src/PatchageCanvas.cpp @@ -85,44 +85,13 @@ PatchageCanvas::remove_module(const std::string& name) PatchagePort* PatchageCanvas::find_port(const PortID& id) { - PatchagePort* pp = nullptr; - auto i = _port_index.find(id); if (i != _port_index.end()) { assert(i->second->get_module()); return i->second; } -#ifdef PATCHAGE_LIBJACK - // Alsa ports are always indexed (or don't exist at all) - if (id.type == PortID::Type::jack_id) { - jack_port_t* jack_port = - jack_port_by_id(_app->jack_driver()->client(), id.id.jack_id); - if (!jack_port) { - return nullptr; - } - - std::string module_name; - std::string port_name; - _app->jack_driver()->port_names(id, module_name, port_name); - - PatchageModule* module = - find_module(module_name, - (jack_port_flags(jack_port) & JackPortIsInput) - ? ModuleType::input - : ModuleType::output); - - if (module) { - pp = module->get_port(port_name); - } - - if (pp) { - index_port(id, pp); - } - } -#endif // PATCHAGE_LIBJACK - - return pp; + return nullptr; } void diff --git a/src/PatchageEvent.cpp b/src/PatchageEvent.cpp index ce9cd48..abff4b8 100644 --- a/src/PatchageEvent.cpp +++ b/src/PatchageEvent.cpp @@ -56,12 +56,12 @@ PatchageEvent::execute(Patchage* patchage) } else if (_type == Type::port_creation) { Driver* driver = nullptr; - if (_port_1.type == PortID::Type::jack_id) { + if (_port_1.type() == PortID::Type::jack) { #if defined(PATCHAGE_LIBJACK) || defined(HAVE_JACK_DBUS) driver = patchage->jack_driver(); #endif #ifdef HAVE_ALSA - } else if (_port_1.type == PortID::Type::alsa_addr) { + } else if (_port_1.type() == PortID::Type::alsa) { driver = patchage->alsa_driver(); #endif } diff --git a/src/PatchageEvent.hpp b/src/PatchageEvent.hpp index 2bb239a..dca4dbd 100644 --- a/src/PatchageEvent.hpp +++ b/src/PatchageEvent.hpp @@ -22,19 +22,11 @@ #include "PatchagePort.hpp" #include "PortID.hpp" -#ifdef PATCHAGE_LIBJACK -# include <jack/jack.h> -#endif -#ifdef HAVE_ALSA -# include <alsa/asoundlib.h> -#endif - #include <cstring> class Patchage; -/** A Driver event to be processed by the GUI thread. - */ +/// An event from drivers that is processed by the GUI class PatchageEvent { public: @@ -50,25 +42,22 @@ public: disconnection, }; - explicit PatchageEvent(Type type = Type::noop) - : _type(type) - {} - PatchageEvent(Type type, const char* str) : _str(g_strdup(str)) + , _port_1(PortID::nothing()) + , _port_2(PortID::nothing()) , _type(type) {} - template<typename P> - PatchageEvent(Type type, P port) - : _port_1(port) + PatchageEvent(Type type, PortID port) + : _port_1(std::move(port)) + , _port_2(PortID::nothing()) , _type(type) {} - template<typename P> - PatchageEvent(Type type, P port_1, P port_2) - : _port_1(port_1, false) - , _port_2(port_2, true) + PatchageEvent(Type type, PortID tail, PortID head) + : _port_1(std::move(tail)) + , _port_2(std::move(head)) , _type(type) {} diff --git a/src/PatchagePort.hpp b/src/PatchagePort.hpp index 03a6f83..32b0cec 100644 --- a/src/PatchagePort.hpp +++ b/src/PatchagePort.hpp @@ -54,7 +54,7 @@ public: is_input, color) , _type(type) - , _id(id) + , _id(std::move(id)) , _name(name) , _human_name(human_name) , _order(order) diff --git a/src/PortID.hpp b/src/PortID.hpp index 2d41f92..2a53881 100644 --- a/src/PortID.hpp +++ b/src/PortID.hpp @@ -17,126 +17,117 @@ #ifndef PATCHAGE_PORTID_HPP #define PATCHAGE_PORTID_HPP -#include "patchage_config.h" - -#include "PatchagePort.hpp" - -#ifdef PATCHAGE_LIBJACK -# include <jack/jack.h> -#endif -#ifdef HAVE_ALSA -# include <alsa/asoundlib.h> -#endif - -#include <cstring> +#include <cassert> #include <iostream> +#include <string> +#include <tuple> +/// An ID for some port on a client (program) struct PortID { enum class Type { nothing, - jack_id, - alsa_addr, + jack, + alsa, }; - PortID() = default; + PortID(const PortID& copy) = default; + PortID& operator=(const PortID& copy) = default; -#if defined(PATCHAGE_LIBJACK) || defined(HAVE_JACK_DBUS) - explicit PortID(uint32_t jack_id, bool = false) - : type(Type::jack_id) + PortID(PortID&& id) = default; + PortID& operator=(PortID&& id) = default; + + ~PortID() = default; + + /// Return a null ID that refers to nothing + static PortID nothing() { return PortID{}; } + + /// Return an ID for a JACK port by full name (like "client:port") + static PortID jack(std::string name) { - id.jack_id = jack_id; + return PortID{Type::jack, std::move(name)}; } -#endif -#ifdef HAVE_ALSA - PortID(snd_seq_addr_t addr, bool in) - : type(Type::alsa_addr) + /// 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) { - id.alsa_addr = addr; - id.is_input = in; + return PortID{Type::alsa, client_id, port, is_input}; } -#endif - PortID(const PortID& copy) = default; - PortID& operator=(const PortID& copy) = default; - - PortID(PortID&& id) = default; - PortID& operator=(PortID&& id) = default; + Type type() const { return _type; } + const std::string& jack_name() const { return _jack_name; } + uint8_t alsa_client() const { return _alsa_client; } + uint8_t alsa_port() const { return _alsa_port; } + bool alsa_is_input() const { return _alsa_is_input; } - ~PortID() = default; +private: + PortID() = default; - Type type = Type::nothing; + PortID(const Type type, std::string jack_name) + : _type{type} + , _jack_name{std::move(jack_name)} + { + assert(_type == Type::jack); + } - union + PortID(const Type type, + const uint8_t alsa_client, + const uint8_t alsa_port, + const bool is_input) + : _type{type} + , _alsa_client{alsa_client} + , _alsa_port{alsa_port} + , _alsa_is_input{is_input} { -#if defined(PATCHAGE_LIBJACK) || defined(HAVE_JACK_DBUS) - uint32_t jack_id; -#endif -#ifdef HAVE_ALSA - struct - { - snd_seq_addr_t alsa_addr; - bool is_input : 1; - }; -#endif - } id = {}; + assert(_type == Type::alsa); + } + + Type _type{Type::nothing}; ///< Determines which field is active + std::string _jack_name{}; ///< Full port name for Type::jack + uint8_t _alsa_client{}; ///< Client ID for Type::alsa + uint8_t _alsa_port{}; ///< Port ID for Type::alsa + bool _alsa_is_input{}; ///< Input flag for Type::alsa }; static inline std::ostream& operator<<(std::ostream& os, const PortID& id) { - switch (id.type) { + switch (id.type()) { case PortID::Type::nothing: return os << "(null)"; - case PortID::Type::jack_id: -#ifdef PATCHAGE_LIBJACK - return os << "jack:" << id.id.jack_id; -#endif - break; - case PortID::Type::alsa_addr: -#ifdef HAVE_ALSA - return os << "alsa:" << int(id.id.alsa_addr.client) << ":" - << int(id.id.alsa_addr.port) << ":" - << (id.id.is_input ? "in" : "out"); -#endif - break; + case PortID::Type::jack: + return os << "jack:" << id.jack_name(); + case PortID::Type::alsa: + return os << "alsa:" << int(id.alsa_client()) << ":" + << int(id.alsa_port()) << ":" + << (id.alsa_is_input() ? "in" : "out"); } + assert(false); return os; } static inline bool -operator<(const PortID& a, const PortID& b) +operator<(const PortID& lhs, const PortID& rhs) { - if (a.type != b.type) { - return a.type < b.type; + if (lhs.type() != rhs.type()) { + return lhs.type() < rhs.type(); } - switch (a.type) { + switch (lhs.type()) { case PortID::Type::nothing: return true; - case PortID::Type::jack_id: -#if defined(PATCHAGE_LIBJACK) || defined(HAVE_JACK_DBUS) - return a.id.jack_id < b.id.jack_id; -#endif - break; - case PortID::Type::alsa_addr: -#ifdef HAVE_ALSA - if ((a.id.alsa_addr.client < b.id.alsa_addr.client) || - ((a.id.alsa_addr.client == b.id.alsa_addr.client) && - a.id.alsa_addr.port < b.id.alsa_addr.port)) { - return true; - } else if (a.id.alsa_addr.client == b.id.alsa_addr.client && - a.id.alsa_addr.port == b.id.alsa_addr.port) { - return (a.id.is_input < b.id.is_input); - } else { - return false; - } -#endif - break; + 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; } |