summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2021-05-11 12:04:36 -0400
committerDavid Robillard <d@drobilla.net>2021-05-11 13:35:16 -0400
commit75ee1ed27d5d2c60e867abef09ee920446ac13de (patch)
tree7c711813cf6282de24f08c96fd6e5465ea7414e5 /src
parent37ede19b4d1e924f954d8b16d3e071a4768ce278 (diff)
downloadpatchage-75ee1ed27d5d2c60e867abef09ee920446ac13de.tar.gz
patchage-75ee1ed27d5d2c60e867abef09ee920446ac13de.tar.bz2
patchage-75ee1ed27d5d2c60e867abef09ee920446ac13de.zip
Move drivers to a separate object
Towards eliminating dependencies on the Patchage "god object".
Diffstat (limited to 'src')
-rw-r--r--src/Drivers.cpp66
-rw-r--r--src/Drivers.hpp65
-rw-r--r--src/Patchage.cpp85
-rw-r--r--src/Patchage.hpp15
-rw-r--r--src/Reactor.cpp44
-rw-r--r--src/Reactor.hpp17
6 files changed, 195 insertions, 97 deletions
diff --git a/src/Drivers.cpp b/src/Drivers.cpp
new file mode 100644
index 0000000..94ab6f9
--- /dev/null
+++ b/src/Drivers.cpp
@@ -0,0 +1,66 @@
+/* This file is part of Patchage.
+ * Copyright 2007-2021 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 "Drivers.hpp"
+
+#include "AudioDriver.hpp"
+#include "Driver.hpp"
+#include "Event.hpp"
+#include "make_alsa_driver.hpp"
+#include "make_jack_driver.hpp"
+
+#include <functional>
+#include <utility>
+
+namespace patchage {
+
+Drivers::Drivers(ILog& log, Driver::EventSink emit_event)
+ : _log{log}
+ , _emit_event{std::move(emit_event)}
+ , _alsa_driver{make_alsa_driver(
+ log,
+ [this](const Event& event) { _emit_event(event); })}
+ , _jack_driver{make_jack_driver(_log, [this](const Event& event) {
+ _emit_event(event);
+ })}
+{}
+
+void
+Drivers::refresh()
+{
+ if (_alsa_driver) {
+ _alsa_driver->refresh(_emit_event);
+ }
+
+ if (_jack_driver) {
+ _jack_driver->refresh(_emit_event);
+ }
+}
+
+Driver*
+Drivers::driver(const ClientType type)
+{
+ switch (type) {
+ case ClientType::jack:
+ return _jack_driver.get();
+ case ClientType::alsa:
+ return _alsa_driver.get();
+ }
+
+ return nullptr;
+}
+
+} // namespace patchage
diff --git a/src/Drivers.hpp b/src/Drivers.hpp
new file mode 100644
index 0000000..0e3cdce
--- /dev/null
+++ b/src/Drivers.hpp
@@ -0,0 +1,65 @@
+/* This file is part of Patchage.
+ * Copyright 2007-2021 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_DRIVERS_HPP
+#define PATCHAGE_DRIVERS_HPP
+
+#include "ClientType.hpp"
+#include "Driver.hpp"
+
+#include <memory>
+
+namespace patchage {
+
+class AudioDriver;
+class ILog;
+
+/// Manager for all drivers
+class Drivers
+{
+public:
+ Drivers(ILog& log, Driver::EventSink emit_event);
+
+ Drivers(const Drivers&) = delete;
+ Drivers& operator=(const Drivers&) = delete;
+
+ Drivers(Drivers&&) = delete;
+ Drivers& operator=(Drivers&&) = delete;
+
+ ~Drivers() = default;
+
+ /// Refresh all drivers and emit results to the event sink
+ void refresh();
+
+ /// Return a pointer to the driver for the given client type (or null)
+ Driver* driver(ClientType type);
+
+ /// Return a pointer to the ALSA driver (or null)
+ const std::unique_ptr<Driver>& alsa() { return _alsa_driver; }
+
+ /// Return a pointer to the JACK driver (or null)
+ const std::unique_ptr<AudioDriver>& jack() { return _jack_driver; }
+
+protected:
+ ILog& _log;
+ std::unique_ptr<Driver> _alsa_driver;
+ std::unique_ptr<AudioDriver> _jack_driver;
+ Driver::EventSink _emit_event;
+};
+
+} // namespace patchage
+
+#endif // PATCHAGE_DRIVER_HPP
diff --git a/src/Patchage.cpp b/src/Patchage.cpp
index bb6b4a8..5045691 100644
--- a/src/Patchage.cpp
+++ b/src/Patchage.cpp
@@ -26,12 +26,9 @@
#include "Driver.hpp"
#include "Event.hpp"
#include "Legend.hpp"
-#include "PortID.hpp"
#include "UIFile.hpp"
#include "event_to_string.hpp"
#include "handle_event.hpp"
-#include "make_alsa_driver.hpp"
-#include "make_jack_driver.hpp"
#include "patchage_config.h" // IWYU pragma: keep
#include "warnings.hpp"
@@ -204,6 +201,7 @@ Patchage::Patchage(Options options)
, _legend(nullptr)
, _log(_status_text)
, _reactor(*this)
+ , _drivers(_log, [this](const Event& event) { on_driver_event(event); })
, _action_sink([this](const Action& action) { _reactor(action); })
, _options{options}
, _pane_initialized(false)
@@ -317,34 +315,23 @@ Patchage::Patchage(Options options)
}
#endif
- // Make Jack driver if possible
- _jack_driver = make_jack_driver(
- _log, [this](const Event& event) { on_driver_event(event); });
-
- if (_jack_driver) {
- _reactor.add_driver(PortID::Type::jack, _jack_driver.get());
-
+ // Enable JACK menu items if driver is present
+ if (_drivers.jack()) {
_menu_jack_connect->signal_activate().connect(sigc::bind(
- sigc::mem_fun(_jack_driver.get(), &AudioDriver::attach), true));
+ sigc::mem_fun(_drivers.jack().get(), &AudioDriver::attach), true));
_menu_jack_disconnect->signal_activate().connect(
- sigc::mem_fun(_jack_driver.get(), &AudioDriver::detach));
+ sigc::mem_fun(_drivers.jack().get(), &AudioDriver::detach));
} else {
_menu_jack_connect->set_sensitive(false);
_menu_jack_disconnect->set_sensitive(false);
}
- // Make ALSA driver if possible
- _alsa_driver = make_alsa_driver(
- _log, [this](const Event& event) { on_driver_event(event); });
-
- if (_alsa_driver) {
- _reactor.add_driver(PortID::Type::alsa, _alsa_driver.get());
-
+ // Enable ALSA menu items if driver is present
+ if (_drivers.alsa()) {
_menu_alsa_connect->signal_activate().connect(
- sigc::bind(sigc::mem_fun(_alsa_driver.get(), &Driver::attach), false));
+ sigc::bind(sigc::mem_fun(_drivers.alsa().get(), &Driver::attach), false));
_menu_alsa_disconnect->signal_activate().connect(
- sigc::mem_fun(_alsa_driver.get(), &Driver::detach));
-
+ sigc::mem_fun(_drivers.alsa().get(), &Driver::detach));
} else {
_menu_alsa_connect->set_sensitive(false);
_menu_alsa_disconnect->set_sensitive(false);
@@ -385,8 +372,6 @@ Patchage::Patchage(Options options)
Patchage::~Patchage()
{
- _jack_driver.reset();
- _alsa_driver.reset();
_about_win.destroy();
_xml.reset();
}
@@ -394,12 +379,12 @@ Patchage::~Patchage()
void
Patchage::attach()
{
- if (_jack_driver && _options.jack_driver_autoattach) {
- _jack_driver->attach(true);
+ if (_drivers.jack() && _options.jack_driver_autoattach) {
+ _drivers.jack()->attach(true);
}
- if (_alsa_driver && _options.alsa_driver_autoattach) {
- _alsa_driver->attach(false);
+ if (_drivers.alsa() && _options.alsa_driver_autoattach) {
+ _drivers.alsa()->attach(false);
}
process_events();
@@ -440,9 +425,9 @@ Patchage::update_toolbar()
updating = true;
- if (_jack_driver && _jack_driver->is_attached()) {
- const auto buffer_size = _jack_driver->buffer_size();
- const auto sample_rate = _jack_driver->sample_rate();
+ if (_drivers.jack() && _drivers.jack()->is_attached()) {
+ const auto buffer_size = _drivers.jack()->buffer_size();
+ const auto sample_rate = _drivers.jack()->sample_rate();
if (sample_rate != 0) {
const auto latency_ms = buffer_size * 1000 / float(sample_rate);
@@ -450,7 +435,7 @@ Patchage::update_toolbar()
" frames @ {} kHz ({:0.2f} ms)", sample_rate / 1000, latency_ms));
_latency_label->set_visible(true);
_buf_size_combo->set_active(
- static_cast<int>(log2f(_jack_driver->buffer_size()) - 5));
+ static_cast<int>(log2f(_drivers.jack()->buffer_size()) - 5));
updating = false;
return;
}
@@ -463,8 +448,8 @@ Patchage::update_toolbar()
bool
Patchage::update_load()
{
- if (_jack_driver && _jack_driver->is_attached()) {
- const auto xruns = _jack_driver->xruns();
+ if (_drivers.jack() && _drivers.jack()->is_attached()) {
+ const auto xruns = _drivers.jack()->xruns();
if (xruns > 0u) {
_dropouts_label->set_text(fmt::format(" Dropouts: {}", xruns));
_dropouts_label->show();
@@ -490,12 +475,12 @@ Patchage::refresh()
if (_canvas) {
_canvas->clear();
- if (_jack_driver) {
- _jack_driver->refresh(sink);
+ if (_drivers.jack()) {
+ _drivers.jack()->refresh(sink);
}
- if (_alsa_driver) {
- _alsa_driver->refresh(sink);
+ if (_drivers.alsa()) {
+ _drivers.alsa()->refresh(sink);
}
}
}
@@ -508,8 +493,8 @@ Patchage::driver_attached(const ClientType type)
_menu_jack_connect->set_sensitive(false);
_menu_jack_disconnect->set_sensitive(true);
- if (_jack_driver) {
- _jack_driver->refresh(
+ if (_drivers.jack()) {
+ _drivers.jack()->refresh(
[this](const Event& event) { handle_event(*this, event); });
}
@@ -518,8 +503,8 @@ Patchage::driver_attached(const ClientType type)
_menu_alsa_connect->set_sensitive(false);
_menu_alsa_disconnect->set_sensitive(true);
- if (_alsa_driver) {
- _alsa_driver->refresh(
+ if (_drivers.alsa()) {
+ _drivers.alsa()->refresh(
[this](const Event& event) { handle_event(*this, event); });
}
@@ -577,8 +562,8 @@ Patchage::clear_load()
_dropouts_label->set_text(" Dropouts: 0");
_dropouts_label->hide();
_clear_load_but->hide();
- if (_jack_driver) {
- _jack_driver->reset_xruns();
+ if (_drivers.jack()) {
+ _drivers.jack()->reset_xruns();
}
}
@@ -792,12 +777,12 @@ Patchage::quit()
void
Patchage::on_quit()
{
- if (_alsa_driver) {
- _alsa_driver->detach();
+ if (_drivers.alsa()) {
+ _drivers.alsa()->detach();
}
- if (_jack_driver) {
- _jack_driver->detach();
+ if (_drivers.jack()) {
+ _drivers.jack()->detach();
}
_main_win->hide();
@@ -895,14 +880,14 @@ Patchage::on_scroll(GdkEventScroll*)
void
Patchage::buffer_size_changed()
{
- if (_jack_driver) {
+ if (_drivers.jack()) {
const int selected = _buf_size_combo->get_active_row_number();
if (selected == -1) {
update_toolbar();
} else {
const uint32_t buffer_size = 1u << (selected + 5);
- _jack_driver->set_buffer_size(buffer_size);
+ _drivers.jack()->set_buffer_size(buffer_size);
update_toolbar();
}
}
diff --git a/src/Patchage.hpp b/src/Patchage.hpp
index 38917cf..4dc2ecf 100644
--- a/src/Patchage.hpp
+++ b/src/Patchage.hpp
@@ -27,6 +27,7 @@
#include "ActionSink.hpp"
#include "ClientType.hpp"
#include "Configuration.hpp"
+#include "Drivers.hpp"
#include "Event.hpp"
#include "Metadata.hpp"
#include "Options.hpp"
@@ -66,9 +67,7 @@ class Window;
namespace patchage {
-class AudioDriver;
class Canvas;
-class Driver;
class ILog;
class Legend;
@@ -102,6 +101,7 @@ public:
bool sort_ports() const { return _menu_view_sort_ports->get_active(); }
+ Drivers& drivers() { return _drivers; }
Gtk::Window* window() { return _main_win.get(); }
ILog& log() { return _log; }
Metadata& metadata() { return _metadata; }
@@ -155,15 +155,11 @@ protected:
Glib::RefPtr<Gtk::Builder> _xml;
- std::mutex _events_mutex;
- std::queue<Event> _driver_events;
-
- std::unique_ptr<Driver> _alsa_driver;
-
+ std::mutex _events_mutex;
+ std::queue<Event> _driver_events;
std::unique_ptr<Canvas> _canvas;
- std::unique_ptr<AudioDriver> _jack_driver;
- Configuration _conf;
+ Configuration _conf;
BufferSizeColumns _buf_size_columns;
@@ -205,6 +201,7 @@ protected:
Legend* _legend;
TextViewLog _log;
Metadata _metadata;
+ Drivers _drivers;
Reactor _reactor;
ActionSink _action_sink;
diff --git a/src/Reactor.cpp b/src/Reactor.cpp
index f8504a1..b875eb2 100644
--- a/src/Reactor.cpp
+++ b/src/Reactor.cpp
@@ -21,6 +21,7 @@
#include "CanvasPort.hpp"
#include "Configuration.hpp"
#include "Driver.hpp"
+#include "Drivers.hpp"
#include "ILog.hpp"
#include "Patchage.hpp"
#include "PortID.hpp"
@@ -35,37 +36,27 @@ PATCHAGE_RESTORE_WARNINGS
#include <boost/variant/apply_visitor.hpp>
#include <memory>
-#include <unordered_map>
-#include <utility>
namespace patchage {
Reactor::Reactor(Patchage& patchage)
: _patchage{patchage}
, _log{patchage.log()}
+ , _drivers{patchage.drivers()}
{}
void
-Reactor::add_driver(PortID::Type type, Driver* driver)
-{
- _drivers.emplace(type, driver);
-}
-
-void
Reactor::operator()(const action::ConnectPorts& action)
{
- if (action.tail.type() != action.head.type()) {
+ if (action.tail.type() == action.head.type()) {
+ if (auto* d = _drivers.driver(action.tail.type())) {
+ d->connect(action.tail, action.head);
+ } else {
+ _log.error(fmt::format("No driver for port type {}", action.tail.type()));
+ }
+ } else {
_log.warning("Unable to connect incompatible port types");
- return;
- }
-
- auto d = _drivers.find(action.tail.type());
- if (d == _drivers.end()) {
- _log.error(fmt::format("No driver for port type {}", action.tail.type()));
- return;
}
-
- d->second->connect(action.tail, action.head);
}
void
@@ -89,18 +80,15 @@ Reactor::operator()(const action::DisconnectPort& action)
void
Reactor::operator()(const action::DisconnectPorts& action)
{
- if (action.tail.type() != action.head.type()) {
+ if (action.tail.type() == action.head.type()) {
+ if (auto* d = _drivers.driver(action.tail.type())) {
+ d->disconnect(action.tail, action.head);
+ } else {
+ _log.error(fmt::format("No driver for port type {}", action.tail.type()));
+ }
+ } else {
_log.error("Unable to disconnect incompatible port types");
- return;
}
-
- auto d = _drivers.find(action.tail.type());
- if (d == _drivers.end()) {
- _log.error("No driver for port type");
- return;
- }
-
- d->second->disconnect(action.tail, action.head);
}
void
diff --git a/src/Reactor.hpp b/src/Reactor.hpp
index 04b699d..9317b0a 100644
--- a/src/Reactor.hpp
+++ b/src/Reactor.hpp
@@ -18,19 +18,18 @@
#define PATCHAGE_REACTOR_HPP
#include "Action.hpp"
-#include "PortID.hpp"
#include "SignalDirection.hpp"
-#include <unordered_map>
-
namespace patchage {
+struct PortID;
+
class CanvasModule;
class CanvasPort;
-class Driver;
+class ClientID;
+class Drivers;
class ILog;
class Patchage;
-class ClientID;
/// Reacts to actions from the user
class Reactor
@@ -48,8 +47,6 @@ public:
~Reactor() = default;
- void add_driver(PortID::Type type, Driver* driver);
-
void operator()(const action::ConnectPorts& action);
void operator()(const action::DisconnectClient& action);
void operator()(const action::DisconnectPort& action);
@@ -64,9 +61,9 @@ private:
CanvasModule* find_module(const ClientID& client, SignalDirection type);
CanvasPort* find_port(const PortID& port);
- Patchage& _patchage;
- ILog& _log;
- std::unordered_map<PortID::Type, Driver*> _drivers;
+ Patchage& _patchage;
+ ILog& _log;
+ Drivers& _drivers;
};
} // namespace patchage