diff options
author | David Robillard <d@drobilla.net> | 2021-05-11 12:04:36 -0400 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2021-05-11 13:35:16 -0400 |
commit | 75ee1ed27d5d2c60e867abef09ee920446ac13de (patch) | |
tree | 7c711813cf6282de24f08c96fd6e5465ea7414e5 | |
parent | 37ede19b4d1e924f954d8b16d3e071a4768ce278 (diff) | |
download | patchage-75ee1ed27d5d2c60e867abef09ee920446ac13de.tar.gz patchage-75ee1ed27d5d2c60e867abef09ee920446ac13de.tar.bz2 patchage-75ee1ed27d5d2c60e867abef09ee920446ac13de.zip |
Move drivers to a separate object
Towards eliminating dependencies on the Patchage "god object".
-rw-r--r-- | src/Drivers.cpp | 66 | ||||
-rw-r--r-- | src/Drivers.hpp | 65 | ||||
-rw-r--r-- | src/Patchage.cpp | 85 | ||||
-rw-r--r-- | src/Patchage.hpp | 15 | ||||
-rw-r--r-- | src/Reactor.cpp | 44 | ||||
-rw-r--r-- | src/Reactor.hpp | 17 | ||||
-rw-r--r-- | wscript | 1 |
7 files changed, 196 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 @@ -240,6 +240,7 @@ def build(bld): src/Canvas.cpp src/CanvasModule.cpp src/Configuration.cpp + src/Drivers.cpp src/Legend.cpp src/Metadata.cpp src/Patchage.cpp |