summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/AlsaDriver.cpp286
-rw-r--r--src/AlsaDriver.hpp35
-rw-r--r--src/Driver.hpp12
-rw-r--r--src/JackDbusDriver.cpp319
-rw-r--r--src/JackDbusDriver.hpp64
-rw-r--r--src/JackDriver.cpp244
-rw-r--r--src/JackDriver.hpp15
-rw-r--r--src/Patchage.cpp28
-rw-r--r--src/PatchageCanvas.cpp87
-rw-r--r--src/PatchageCanvas.hpp8
-rw-r--r--src/handle_event.cpp36
11 files changed, 303 insertions, 831 deletions
diff --git a/src/AlsaDriver.cpp b/src/AlsaDriver.cpp
index 293ee63..6e1cebb 100644
--- a/src/AlsaDriver.cpp
+++ b/src/AlsaDriver.cpp
@@ -20,8 +20,6 @@
#include "ClientInfo.hpp"
#include "Patchage.hpp"
#include "PatchageCanvas.hpp"
-#include "PatchageModule.hpp"
-#include "PatchagePort.hpp"
#include "PortInfo.hpp"
#include "PortType.hpp"
#include "SignalDirection.hpp"
@@ -33,6 +31,7 @@ PATCHAGE_DISABLE_FMT_WARNINGS
PATCHAGE_RESTORE_WARNINGS
#include <cassert>
+#include <limits>
#include <set>
#include <string>
#include <utility>
@@ -85,9 +84,8 @@ port_info(const snd_seq_port_info_t* const pinfo)
} // namespace
-AlsaDriver::AlsaDriver(Patchage* app, ILog& log)
- : _app(app)
- , _log(log)
+AlsaDriver::AlsaDriver(ILog& log)
+ : _log(log)
, _seq(nullptr)
, _refresh_thread{}
{}
@@ -136,32 +134,14 @@ AlsaDriver::detach()
}
}
-static bool
-is_alsa_port(const PatchagePort* port)
-{
- return port->type() == PortType::alsa_midi;
-}
-
void
-AlsaDriver::destroy_all()
+AlsaDriver::refresh(const EventSink& sink)
{
- _app->canvas()->remove_ports(is_alsa_port);
- _modules.clear();
- _port_addrs.clear();
-}
-
-void
-AlsaDriver::refresh()
-{
- if (!is_attached()) {
+ if (!is_attached() || !_seq) {
return;
}
- assert(_seq);
-
- _modules.clear();
_ignored.clear();
- _port_addrs.clear();
snd_seq_client_info_t* cinfo = nullptr;
snd_seq_client_info_alloca(&cinfo);
@@ -170,233 +150,74 @@ AlsaDriver::refresh()
snd_seq_port_info_t* pinfo = nullptr;
snd_seq_port_info_alloca(&pinfo);
- // Create port views
- {
- PatchageModule* parent = nullptr;
- PatchagePort* port = nullptr;
-
- while (snd_seq_query_next_client(_seq, cinfo) >= 0) {
- snd_seq_port_info_set_client(pinfo,
- snd_seq_client_info_get_client(cinfo));
- snd_seq_port_info_set_port(pinfo, -1);
- while (snd_seq_query_next_port(_seq, pinfo) >= 0) {
- const snd_seq_addr_t& addr = *snd_seq_port_info_get_addr(pinfo);
- if (ignore(addr)) {
- continue;
- }
+ // Emit all clients
+ snd_seq_client_info_set_client(cinfo, -1);
+ while (snd_seq_query_next_client(_seq, cinfo) >= 0) {
+ const auto client_id = snd_seq_client_info_get_client(cinfo);
- create_port_view_internal(addr, parent, port);
- }
- }
+ assert(client_id < std::numeric_limits<uint8_t>::max());
+ sink({ClientCreationEvent{
+ ClientID::alsa(static_cast<uint8_t>(client_id)),
+ client_info(cinfo)}});
}
- // Create connections
+ // Emit all ports
snd_seq_client_info_set_client(cinfo, -1);
while (snd_seq_query_next_client(_seq, cinfo) >= 0) {
- snd_seq_port_info_set_client(pinfo,
- snd_seq_client_info_get_client(cinfo));
+ const auto client_id = snd_seq_client_info_get_client(cinfo);
+
+ snd_seq_port_info_set_client(pinfo, client_id);
snd_seq_port_info_set_port(pinfo, -1);
while (snd_seq_query_next_port(_seq, pinfo) >= 0) {
- const snd_seq_addr_t* addr = snd_seq_port_info_get_addr(pinfo);
- if (ignore(*addr)) {
- continue;
- }
-
- PatchagePort* const port1 = _app->canvas()->find_port(
- PortID::alsa(addr->client, addr->port, false));
- if (!port1) {
- continue;
- }
-
- snd_seq_query_subscribe_t* subsinfo = nullptr;
- snd_seq_query_subscribe_alloca(&subsinfo);
- snd_seq_query_subscribe_set_root(subsinfo, addr);
- snd_seq_query_subscribe_set_index(subsinfo, 0);
- while (!snd_seq_query_port_subscribers(_seq, subsinfo)) {
- const snd_seq_addr_t* addr2 =
- snd_seq_query_subscribe_get_addr(subsinfo);
- if (addr2) {
- 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);
- }
+ const auto addr = *snd_seq_port_info_get_addr(pinfo);
+ if (!ignore(addr)) {
+ const auto caps = snd_seq_port_info_get_capability(pinfo);
+ auto info = port_info(pinfo);
+
+ if (caps & SND_SEQ_PORT_CAP_READ) {
+ info.direction = SignalDirection::input;
+ sink({PortCreationEvent{addr_to_id(addr, true), info}});
}
- snd_seq_query_subscribe_set_index(
- subsinfo, snd_seq_query_subscribe_get_index(subsinfo) + 1);
+ if (caps & SND_SEQ_PORT_CAP_WRITE) {
+ info.direction = SignalDirection::output;
+ sink({PortCreationEvent{addr_to_id(addr, false), info}});
+ }
}
}
}
-}
-
-PatchagePort*
-AlsaDriver::create_port_view(Patchage*, const PortID& id)
-{
- PatchageModule* parent = nullptr;
- PatchagePort* port = nullptr;
- create_port_view_internal({id.alsa_client(), id.alsa_port()}, parent, port);
-
- return port;
-}
-
-PatchageModule*
-AlsaDriver::find_module(uint8_t client_id, SignalDirection type)
-{
- const Modules::const_iterator i = _modules.find(client_id);
- if (i == _modules.end()) {
- return nullptr;
- }
-
- PatchageModule* io_module = nullptr;
- for (Modules::const_iterator j = i;
- j != _modules.end() && j->first == client_id;
- ++j) {
- if (j->second->type() == type) {
- return j->second;
- }
- if (j->second->type() == SignalDirection::duplex) {
- io_module = j->second;
- }
- }
-
- // Return InputOutput module for Input or Output, or null if not found
- return io_module;
-}
-
-PatchageModule*
-AlsaDriver::find_or_create_module(Patchage* patchage,
- uint8_t client_id,
- const std::string& client_name,
- SignalDirection type)
-{
- PatchageModule* m = find_module(client_id, type);
- if (!m) {
- m = new PatchageModule(
- patchage, client_name, type, ClientID::alsa(client_id));
- m->load_location();
- _app->canvas()->add_module(ClientID::alsa(client_id), m);
- _modules.insert(std::make_pair(client_id, m));
- }
- return m;
-}
-
-void
-AlsaDriver::create_port_view_internal(snd_seq_addr_t addr,
- PatchageModule*& parent,
- PatchagePort*& port)
-{
- if (ignore(addr)) {
- return;
- }
-
- snd_seq_client_info_t* cinfo = nullptr;
- snd_seq_client_info_alloca(&cinfo);
- snd_seq_client_info_set_client(cinfo, addr.client);
- snd_seq_get_any_client_info(_seq, addr.client, cinfo);
-
- snd_seq_port_info_t* pinfo = nullptr;
- snd_seq_port_info_alloca(&pinfo);
- snd_seq_port_info_set_client(pinfo, addr.client);
- snd_seq_port_info_set_port(pinfo, addr.port);
- snd_seq_get_any_port_info(_seq, addr.client, addr.port, pinfo);
-
- const std::string client_name = snd_seq_client_info_get_name(cinfo);
- const std::string port_name = snd_seq_port_info_get_name(pinfo);
- bool is_input = false;
- bool is_duplex = false;
- bool is_application = true;
-
- const int caps = snd_seq_port_info_get_capability(pinfo);
- const int type = snd_seq_port_info_get_type(pinfo);
-
- // Figure out direction
- if ((caps & SND_SEQ_PORT_CAP_READ) && (caps & SND_SEQ_PORT_CAP_WRITE)) {
- is_duplex = true;
- } else if (caps & SND_SEQ_PORT_CAP_READ) {
- is_input = false;
- } else if (caps & SND_SEQ_PORT_CAP_WRITE) {
- is_input = true;
- }
-
- is_application = (type & SND_SEQ_PORT_TYPE_APPLICATION);
-
- // Because there would be name conflicts, we must force a split if (stupid)
- // alsa duplex ports are present on the client
- bool split = false;
- if (is_duplex) {
- split = true;
- if (!_app->conf()->get_module_split(client_name, !is_application)) {
- _app->conf()->set_module_split(client_name, true);
- }
- } else {
- split = _app->conf()->get_module_split(client_name, !is_application);
- }
-
- const auto port_id = PortID::alsa(addr.client, addr.port, is_input);
+ // Emit all connections
+ snd_seq_client_info_set_client(cinfo, -1);
+ while (snd_seq_query_next_client(_seq, cinfo) >= 0) {
+ const auto client_id = snd_seq_client_info_get_client(cinfo);
- if (!split) {
- parent = find_or_create_module(
- _app, addr.client, client_name, SignalDirection::duplex);
- if (!parent->get_port(port_id)) {
- port = create_port(*parent, port_name, is_input, addr);
- port->show();
- }
+ snd_seq_port_info_set_client(pinfo, client_id);
+ snd_seq_port_info_set_port(pinfo, -1);
+ while (snd_seq_query_next_port(_seq, pinfo) >= 0) {
+ const auto tail_addr = *snd_seq_port_info_get_addr(pinfo);
+ const auto tail_id = addr_to_id(tail_addr, false);
+ if (ignore(tail_addr)) {
+ continue;
+ }
- } else { // split
- {
- const SignalDirection module_type =
- ((is_input) ? SignalDirection::input : SignalDirection::output);
+ snd_seq_query_subscribe_t* sinfo = nullptr;
+ snd_seq_query_subscribe_alloca(&sinfo);
+ snd_seq_query_subscribe_set_root(sinfo, &tail_addr);
+ snd_seq_query_subscribe_set_index(sinfo, 0);
+ while (!snd_seq_query_port_subscribers(_seq, sinfo)) {
+ const auto head_addr = *snd_seq_query_subscribe_get_addr(sinfo);
+ const auto head_id = addr_to_id(head_addr, true);
- parent = find_or_create_module(
- _app, addr.client, client_name, module_type);
- if (!parent->get_port(port_id)) {
- port = create_port(*parent, port_name, is_input, addr);
- port->show();
- }
- }
+ sink({ConnectionEvent{tail_id, head_id}});
- if (is_duplex) {
- const SignalDirection flipped_module_type =
- ((!is_input) ? SignalDirection::input
- : SignalDirection::output);
- parent = find_or_create_module(
- _app, addr.client, client_name, flipped_module_type);
- if (!parent->get_port(port_id)) {
- port = create_port(*parent, port_name, !is_input, addr);
- port->show();
+ snd_seq_query_subscribe_set_index(
+ sinfo, snd_seq_query_subscribe_get_index(sinfo) + 1);
}
}
}
}
-PatchagePort*
-AlsaDriver::create_port(PatchageModule& parent,
- const std::string& name,
- bool is_input,
- snd_seq_addr_t addr)
-{
- const PortID id = PortID::alsa(addr.client, addr.port, is_input);
-
- auto* ret =
- new PatchagePort(parent,
- PortType::alsa_midi,
- id,
- name,
- "",
- is_input,
- _app->conf()->get_port_color(PortType::alsa_midi),
- _app->show_human_names());
-
- dynamic_cast<PatchageCanvas*>(parent.canvas())->index_port(id, ret);
-
- _app->canvas()->index_port(id, ret);
- _port_addrs.insert(std::make_pair(ret, id));
- return ret;
-}
-
bool
AlsaDriver::ignore(const snd_seq_addr_t& addr, bool add)
{
@@ -646,11 +467,6 @@ AlsaDriver::_refresh_main()
PortDestructionEvent{addr_to_id(ev->data.addr, true)});
_events.emplace(
PortDestructionEvent{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(addr_to_id(ev->data.addr, true)));
}
break;
diff --git a/src/AlsaDriver.hpp b/src/AlsaDriver.hpp
index caaaf39..15a5086 100644
--- a/src/AlsaDriver.hpp
+++ b/src/AlsaDriver.hpp
@@ -18,7 +18,6 @@
#define PATCHAGE_ALSADRIVER_HPP
#include "Driver.hpp"
-#include "PatchageModule.hpp"
#include <alsa/asoundlib.h>
#include <pthread.h>
@@ -31,13 +30,12 @@
class ILog;
class Patchage;
-class PatchagePort;
/// Driver for ALSA Sequencer ports
class AlsaDriver : public Driver
{
public:
- explicit AlsaDriver(Patchage* app, ILog& log);
+ explicit AlsaDriver(ILog& log);
AlsaDriver(const AlsaDriver&) = delete;
AlsaDriver& operator=(const AlsaDriver&) = delete;
@@ -52,11 +50,7 @@ public:
bool is_attached() const override { return (_seq != nullptr); }
- void refresh() override;
- void destroy_all() override;
-
- PatchagePort*
- create_port_view(Patchage* patchage, const PortID& id) override;
+ void refresh(const EventSink& sink) override;
bool connect(PortID tail_id, PortID head_id) override;
bool disconnect(PortID tail_id, PortID head_id) override;
@@ -70,23 +64,6 @@ private:
static void* refresh_main(void* me);
void _refresh_main();
- PatchageModule* find_module(uint8_t client_id, SignalDirection type);
-
- PatchageModule* find_or_create_module(Patchage* patchage,
- uint8_t client_id,
- const std::string& client_name,
- SignalDirection type);
-
- void create_port_view_internal(snd_seq_addr_t addr,
- PatchageModule*& parent,
- PatchagePort*& port);
-
- PatchagePort* create_port(PatchageModule& parent,
- const std::string& name,
- bool is_input,
- snd_seq_addr_t addr);
-
- Patchage* _app;
ILog& _log;
snd_seq_t* _seq;
pthread_t _refresh_thread;
@@ -103,13 +80,9 @@ private:
}
};
- using Ignored = std::set<snd_seq_addr_t, SeqAddrComparator>;
- using Modules = std::multimap<uint8_t, PatchageModule*>;
- using PortAddrs = std::map<PatchagePort*, PortID>;
+ using Ignored = std::set<snd_seq_addr_t, SeqAddrComparator>;
- Ignored _ignored;
- Modules _modules;
- PortAddrs _port_addrs;
+ Ignored _ignored;
bool ignore(const snd_seq_addr_t& addr, bool add = true);
};
diff --git a/src/Driver.hpp b/src/Driver.hpp
index 116b29f..d40f7b5 100644
--- a/src/Driver.hpp
+++ b/src/Driver.hpp
@@ -21,16 +21,16 @@
#include <sigc++/sigc++.h>
-#include <string>
+#include <functional>
class Patchage;
-class PatchagePort;
-class PatchageCanvas;
/// Base class for drivers that handle system clients and ports
class Driver
{
public:
+ using EventSink = std::function<void(const PatchageEvent&)>;
+
Driver() = default;
Driver(const Driver&) = delete;
@@ -47,11 +47,7 @@ public:
virtual void detach() = 0;
virtual bool is_attached() const = 0;
- virtual void refresh() = 0;
- virtual void destroy_all() = 0;
-
- virtual PatchagePort*
- create_port_view(Patchage* patchage, const PortID& id) = 0;
+ virtual void refresh(const EventSink& sink) = 0;
virtual bool connect(PortID tail_id, PortID head_id) = 0;
virtual bool disconnect(PortID tail_id, PortID head_id) = 0;
diff --git a/src/JackDbusDriver.cpp b/src/JackDbusDriver.cpp
index 81d6224..85dfae3 100644
--- a/src/JackDbusDriver.cpp
+++ b/src/JackDbusDriver.cpp
@@ -20,14 +20,12 @@
#include "patchage_config.h"
#include "Driver.hpp"
-#include "Patchage.hpp"
-#include "PatchageCanvas.hpp"
#include "PatchageEvent.hpp"
-#include "PatchageModule.hpp"
-#include "PatchagePort.hpp"
#include "PortNames.hpp"
#include "PortType.hpp"
#include "SignalDirection.hpp"
+#include "handle_event.hpp"
+#include "warnings.hpp"
PATCHAGE_DISABLE_FMT_WARNINGS
#include <fmt/core.h>
@@ -57,19 +55,8 @@ PATCHAGE_RESTORE_WARNINGS
#define JACKDBUS_PORT_TYPE_AUDIO 0
#define JACKDBUS_PORT_TYPE_MIDI 1
-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)
+JackDriver::JackDriver(ILog& log)
+ : _log(log)
, _dbus_error()
, _dbus_connection(nullptr)
, _max_dsp_load(0.0f)
@@ -91,19 +78,6 @@ JackDriver::~JackDriver()
}
}
-static bool
-is_jack_port(const PatchagePort* port)
-{
- return port->type() == PortType::jack_audio ||
- port->type() == PortType::jack_midi;
-}
-
-void
-JackDriver::destroy_all()
-{
- _app->canvas()->remove_ports(is_jack_port);
-}
-
void
JackDriver::update_attached()
{
@@ -236,8 +210,9 @@ JackDriver::dbus_message_hook(DBusConnection* /*connection*/,
me->signal_attached.emit();
}
- me->add_port(
- client_id, client_name, port_id, port_name, port_flags, port_type);
+ me->_events.emplace(
+ PortCreationEvent{PortID::jack(client_name, port_name),
+ me->port_info(port_name, port_type, port_flags)});
return DBUS_HANDLER_RESULT_HANDLED;
}
@@ -270,7 +245,8 @@ JackDriver::dbus_message_hook(DBusConnection* /*connection*/,
me->signal_attached.emit();
}
- me->remove_port(client_id, client_name, port_id, port_name);
+ me->_events.emplace(
+ PortDestructionEvent{PortID::jack(client_name, port_name)});
return DBUS_HANDLER_RESULT_HANDLED;
}
@@ -313,15 +289,9 @@ JackDriver::dbus_message_hook(DBusConnection* /*connection*/,
me->signal_attached.emit();
}
- me->connect_ports(connection_id,
- client_id,
- client_name,
- port_id,
- port_name,
- client2_id,
- client2_name,
- port2_id,
- port2_name);
+ me->_events.emplace(
+ ConnectionEvent{PortID::jack(client_name, port_name),
+ PortID::jack(client2_name, port2_name)});
return DBUS_HANDLER_RESULT_HANDLED;
}
@@ -364,15 +334,9 @@ JackDriver::dbus_message_hook(DBusConnection* /*connection*/,
me->signal_attached.emit();
}
- me->disconnect_ports(connection_id,
- client_id,
- client_name,
- port_id,
- port_name,
- client2_id,
- client2_name,
- port2_id,
- port2_name);
+ me->_events.emplace(
+ DisconnectionEvent{PortID::jack(client_name, port_name),
+ PortID::jack(client2_name, port2_name)});
return DBUS_HANDLER_RESULT_HANDLED;
}
@@ -488,15 +452,11 @@ JackDriver::stop_server()
"StopServer",
&reply_ptr,
DBUS_TYPE_INVALID)) {
- return;
+ error_msg("Error stopping JACK server");
}
dbus_message_unref(reply_ptr);
-
- if (!_server_started) {
- _server_started = false;
- signal_detached.emit();
- }
+ signal_detached.emit();
}
void
@@ -563,179 +523,7 @@ JackDriver::is_attached() const
}
void
-JackDriver::add_port(PatchageModule* module,
- PortType type,
- const PortID& id,
- const std::string& name,
- bool is_input)
-{
- if (module->get_port(id)) {
- return;
- }
-
- 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
-JackDriver::add_port(dbus_uint64_t /*client_id*/,
- const char* client_name,
- dbus_uint64_t /*port_id*/,
- const char* port_name,
- dbus_uint32_t port_flags,
- dbus_uint32_t port_type)
-{
- PortType local_port_type;
-
- switch (port_type) {
- case JACKDBUS_PORT_TYPE_AUDIO:
- local_port_type = PortType::jack_audio;
- break;
- case JACKDBUS_PORT_TYPE_MIDI:
- local_port_type = PortType::jack_midi;
- break;
- default:
- error_msg("Unknown JACK D-Bus port type");
- return;
- }
-
- SignalDirection type = SignalDirection::duplex;
- if (_app->conf()->get_module_split(
- client_name, port_flags & JACKDBUS_PORT_FLAG_TERMINAL)) {
- if (port_flags & JACKDBUS_PORT_FLAG_INPUT) {
- type = SignalDirection::input;
- } else {
- type = SignalDirection::output;
- }
- }
-
- PatchageModule* module = find_or_create_module(type, client_name);
-
- add_port(module,
- local_port_type,
- PortID::jack(full_name(client_name, port_name)),
- port_name,
- port_flags & JACKDBUS_PORT_FLAG_INPUT);
-}
-
-void
-JackDriver::remove_port(dbus_uint64_t /*client_id*/,
- const char* client_name,
- dbus_uint64_t /*port_id*/,
- const char* 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;
- }
-
- auto* module = dynamic_cast<PatchageModule*>(port->get_module());
-
- delete port;
-
- // No empty modules (for now)
- if (module->num_ports() == 0) {
- delete module;
- }
-
- if (_app->canvas()->empty()) {
- if (_server_started) {
- signal_detached.emit();
- }
-
- _server_started = false;
- }
-}
-
-PatchageModule*
-JackDriver::find_or_create_module(SignalDirection type, const std::string& name)
-{
- const auto id = ClientID::jack(name);
- PatchageModule* module = _app->canvas()->find_module(id, type);
-
- if (!module) {
- module = new PatchageModule(_app, name, type, id);
- module->load_location();
- _app->canvas()->add_module(id, module);
- }
-
- return module;
-}
-
-void
-JackDriver::connect_ports(dbus_uint64_t /*connection_id*/,
- dbus_uint64_t /*client1_id*/,
- const char* client1_name,
- dbus_uint64_t /*port1_id*/,
- const char* port1_name,
- dbus_uint64_t /*client2_id*/,
- const char* client2_name,
- dbus_uint64_t /*port2_id*/,
- const char* port2_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* 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(tail, head);
-}
-
-void
-JackDriver::disconnect_ports(dbus_uint64_t /*connection_id*/,
- dbus_uint64_t /*client1_id*/,
- const char* client1_name,
- dbus_uint64_t /*port1_id*/,
- const char* port1_name,
- dbus_uint64_t /*client2_id*/,
- const char* client2_name,
- dbus_uint64_t /*port2_id*/,
- const char* port2_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* 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(tail, head);
-}
-
-void
-JackDriver::refresh()
+JackDriver::refresh(const EventSink& sink)
{
DBusMessage* reply_ptr = nullptr;
DBusMessageIter iter = {};
@@ -784,10 +572,9 @@ JackDriver::refresh()
dbus_message_iter_get_basic(&iter, &version);
dbus_message_iter_next(&iter);
- destroy_all();
-
_graph_version = version;
+ // Emit all clients and ports
for (dbus_message_iter_recurse(&iter, &clients_array_iter);
dbus_message_iter_get_arg_type(&clients_array_iter) !=
DBUS_TYPE_INVALID;
@@ -800,6 +587,9 @@ JackDriver::refresh()
dbus_message_iter_get_basic(&client_struct_iter, &client_name);
dbus_message_iter_next(&client_struct_iter);
+ // TODO: Pretty name?
+ sink({ClientCreationEvent{ClientID::jack(client_name), {client_name}}});
+
for (dbus_message_iter_recurse(&client_struct_iter, &ports_array_iter);
dbus_message_iter_get_arg_type(&ports_array_iter) !=
DBUS_TYPE_INVALID;
@@ -818,12 +608,9 @@ JackDriver::refresh()
dbus_message_iter_get_basic(&port_struct_iter, &port_type);
dbus_message_iter_next(&port_struct_iter);
- add_port(client_id,
- client_name,
- port_id,
- port_name,
- port_flags,
- port_type);
+ sink({PortCreationEvent{
+ PortID::jack(client_name, port_name),
+ port_info(port_name, port_type, port_flags)}});
}
dbus_message_iter_next(&client_struct_iter);
@@ -831,6 +618,7 @@ JackDriver::refresh()
dbus_message_iter_next(&iter);
+ // Emit all connections
for (dbus_message_iter_recurse(&iter, &connections_array_iter);
dbus_message_iter_get_arg_type(&connections_array_iter) !=
DBUS_TYPE_INVALID;
@@ -865,15 +653,8 @@ JackDriver::refresh()
dbus_message_iter_get_basic(&connection_struct_iter, &connection_id);
dbus_message_iter_next(&connection_struct_iter);
- connect_ports(connection_id,
- client_id,
- client_name,
- port_id,
- port_name,
- client2_id,
- client2_name,
- port2_id,
- port2_name);
+ sink({ConnectionEvent{PortID::jack(client_name, port_name),
+ PortID::jack(client2_name, port2_name)}});
}
}
@@ -1155,11 +936,37 @@ JackDriver::reset_max_dsp_load()
_max_dsp_load = 0.0;
}
-PatchagePort*
-JackDriver::create_port_view(Patchage*, const PortID&)
+PortType
+JackDriver::patchage_port_type(const dbus_uint32_t dbus_port_type) const
+{
+ switch (dbus_port_type) {
+ case JACKDBUS_PORT_TYPE_AUDIO:
+ return PortType::jack_audio;
+ case JACKDBUS_PORT_TYPE_MIDI:
+ return PortType::jack_midi;
+ default:
+ break;
+ }
+
+ error_msg(fmt::format("Unknown JACK D-Bus port type {}", dbus_port_type));
+ return PortType::jack_audio;
+}
+
+PortInfo
+JackDriver::port_info(const std::string& port_name,
+ const dbus_uint32_t port_type,
+ const dbus_uint32_t port_flags) const
{
- assert(false); // we dont use events at all
- return nullptr;
+ const SignalDirection direction =
+ ((port_flags & JACKDBUS_PORT_FLAG_INPUT) ? SignalDirection::input
+ : SignalDirection::output);
+
+ // TODO: Metadata?
+ return {port_name,
+ patchage_port_type(port_type),
+ direction,
+ {},
+ bool(port_flags & JACKDBUS_PORT_FLAG_TERMINAL)};
}
void
@@ -1173,3 +980,13 @@ JackDriver::info_msg(const std::string& msg) const
{
_log.info(std::string{"[JACK] "} + msg);
}
+
+void
+JackDriver::process_events(Patchage* app)
+{
+ while (!_events.empty()) {
+ PatchageEvent& ev = _events.front();
+ handle_event(*app, ev);
+ _events.pop();
+ }
+}
diff --git a/src/JackDbusDriver.hpp b/src/JackDbusDriver.hpp
index 37a7877..db77658 100644
--- a/src/JackDbusDriver.hpp
+++ b/src/JackDbusDriver.hpp
@@ -20,23 +20,21 @@
#include "Driver.hpp"
#include "Patchage.hpp"
-#include "PatchageModule.hpp"
#include <dbus/dbus.h>
#include <glibmm/thread.h>
#include <jack/jack.h>
#include <jack/statistics.h>
+#include <queue>
#include <string>
class ILog;
-class PatchageCanvas;
-class PatchagePort;
class JackDriver : public Driver
{
public:
- explicit JackDriver(Patchage* app, ILog& log);
+ explicit JackDriver(ILog& log);
JackDriver(const JackDriver&) = delete;
JackDriver& operator=(const JackDriver&) = delete;
@@ -52,8 +50,7 @@ public:
bool is_attached() const override;
bool is_realtime() const;
- void refresh() override;
- void destroy_all() override;
+ void refresh(const EventSink& sink) override;
bool connect(PortID tail_id, PortID head_id) override;
bool disconnect(PortID tail_id, PortID head_id) override;
@@ -67,56 +64,18 @@ public:
jack_nframes_t buffer_size();
bool set_buffer_size(jack_nframes_t size);
- void process_events(Patchage*) override {}
-
- PatchagePort*
- create_port_view(Patchage* patchage, const PortID& ref) override;
+ void process_events(Patchage* app) override;
private:
+ PortType patchage_port_type(dbus_uint32_t dbus_port_type) const;
+
+ PortInfo port_info(const std::string& port_name,
+ dbus_uint32_t port_type,
+ dbus_uint32_t port_flags) const;
+
void error_msg(const std::string& msg) const;
void info_msg(const std::string& msg) const;
- PatchageModule*
- find_or_create_module(SignalDirection type, const std::string& name);
-
- void add_port(PatchageModule* module,
- PortType type,
- const PortID& id,
- const std::string& name,
- bool is_input);
-
- void add_port(dbus_uint64_t client_id,
- const char* client_name,
- dbus_uint64_t port_id,
- const char* port_name,
- dbus_uint32_t port_flags,
- dbus_uint32_t port_type);
-
- void remove_port(dbus_uint64_t client_id,
- const char* client_name,
- dbus_uint64_t port_id,
- const char* port_name);
-
- void connect_ports(dbus_uint64_t connection_id,
- dbus_uint64_t client1_id,
- const char* client1_name,
- dbus_uint64_t port1_id,
- const char* port1_name,
- dbus_uint64_t client2_id,
- const char* client2_name,
- dbus_uint64_t port2_id,
- const char* port2_name);
-
- void disconnect_ports(dbus_uint64_t connection_id,
- dbus_uint64_t client1_id,
- const char* client1_name,
- dbus_uint64_t port1_id,
- const char* port1_name,
- dbus_uint64_t client2_id,
- const char* client2_name,
- dbus_uint64_t port2_id,
- const char* port2_name);
-
bool call(bool response_expected,
const char* iface,
const char* method,
@@ -140,12 +99,13 @@ private:
void on_jack_disappeared();
- Patchage* _app;
ILog& _log;
DBusError _dbus_error;
DBusConnection* _dbus_connection;
float _max_dsp_load;
+ std::queue<PatchageEvent> _events;
+
bool _server_responding;
bool _server_started;
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);
}
diff --git a/src/JackDriver.hpp b/src/JackDriver.hpp
index 6e41fbb..1e680a0 100644
--- a/src/JackDriver.hpp
+++ b/src/JackDriver.hpp
@@ -31,15 +31,12 @@
class ILog;
class Patchage;
-class PatchageCanvas;
-class PatchageModule;
-class PatchagePort;
/// Driver for JACK audio and midi ports
class JackDriver : public Driver
{
public:
- explicit JackDriver(Patchage* app, ILog& log);
+ explicit JackDriver(ILog& log);
JackDriver(const JackDriver&) = delete;
JackDriver& operator=(const JackDriver&) = delete;
@@ -56,16 +53,12 @@ public:
bool is_realtime() const { return _client && jack_is_realtime(_client); }
- void refresh() override;
- void destroy_all() override;
+ void refresh(const EventSink& sink) override;
bool port_names(const PortID& id,
std::string& module_name,
std::string& port_name);
- PatchagePort*
- create_port_view(Patchage* patchage, const PortID& id) override;
-
bool connect(PortID tail_id, PortID head_id) override;
bool disconnect(PortID tail_id, PortID head_id) override;
@@ -86,9 +79,6 @@ private:
ClientInfo get_client_info(const char* name);
PortInfo get_port_info(const jack_port_t* port);
- PatchagePort*
- create_port(PatchageModule& parent, jack_port_t* port, const PortID& id);
-
void shutdown();
static void jack_client_registration_cb(const char* name,
@@ -108,7 +98,6 @@ private:
static void jack_shutdown_cb(void* jack_driver);
- Patchage* _app;
ILog& _log;
jack_client_t* _client;
diff --git a/src/Patchage.cpp b/src/Patchage.cpp
index 7613935..e0b5dc7 100644
--- a/src/Patchage.cpp
+++ b/src/Patchage.cpp
@@ -22,6 +22,8 @@
#include "PatchageEvent.hpp"
#include "PatchagePort.hpp"
#include "UIFile.hpp"
+#include "event_to_string.hpp"
+#include "handle_event.hpp"
#include "patchage_config.h"
#include "warnings.hpp"
@@ -342,7 +344,7 @@ Patchage::Patchage(int argc, char** argv)
#endif
#if defined(PATCHAGE_LIBJACK) || defined(HAVE_JACK_DBUS)
- _jack_driver = new JackDriver(this, _log);
+ _jack_driver = new JackDriver(_log);
_connector.add_driver(PortID::Type::jack, _jack_driver);
_jack_driver->signal_detached.connect(
@@ -355,7 +357,7 @@ Patchage::Patchage(int argc, char** argv)
#endif
#ifdef HAVE_ALSA
- _alsa_driver = new AlsaDriver(this, _log);
+ _alsa_driver = new AlsaDriver(_log);
_connector.add_driver(PortID::Type::alsa, _alsa_driver);
#endif
@@ -461,12 +463,19 @@ Patchage::idle_callback()
} else if (_driver_detached) {
#if defined(PATCHAGE_LIBJACK) || defined(HAVE_JACK_DBUS)
if (_jack_driver && !_jack_driver->is_attached()) {
- _jack_driver->destroy_all();
+ _canvas->remove_ports([](const PatchagePort* port) {
+ return (port->type() == PortType::jack_audio ||
+ port->type() == PortType::jack_midi ||
+ port->type() == PortType::jack_osc ||
+ port->type() == PortType::jack_cv);
+ });
}
#endif
#ifdef HAVE_ALSA
if (_alsa_driver && !_alsa_driver->is_attached()) {
- _alsa_driver->destroy_all();
+ _canvas->remove_ports([](const PatchagePort* port) {
+ return port->type() == PortType::alsa_midi;
+ });
}
#endif
}
@@ -542,18 +551,22 @@ Patchage::zoom(double z)
void
Patchage::refresh()
{
+ auto sink = [this](const PatchageEvent& event) {
+ handle_event(*this, event);
+ };
+
if (_canvas && _enable_refresh) {
_canvas->clear();
#if defined(PATCHAGE_LIBJACK) || defined(HAVE_JACK_DBUS)
if (_jack_driver) {
- _jack_driver->refresh();
+ _jack_driver->refresh(sink);
}
#endif
#ifdef HAVE_ALSA
if (_alsa_driver) {
- _alsa_driver->refresh();
+ _alsa_driver->refresh(sink);
}
#endif
}
@@ -762,7 +775,8 @@ void
Patchage::menu_alsa_connect()
{
_alsa_driver->attach(false);
- _alsa_driver->refresh();
+ _alsa_driver->refresh(
+ [this](const PatchageEvent& event) { handle_event(*this, event); });
}
void
diff --git a/src/PatchageCanvas.cpp b/src/PatchageCanvas.cpp
index b94806d..bb9c484 100644
--- a/src/PatchageCanvas.cpp
+++ b/src/PatchageCanvas.cpp
@@ -19,8 +19,10 @@
#include "patchage_config.h"
#include "Connector.hpp"
+#include "Patchage.hpp"
#include "PatchageModule.hpp"
#include "PatchagePort.hpp"
+#include "PortNames.hpp"
#include "SignalDirection.hpp"
#include "warnings.hpp"
@@ -30,6 +32,11 @@ PATCHAGE_DISABLE_GANV_WARNINGS
#include "ganv/Edge.hpp"
PATCHAGE_RESTORE_WARNINGS
+PATCHAGE_DISABLE_FMT_WARNINGS
+#include <fmt/core.h>
+#include <fmt/ostream.h>
+PATCHAGE_RESTORE_WARNINGS
+
PatchageCanvas::PatchageCanvas(Connector& connector, int width, int height)
: Ganv::Canvas(width, height)
, _connector(connector)
@@ -41,6 +48,84 @@ PatchageCanvas::PatchageCanvas(Connector& connector, int width, int height)
}
PatchageModule*
+PatchageCanvas::create_module(Patchage& patchage,
+ const ClientID& id,
+ const ClientInfo& info)
+{
+ (void)patchage;
+ (void)id;
+ (void)info;
+ return nullptr;
+}
+
+PatchagePort*
+PatchageCanvas::create_port(Patchage& patchage,
+ const PortID& id,
+ const PortInfo& info)
+{
+ const auto client_id = id.client();
+
+ const auto port_name =
+ ((id.type() == PortID::Type::alsa) ? info.label : PortNames(id).port());
+
+ // Figure out the client name, for ALSA we need the metadata cache
+ std::string client_name;
+ if (id.type() == PortID::Type::alsa) {
+ const auto client_info = patchage.metadata().client(client_id);
+ if (!client_info.has_value()) {
+ patchage.log().error(fmt::format(
+ "Unable to add port \"{}\", client \"{}\" is unknown",
+ id,
+ client_id));
+
+ return nullptr;
+ }
+
+ client_name = client_info->label;
+ } else {
+ client_name = PortNames(id).client();
+ }
+
+ // Determine the module type to place the port on in case of splitting
+ SignalDirection module_type = SignalDirection::duplex;
+ if (patchage.conf()->get_module_split(client_name, info.is_terminal)) {
+ module_type = info.direction;
+ }
+
+ // Find or create parent module
+ PatchageModule* parent = find_module(client_id, module_type);
+ if (!parent) {
+ parent =
+ new PatchageModule(&patchage, client_name, module_type, client_id);
+
+ parent->load_location();
+ add_module(client_id, parent);
+ }
+
+ if (parent->get_port(id)) {
+ // TODO: Update existing port?
+ patchage.log().error(fmt::format(
+ "Module \"{}\" already has port \"{}\"", client_name, port_name));
+ return nullptr;
+ }
+
+ auto* const port =
+ new PatchagePort(*parent,
+ info.type,
+ id,
+ port_name,
+ info.label,
+ info.direction == SignalDirection::input,
+ patchage.conf()->get_port_color(info.type),
+ patchage.show_human_names(),
+ info.order);
+
+ index_port(id, port);
+
+ return port;
+}
+
+PatchageModule*
PatchageCanvas::find_module(const ClientID& id, const SignalDirection type)
{
auto i = _module_index.find(id);
@@ -199,7 +284,7 @@ PatchageCanvas::add_module(const ClientID& id, PatchageModule* module)
in_module = module;
out_module = find_module(id, SignalDirection::output);
} else if (module->type() == SignalDirection::output) {
- in_module = find_module(id, SignalDirection::output);
+ in_module = find_module(id, SignalDirection::input);
out_module = module;
}
diff --git a/src/PatchageCanvas.hpp b/src/PatchageCanvas.hpp
index 0debcf8..073b3fb 100644
--- a/src/PatchageCanvas.hpp
+++ b/src/PatchageCanvas.hpp
@@ -36,6 +36,7 @@ PATCHAGE_RESTORE_WARNINGS
#include <string>
#include <utility>
+class Patchage;
class PatchageModule;
class PatchagePort;
class Connector;
@@ -45,6 +46,13 @@ class PatchageCanvas : public Ganv::Canvas
public:
PatchageCanvas(Connector& connector, int width, int height);
+ PatchageModule* create_module(Patchage& patchage,
+ const ClientID& id,
+ const ClientInfo& info);
+
+ PatchagePort*
+ create_port(Patchage& patchage, const PortID& id, const PortInfo& info);
+
PatchageModule* find_module(const ClientID& id, SignalDirection type);
PatchagePort* find_port(const PortID& id);
diff --git a/src/handle_event.cpp b/src/handle_event.cpp
index 2bd3609..200f819 100644
--- a/src/handle_event.cpp
+++ b/src/handle_event.cpp
@@ -15,26 +15,19 @@
*/
#include "handle_event.hpp"
+#include "event_to_string.hpp"
#include "PatchageEvent.hpp"
#include "patchage_config.h"
-#include "Driver.hpp"
+#include "event_to_string.hpp"
+
#include "Patchage.hpp"
#include "PatchageCanvas.hpp"
#include "PatchageModule.hpp"
#include "PatchagePort.hpp"
-#if defined(HAVE_JACK_DBUS)
-# include "JackDbusDriver.hpp"
-#elif defined(PATCHAGE_LIBJACK)
-# include "JackDriver.hpp"
-#endif
-#ifdef HAVE_ALSA
-# include "AlsaDriver.hpp"
-#endif
-
PATCHAGE_DISABLE_FMT_WARNINGS
#include <fmt/core.h>
#include <fmt/ostream.h>
@@ -65,27 +58,14 @@ public:
void operator()(const PortCreationEvent& event)
{
- Driver* driver = nullptr;
- if (event.id.type() == PortID::Type::jack) {
-#if defined(PATCHAGE_LIBJACK) || defined(HAVE_JACK_DBUS)
- driver = _patchage.jack_driver();
-#endif
-#ifdef HAVE_ALSA
- } else if (event.id.type() == PortID::Type::alsa) {
- driver = _patchage.alsa_driver();
-#endif
- }
_patchage.metadata().set_port(event.id, event.info);
- if (driver) {
- PatchagePort* port = driver->create_port_view(&_patchage, event.id);
- if (!port) {
- _patchage.log().error(fmt::format(
- "Unable to create view for port \"{}\"", event.id));
- }
- } else {
+ auto* const port =
+ _patchage.canvas()->create_port(_patchage, event.id, event.info);
+
+ if (!port) {
_patchage.log().error(
- fmt::format("Unknown type for port \"{}\"", event.id));
+ fmt::format("Unable to create view for port \"{}\"", event.id));
}
}