summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2020-11-28 12:32:24 +0100
committerDavid Robillard <d@drobilla.net>2020-11-28 12:45:57 +0100
commitdb5d1f603e0dd3076444f27008fcf1a61a4e151c (patch)
tree78af24e87c81e54fab14a59389adea859577f49e
parent0ae4276ac187a9a361950f26bd67eb2d54636aff (diff)
downloadpatchage-db5d1f603e0dd3076444f27008fcf1a61a4e151c.tar.gz
patchage-db5d1f603e0dd3076444f27008fcf1a61a4e151c.tar.bz2
patchage-db5d1f603e0dd3076444f27008fcf1a61a4e151c.zip
Factor out Connector from PatchageCanvas
This finally breaks the dependency of the canvas on the entire application, and fixes the confusing situation where it wasn't clear whether connect/disconnect methods made/broke connections on the canvas or on the system.
-rw-r--r--src/Connector.cpp67
-rw-r--r--src/Connector.hpp43
-rw-r--r--src/Patchage.cpp6
-rw-r--r--src/Patchage.hpp2
-rw-r--r--src/PatchageCanvas.cpp103
-rw-r--r--src/PatchageCanvas.hpp15
-rw-r--r--src/PortID.hpp14
-rw-r--r--wscript1
8 files changed, 169 insertions, 82 deletions
diff --git a/src/Connector.cpp b/src/Connector.cpp
new file mode 100644
index 0000000..c26c7a7
--- /dev/null
+++ b/src/Connector.cpp
@@ -0,0 +1,67 @@
+/* This file is part of Patchage.
+ * Copyright 2007-2020 David Robillard <d@drobilla.net>
+ *
+ * Patchage is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * Patchage is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Patchage. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "Connector.hpp"
+
+#include "Driver.hpp"
+#include "ILog.hpp"
+#include "PortID.hpp"
+
+#include <unordered_map>
+
+Connector::Connector(ILog& log)
+ : _log(log)
+{}
+
+void
+Connector::add_driver(PortID::Type type, Driver* driver)
+{
+ _drivers.emplace(type, driver);
+}
+
+void
+Connector::connect(const PortID& tail, const PortID& head)
+{
+ if (tail.type() != head.type()) {
+ _log.warning("Unable to connect incompatible port types");
+ return;
+ }
+
+ auto d = _drivers.find(tail.type());
+ if (d == _drivers.end()) {
+ _log.error("No driver for port type");
+ return;
+ }
+
+ d->second->connect(tail, head);
+}
+
+void
+Connector::disconnect(const PortID& tail, const PortID& head)
+{
+ if (tail.type() != head.type()) {
+ _log.error("Unable to disconnect incompatible port types");
+ return;
+ }
+
+ auto d = _drivers.find(tail.type());
+ if (d == _drivers.end()) {
+ _log.error("No driver for port type");
+ return;
+ }
+
+ d->second->disconnect(tail, head);
+}
diff --git a/src/Connector.hpp b/src/Connector.hpp
new file mode 100644
index 0000000..084217e
--- /dev/null
+++ b/src/Connector.hpp
@@ -0,0 +1,43 @@
+/* This file is part of Patchage.
+ * Copyright 2007-2020 David Robillard <d@drobilla.net>
+ *
+ * Patchage is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * Patchage is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Patchage. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef PATCHAGE_CONNECTOR_HPP
+#define PATCHAGE_CONNECTOR_HPP
+
+#include "PortID.hpp"
+
+#include <unordered_map>
+
+class Driver;
+class ILog;
+
+/// Controller that makes and breaks connections on the system
+class Connector
+{
+public:
+ explicit Connector(ILog& log);
+
+ void add_driver(PortID::Type type, Driver* driver);
+
+ void connect(const PortID& tail, const PortID& head);
+ void disconnect(const PortID& tail, const PortID& head);
+
+private:
+ ILog& _log;
+ std::unordered_map<PortID::Type, Driver*> _drivers;
+};
+
+#endif // PATCHAGE_CONNECTOR_HPP
diff --git a/src/Patchage.cpp b/src/Patchage.cpp
index fb269d5..fdd0ce9 100644
--- a/src/Patchage.cpp
+++ b/src/Patchage.cpp
@@ -168,6 +168,7 @@ Patchage::Patchage(int argc, char** argv)
, INIT_WIDGET(_status_text)
, _legend(nullptr)
, _log(_status_text)
+ , _connector(_log)
, _pane_initialized(false)
, _attach(true)
, _driver_detached(false)
@@ -179,7 +180,7 @@ Patchage::Patchage(int argc, char** argv)
#endif
{
_conf = new Configuration();
- _canvas = std::make_shared<PatchageCanvas>(this, 1600 * 2, 1200 * 2);
+ _canvas = std::make_shared<PatchageCanvas>(_connector, 1600 * 2, 1200 * 2);
while (argc > 0) {
if (!strcmp(*argv, "-h") || !strcmp(*argv, "--help")) {
@@ -338,6 +339,8 @@ Patchage::Patchage(int argc, char** argv)
#if defined(PATCHAGE_LIBJACK) || defined(HAVE_JACK_DBUS)
_jack_driver = new JackDriver(this, _log);
+ _connector.add_driver(PortID::Type::jack, _jack_driver);
+
_jack_driver->signal_detached.connect(
sigc::mem_fun(this, &Patchage::driver_detached));
@@ -349,6 +352,7 @@ Patchage::Patchage(int argc, char** argv)
#ifdef HAVE_ALSA
_alsa_driver = new AlsaDriver(this, _log);
+ _connector.add_driver(PortID::Type::alsa, _alsa_driver);
#endif
connect_widgets();
diff --git a/src/Patchage.hpp b/src/Patchage.hpp
index e453b68..19b2e9f 100644
--- a/src/Patchage.hpp
+++ b/src/Patchage.hpp
@@ -38,6 +38,7 @@
#include <gtkmm/viewport.h>
#include <gtkmm/window.h>
+#include "Connector.hpp"
#include "ILog.hpp"
#include "Legend.hpp"
#include "TextViewLog.hpp"
@@ -210,6 +211,7 @@ protected:
Widget<Gtk::TextView> _status_text;
Legend* _legend;
TextViewLog _log;
+ Connector _connector;
Glib::RefPtr<Gtk::TextTag> _error_tag;
Glib::RefPtr<Gtk::TextTag> _warning_tag;
diff --git a/src/PatchageCanvas.cpp b/src/PatchageCanvas.cpp
index 6bae432..167df2b 100644
--- a/src/PatchageCanvas.cpp
+++ b/src/PatchageCanvas.cpp
@@ -18,31 +18,25 @@
#include "patchage_config.h"
-#include "Patchage.hpp"
+#include "Connector.hpp"
#include "PatchageModule.hpp"
#include "PatchagePort.hpp"
#include "warnings.hpp"
-#if defined(HAVE_JACK_DBUS)
-# include "JackDbusDriver.hpp"
-#elif defined(PATCHAGE_LIBJACK)
-# include "JackDriver.hpp"
-#endif
-#ifdef HAVE_ALSA
-# include "AlsaDriver.hpp"
-#endif
+#include <set>
PATCHAGE_DISABLE_GANV_WARNINGS
#include "ganv/Edge.hpp"
PATCHAGE_RESTORE_WARNINGS
-PatchageCanvas::PatchageCanvas(Patchage* app, int width, int height)
+PatchageCanvas::PatchageCanvas(Connector& connector, int width, int height)
: Ganv::Canvas(width, height)
- , _app(app)
+ , _connector(connector)
{
signal_event.connect(sigc::mem_fun(this, &PatchageCanvas::on_event));
- signal_connect.connect(sigc::mem_fun(this, &PatchageCanvas::connect));
- signal_disconnect.connect(sigc::mem_fun(this, &PatchageCanvas::disconnect));
+ signal_connect.connect(sigc::mem_fun(this, &PatchageCanvas::on_connect));
+ signal_disconnect.connect(
+ sigc::mem_fun(this, &PatchageCanvas::on_disconnect));
}
PatchageModule*
@@ -189,71 +183,32 @@ PatchageCanvas::find_port_by_name(const std::string& client_name,
}
void
-PatchageCanvas::connect(Ganv::Node* port1, Ganv::Node* port2)
+PatchageCanvas::on_connect(Ganv::Node* port1, Ganv::Node* port2)
{
- auto* p1 = dynamic_cast<PatchagePort*>(port1);
- auto* p2 = dynamic_cast<PatchagePort*>(port2);
- if (!p1 || !p2) {
- return;
- }
-
- if ((p1->type() == PortType::jack_audio &&
- p2->type() == PortType::jack_audio) ||
- (p1->type() == PortType::jack_midi &&
- p2->type() == PortType::jack_midi) ||
- (p1->type() == PortType::jack_audio &&
- p2->type() == PortType::jack_cv) ||
- (p1->type() == PortType::jack_cv && p2->type() == PortType::jack_cv) ||
- (p1->type() == PortType::jack_osc &&
- p2->type() == PortType::jack_osc)) {
-#if defined(PATCHAGE_LIBJACK) || defined(HAVE_JACK_DBUS)
- _app->jack_driver()->connect(p1->id(), p2->id());
-#endif
-#ifdef HAVE_ALSA
- } else if (p1->type() == PortType::alsa_midi &&
- p2->type() == PortType::alsa_midi) {
- _app->alsa_driver()->connect(p1->id(), p2->id());
-#endif
- } else {
- _app->log().warning("Cannot make connection, incompatible port types");
+ auto* const p1 = dynamic_cast<PatchagePort*>(port1);
+ auto* const p2 = dynamic_cast<PatchagePort*>(port2);
+
+ if (p1 && p2) {
+ if (p1->is_output() && p2->is_input()) {
+ _connector.connect(p1->id(), p2->id());
+ } else if (p2->is_output() && p1->is_input()) {
+ _connector.connect(p2->id(), p1->id());
+ }
}
}
void
-PatchageCanvas::disconnect(Ganv::Node* port1, Ganv::Node* port2)
+PatchageCanvas::on_disconnect(Ganv::Node* port1, Ganv::Node* port2)
{
- auto* input = dynamic_cast<PatchagePort*>(port1);
- auto* output = dynamic_cast<PatchagePort*>(port2);
- if (!input || !output) {
- return;
- }
-
- if (input->is_output() && output->is_input()) {
- // Damn, guessed wrong
- PatchagePort* swap = input;
- input = output;
- output = swap;
- }
-
- if (!input || !output || input->is_output() || output->is_input()) {
- _app->log().error("Attempt to disconnect mismatched/unknown ports");
- return;
- }
-
- if (input->type() == PortType::jack_audio ||
- input->type() == PortType::jack_midi ||
- input->type() == PortType::jack_cv ||
- input->type() == PortType::jack_osc) {
-#if defined(PATCHAGE_LIBJACK) || defined(HAVE_JACK_DBUS)
- _app->jack_driver()->disconnect(output->id(), input->id());
-
-#endif
-#ifdef HAVE_ALSA
- } else if (input->type() == PortType::alsa_midi) {
- _app->alsa_driver()->disconnect(output->id(), input->id());
-#endif
- } else {
- _app->log().error("Attempt to disconnect ports with strange types");
+ auto* const p1 = dynamic_cast<PatchagePort*>(port1);
+ auto* const p2 = dynamic_cast<PatchagePort*>(port2);
+
+ if (p1 && p2) {
+ if (p1->is_output() && p2->is_input()) {
+ _connector.disconnect(p1->id(), p2->id());
+ } else if (p2->is_output() && p1->is_input()) {
+ _connector.disconnect(p2->id(), p1->id());
+ }
}
}
@@ -278,12 +233,12 @@ PatchageCanvas::add_module(const std::string& name, PatchageModule* module)
}
}
-static void
+void
disconnect_edge(GanvEdge* edge, void* data)
{
auto* canvas = static_cast<PatchageCanvas*>(data);
Ganv::Edge* edgemm = Glib::wrap(edge);
- canvas->disconnect(edgemm->get_tail(), edgemm->get_head());
+ canvas->on_disconnect(edgemm->get_tail(), edgemm->get_head());
}
bool
diff --git a/src/PatchageCanvas.hpp b/src/PatchageCanvas.hpp
index 40ec51c..349512b 100644
--- a/src/PatchageCanvas.hpp
+++ b/src/PatchageCanvas.hpp
@@ -36,14 +36,14 @@ PATCHAGE_RESTORE_WARNINGS
#include <string>
#include <utility>
-class Patchage;
class PatchageModule;
class PatchagePort;
+class Connector;
class PatchageCanvas : public Ganv::Canvas
{
public:
- PatchageCanvas(Patchage* _app, int width, int height);
+ PatchageCanvas(Connector& connector, int width, int height);
PatchageModule* find_module(const std::string& name, ModuleType type);
PatchagePort* find_port(const PortID& id);
@@ -54,10 +54,6 @@ public:
PatchagePort* find_port_by_name(const std::string& client_name,
const std::string& port_name);
- void connect(Ganv::Node* port1, Ganv::Node* port2);
-
- void disconnect(Ganv::Node* port1, Ganv::Node* port2);
-
void index_port(const PortID& id, PatchagePort* port)
{
_port_index.insert(std::make_pair(id, port));
@@ -77,10 +73,15 @@ private:
using PortIndex = std::map<const PortID, PatchagePort*>;
using ModuleIndex = std::multimap<const std::string, PatchageModule*>;
+ friend void disconnect_edge(GanvEdge*, void*);
+
bool on_event(GdkEvent* ev);
bool on_connection_event(Ganv::Edge* c, GdkEvent* ev);
- Patchage* _app;
+ void on_connect(Ganv::Node* port1, Ganv::Node* port2);
+ void on_disconnect(Ganv::Node* port1, Ganv::Node* port2);
+
+ Connector& _connector;
PortIndex _port_index;
ModuleIndex _module_index;
};
diff --git a/src/PortID.hpp b/src/PortID.hpp
index efdd78d..84c08a4 100644
--- a/src/PortID.hpp
+++ b/src/PortID.hpp
@@ -21,6 +21,7 @@
#include <iostream>
#include <string>
#include <tuple>
+#include <utility>
/// An ID for some port on a client (program)
struct PortID
@@ -133,4 +134,17 @@ operator<(const PortID& lhs, const PortID& rhs)
return false;
}
+namespace std {
+
+template<>
+struct hash<PortID::Type>
+{
+ size_t operator()(const PortID::Type& v) const noexcept
+ {
+ return hash<unsigned>()(static_cast<unsigned>(v));
+ }
+};
+
+} // namespace std
+
#endif // PATCHAGE_PORTID_HPP
diff --git a/wscript b/wscript
index 2d80c4e..b0a0734 100644
--- a/wscript
+++ b/wscript
@@ -239,6 +239,7 @@ def build(bld):
install_path = '${BINDIR}')
prog.source = '''
src/Configuration.cpp
+ src/Connector.cpp
src/Legend.cpp
src/Patchage.cpp
src/PatchageCanvas.cpp