diff options
Diffstat (limited to 'src/JackDriver.cpp')
-rw-r--r-- | src/JackDriver.cpp | 244 |
1 files changed, 39 insertions, 205 deletions
diff --git a/src/JackDriver.cpp b/src/JackDriver.cpp index a491453..cfcc541 100644 --- a/src/JackDriver.cpp +++ b/src/JackDriver.cpp @@ -21,8 +21,6 @@ #include "Patchage.hpp" #include "PatchageCanvas.hpp" #include "PatchageEvent.hpp" -#include "PatchageModule.hpp" -#include "PatchagePort.hpp" #include "PortNames.hpp" #include "PortType.hpp" #include "SignalDirection.hpp" @@ -45,10 +43,10 @@ PATCHAGE_RESTORE_WARNINGS #include <cstring> #include <set> #include <string> +#include <unordered_set> -JackDriver::JackDriver(Patchage* app, ILog& log) - : _app(app) - , _log(log) +JackDriver::JackDriver(ILog& log) + : _log(log) , _client(nullptr) , _last_pos{} , _buffer_size(0) @@ -119,78 +117,6 @@ JackDriver::detach() _log.info("[JACK] Detached"); } -static bool -is_jack_port(const PatchagePort* port) -{ - return (port->type() == PortType::jack_audio || - port->type() == PortType::jack_midi || - port->type() == PortType::jack_osc || - port->type() == PortType::jack_cv); -} - -void -JackDriver::destroy_all() -{ - if (_app->canvas()) { - _app->canvas()->remove_ports(is_jack_port); - } -} - -PatchagePort* -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) { - _log.error(fmt::format("[JACK] Failed to find port with name \"{}\"", - id.jack_name())); - return nullptr; - } - - const int jack_flags = jack_port_flags(jack_port); - - std::string module_name; - std::string port_name; - port_names(id, module_name, port_name); - - SignalDirection type = SignalDirection::duplex; - if (_app->conf()->get_module_split(module_name, - (jack_flags & JackPortIsTerminal))) { - if (jack_flags & JackPortIsInput) { - type = SignalDirection::input; - } else { - type = SignalDirection::output; - } - } - - 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(client_id, parent); - } - - if (parent->get_port(id)) { - _log.error(fmt::format("[JACK] Module \"{}\" already has port \"{}\"", - module_name, - port_name)); - return nullptr; - } - - PatchagePort* port = create_port(*parent, jack_port, id); - port->show(); - if (port->is_input()) { - parent->set_is_source(false); - } - - return port; -} - static std::string get_property(const jack_uuid_t subject, const char* const key) { @@ -266,32 +192,6 @@ JackDriver::get_port_info(const jack_port_t* const port) return {label, type, direction, order, bool(flags & JackPortIsTerminal)}; } -PatchagePort* -JackDriver::create_port(PatchageModule& parent, - jack_port_t* port, - const PortID& id) -{ - if (!port) { - return nullptr; - } - - const auto info = get_port_info(port); - - auto* ret = new PatchagePort(parent, - info.type, - id, - jack_port_short_name(port), - info.label, - (jack_port_flags(port) & JackPortIsInput), - _app->conf()->get_port_color(info.type), - _app->show_human_names(), - info.order); - - _app->canvas()->index_port(id, ret); - - return ret; -} - void JackDriver::shutdown() { @@ -299,133 +199,67 @@ JackDriver::shutdown() } void -JackDriver::refresh() +JackDriver::refresh(const EventSink& sink) { - 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 - std::lock_guard<std::mutex> lock{_shutdown_mutex}; - if (_client == nullptr) { + if (!_client) { shutdown(); return; } // Get all existing ports - const char** ports = jack_get_ports(_client, nullptr, nullptr, 0); - + const char** const ports = jack_get_ports(_client, nullptr, nullptr, 0); if (!ports) { return; } - std::string client1_name; - std::string port1_name; - std::string client2_name; - std::string port2_name; - size_t colon = std::string::npos; - - // Add all ports - for (int i = 0; ports[i]; ++i) { - port = jack_port_by_name(_client, ports[i]); - - client1_name = ports[i]; - client1_name = client1_name.substr(0, client1_name.find(':')); - - SignalDirection type = SignalDirection::duplex; - if (_app->conf()->get_module_split( - client1_name, (jack_port_flags(port) & JackPortIsTerminal))) { - if (jack_port_flags(port) & JackPortIsInput) { - type = SignalDirection::input; - } else { - type = SignalDirection::output; - } - } - - 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, client1_id); - m->load_location(); - _app->canvas()->add_module(client1_id, m); - } - - if (!m->get_port(port1_id)) { - create_port(*m, port, PortID::jack(ports[i])); - } + // Get all client names (to only send a creation event once for each) + std::unordered_set<std::string> client_names; + for (auto i = 0u; ports[i]; ++i) { + client_names.insert(PortID::jack(ports[i]).client().jack_name()); } - // Add all connections - for (int i = 0; ports[i]; ++i) { - port = jack_port_by_name(_client, ports[i]); - const char** connected_ports = - jack_port_get_all_connections(_client, port); - - client1_name = ports[i]; - colon = client1_name.find(':'); - port1_name = client1_name.substr(colon + 1); - client1_name = client1_name.substr(0, colon); - - const SignalDirection port1_type = - (jack_port_flags(port) & JackPortIsInput) ? SignalDirection::input - : SignalDirection::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_id, port1_type); - - if (connected_ports) { - for (int j = 0; connected_ports[j]; ++j) { - - client2_name = connected_ports[j]; - colon = client2_name.find(':'); - 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 SignalDirection port2_type = - (port1_type == SignalDirection::input) - ? SignalDirection::output - : SignalDirection::input; - - PatchageModule* client2_module = - _app->canvas()->find_module(client2_id, port2_type); + // Emit all clients + for (const auto& client_name : client_names) { + sink({ClientCreationEvent{ClientID::jack(client_name), + get_client_info(client_name.c_str())}}); + } - Ganv::Port* port1 = client1_module->get_port(port1_id); - Ganv::Port* port2 = client2_module->get_port(port2_id); + // Emit all ports + for (auto i = 0u; ports[i]; ++i) { + const jack_port_t* const port = jack_port_by_name(_client, ports[i]); - if (!port1 || !port2) { - continue; - } + sink({PortCreationEvent{PortID::jack(ports[i]), get_port_info(port)}}); + } - Ganv::Port* src = nullptr; - Ganv::Port* dst = nullptr; + // Get all connections (again to only create them once) + std::set<std::pair<std::string, std::string>> connections; + for (auto i = 0u; ports[i]; ++i) { + const jack_port_t* const port = jack_port_by_name(_client, ports[i]); + const char** const peers = jack_port_get_all_connections(_client, port); - if (port1->is_output() && port2->is_input()) { - src = port1; - dst = port2; - } else { - src = port2; - dst = port1; + if (peers) { + if (jack_port_flags(port) & JackPortIsInput) { + for (auto j = 0u; peers[j]; ++j) { + connections.emplace(peers[j], ports[i]); } - - if (src && dst && !_app->canvas()->get_edge(src, dst)) { - _app->canvas()->make_connection(src, dst); + } else { + for (auto j = 0u; peers[j]; ++j) { + connections.emplace(ports[i], peers[j]); } } - jack_free(connected_ports); + jack_free(peers); } } + // Emit all connections + for (const auto& connection : connections) { + sink({ConnectionEvent{PortID::jack(connection.first), + PortID::jack(connection.second)}}); + } + jack_free(ports); } |