diff options
Diffstat (limited to 'src')
56 files changed, 1136 insertions, 1505 deletions
diff --git a/src/Action.hpp b/src/Action.hpp index 0a13216..c791445 100644 --- a/src/Action.hpp +++ b/src/Action.hpp @@ -1,18 +1,5 @@ -/* 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/>. - */ +// Copyright 2007-2021 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef PATCHAGE_ACTION_HPP #define PATCHAGE_ACTION_HPP @@ -22,7 +9,7 @@ #include "Setting.hpp" #include "SignalDirection.hpp" -#include <boost/variant/variant.hpp> +#include <variant> namespace patchage { namespace action { @@ -81,22 +68,22 @@ struct ZoomOut {}; } // namespace action /// A high-level action from the user -using Action = boost::variant<action::ChangeSetting, - action::ConnectPorts, - action::DecreaseFontSize, - action::DisconnectClient, - action::DisconnectPort, - action::DisconnectPorts, - action::IncreaseFontSize, - action::MoveModule, - action::Refresh, - action::ResetFontSize, - action::SplitModule, - action::UnsplitModule, - action::ZoomFull, - action::ZoomIn, - action::ZoomNormal, - action::ZoomOut>; +using Action = std::variant<action::ChangeSetting, + action::ConnectPorts, + action::DecreaseFontSize, + action::DisconnectClient, + action::DisconnectPort, + action::DisconnectPorts, + action::IncreaseFontSize, + action::MoveModule, + action::Refresh, + action::ResetFontSize, + action::SplitModule, + action::UnsplitModule, + action::ZoomFull, + action::ZoomIn, + action::ZoomNormal, + action::ZoomOut>; } // namespace patchage diff --git a/src/ActionSink.hpp b/src/ActionSink.hpp index c0d92ec..7e023f8 100644 --- a/src/ActionSink.hpp +++ b/src/ActionSink.hpp @@ -1,18 +1,5 @@ -/* 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/>. - */ +// Copyright 2007-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef PATCHAGE_ACTION_SINK_HPP #define PATCHAGE_ACTION_SINK_HPP diff --git a/src/AlsaDriver.cpp b/src/AlsaDriver.cpp index 8ad3569..d320135 100644 --- a/src/AlsaDriver.cpp +++ b/src/AlsaDriver.cpp @@ -1,18 +1,5 @@ -/* 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/>. - */ +// Copyright 2007-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #include "make_alsa_driver.hpp" @@ -30,23 +17,21 @@ PATCHAGE_DISABLE_FMT_WARNINGS #include <fmt/core.h> -#include <fmt/ostream.h> PATCHAGE_RESTORE_WARNINGS #include <alsa/asoundlib.h> #include <pthread.h> -#include <boost/optional/optional.hpp> - #include <cassert> #include <cstdint> #include <functional> -#include <iosfwd> #include <limits> #include <memory> +#include <optional> #include <set> #include <string> #include <utility> +#include <variant> namespace patchage { namespace { @@ -57,10 +42,10 @@ class AlsaDriver : public Driver public: explicit AlsaDriver(ILog& log, EventSink emit_event); - AlsaDriver(const AlsaDriver&) = delete; + AlsaDriver(const AlsaDriver&) = delete; AlsaDriver& operator=(const AlsaDriver&) = delete; - AlsaDriver(AlsaDriver&&) = delete; + AlsaDriver(AlsaDriver&&) = delete; AlsaDriver& operator=(AlsaDriver&&) = delete; ~AlsaDriver() override; @@ -82,8 +67,8 @@ private: void _refresh_main(); ILog& _log; - snd_seq_t* _seq; - pthread_t _refresh_thread; + snd_seq_t* _seq{nullptr}; + pthread_t _refresh_thread{}; struct SeqAddrComparator { bool operator()(const snd_seq_addr_t& a, const snd_seq_addr_t& b) const @@ -109,7 +94,7 @@ addr_to_id(const snd_seq_addr_t& addr, const bool is_input) SignalDirection port_direction(const snd_seq_port_info_t* const pinfo) { - const int caps = snd_seq_port_info_get_capability(pinfo); + const unsigned caps = snd_seq_port_info_get_capability(pinfo); if ((caps & SND_SEQ_PORT_CAP_READ) && (caps & SND_SEQ_PORT_CAP_WRITE)) { return SignalDirection::duplex; @@ -135,7 +120,7 @@ client_info(snd_seq_client_info_t* const cinfo) PortInfo port_info(const snd_seq_port_info_t* const pinfo) { - const int type = snd_seq_port_info_get_type(pinfo); + const unsigned type = snd_seq_port_info_get_type(pinfo); return {snd_seq_port_info_get_name(pinfo), PortType::alsa_midi, @@ -147,14 +132,9 @@ port_info(const snd_seq_port_info_t* const pinfo) AlsaDriver::AlsaDriver(ILog& log, EventSink emit_event) : Driver{std::move(emit_event)} , _log(log) - , _seq(nullptr) - , _refresh_thread{} {} -AlsaDriver::~AlsaDriver() -{ - detach(); -} +AlsaDriver::~AlsaDriver() = default; void AlsaDriver::attach(bool /*launch_daemon*/) @@ -299,8 +279,8 @@ AlsaDriver::ignore(const snd_seq_addr_t& addr, bool add) snd_seq_port_info_set_port(pinfo, addr.port); snd_seq_get_any_port_info(_seq, addr.client, addr.port, pinfo); - const int type = snd_seq_port_info_get_type(pinfo); - const int caps = snd_seq_port_info_get_capability(pinfo); + const unsigned type = snd_seq_port_info_get_type(pinfo); + const unsigned caps = snd_seq_port_info_get_capability(pinfo); if (caps & SND_SEQ_PORT_CAP_NO_EXPORT) { _ignored.insert(addr); @@ -357,7 +337,7 @@ AlsaDriver::connect(const PortID& tail_id, const PortID& head_id) result = false; } - int ret = snd_seq_subscribe_port(_seq, subs); + const int ret = snd_seq_subscribe_port(_seq, subs); if (ret < 0) { _log.error( fmt::format("[ALSA] Subscription failed ({})", snd_strerror(ret))); @@ -398,7 +378,7 @@ AlsaDriver::disconnect(const PortID& tail_id, const PortID& head_id) return false; } - int ret = snd_seq_unsubscribe_port(_seq, subs); + const int ret = snd_seq_unsubscribe_port(_seq, subs); if (ret < 0) { _log.error(fmt::format("[ALSA] Failed to disconnect {} => {} ({})", tail_id, @@ -413,16 +393,16 @@ AlsaDriver::disconnect(const PortID& tail_id, const PortID& head_id) bool AlsaDriver::create_refresh_port() { - snd_seq_port_info_t* port_info = nullptr; - snd_seq_port_info_alloca(&port_info); - snd_seq_port_info_set_name(port_info, "System Announcement Receiver"); - snd_seq_port_info_set_type(port_info, SND_SEQ_PORT_TYPE_APPLICATION); - snd_seq_port_info_set_capability(port_info, + snd_seq_port_info_t* info = nullptr; + snd_seq_port_info_alloca(&info); + snd_seq_port_info_set_name(info, "System Announcement Receiver"); + snd_seq_port_info_set_type(info, SND_SEQ_PORT_TYPE_APPLICATION); + snd_seq_port_info_set_capability(info, SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE | SND_SEQ_PORT_CAP_NO_EXPORT); - int ret = snd_seq_create_port(_seq, port_info); + int ret = snd_seq_create_port(_seq, info); if (ret) { _log.error( fmt::format("[ALSA] Error creating port ({})", snd_strerror(ret))); @@ -431,7 +411,7 @@ AlsaDriver::create_refresh_port() // Subscribe the port to the system announcer ret = snd_seq_connect_from(_seq, - snd_seq_port_info_get_port(port_info), + snd_seq_port_info_get_port(info), SND_SEQ_CLIENT_SYSTEM, SND_SEQ_PORT_SYSTEM_ANNOUNCE); if (ret) { @@ -460,7 +440,7 @@ AlsaDriver::_refresh_main() return; } - int caps = 0; + unsigned caps = 0U; snd_seq_client_info_t* cinfo = nullptr; snd_seq_client_info_alloca(&cinfo); diff --git a/src/AlsaStubDriver.cpp b/src/AlsaStubDriver.cpp new file mode 100644 index 0000000..5dc8f0b --- /dev/null +++ b/src/AlsaStubDriver.cpp @@ -0,0 +1,18 @@ +// Copyright 2007-2022 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "AudioDriver.hpp" +#include "Driver.hpp" +#include "make_alsa_driver.hpp" + +#include <memory> + +namespace patchage { + +std::unique_ptr<Driver> +make_alsa_driver(ILog&, Driver::EventSink) +{ + return nullptr; +} + +} // namespace patchage diff --git a/src/AudioDriver.hpp b/src/AudioDriver.hpp index 06cfe7f..ac3d5ec 100644 --- a/src/AudioDriver.hpp +++ b/src/AudioDriver.hpp @@ -1,18 +1,5 @@ -/* 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/>. - */ +// Copyright 2007-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef PATCHAGE_AUDIODRIVER_HPP #define PATCHAGE_AUDIODRIVER_HPP diff --git a/src/Canvas.cpp b/src/Canvas.cpp index d86049d..ae8c51d 100644 --- a/src/Canvas.cpp +++ b/src/Canvas.cpp @@ -1,29 +1,20 @@ -/* 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/>. - */ +// Copyright 2007-2022 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #include "Canvas.hpp" #include "Action.hpp" +#include "ActionSink.hpp" #include "CanvasModule.hpp" #include "CanvasPort.hpp" +#include "ClientID.hpp" #include "ClientInfo.hpp" +#include "ClientType.hpp" #include "Configuration.hpp" #include "Coord.hpp" #include "ILog.hpp" #include "Metadata.hpp" +#include "PortID.hpp" #include "PortInfo.hpp" #include "PortNames.hpp" #include "Setting.hpp" @@ -31,37 +22,84 @@ #include "warnings.hpp" PATCHAGE_DISABLE_GANV_WARNINGS -#include "ganv/Edge.hpp" -#include "ganv/Module.hpp" -#include "ganv/Node.hpp" -#include "ganv/Port.hpp" -#include "ganv/module.h" +#include <ganv/Canvas.hpp> +#include <ganv/Edge.hpp> +#include <ganv/Module.hpp> +#include <ganv/Node.hpp> +#include <ganv/Port.hpp> +#include <ganv/module.h> +#include <ganv/types.h> PATCHAGE_RESTORE_WARNINGS PATCHAGE_DISABLE_FMT_WARNINGS #include <fmt/core.h> -#include <fmt/ostream.h> PATCHAGE_RESTORE_WARNINGS -#include <boost/optional/optional.hpp> #include <gdk/gdkkeysyms.h> #include <sigc++/functors/mem_fun.h> #include <sigc++/signal.h> #include <cassert> -#include <cstdlib> #include <functional> -#include <iosfwd> +#include <optional> #include <set> #include <string> #include <utility> +#include <variant> namespace patchage { +namespace { + +struct RemovePortsData { + using Predicate = bool (*)(const CanvasPort*); + + explicit RemovePortsData(Predicate p) + : pred(p) + {} + + Predicate pred; + std::set<ClientID> empty_clients; +}; + +void +delete_port_if_matches(GanvPort* port, void* cdata) +{ + auto* data = static_cast<RemovePortsData*>(cdata); + auto* pport = dynamic_cast<CanvasPort*>(Glib::wrap(port)); + if (pport && data->pred(pport)) { + delete pport; + } +} + +void +remove_ports_matching(GanvNode* node, void* cdata) +{ + if (!GANV_IS_MODULE(node)) { + return; + } + + Ganv::Module* cmodule = Glib::wrap(GANV_MODULE(node)); + auto* pmodule = dynamic_cast<CanvasModule*>(cmodule); + if (!pmodule) { + return; + } + + auto* data = static_cast<RemovePortsData*>(cdata); + + pmodule->for_each_port(delete_port_if_matches, data); + + if (pmodule->num_ports() == 0) { + data->empty_clients.insert(pmodule->id()); + } +} + +} // namespace Canvas::Canvas(ILog& log, ActionSink& action_sink, int width, int height) : Ganv::Canvas(width, height) , _log(log) , _action_sink(action_sink) + , _rng(width + height) { signal_event.connect(sigc::mem_fun(this, &Canvas::on_event)); signal_connect.connect(sigc::mem_fun(this, &Canvas::on_connect)); @@ -85,7 +123,7 @@ Canvas::create_port(Configuration& conf, const auto client_info = metadata.client(client_id); if (!client_info) { _log.error(fmt::format( - R"(Unable to add port "{}", client "{}" is unknown)", id, client_id)); + u8"(Unable to add port “{}”, client “{}” is unknown)", id, client_id)); return nullptr; } @@ -108,8 +146,8 @@ Canvas::create_port(Configuration& conf, Coord loc; if (!conf.get_module_location(client_name, module_type, loc)) { // No position saved, come up with a pseudo-random one - loc.x = 20 + rand() % 640; - loc.y = 20 + rand() % 480; + loc.x = static_cast<double>(20 + (_rng() % 640)); + loc.y = static_cast<double>(20 + (_rng() % 480)); conf.set_module_location(client_name, module_type, loc); } @@ -123,7 +161,7 @@ Canvas::create_port(Configuration& conf, if (parent->get_port(id)) { // TODO: Update existing port? _log.error(fmt::format( - R"(Module "{}" already has port "{}")", client_name, port_name)); + u8"(Module “{}” already has port “{}”)", client_name, port_name)); return nullptr; } @@ -192,49 +230,6 @@ Canvas::remove_port(const PortID& id) delete port; } -struct RemovePortsData { - using Predicate = bool (*)(const CanvasPort*); - - explicit RemovePortsData(Predicate p) - : pred(p) - {} - - Predicate pred; - std::set<ClientID> empty_clients; -}; - -static void -delete_port_if_matches(GanvPort* port, void* cdata) -{ - auto* data = static_cast<RemovePortsData*>(cdata); - auto* pport = dynamic_cast<CanvasPort*>(Glib::wrap(port)); - if (pport && data->pred(pport)) { - delete pport; - } -} - -static void -remove_ports_matching(GanvNode* node, void* cdata) -{ - if (!GANV_IS_MODULE(node)) { - return; - } - - Ganv::Module* cmodule = Glib::wrap(GANV_MODULE(node)); - auto* pmodule = dynamic_cast<CanvasModule*>(cmodule); - if (!pmodule) { - return; - } - - auto* data = static_cast<RemovePortsData*>(cdata); - - pmodule->for_each_port(delete_port_if_matches, data); - - if (pmodule->num_ports() == 0) { - data->empty_clients.insert(pmodule->id()); - } -} - void Canvas::remove_ports(bool (*pred)(const CanvasPort*)) { diff --git a/src/Canvas.hpp b/src/Canvas.hpp index 943b399..5ab8a7e 100644 --- a/src/Canvas.hpp +++ b/src/Canvas.hpp @@ -1,18 +1,5 @@ -/* 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/>. - */ +// Copyright 2007-2021 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef PATCHAGE_CANVAS_HPP #define PATCHAGE_CANVAS_HPP @@ -20,17 +7,17 @@ #include "ActionSink.hpp" #include "ClientID.hpp" #include "PortID.hpp" -#include "SignalDirection.hpp" #include "warnings.hpp" PATCHAGE_DISABLE_GANV_WARNINGS -#include "ganv/Canvas.hpp" -#include "ganv/types.h" +#include <ganv/Canvas.hpp> +#include <ganv/types.h> PATCHAGE_RESTORE_WARNINGS #include <gdk/gdk.h> #include <map> +#include <random> namespace Ganv { class Node; @@ -38,6 +25,8 @@ class Node; namespace patchage { +enum class SignalDirection; + struct PortInfo; class CanvasModule; @@ -86,6 +75,8 @@ private: ActionSink& _action_sink; PortIndex _port_index; ModuleIndex _module_index; + + std::minstd_rand _rng; }; } // namespace patchage diff --git a/src/CanvasModule.cpp b/src/CanvasModule.cpp index d9e3c9c..43d2c8d 100644 --- a/src/CanvasModule.cpp +++ b/src/CanvasModule.cpp @@ -1,33 +1,23 @@ -/* This file is part of Patchage. - * Copyright 2010-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/>. - */ +// Copyright 2010-2021 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #include "CanvasModule.hpp" #include "Action.hpp" +#include "ActionSink.hpp" #include "Canvas.hpp" #include "CanvasPort.hpp" +#include "ClientID.hpp" #include "PortID.hpp" #include "SignalDirection.hpp" +#include "i18n.hpp" #include "warnings.hpp" PATCHAGE_DISABLE_GANV_WARNINGS -#include "ganv/Port.hpp" +#include <ganv/Module.hpp> +#include <ganv/Port.hpp> PATCHAGE_RESTORE_WARNINGS -#include <glibmm/helperlist.h> #include <gtkmm/menu.h> #include <gtkmm/menu_elems.h> #include <gtkmm/menuitem.h> @@ -39,6 +29,7 @@ PATCHAGE_RESTORE_WARNINGS #include <functional> #include <memory> #include <utility> +#include <variant> namespace patchage { @@ -94,21 +85,21 @@ CanvasModule::update_menu() bool CanvasModule::show_menu(GdkEventButton* ev) { - _menu = std::unique_ptr<Gtk::Menu>{new Gtk::Menu()}; + _menu = std::make_unique<Gtk::Menu>(); Gtk::Menu::MenuList& items = _menu->items(); if (_type == SignalDirection::duplex) { items.push_back(Gtk::Menu_Helpers::MenuElem( - "_Split", sigc::mem_fun(this, &CanvasModule::on_split))); + T("_Split"), sigc::mem_fun(this, &CanvasModule::on_split))); update_menu(); } else { items.push_back(Gtk::Menu_Helpers::MenuElem( - "_Join", sigc::mem_fun(this, &CanvasModule::on_join))); + T("_Join"), sigc::mem_fun(this, &CanvasModule::on_join))); } items.push_back(Gtk::Menu_Helpers::MenuElem( - "_Disconnect", sigc::mem_fun(this, &CanvasModule::on_disconnect))); + T("_Disconnect"), sigc::mem_fun(this, &CanvasModule::on_disconnect))); _menu->popup(ev->button, ev->time); return true; diff --git a/src/CanvasModule.hpp b/src/CanvasModule.hpp index e86699c..2ba7570 100644 --- a/src/CanvasModule.hpp +++ b/src/CanvasModule.hpp @@ -1,29 +1,15 @@ -/* 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/>. - */ +// Copyright 2007-2021 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef PATCHAGE_CANVASMODULE_HPP #define PATCHAGE_CANVASMODULE_HPP #include "ActionSink.hpp" #include "ClientID.hpp" -#include "SignalDirection.hpp" #include "warnings.hpp" PATCHAGE_DISABLE_GANV_WARNINGS -#include "ganv/Module.hpp" +#include <ganv/Module.hpp> PATCHAGE_RESTORE_WARNINGS #include <gdk/gdk.h> @@ -34,6 +20,8 @@ PATCHAGE_RESTORE_WARNINGS namespace patchage { +enum class SignalDirection; + struct PortID; class Canvas; @@ -50,10 +38,10 @@ public: double x, double y); - CanvasModule(const CanvasModule&) = delete; + CanvasModule(const CanvasModule&) = delete; CanvasModule& operator=(const CanvasModule&) = delete; - CanvasModule(CanvasModule&&) = delete; + CanvasModule(CanvasModule&&) = delete; CanvasModule& operator=(CanvasModule&&) = delete; ~CanvasModule() override = default; @@ -64,7 +52,7 @@ public: CanvasPort* get_port(const PortID& id); SignalDirection type() const { return _type; } - ClientID id() const { return _id; } + const ClientID& id() const { return _id; } const std::string& name() const { return _name; } protected: diff --git a/src/CanvasPort.hpp b/src/CanvasPort.hpp index 3376e15..1210519 100644 --- a/src/CanvasPort.hpp +++ b/src/CanvasPort.hpp @@ -1,31 +1,18 @@ -/* 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/>. - */ +// Copyright 2007-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef PATCHAGE_CANVASPORT_HPP #define PATCHAGE_CANVASPORT_HPP #include "PortID.hpp" #include "PortType.hpp" +#include "i18n.hpp" #include "warnings.hpp" PATCHAGE_DISABLE_GANV_WARNINGS -#include "ganv/Port.hpp" +#include <ganv/Port.hpp> PATCHAGE_RESTORE_WARNINGS -#include <boost/optional/optional.hpp> #include <gdk/gdk.h> #include <gtkmm/menu.h> #include <gtkmm/menu_elems.h> @@ -35,6 +22,7 @@ PATCHAGE_RESTORE_WARNINGS #include <sigc++/signal.h> #include <cstdint> +#include <optional> #include <string> #include <utility> @@ -48,15 +36,15 @@ namespace patchage { class CanvasPort : public Ganv::Port { public: - CanvasPort(Ganv::Module& module, - PortType type, - PortID id, - const std::string& name, - const std::string& human_name, - bool is_input, - uint32_t color, - bool show_human_name, - boost::optional<int> order = boost::optional<int>()) + CanvasPort(Ganv::Module& module, + PortType type, + PortID id, + const std::string& name, + const std::string& human_name, + bool is_input, + uint32_t color, + bool show_human_name, + std::optional<int> order = std::optional<int>()) : Port(module, (show_human_name && !human_name.empty()) ? human_name : name, is_input, @@ -70,10 +58,10 @@ public: signal_event().connect(sigc::mem_fun(this, &CanvasPort::on_event)); } - CanvasPort(const CanvasPort&) = delete; + CanvasPort(const CanvasPort&) = delete; CanvasPort& operator=(const CanvasPort&) = delete; - CanvasPort(CanvasPort&&) = delete; + CanvasPort(CanvasPort&&) = delete; CanvasPort& operator=(CanvasPort&&) = delete; ~CanvasPort() override = default; @@ -95,24 +83,24 @@ public: Gtk::Menu* menu = Gtk::manage(new Gtk::Menu()); menu->items().push_back(Gtk::Menu_Helpers::MenuElem( - "Disconnect", sigc::mem_fun(this, &Port::disconnect))); + T("Disconnect"), sigc::mem_fun(this, &Port::disconnect))); menu->popup(ev->button.button, ev->button.time); return true; } - PortType type() const { return _type; } - PortID id() const { return _id; } - const std::string& name() const { return _name; } - const std::string& human_name() const { return _human_name; } - const boost::optional<int>& order() const { return _order; } + PortType type() const { return _type; } + const PortID& id() const { return _id; } + const std::string& name() const { return _name; } + const std::string& human_name() const { return _human_name; } + const std::optional<int>& order() const { return _order; } private: - PortType _type; - PortID _id; - std::string _name; - std::string _human_name; - boost::optional<int> _order; + PortType _type; + PortID _id; + std::string _name; + std::string _human_name; + std::optional<int> _order; }; } // namespace patchage diff --git a/src/ClientID.hpp b/src/ClientID.hpp index 911d2ec..dbe5b75 100644 --- a/src/ClientID.hpp +++ b/src/ClientID.hpp @@ -1,23 +1,16 @@ -/* This file is part of Patchage. - * Copyright 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/>. - */ +// Copyright 2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef PATCHAGE_CLIENTID_HPP #define PATCHAGE_CLIENTID_HPP #include "ClientType.hpp" +#include "warnings.hpp" + +PATCHAGE_DISABLE_FMT_WARNINGS +#include <fmt/core.h> +#include <fmt/ostream.h> +PATCHAGE_RESTORE_WARNINGS #include <cassert> #include <cstdint> @@ -31,10 +24,10 @@ namespace patchage { struct ClientID { using Type = ClientType; - ClientID(const ClientID& copy) = default; + ClientID(const ClientID& copy) = default; ClientID& operator=(const ClientID& copy) = default; - ClientID(ClientID&& id) = default; + ClientID(ClientID&& id) = default; ClientID& operator=(ClientID&& id) = default; ~ClientID() = default; @@ -67,26 +60,26 @@ private: assert(_type == Type::alsa); } - Type _type; ///< Determines which field is active - std::string _jack_name{}; ///< Client name for Type::jack - uint8_t _alsa_id{}; ///< Client ID for Type::alsa + Type _type; ///< Determines which field is active + std::string _jack_name; ///< Client name for Type::jack + uint8_t _alsa_id{}; ///< Client ID for Type::alsa }; -static inline std::ostream& +inline std::ostream& operator<<(std::ostream& os, const ClientID& id) { switch (id.type()) { case ClientID::Type::jack: return os << "jack:" << id.jack_name(); case ClientID::Type::alsa: - return os << "alsa:" << int(id.alsa_id()); + return os << "alsa:" << static_cast<int>(id.alsa_id()); } assert(false); return os; } -static inline bool +inline bool operator==(const ClientID& lhs, const ClientID& rhs) { if (lhs.type() != rhs.type()) { @@ -104,7 +97,7 @@ operator==(const ClientID& lhs, const ClientID& rhs) return false; } -static inline bool +inline bool operator<(const ClientID& lhs, const ClientID& rhs) { if (lhs.type() != rhs.type()) { @@ -124,4 +117,7 @@ operator<(const ClientID& lhs, const ClientID& rhs) } // namespace patchage +template<> +struct fmt::formatter<patchage::ClientID> : fmt::ostream_formatter {}; + #endif // PATCHAGE_CLIENTID_HPP diff --git a/src/ClientInfo.hpp b/src/ClientInfo.hpp index 8acddfe..2dd755e 100644 --- a/src/ClientInfo.hpp +++ b/src/ClientInfo.hpp @@ -1,18 +1,5 @@ -/* 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/>. - */ +// Copyright 2007-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef PATCHAGE_CLIENTINFO_HPP #define PATCHAGE_CLIENTINFO_HPP diff --git a/src/ClientType.hpp b/src/ClientType.hpp index 4785501..7a3f87a 100644 --- a/src/ClientType.hpp +++ b/src/ClientType.hpp @@ -1,22 +1,18 @@ -/* This file is part of Patchage. - * Copyright 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/>. - */ +// Copyright 2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef PATCHAGE_CLIENTTYPE_HPP #define PATCHAGE_CLIENTTYPE_HPP +#include "warnings.hpp" + +PATCHAGE_DISABLE_FMT_WARNINGS +#include <fmt/core.h> +#include <fmt/ostream.h> +PATCHAGE_RESTORE_WARNINGS + +#include <ostream> + namespace patchage { /// A type of client (program) with supported ports @@ -25,6 +21,22 @@ enum class ClientType { alsa, }; +inline std::ostream& +operator<<(std::ostream& os, const ClientType type) +{ + switch (type) { + case ClientType::jack: + return os << "JACK"; + case ClientType::alsa: + return os << "ALSA"; + } + + return os; +} + } // namespace patchage +template<> +struct fmt::formatter<patchage::ClientType> : fmt::ostream_formatter {}; + #endif // PATCHAGE_CLIENTTYPE_HPP diff --git a/src/Configuration.cpp b/src/Configuration.cpp index e498487..f77f825 100644 --- a/src/Configuration.cpp +++ b/src/Configuration.cpp @@ -1,21 +1,9 @@ -/* 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/>. - */ +// Copyright 2007-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #include "Configuration.hpp" +#include "Coord.hpp" #include "PortType.hpp" #include "Setting.hpp" #include "SignalDirection.hpp" @@ -24,19 +12,45 @@ #include <cctype> #include <cstdlib> #include <fstream> -#include <ios> #include <iostream> #include <limits> #include <utility> #include <vector> namespace patchage { +namespace { + +/// Return a vector of filenames in descending order by preference +std::vector<std::string> +get_filenames() +{ + std::vector<std::string> filenames; + + const char* xdg_config_home = getenv("XDG_CONFIG_HOME"); + const char* home = getenv("HOME"); + + // XDG spec + if (xdg_config_home) { + filenames.push_back(std::string(xdg_config_home) + "/patchagerc"); + } else if (home) { + filenames.push_back(std::string(home) + "/.config/patchagerc"); + } + + // Old location + if (home) { + filenames.push_back(std::string(home) + "/.patchagerc"); + } + + // Current directory (bundle or last-ditch effort) + filenames.emplace_back("patchagerc"); + + return filenames; +} -static const char* const port_type_names[N_PORT_TYPES] = {"JACK_AUDIO", - "JACK_MIDI", - "ALSA_MIDI", - "JACK_OSC", - "JACK_CV"}; +} // namespace + +static const char* const port_type_names[Configuration::n_port_types] = + {"JACK_AUDIO", "JACK_MIDI", "ALSA_MIDI", "JACK_OSC", "JACK_CV"}; Configuration::Configuration(std::function<void(const Setting&)> on_change) : _on_change(std::move(on_change)) @@ -46,7 +60,7 @@ Configuration::Configuration(std::function<void(const Setting&)> on_change) std::get<setting::WindowSize>(_settings).value = Coord{960.0, 540.0}; std::get<setting::Zoom>(_settings).value = 1.0f; -#ifdef PATCHAGE_USE_LIGHT_THEME +#if PATCHAGE_USE_LIGHT_THEME _port_colors[static_cast<unsigned>(PortType::jack_audio)] = _default_port_colors[static_cast<unsigned>(PortType::jack_audio)] = 0xA4BC8CFF; @@ -166,34 +180,6 @@ Configuration::set_module_split(const std::string& name, bool split) } } -/** Return a vector of filenames in descending order by preference. */ -static std::vector<std::string> -get_filenames() -{ - std::vector<std::string> filenames; - std::string prefix; - - const char* xdg_config_home = getenv("XDG_CONFIG_HOME"); - const char* home = getenv("HOME"); - - // XDG spec - if (xdg_config_home) { - filenames.push_back(std::string(xdg_config_home) + "/patchagerc"); - } else if (home) { - filenames.push_back(std::string(home) + "/.config/patchagerc"); - } - - // Old location - if (home) { - filenames.push_back(std::string(home) + "/.patchagerc"); - } - - // Current directory (bundle or last-ditch effort) - filenames.emplace_back("patchagerc"); - - return filenames; -} - void Configuration::load() { @@ -203,13 +189,13 @@ Configuration::load() for (const auto& filename : filenames) { file.open(filename.c_str(), std::ios::in); if (file.good()) { - std::cout << "Loading configuration from " << filename << std::endl; + std::cout << "Loading configuration from " << filename << "\n"; break; } } if (!file.good()) { - std::cout << "No configuration file present" << std::endl; + std::cout << "No configuration file present\n"; return; } @@ -248,7 +234,7 @@ Configuration::load() file >> std::get<setting::HumanNames>(_settings).value; } else if (key == "port_color") { std::string type_name; - uint32_t rgba = 0u; + uint32_t rgba = 0U; file >> type_name; file.ignore(1, '#'); file >> std::hex >> std::uppercase; @@ -256,7 +242,7 @@ Configuration::load() file >> std::dec >> std::nouppercase; bool found = false; - for (int i = 0; i < N_PORT_TYPES; ++i) { + for (unsigned i = 0U; i < n_port_types; ++i) { if (type_name == port_type_names[i]) { _port_colors[i] = rgba; found = true; @@ -264,8 +250,8 @@ Configuration::load() } } if (!found) { - std::cerr << "error: color for unknown port type `" << type_name << "'" - << std::endl; + std::cerr << "error: color for unknown port type `" << type_name + << "'\n"; } } else if (key == "module_position") { Coord loc; @@ -284,7 +270,7 @@ Configuration::load() type = SignalDirection::duplex; } else { std::cerr << "error: bad position type `" << type_str - << "' for module `" << name << "'" << std::endl; + << "' for module `" << name << "'\n"; file.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); continue; } @@ -294,8 +280,7 @@ Configuration::load() set_module_location(name, type, loc); } else { - std::cerr << "warning: unknown configuration key `" << key << "'" - << std::endl; + std::cerr << "warning: unknown configuration key `" << key << "'\n"; file.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); } @@ -308,16 +293,20 @@ Configuration::load() file.close(); } -static inline void +namespace { + +inline void write_module_position(std::ofstream& os, const std::string& name, const char* type, const Coord& loc) { os << "module_position \"" << name << "\"" - << " " << type << " " << loc.x << " " << loc.y << std::endl; + << " " << type << " " << loc.x << " " << loc.y << "\n"; } +} // namespace + void Configuration::save() { @@ -327,36 +316,36 @@ Configuration::save() for (const std::string& filename : filenames) { file.open(filename.c_str(), std::ios::out); if (file.good()) { - std::cout << "Writing configuration to " << filename << std::endl; + std::cout << "Writing configuration to " << filename << "\n"; break; } } if (!file.good()) { - std::cout << "Unable to open configuration file to write" << std::endl; + std::cout << "Unable to open configuration file to write\n"; return; } file << "window_location " << get<setting::WindowLocation>().x << " " - << get<setting::WindowLocation>().y << std::endl; + << get<setting::WindowLocation>().y << "\n"; file << "window_size " << get<setting::WindowSize>().x << " " - << get<setting::WindowSize>().y << std::endl; + << get<setting::WindowSize>().y << "\n"; - file << "zoom_level " << get<setting::Zoom>() << std::endl; - file << "font_size " << get<setting::FontSize>() << std::endl; - file << "show_toolbar " << get<setting::ToolbarVisible>() << std::endl; - file << "sprung_layout " << get<setting::SprungLayout>() << std::endl; - file << "show_messages " << get<setting::MessagesVisible>() << std::endl; - file << "sort_ports " << get<setting::SortedPorts>() << std::endl; - file << "messages_height " << get<setting::MessagesHeight>() << std::endl; - file << "human_names " << get<setting::HumanNames>() << std::endl; + file << "zoom_level " << get<setting::Zoom>() << "\n"; + file << "font_size " << get<setting::FontSize>() << "\n"; + file << "show_toolbar " << get<setting::ToolbarVisible>() << "\n"; + file << "sprung_layout " << get<setting::SprungLayout>() << "\n"; + file << "show_messages " << get<setting::MessagesVisible>() << "\n"; + file << "sort_ports " << get<setting::SortedPorts>() << "\n"; + file << "messages_height " << get<setting::MessagesHeight>() << "\n"; + file << "human_names " << get<setting::HumanNames>() << "\n"; file << std::hex << std::uppercase; - for (int i = 0; i < N_PORT_TYPES; ++i) { + for (unsigned i = 0U; i < n_port_types; ++i) { if (_port_colors[i] != _default_port_colors[i]) { file << "port_color " << port_type_names[i] << " " << _port_colors[i] - << std::endl; + << "\n"; } } file << std::dec << std::nouppercase; diff --git a/src/Configuration.hpp b/src/Configuration.hpp index d98968f..59039fc 100644 --- a/src/Configuration.hpp +++ b/src/Configuration.hpp @@ -1,43 +1,31 @@ -/* 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/>. - */ +// Copyright 2007-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef PATCHAGE_CONFIGURATION_HPP #define PATCHAGE_CONFIGURATION_HPP #include "Coord.hpp" -#include "PortType.hpp" #include "Setting.hpp" -#include "SignalDirection.hpp" - -#include <boost/optional/optional.hpp> #include <cstdint> #include <functional> #include <map> +#include <optional> #include <string> #include <tuple> #include <utility> - -#define N_PORT_TYPES 5 +#include <variant> namespace patchage { +enum class SignalDirection; +enum class PortType; + class Configuration { public: + static constexpr unsigned n_port_types = 5U; + explicit Configuration(std::function<void(const Setting&)> on_change); void load(); @@ -67,7 +55,7 @@ public: // Set a global configuration setting template<class S> - void set(typename S::Value value) + void set(decltype(S::value) value) { S& setting = std::get<S>(_settings); @@ -77,9 +65,25 @@ public: } } + // Set a global configuration setting + template<class S> + void set_setting(S new_setting) + { + set<S>(new_setting.value); + } + + // Set a global port color setting + void set_setting(setting::PortColor new_setting) + { + const auto& color = _port_colors[static_cast<unsigned>(new_setting.type)]; + if (color != new_setting.color) { + set_port_color(new_setting.type, new_setting.color); + } + } + // Get a global configuration setting template<class S> - typename S::Value get() const + decltype(S::value) get() const { return std::get<S>(_settings).value; } @@ -99,7 +103,7 @@ public: visitor(std::get<setting::WindowSize>(_settings)); visitor(std::get<setting::Zoom>(_settings)); - for (auto i = 0u; i < N_PORT_TYPES; ++i) { + for (auto i = 0U; i < n_port_types; ++i) { visitor(setting::PortColor{static_cast<PortType>(i), _port_colors[i]}); } } @@ -110,16 +114,16 @@ private: : split(s) {} - boost::optional<Coord> input_location; - boost::optional<Coord> output_location; - boost::optional<Coord> inout_location; - bool split; + std::optional<Coord> input_location; + std::optional<Coord> output_location; + std::optional<Coord> inout_location; + bool split; }; std::map<std::string, ModuleSettings> _module_settings; - uint32_t _default_port_colors[N_PORT_TYPES] = {}; - uint32_t _port_colors[N_PORT_TYPES] = {}; + uint32_t _default_port_colors[n_port_types] = {}; + uint32_t _port_colors[n_port_types] = {}; using Settings = std::tuple<setting::AlsaAttached, setting::FontSize, diff --git a/src/Coord.hpp b/src/Coord.hpp index 2d6a85a..b24d7dc 100644 --- a/src/Coord.hpp +++ b/src/Coord.hpp @@ -1,18 +1,5 @@ -/* 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/>. - */ +// Copyright 2007-2021 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef PATCHAGE_COORD_HPP #define PATCHAGE_COORD_HPP diff --git a/src/Driver.hpp b/src/Driver.hpp index da11765..4cb890b 100644 --- a/src/Driver.hpp +++ b/src/Driver.hpp @@ -1,18 +1,5 @@ -/* 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/>. - */ +// Copyright 2007-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef PATCHAGE_DRIVER_HPP #define PATCHAGE_DRIVER_HPP @@ -36,10 +23,10 @@ public: : _emit_event{std::move(emit_event)} {} - Driver(const Driver&) = delete; + Driver(const Driver&) = delete; Driver& operator=(const Driver&) = delete; - Driver(Driver&&) = delete; + Driver(Driver&&) = delete; Driver& operator=(Driver&&) = delete; virtual ~Driver() = default; diff --git a/src/Drivers.cpp b/src/Drivers.cpp index 4f57f34..7104b00 100644 --- a/src/Drivers.cpp +++ b/src/Drivers.cpp @@ -1,22 +1,10 @@ -/* 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/>. - */ +// Copyright 2007-2021 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #include "Drivers.hpp" #include "AudioDriver.hpp" +#include "ClientType.hpp" #include "Driver.hpp" #include "Event.hpp" #include "make_alsa_driver.hpp" @@ -24,6 +12,7 @@ #include <functional> #include <utility> +#include <variant> namespace patchage { @@ -38,6 +27,17 @@ Drivers::Drivers(ILog& log, Driver::EventSink emit_event) })} {} +Drivers::~Drivers() +{ + if (_alsa_driver) { + _alsa_driver->detach(); + } + + if (_jack_driver) { + _jack_driver->detach(); + } +} + void Drivers::refresh() { diff --git a/src/Drivers.hpp b/src/Drivers.hpp index ae3c063..a281d2e 100644 --- a/src/Drivers.hpp +++ b/src/Drivers.hpp @@ -1,31 +1,18 @@ -/* 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/>. - */ +// Copyright 2007-2021 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef PATCHAGE_DRIVERS_HPP #define PATCHAGE_DRIVERS_HPP -#include "AudioDriver.hpp" -#include "ClientType.hpp" #include "Driver.hpp" #include <memory> namespace patchage { +class AudioDriver; class ILog; +enum class ClientType; /// Manager for all drivers class Drivers @@ -33,13 +20,13 @@ class Drivers public: Drivers(ILog& log, Driver::EventSink emit_event); - Drivers(const Drivers&) = delete; + Drivers(const Drivers&) = delete; Drivers& operator=(const Drivers&) = delete; - Drivers(Drivers&&) = delete; + Drivers(Drivers&&) = delete; Drivers& operator=(Drivers&&) = delete; - ~Drivers() = default; + ~Drivers(); /// Refresh all drivers and emit results to the event sink void refresh(); diff --git a/src/Event.hpp b/src/Event.hpp index 233d1a1..36166e7 100644 --- a/src/Event.hpp +++ b/src/Event.hpp @@ -1,18 +1,5 @@ -/* 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/>. - */ +// Copyright 2007-2021 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef PATCHAGE_EVENT_HPP #define PATCHAGE_EVENT_HPP @@ -23,7 +10,7 @@ #include "PortID.hpp" #include "PortInfo.hpp" -#include <boost/variant/variant.hpp> +#include <variant> namespace patchage { namespace event { @@ -69,15 +56,15 @@ struct PortsDisconnected { } // namespace event /// An event from drivers that represents a change to the system -using Event = boost::variant<event::Cleared, - event::ClientCreated, - event::ClientDestroyed, - event::DriverAttached, - event::DriverDetached, - event::PortCreated, - event::PortDestroyed, - event::PortsConnected, - event::PortsDisconnected>; +using Event = std::variant<event::Cleared, + event::ClientCreated, + event::ClientDestroyed, + event::DriverAttached, + event::DriverDetached, + event::PortCreated, + event::PortDestroyed, + event::PortsConnected, + event::PortsDisconnected>; } // namespace patchage diff --git a/src/ILog.hpp b/src/ILog.hpp index d71059a..5e00602 100644 --- a/src/ILog.hpp +++ b/src/ILog.hpp @@ -1,18 +1,5 @@ -/* 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/>. - */ +// Copyright 2007-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef PATCHAGE_ILOG_HPP #define PATCHAGE_ILOG_HPP @@ -27,10 +14,10 @@ class ILog public: ILog() = default; - ILog(const ILog&) = default; + ILog(const ILog&) = default; ILog& operator=(const ILog&) = default; - ILog(ILog&&) = default; + ILog(ILog&&) = default; ILog& operator=(ILog&&) = default; virtual ~ILog() = default; diff --git a/src/JackDbusDriver.cpp b/src/JackDbusDriver.cpp index 23c12f2..f84cb51 100644 --- a/src/JackDbusDriver.cpp +++ b/src/JackDbusDriver.cpp @@ -1,24 +1,15 @@ -/* This file is part of Patchage. - * Copyright 2008-2020 David Robillard <d@drobilla.net> - * Copyright 2008 Nedko Arnaudov <nedko@arnaudov.name> - * - * 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/>. - */ +// Copyright 2008-2020 David Robillard <d@drobilla.net> +// Copyright 2008 Nedko Arnaudov <nedko@arnaudov.name> +// SPDX-License-Identifier: GPL-3.0-or-later +#include "AudioDriver.hpp" +#include "ClientID.hpp" #include "ClientType.hpp" #include "Driver.hpp" #include "Event.hpp" #include "ILog.hpp" +#include "PortID.hpp" +#include "PortInfo.hpp" #include "PortNames.hpp" #include "PortType.hpp" #include "SignalDirection.hpp" @@ -27,35 +18,42 @@ PATCHAGE_DISABLE_FMT_WARNINGS #include <fmt/core.h> -#include <fmt/ostream.h> PATCHAGE_RESTORE_WARNINGS #include <dbus/dbus-glib-lowlevel.h> -#include <dbus/dbus-glib.h> +#include <dbus/dbus-protocol.h> +#include <dbus/dbus-shared.h> #include <dbus/dbus.h> -#include <glib.h> #include <cassert> +#include <cstdarg> #include <cstdint> #include <cstring> -#include <set> +#include <functional> +#include <memory> +#include <optional> +#include <stdexcept> #include <string> +#include <utility> +#include <variant> #define JACKDBUS_SERVICE "org.jackaudio.service" #define JACKDBUS_OBJECT "/org/jackaudio/Controller" #define JACKDBUS_IFACE_CONTROL "org.jackaudio.JackControl" #define JACKDBUS_IFACE_PATCHBAY "org.jackaudio.JackPatchbay" -#define JACKDBUS_CALL_DEFAULT_TIMEOUT 1000 // in milliseconds +namespace patchage { +namespace { -#define JACKDBUS_PORT_FLAG_INPUT 0x00000001 -#define JACKDBUS_PORT_FLAG_TERMINAL 0x00000010 +constexpr auto default_timeout = 1000; // in milliseconds -#define JACKDBUS_PORT_TYPE_AUDIO 0 -#define JACKDBUS_PORT_TYPE_MIDI 1 +constexpr auto port_flag_input = 0x00000001U; +constexpr auto port_flag_terminal = 0x00000010U; -namespace patchage { -namespace { +enum JackDBusPortType { + AUDIO = 0, + MIDI = 1, +}; /// Driver for JACK audio and midi ports that uses D-Bus class JackDriver : public AudioDriver @@ -63,10 +61,10 @@ class JackDriver : public AudioDriver public: explicit JackDriver(ILog& log, EventSink emit_event); - JackDriver(const JackDriver&) = delete; + JackDriver(const JackDriver&) = delete; JackDriver& operator=(const JackDriver&) = delete; - JackDriver(JackDriver&&) = delete; + JackDriver(JackDriver&&) = delete; JackDriver& operator=(JackDriver&&) = delete; ~JackDriver() override; @@ -121,22 +119,18 @@ private: ILog& _log; DBusError _dbus_error; - DBusConnection* _dbus_connection; + DBusConnection* _dbus_connection{}; - mutable bool _server_responding; - bool _server_started; + mutable bool _server_responding{}; + bool _server_started{}; - dbus_uint64_t _graph_version; + dbus_uint64_t _graph_version{}; }; JackDriver::JackDriver(ILog& log, EventSink emit_event) : AudioDriver{std::move(emit_event)} , _log(log) , _dbus_error() - , _dbus_connection(nullptr) - , _server_responding(false) - , _server_started(false) - , _graph_version(0) { dbus_error_init(&_dbus_error); } @@ -155,23 +149,23 @@ JackDriver::~JackDriver() void JackDriver::update_attached() { - bool was_attached = _server_started; - _server_started = is_started(); + const bool was_attached = _server_started; + _server_started = is_started(); if (!_server_responding) { if (was_attached) { - _emit_event(DriverDetachmentEvent{ClientType::jack}); + _emit_event(event::DriverDetached{ClientType::jack}); } return; } if (_server_started && !was_attached) { - _emit_event(DriverAttachmentEvent{ClientType::jack}); + _emit_event(event::DriverAttached{ClientType::jack}); return; } if (!_server_started && was_attached) { - _emit_event(DriverDetachmentEvent{ClientType::jack}); + _emit_event(event::DriverDetached{ClientType::jack}); return; } } @@ -194,7 +188,7 @@ JackDriver::on_jack_disappeared() _server_responding = false; if (_server_started) { - _emit_event(DriverDetachmentEvent{ClientType::jack}); + _emit_event(event::DriverDetached{ClientType::jack}); } _server_started = false; @@ -212,14 +206,14 @@ JackDriver::dbus_message_hook(DBusConnection* /*connection*/, const char* old_owner = nullptr; const char* port2_name = nullptr; const char* port_name = nullptr; - dbus_uint32_t port_flags = 0u; - dbus_uint32_t port_type = 0u; - dbus_uint64_t client2_id = 0u; - dbus_uint64_t client_id = 0u; - dbus_uint64_t connection_id = 0u; - dbus_uint64_t new_graph_version = 0u; - dbus_uint64_t port2_id = 0u; - dbus_uint64_t port_id = 0u; + dbus_uint32_t port_flags = 0U; + dbus_uint32_t port_type = 0U; + dbus_uint64_t client2_id = 0U; + dbus_uint64_t client_id = 0U; + dbus_uint64_t connection_id = 0U; + dbus_uint64_t new_graph_version = 0U; + dbus_uint64_t port2_id = 0U; + dbus_uint64_t port_id = 0U; assert(jack_driver); auto* me = static_cast<JackDriver*>(jack_driver); @@ -279,12 +273,12 @@ JackDriver::dbus_message_hook(DBusConnection* /*connection*/, if (!me->_server_started) { me->_server_started = true; - me->_emit_event(DriverAttachmentEvent{ClientType::jack}); + me->_emit_event(event::DriverAttached{ClientType::jack}); } me->_emit_event( - PortCreationEvent{PortID::jack(client_name, port_name), - me->port_info(port_name, port_type, port_flags)}); + event::PortCreated{PortID::jack(client_name, port_name), + me->port_info(port_name, port_type, port_flags)}); return DBUS_HANDLER_RESULT_HANDLED; } @@ -313,10 +307,10 @@ JackDriver::dbus_message_hook(DBusConnection* /*connection*/, if (!me->_server_started) { me->_server_started = true; - me->_emit_event(DriverAttachmentEvent{ClientType::jack}); + me->_emit_event(event::DriverAttached{ClientType::jack}); } - me->_emit_event(PortDestructionEvent{PortID::jack(client_name, port_name)}); + me->_emit_event(event::PortDestroyed{PortID::jack(client_name, port_name)}); return DBUS_HANDLER_RESULT_HANDLED; } @@ -355,11 +349,12 @@ JackDriver::dbus_message_hook(DBusConnection* /*connection*/, if (!me->_server_started) { me->_server_started = true; - me->_emit_event(DriverAttachmentEvent{ClientType::jack}); + me->_emit_event(event::DriverAttached{ClientType::jack}); } - me->_emit_event(ConnectionEvent{PortID::jack(client_name, port_name), - PortID::jack(client2_name, port2_name)}); + me->_emit_event( + event::PortsConnected{PortID::jack(client_name, port_name), + PortID::jack(client2_name, port2_name)}); return DBUS_HANDLER_RESULT_HANDLED; } @@ -398,11 +393,12 @@ JackDriver::dbus_message_hook(DBusConnection* /*connection*/, if (!me->_server_started) { me->_server_started = true; - me->_emit_event(DriverAttachmentEvent{ClientType::jack}); + me->_emit_event(event::DriverAttached{ClientType::jack}); } - me->_emit_event(DisconnectionEvent{PortID::jack(client_name, port_name), - PortID::jack(client2_name, port2_name)}); + me->_emit_event( + event::PortsDisconnected{PortID::jack(client_name, port_name), + PortID::jack(client2_name, port2_name)}); return DBUS_HANDLER_RESULT_HANDLED; } @@ -436,7 +432,7 @@ JackDriver::call(bool response_expected, // send message and get a handle for a reply reply_ptr = dbus_connection_send_with_reply_and_block( - _dbus_connection, request_ptr, JACKDBUS_CALL_DEFAULT_TIMEOUT, &_dbus_error); + _dbus_connection, request_ptr, default_timeout, &_dbus_error); dbus_message_unref(request_ptr); @@ -518,7 +514,7 @@ JackDriver::stop_server() } dbus_message_unref(reply_ptr); - _emit_event(DriverDetachmentEvent{ClientType::jack}); + _emit_event(event::DriverDetached{ClientType::jack}); } void @@ -588,7 +584,7 @@ JackDriver::refresh(const EventSink& sink) { DBusMessage* reply_ptr = nullptr; DBusMessageIter iter = {}; - dbus_uint64_t version = 0u; + dbus_uint64_t version = 0U; const char* reply_signature = nullptr; DBusMessageIter clients_array_iter = {}; DBusMessageIter client_struct_iter = {}; @@ -596,17 +592,17 @@ JackDriver::refresh(const EventSink& sink) DBusMessageIter port_struct_iter = {}; DBusMessageIter connections_array_iter = {}; DBusMessageIter connection_struct_iter = {}; - dbus_uint64_t client_id = 0u; + dbus_uint64_t client_id = 0U; const char* client_name = nullptr; - dbus_uint64_t port_id = 0u; + dbus_uint64_t port_id = 0U; const char* port_name = nullptr; - dbus_uint32_t port_flags = 0u; - dbus_uint32_t port_type = 0u; - dbus_uint64_t client2_id = 0u; + dbus_uint32_t port_flags = 0U; + dbus_uint32_t port_type = 0U; + dbus_uint64_t client2_id = 0U; const char* client2_name = nullptr; - dbus_uint64_t port2_id = 0u; + dbus_uint64_t port2_id = 0U; const char* port2_name = nullptr; - dbus_uint64_t connection_id = 0u; + dbus_uint64_t connection_id = 0U; if (!call(true, JACKDBUS_IFACE_PATCHBAY, @@ -648,7 +644,7 @@ JackDriver::refresh(const EventSink& sink) dbus_message_iter_next(&client_struct_iter); // TODO: Pretty name? - sink({ClientCreationEvent{ClientID::jack(client_name), {client_name}}}); + sink({event::ClientCreated{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; @@ -667,8 +663,8 @@ JackDriver::refresh(const EventSink& sink) dbus_message_iter_get_basic(&port_struct_iter, &port_type); dbus_message_iter_next(&port_struct_iter); - sink({PortCreationEvent{PortID::jack(client_name, port_name), - port_info(port_name, port_type, port_flags)}}); + sink({event::PortCreated{PortID::jack(client_name, port_name), + port_info(port_name, port_type, port_flags)}}); } dbus_message_iter_next(&client_struct_iter); @@ -710,8 +706,8 @@ JackDriver::refresh(const EventSink& sink) dbus_message_iter_get_basic(&connection_struct_iter, &connection_id); dbus_message_iter_next(&connection_struct_iter); - sink({ConnectionEvent{PortID::jack(client_name, port_name), - PortID::jack(client2_name, port2_name)}}); + sink({event::PortsConnected{PortID::jack(client_name, port_name), + PortID::jack(client2_name, port2_name)}}); } } @@ -783,7 +779,7 @@ uint32_t JackDriver::xruns() { DBusMessage* reply_ptr = nullptr; - dbus_uint32_t xruns = 0u; + dbus_uint32_t xruns = 0U; if (_server_responding && !_server_started) { return 0; @@ -830,7 +826,7 @@ uint32_t JackDriver::buffer_size() { DBusMessage* reply_ptr = nullptr; - dbus_uint32_t buffer_size = 0u; + dbus_uint32_t buffer_size = 0U; if (_server_responding && !_server_started) { return 4096; @@ -885,7 +881,7 @@ uint32_t JackDriver::sample_rate() { DBusMessage* reply_ptr = nullptr; - dbus_uint32_t sample_rate = 0u; + dbus_uint32_t sample_rate = 0U; if (!call(true, JACKDBUS_IFACE_CONTROL, @@ -915,9 +911,9 @@ PortType JackDriver::patchage_port_type(const dbus_uint32_t dbus_port_type) const { switch (dbus_port_type) { - case JACKDBUS_PORT_TYPE_AUDIO: + case JackDBusPortType::AUDIO: return PortType::jack_audio; - case JACKDBUS_PORT_TYPE_MIDI: + case JackDBusPortType::MIDI: return PortType::jack_midi; default: break; @@ -933,15 +929,15 @@ JackDriver::port_info(const std::string& port_name, const dbus_uint32_t port_flags) const { const SignalDirection direction = - ((port_flags & JACKDBUS_PORT_FLAG_INPUT) ? SignalDirection::input - : SignalDirection::output); + ((port_flags & 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)}; + static_cast<bool>(port_flags & port_flag_terminal)}; } void diff --git a/src/JackLibDriver.cpp b/src/JackLibDriver.cpp index 8728222..b540347 100644 --- a/src/JackLibDriver.cpp +++ b/src/JackLibDriver.cpp @@ -1,18 +1,5 @@ -/* 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/>. - */ +// Copyright 2007-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #include "AudioDriver.hpp" #include "ClientID.hpp" @@ -31,7 +18,7 @@ #include "patchage_config.h" #include "warnings.hpp" -#ifdef HAVE_JACK_METADATA +#if USE_JACK_METADATA # include <jack/metadata.h> #endif @@ -39,7 +26,6 @@ PATCHAGE_DISABLE_FMT_WARNINGS #include <fmt/core.h> PATCHAGE_RESTORE_WARNINGS -#include <boost/optional/optional.hpp> #include <jack/jack.h> #include <jack/types.h> @@ -48,10 +34,12 @@ PATCHAGE_RESTORE_WARNINGS #include <functional> #include <memory> #include <mutex> +#include <optional> #include <set> #include <string> #include <unordered_set> #include <utility> +#include <variant> namespace patchage { namespace { @@ -62,10 +50,10 @@ class JackLibDriver : public AudioDriver public: explicit JackLibDriver(ILog& log, EventSink emit_event); - JackLibDriver(const JackLibDriver&) = delete; + JackLibDriver(const JackLibDriver&) = delete; JackLibDriver& operator=(const JackLibDriver&) = delete; - JackLibDriver(JackLibDriver&&) = delete; + JackLibDriver(JackLibDriver&&) = delete; JackLibDriver& operator=(JackLibDriver&&) = delete; ~JackLibDriver() override; @@ -86,8 +74,8 @@ public: uint32_t sample_rate() override; private: - ClientInfo get_client_info(const char* name); - PortInfo get_port_info(const jack_port_t* port); + static ClientInfo get_client_info(const char* name); + PortInfo get_port_info(const jack_port_t* port); static void on_client(const char* name, int registered, void* driver); @@ -106,8 +94,8 @@ private: std::mutex _shutdown_mutex; jack_client_t* _client = nullptr; - jack_nframes_t _buffer_size = 0u; - uint32_t _xruns = 0u; + jack_nframes_t _buffer_size = 0U; + uint32_t _xruns = 0U; bool _is_activated = false; }; @@ -116,10 +104,7 @@ JackLibDriver::JackLibDriver(ILog& log, EventSink emit_event) , _log{log} {} -JackLibDriver::~JackLibDriver() -{ - detach(); -} +JackLibDriver::~JackLibDriver() = default; void JackLibDriver::attach(const bool launch_daemon) @@ -159,7 +144,7 @@ JackLibDriver::attach(const bool launch_daemon) void JackLibDriver::detach() { - std::lock_guard<std::mutex> lock{_shutdown_mutex}; + const std::lock_guard<std::mutex> lock{_shutdown_mutex}; if (_client) { jack_deactivate(_client); @@ -182,7 +167,7 @@ get_property(const jack_uuid_t subject, const char* const key) { std::string result; -#ifdef HAVE_JACK_METADATA +#if USE_JACK_METADATA char* value = nullptr; char* datatype = nullptr; if (!jack_get_property(subject, key, &value, &datatype)) { @@ -208,12 +193,12 @@ PortInfo JackLibDriver::get_port_info(const jack_port_t* const port) { const auto uuid = jack_port_uuid(port); - const auto flags = jack_port_flags(port); + const auto flags = static_cast<unsigned>(jack_port_flags(port)); const std::string name = jack_port_name(port); auto label = PortNames{name}.port(); // Get pretty name to use as a label, if present -#ifdef HAVE_JACK_METADATA +#if USE_JACK_METADATA const auto pretty_name = get_property(uuid, JACK_METADATA_PRETTY_NAME); if (!pretty_name.empty()) { label = pretty_name; @@ -243,19 +228,23 @@ JackLibDriver::get_port_info(const jack_port_t* const port) : SignalDirection::output); // Get port order from metadata if possible - boost::optional<int> order; - const std::string order_str = get_property(uuid, JACKEY_ORDER); + std::optional<int> order; + const std::string order_str = get_property(uuid, JACKEY_ORDER); if (!order_str.empty()) { order = std::stoi(order_str); } - return {label, type, direction, order, bool(flags & JackPortIsTerminal)}; + return {label, + type, + direction, + order, + static_cast<bool>(flags & JackPortIsTerminal)}; } void JackLibDriver::refresh(const EventSink& sink) { - std::lock_guard<std::mutex> lock{_shutdown_mutex}; + const std::lock_guard<std::mutex> lock{_shutdown_mutex}; if (!_client) { return; @@ -269,7 +258,7 @@ JackLibDriver::refresh(const EventSink& sink) // 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) { + for (auto i = 0U; ports[i]; ++i) { client_names.insert(PortID::jack(ports[i]).client().jack_name()); } @@ -280,7 +269,7 @@ JackLibDriver::refresh(const EventSink& sink) } // Emit all ports - for (auto i = 0u; ports[i]; ++i) { + for (auto i = 0U; ports[i]; ++i) { const jack_port_t* const port = jack_port_by_name(_client, ports[i]); sink({event::PortCreated{PortID::jack(ports[i]), get_port_info(port)}}); @@ -288,17 +277,18 @@ JackLibDriver::refresh(const EventSink& sink) // 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) { + 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 (peers) { - if (jack_port_flags(port) & JackPortIsInput) { - for (auto j = 0u; peers[j]; ++j) { + const auto flags = static_cast<unsigned>(jack_port_flags(port)); + if (flags & JackPortIsInput) { + for (auto j = 0U; peers[j]; ++j) { connections.emplace(peers[j], ports[i]); } } else { - for (auto j = 0u; peers[j]; ++j) { + for (auto j = 0U; peers[j]; ++j) { connections.emplace(ports[i], peers[j]); } } @@ -483,7 +473,7 @@ JackLibDriver::on_shutdown(void* const driver) So, since JACK is a hot mess and it's impossible to gracefully handle this situation, just leak the client. */ - std::lock_guard<std::mutex> lock{me->_shutdown_mutex}; + const std::lock_guard<std::mutex> lock{me->_shutdown_mutex}; me->_client = nullptr; me->_is_activated = false; diff --git a/src/JackStubDriver.cpp b/src/JackStubDriver.cpp new file mode 100644 index 0000000..a062df1 --- /dev/null +++ b/src/JackStubDriver.cpp @@ -0,0 +1,18 @@ +// Copyright 2020-2022 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "AudioDriver.hpp" +#include "Driver.hpp" +#include "make_jack_driver.hpp" + +#include <memory> + +namespace patchage { + +std::unique_ptr<AudioDriver> +make_jack_driver(ILog&, Driver::EventSink) +{ + return nullptr; +} + +} // namespace patchage diff --git a/src/Legend.cpp b/src/Legend.cpp index e8e4743..ff0f7fe 100644 --- a/src/Legend.cpp +++ b/src/Legend.cpp @@ -1,27 +1,15 @@ -/* This file is part of Patchage. - * Copyright 2014-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/>. - */ +// Copyright 2014-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #include "Legend.hpp" #include "Configuration.hpp" #include "PortType.hpp" +#include "i18n.hpp" #include "patchage_config.h" #include <gdkmm/color.h> -#include <glibmm/signalproxy.h> +#include <glibmm/ustring.h> #include <gtkmm/box.h> #include <gtkmm/colorbutton.h> #include <gtkmm/label.h> @@ -36,10 +24,10 @@ namespace patchage { Legend::Legend(const Configuration& configuration) { add_button(PortType::jack_audio, - "Audio", + T("Audio"), configuration.get_port_color(PortType::jack_audio)); -#ifdef HAVE_JACK_METADATA +#if USE_JACK_METADATA add_button( PortType::jack_cv, "CV", configuration.get_port_color(PortType::jack_cv)); add_button(PortType::jack_osc, @@ -62,9 +50,9 @@ void Legend::add_button(const PortType id, const std::string& label, uint32_t rgba) { Gdk::Color col; - col.set_rgb(((rgba >> 24) & 0xFF) * 0x100, - ((rgba >> 16) & 0xFF) * 0x100, - ((rgba >> 8) & 0xFF) * 0x100); + col.set_rgb(((rgba >> 24U) & 0xFFU) * 0x100U, + ((rgba >> 16U) & 0xFFU) * 0x100U, + ((rgba >> 8U) & 0xFFU) * 0x100U); auto* box = new Gtk::HBox(); auto* but = new Gtk::ColorButton(col); @@ -85,8 +73,8 @@ Legend::on_color_set(const PortType id, { const Gdk::Color col = but->get_color(); const uint32_t rgba = - (((col.get_red() / 0x100) << 24) | ((col.get_green() / 0x100) << 16) | - ((col.get_blue() / 0x100) << 8) | 0xFF); + (((col.get_red() / 0x100U) << 24U) | ((col.get_green() / 0x100U) << 16U) | + ((col.get_blue() / 0x100U) << 8U) | 0xFFU); signal_color_changed.emit(id, label, rgba); } diff --git a/src/Legend.hpp b/src/Legend.hpp index 81fbd86..c73a74e 100644 --- a/src/Legend.hpp +++ b/src/Legend.hpp @@ -1,24 +1,9 @@ -/* This file is part of Patchage. - * Copyright 2014-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/>. - */ +// Copyright 2014-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef PATCHAGE_LEGEND_HPP #define PATCHAGE_LEGEND_HPP -#include "PortType.hpp" - #include <gtkmm/box.h> #include <sigc++/signal.h> @@ -31,6 +16,8 @@ class ColorButton; namespace patchage { +enum class PortType; + class Configuration; class Legend : public Gtk::HBox diff --git a/src/Metadata.cpp b/src/Metadata.cpp index e75cf19..929b090 100644 --- a/src/Metadata.cpp +++ b/src/Metadata.cpp @@ -1,18 +1,5 @@ -/* This file is part of Patchage. - * Copyright 2014-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/>. - */ +// Copyright 2014-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #include "Metadata.hpp" @@ -21,13 +8,12 @@ #include "PortID.hpp" #include "PortInfo.hpp" -#include <boost/optional/optional.hpp> - +#include <optional> #include <utility> namespace patchage { -boost::optional<ClientInfo> +std::optional<ClientInfo> Metadata::client(const ClientID& id) const { const auto i = _client_data.find(id); @@ -38,7 +24,7 @@ Metadata::client(const ClientID& id) const return i->second; } -boost::optional<PortInfo> +std::optional<PortInfo> Metadata::port(const PortID& id) const { const auto i = _port_data.find(id); diff --git a/src/Metadata.hpp b/src/Metadata.hpp index 489c0b2..520b0ce 100644 --- a/src/Metadata.hpp +++ b/src/Metadata.hpp @@ -1,18 +1,5 @@ -/* 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/>. - */ +// Copyright 2007-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef PATCHAGE_METADATA_HPP #define PATCHAGE_METADATA_HPP @@ -22,9 +9,8 @@ #include "PortID.hpp" #include "PortInfo.hpp" -#include <boost/optional/optional.hpp> - #include <map> +#include <optional> namespace patchage { @@ -34,8 +20,8 @@ class Metadata public: Metadata() = default; - boost::optional<ClientInfo> client(const ClientID& id) const; - boost::optional<PortInfo> port(const PortID& id) const; + std::optional<ClientInfo> client(const ClientID& id) const; + std::optional<PortInfo> port(const PortID& id) const; void set_client(const ClientID& id, const ClientInfo& info); void set_port(const PortID& id, const PortInfo& info); diff --git a/src/Options.hpp b/src/Options.hpp index dd143fe..76846aa 100644 --- a/src/Options.hpp +++ b/src/Options.hpp @@ -1,18 +1,5 @@ -/* 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/>. - */ +// Copyright 2007-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef PATCHAGE_OPTIONS_HPP #define PATCHAGE_OPTIONS_HPP diff --git a/src/Patchage.cpp b/src/Patchage.cpp index 7997354..349fbf0 100644 --- a/src/Patchage.cpp +++ b/src/Patchage.cpp @@ -1,18 +1,5 @@ -/* 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/>. - */ +// Copyright 2007-2021 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #include "Patchage.hpp" @@ -24,38 +11,40 @@ #include "Configuration.hpp" #include "Coord.hpp" #include "Driver.hpp" +#include "Drivers.hpp" #include "Event.hpp" #include "Legend.hpp" +#include "Options.hpp" +#include "PortType.hpp" +#include "Reactor.hpp" #include "Setting.hpp" +#include "TextViewLog.hpp" #include "UIFile.hpp" +#include "Widget.hpp" #include "event_to_string.hpp" #include "handle_event.hpp" -#include "patchage_config.h" // IWYU pragma: keep +#include "i18n.hpp" #include "warnings.hpp" PATCHAGE_DISABLE_GANV_WARNINGS -#include "ganv/Edge.hpp" -#include "ganv/Module.hpp" -#include "ganv/Node.hpp" -#include "ganv/Port.hpp" -#include "ganv/module.h" -#include "ganv/types.h" +#include <ganv/Edge.hpp> +#include <ganv/Module.hpp> +#include <ganv/Node.hpp> +#include <ganv/Port.hpp> +#include <ganv/module.h> +#include <ganv/types.h> PATCHAGE_RESTORE_WARNINGS PATCHAGE_DISABLE_FMT_WARNINGS #include <fmt/core.h> PATCHAGE_RESTORE_WARNINGS -#include <boost/optional/optional.hpp> -#include <boost/variant/apply_visitor.hpp> -#include <boost/variant/variant.hpp> #include <glib-object.h> #include <glib.h> #include <glibmm/fileutils.h> #include <glibmm/main.h> #include <glibmm/miscutils.h> #include <glibmm/propertyproxy.h> -#include <glibmm/signalproxy.h> #include <glibmm/ustring.h> #include <gobject/gclosure.h> #include <gtk/gtk.h> @@ -93,6 +82,8 @@ PATCHAGE_RESTORE_WARNINGS #include <gtkmm/window.h> #include <sigc++/adaptors/bind.h> #include <sigc++/functors/mem_fun.h> +#include <sigc++/functors/ptr_fun.h> +#include <sigc++/functors/slot.h> #include <sigc++/signal.h> #include <algorithm> @@ -101,7 +92,9 @@ PATCHAGE_RESTORE_WARNINGS #include <cstdlib> #include <functional> #include <map> +#include <optional> #include <utility> +#include <variant> #ifdef PATCHAGE_GTK_OSX @@ -145,8 +138,10 @@ port_order(const GanvPort* a, const GanvPort* b, void*) const auto* pa = dynamic_cast<const CanvasPort*>(Glib::wrap(a)); const auto* pb = dynamic_cast<const CanvasPort*>(Glib::wrap(b)); if (pa && pb) { - if (pa->order() && pb->order()) { - return *pa->order() - *pb->order(); + const auto oa = pa->order(); + const auto ob = pb->order(); + if (oa && ob) { + return *oa - *ob; } if (pa->order()) { @@ -162,6 +157,79 @@ port_order(const GanvPort* a, const GanvPort* b, void*) return 0; } +template<class S> +void +on_setting_toggled(Reactor* const reactor, const Gtk::CheckMenuItem* const item) +{ + (*reactor)(action::ChangeSetting{{S{item->get_active()}}}); +} + +void +update_labels(GanvNode* node, void* data) +{ + const bool human_names = *static_cast<const bool*>(data); + if (GANV_IS_MODULE(node)) { + Ganv::Module* gmod = Glib::wrap(GANV_MODULE(node)); + if (dynamic_cast<const CanvasModule*>(gmod)) { + for (Ganv::Port* gport : *gmod) { + auto* pport = dynamic_cast<CanvasPort*>(gport); + if (pport) { + pport->show_human_name(human_names); + } + } + } + } +} + +inline guint +highlight_color(guint c, guint delta) +{ + const guint max_char = 255U; + const guint r = MIN((c >> 24U) + delta, max_char); + const guint g = MIN(((c >> 16U) & 0xFFU) + delta, max_char); + const guint b = MIN(((c >> 8U) & 0xFFU) + delta, max_char); + const guint a = c & 0xFFU; + + return ((r << 24U) | (g << 16U) | (b << 8U) | a); +} + +void +update_port_colors(GanvNode* node, void* data) +{ + auto* patchage = static_cast<Patchage*>(data); + if (!GANV_IS_MODULE(node)) { + return; + } + + Ganv::Module* gmod = Glib::wrap(GANV_MODULE(node)); + if (!dynamic_cast<CanvasModule*>(gmod)) { + return; + } + + for (Ganv::Port* p : *gmod) { + auto* port = dynamic_cast<CanvasPort*>(p); + if (port) { + const uint32_t rgba = patchage->conf().get_port_color(port->type()); + port->set_fill_color(rgba); + port->set_border_color(highlight_color(rgba, 0x20)); + } + } +} + +void +update_edge_color(GanvEdge* edge, void* data) +{ + auto* patchage = static_cast<Patchage*>(data); + Ganv::Edge* edgemm = Glib::wrap(edge); + + if (edgemm) { + const auto* tail = dynamic_cast<const CanvasPort*>((edgemm)->get_tail()); + if (tail) { + edgemm->set_color(patchage->conf().get_port_color(tail->type())); + } + } +} + } // namespace #define INIT_WIDGET(x) x(_xml, (#x) + 1) @@ -206,12 +274,10 @@ Patchage::Patchage(Options options) , _conf([this](const Setting& setting) { on_conf_change(setting); }) , _log(_status_text) , _canvas(new Canvas{_log, _action_sink, 1600 * 2, 1200 * 2}) - , _legend(nullptr) , _drivers(_log, [this](const Event& event) { on_driver_event(event); }) , _reactor(_conf, _drivers, *_canvas, _log) , _action_sink([this](const Action& action) { _reactor(action); }) , _options{options} - , _attach(true) { Glib::set_application_name("Patchage"); _about_win->property_program_name() = "Patchage"; @@ -219,11 +285,11 @@ Patchage::Patchage(Options options) gtk_window_set_default_icon_name("patchage"); // Create list model for buffer size selector - Glib::RefPtr<Gtk::ListStore> buf_size_store = + const Glib::RefPtr<Gtk::ListStore> buf_size_store = Gtk::ListStore::create(_buf_size_columns); for (size_t i = 32; i <= 4096; i *= 2) { - Gtk::TreeModel::Row row = *(buf_size_store->append()); - row[_buf_size_columns.label] = std::to_string(i); + const Gtk::TreeModel::Row row = *(buf_size_store->append()); + row[_buf_size_columns.label] = std::to_string(i); } _buf_size_combo->set_model(buf_size_store); @@ -235,7 +301,7 @@ Patchage::Patchage(Options options) _main_scrolledwin->property_vadjustment().get_value()->set_step_increment(10); _main_scrolledwin->signal_scroll_event().connect( - sigc::mem_fun(this, &Patchage::on_scroll)); + sigc::ptr_fun(&Patchage::on_scroll)); _clear_load_but->signal_clicked().connect( sigc::mem_fun(this, &Patchage::clear_load)); _buf_size_combo->signal_changed().connect( @@ -249,18 +315,35 @@ Patchage::Patchage(Options options) sigc::mem_fun(this, &Patchage::on_export_image)); _menu_view_refresh->signal_activate().connect(sigc::bind( sigc::mem_fun(this, &Patchage::on_menu_action), Action{action::Refresh{}})); + _menu_view_human_names->signal_activate().connect( - sigc::mem_fun(this, &Patchage::on_view_human_names)); + sigc::bind(sigc::ptr_fun(&on_setting_toggled<setting::HumanNames>), + &_reactor, + _menu_view_human_names.get())); + _menu_view_sort_ports->signal_activate().connect( - sigc::mem_fun(this, &Patchage::on_view_sort_ports)); + sigc::bind(sigc::ptr_fun(&on_setting_toggled<setting::SortedPorts>), + &_reactor, + _menu_view_sort_ports.get())); + _menu_view_arrange->signal_activate().connect( sigc::mem_fun(this, &Patchage::on_arrange)); + _menu_view_sprung_layout->signal_activate().connect( - sigc::mem_fun(this, &Patchage::on_sprung_layout_toggled)); + sigc::bind(sigc::ptr_fun(&on_setting_toggled<setting::SprungLayout>), + &_reactor, + _menu_view_sprung_layout.get())); + _menu_view_messages->signal_activate().connect( - sigc::mem_fun(this, &Patchage::on_view_messages)); + sigc::bind(sigc::ptr_fun(&on_setting_toggled<setting::MessagesVisible>), + &_reactor, + _menu_view_messages.get())); + _menu_view_toolbar->signal_activate().connect( - sigc::mem_fun(this, &Patchage::on_view_toolbar)); + sigc::bind(sigc::ptr_fun(&on_setting_toggled<setting::ToolbarVisible>), + &_reactor, + _menu_view_toolbar.get())); + _menu_help_about->signal_activate().connect( sigc::mem_fun(this, &Patchage::on_help_about)); @@ -296,7 +379,8 @@ Patchage::Patchage(Options options) _main_win->present(); // Set the default font size based on the current GUI environment - _conf.set<setting::FontSize>(_canvas->get_default_font_size()); + _conf.set<setting::FontSize>( + static_cast<float>(_canvas->get_default_font_size())); // Load configuration file (but do not apply it yet, see below) _conf.load(); @@ -430,13 +514,17 @@ Patchage::update_toolbar() 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); + const auto sample_rate_khz = sample_rate / 1000.0; + const auto latency_ms = buffer_size / sample_rate_khz; + + _latency_label->set_label(" " + + fmt::format(T("frames at {} kHz ({:0.2f} ms)"), + sample_rate_khz, + latency_ms)); - _latency_label->set_label(fmt::format( - " frames @ {} kHz ({:0.2f} ms)", sample_rate / 1000, latency_ms)); _latency_label->set_visible(true); - _buf_size_combo->set_active( - static_cast<int>(log2f(_drivers.jack()->buffer_size()) - 5)); + _buf_size_combo->set_active(static_cast<int>( + log2f(static_cast<float>(_drivers.jack()->buffer_size())) - 5)); updating = false; return; } @@ -451,12 +539,13 @@ Patchage::update_load() { 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->set_text(" " + fmt::format(T("Dropouts: {}"), xruns)); + + if (xruns > 0U) { _dropouts_label->show(); _clear_load_but->show(); } else { - _dropouts_label->set_text(" Dropouts: 0"); _dropouts_label->hide(); _clear_load_but->hide(); } @@ -476,14 +565,17 @@ Patchage::store_window_location() int size_y = 0; _main_win->get_size(size_x, size_y); - _conf.set<setting::WindowLocation>({double(loc_x), double(loc_y)}); - _conf.set<setting::WindowSize>({double(size_x), double(size_y)}); + _conf.set<setting::WindowLocation>( + {static_cast<double>(loc_x), static_cast<double>(loc_y)}); + + _conf.set<setting::WindowSize>( + {static_cast<double>(size_x), static_cast<double>(size_y)}); } void Patchage::clear_load() { - _dropouts_label->set_text(" Dropouts: 0"); + _dropouts_label->set_text(" " + fmt::format(T("Dropouts: {}"), 0U)); _dropouts_label->hide(); _clear_load_but->hide(); if (_drivers.jack()) { @@ -546,24 +638,6 @@ Patchage::operator()(const setting::FontSize& setting) } } -static void -update_labels(GanvNode* node, void* data) -{ - const bool human_names = *static_cast<const bool*>(data); - if (GANV_IS_MODULE(node)) { - Ganv::Module* gmod = Glib::wrap(GANV_MODULE(node)); - auto* pmod = dynamic_cast<CanvasModule*>(gmod); - if (pmod) { - for (Ganv::Port* gport : *gmod) { - auto* pport = dynamic_cast<CanvasPort*>(gport); - if (pport) { - pport->show_human_name(human_names); - } - } - } - } -} - void Patchage::operator()(const setting::HumanNames& setting) { @@ -598,56 +672,6 @@ Patchage::operator()(const setting::MessagesVisible& setting) _menu_view_messages->set_active(setting.value); } -static inline guint -highlight_color(guint c, guint delta) -{ - const guint max_char = 255; - const guint r = MIN((c >> 24) + delta, max_char); - const guint g = MIN(((c >> 16) & 0xFF) + delta, max_char); - const guint b = MIN(((c >> 8) & 0xFF) + delta, max_char); - const guint a = c & 0xFF; - - return ((r << 24u) | (g << 16u) | (b << 8u) | a); -} - -static void -update_port_colors(GanvNode* node, void* data) -{ - auto* patchage = static_cast<Patchage*>(data); - if (!GANV_IS_MODULE(node)) { - return; - } - - Ganv::Module* gmod = Glib::wrap(GANV_MODULE(node)); - auto* pmod = dynamic_cast<CanvasModule*>(gmod); - if (!pmod) { - return; - } - - for (Ganv::Port* p : *pmod) { - auto* port = dynamic_cast<CanvasPort*>(p); - if (port) { - const uint32_t rgba = patchage->conf().get_port_color(port->type()); - port->set_fill_color(rgba); - port->set_border_color(highlight_color(rgba, 0x20)); - } - } -} - -static void -update_edge_color(GanvEdge* edge, void* data) -{ - auto* patchage = static_cast<Patchage*>(data); - Ganv::Edge* edgemm = Glib::wrap(edge); - - if (edgemm) { - auto* tail = dynamic_cast<CanvasPort*>((edgemm)->get_tail()); - if (tail) { - edgemm->set_color(patchage->conf().get_port_color(tail->type())); - } - } -} - void Patchage::operator()(const setting::PortColor&) { @@ -726,7 +750,7 @@ Patchage::operator()(const setting::Zoom& setting) void Patchage::on_driver_event(const Event& event) { - std::lock_guard<std::mutex> lock{_events_mutex}; + const std::lock_guard<std::mutex> lock{_events_mutex}; _driver_events.emplace(event); } @@ -734,7 +758,7 @@ Patchage::on_driver_event(const Event& event) void Patchage::process_events() { - std::lock_guard<std::mutex> lock{_events_mutex}; + const std::lock_guard<std::mutex> lock{_events_mutex}; while (!_driver_events.empty()) { const Event& event = _driver_events.front(); @@ -749,7 +773,7 @@ Patchage::process_events() void Patchage::on_conf_change(const Setting& setting) { - boost::apply_visitor(*this, setting); + std::visit(*this, setting); } void @@ -761,12 +785,6 @@ Patchage::on_arrange() } void -Patchage::on_sprung_layout_toggled() -{ - _conf.set<setting::SprungLayout>(_menu_view_sprung_layout->get_active()); -} - -void Patchage::on_help_about() { _about_win->run(); @@ -774,22 +792,9 @@ Patchage::on_help_about() } void -Patchage::on_view_human_names() -{ - _conf.set<setting::HumanNames>(_menu_view_human_names->get_active()); -} - -void -Patchage::on_view_sort_ports() -{ - _conf.set<setting::SortedPorts>(_menu_view_sort_ports->get_active()); - _reactor(action::Refresh{}); -} - -void Patchage::on_legend_color_change(PortType id, const std::string&, uint32_t rgba) { - _conf.set_port_color(id, rgba); + _reactor(action::ChangeSetting{{setting::PortColor{id, rgba}}}); } void @@ -803,7 +808,8 @@ Patchage::on_messages_resized(Gtk::Allocation&) void Patchage::save() { - _conf.set<setting::Zoom>(_canvas->get_zoom()); // Can be changed by ganv + // Zoom can be changed by ganv + _conf.set<setting::Zoom>(static_cast<float>(_canvas->get_zoom())); _conf.save(); } @@ -830,7 +836,9 @@ Patchage::on_quit() void Patchage::on_export_image() { - Gtk::FileChooserDialog dialog("Export Image", Gtk::FILE_CHOOSER_ACTION_SAVE); + Gtk::FileChooserDialog dialog(T("Export Image"), + Gtk::FILE_CHOOSER_ACTION_SAVE); + dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); dialog.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK); dialog.set_default_response(Gtk::RESPONSE_OK); @@ -850,7 +858,7 @@ Patchage::on_export_image() dialog.add_filter(filt); } - auto* bg_but = new Gtk::CheckButton("Draw _Background", true); + auto* bg_but = new Gtk::CheckButton(T("Draw _Background"), true); auto* extra = new Gtk::Alignment(1.0, 0.5, 0.0, 0.0); bg_but->set_active(true); extra->add(*Gtk::manage(bg_but)); @@ -860,12 +868,12 @@ Patchage::on_export_image() if (dialog.run() == Gtk::RESPONSE_OK) { const std::string filename = dialog.get_filename(); if (Glib::file_test(filename, Glib::FILE_TEST_EXISTS)) { - Gtk::MessageDialog confirm(std::string("File exists! Overwrite ") + - filename + "?", - true, - Gtk::MESSAGE_WARNING, - Gtk::BUTTONS_YES_NO, - true); + Gtk::MessageDialog confirm( + fmt::format(T("File exists! Overwrite {}?"), filename), + true, + Gtk::MESSAGE_WARNING, + Gtk::BUTTONS_YES_NO, + true); confirm.set_transient_for(dialog); if (confirm.run() != Gtk::RESPONSE_YES) { return; @@ -875,18 +883,6 @@ Patchage::on_export_image() } } -void -Patchage::on_view_messages() -{ - _conf.set<setting::MessagesVisible>(_menu_view_messages->get_active()); -} - -void -Patchage::on_view_toolbar() -{ - _conf.set<setting::ToolbarVisible>(_menu_view_toolbar->get_active()); -} - bool Patchage::on_scroll(GdkEventScroll*) { @@ -905,10 +901,10 @@ Patchage::buffer_size_changed() if (_drivers.jack()) { const int selected = _buf_size_combo->get_active_row_number(); - if (selected == -1) { + if (selected < 0) { update_toolbar(); } else { - const uint32_t buffer_size = 1u << (selected + 5); + const uint32_t buffer_size = 1U << (static_cast<unsigned>(selected) + 5U); _drivers.jack()->set_buffer_size(buffer_size); update_toolbar(); } diff --git a/src/Patchage.hpp b/src/Patchage.hpp index c3ed61d..720a57c 100644 --- a/src/Patchage.hpp +++ b/src/Patchage.hpp @@ -1,18 +1,5 @@ -/* 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/>. - */ +// Copyright 2007-2021 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef PATCHAGE_PATCHAGE_HPP #define PATCHAGE_PATCHAGE_HPP @@ -30,7 +17,6 @@ #include "Event.hpp" #include "Metadata.hpp" #include "Options.hpp" -#include "PortType.hpp" #include "Reactor.hpp" #include "Setting.hpp" #include "TextViewLog.hpp" @@ -68,6 +54,8 @@ class Window; namespace patchage { +enum class PortType; + class Canvas; class ILog; class Legend; @@ -79,10 +67,10 @@ public: explicit Patchage(Options options); ~Patchage(); - Patchage(const Patchage&) = delete; + Patchage(const Patchage&) = delete; Patchage& operator=(const Patchage&) = delete; - Patchage(Patchage&&) = delete; + Patchage(Patchage&&) = delete; Patchage& operator=(Patchage&&) = delete; void operator()(const setting::AlsaAttached& setting); @@ -127,15 +115,10 @@ protected: void on_conf_change(const Setting& setting); void on_arrange(); - void on_sprung_layout_toggled(); void on_help_about(); void on_quit(); void on_export_image(); - void on_view_messages(); - void on_view_toolbar(); void on_store_positions(); - void on_view_human_names(); - void on_view_sort_ports(); void on_legend_color_change(PortType id, const std::string& label, @@ -143,7 +126,7 @@ protected: void on_messages_resized(Gtk::Allocation& alloc); - bool on_scroll(GdkEventScroll* ev); + static bool on_scroll(GdkEventScroll* ev); void on_menu_action(const Action& action); @@ -198,7 +181,7 @@ protected: std::mutex _events_mutex; std::queue<Event> _driver_events; BufferSizeColumns _buf_size_columns; - Legend* _legend; + Legend* _legend{nullptr}; Metadata _metadata; Drivers _drivers; Reactor _reactor; @@ -208,7 +191,7 @@ protected: Glib::RefPtr<Gtk::TextTag> _warning_tag; Options _options; - bool _attach; + bool _attach{true}; }; } // namespace patchage diff --git a/src/PortID.hpp b/src/PortID.hpp index 2ef7a0c..e22e670 100644 --- a/src/PortID.hpp +++ b/src/PortID.hpp @@ -1,18 +1,5 @@ -/* This file is part of Patchage. - * Copyright 2008-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/>. - */ +// Copyright 2008-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef PATCHAGE_PORTID_HPP #define PATCHAGE_PORTID_HPP @@ -36,10 +23,10 @@ namespace patchage { struct PortID { using Type = ClientType; - PortID(const PortID& copy) = default; + PortID(const PortID& copy) = default; PortID& operator=(const PortID& copy) = default; - PortID(PortID&& id) = default; + PortID(PortID&& id) = default; PortID& operator=(PortID&& id) = default; ~PortID() = default; @@ -114,22 +101,23 @@ private: bool _alsa_is_input{}; ///< Input flag for Type::alsa }; -static inline std::ostream& +inline std::ostream& operator<<(std::ostream& os, const PortID& id) { switch (id.type()) { case PortID::Type::jack: return os << "jack:" << id.jack_name(); case PortID::Type::alsa: - return os << "alsa:" << int(id.alsa_client()) << ":" << int(id.alsa_port()) - << ":" << (id.alsa_is_input() ? "in" : "out"); + return os << "alsa:" << static_cast<int>(id.alsa_client()) << ":" + << static_cast<int>(id.alsa_port()) << ":" + << (id.alsa_is_input() ? "in" : "out"); } assert(false); return os; } -static inline bool +inline bool operator==(const PortID& lhs, const PortID& rhs) { if (lhs.type() != rhs.type()) { @@ -150,7 +138,7 @@ operator==(const PortID& lhs, const PortID& rhs) return false; } -static inline bool +inline bool operator<(const PortID& lhs, const PortID& rhs) { if (lhs.type() != rhs.type()) { @@ -185,4 +173,7 @@ struct hash<patchage::PortID::Type> { } // namespace std +template<> +struct fmt::formatter<patchage::PortID> : fmt::ostream_formatter {}; + #endif // PATCHAGE_PORTID_HPP diff --git a/src/PortInfo.hpp b/src/PortInfo.hpp index 3a4103d..b6d88b5 100644 --- a/src/PortInfo.hpp +++ b/src/PortInfo.hpp @@ -1,18 +1,5 @@ -/* 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/>. - */ +// Copyright 2007-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef PATCHAGE_PORTINFO_HPP #define PATCHAGE_PORTINFO_HPP @@ -20,18 +7,18 @@ #include "PortType.hpp" #include "SignalDirection.hpp" -#include <boost/optional/optional.hpp> +#include <optional> #include <string> namespace patchage { /// Extra information about a port not expressed in its ID struct PortInfo { - std::string label; ///< Human-friendly label - PortType type; ///< Detailed port type - SignalDirection direction; ///< Signal direction - boost::optional<int> order; ///< Order key on client - bool is_terminal; ///< True if this is a system port + std::string label; ///< Human-friendly label + PortType type; ///< Detailed port type + SignalDirection direction; ///< Signal direction + std::optional<int> order; ///< Order key on client + bool is_terminal; ///< True if this is a system port }; } // namespace patchage diff --git a/src/PortNames.hpp b/src/PortNames.hpp index 1ec7685..4dce7c6 100644 --- a/src/PortNames.hpp +++ b/src/PortNames.hpp @@ -1,18 +1,5 @@ -/* This file is part of Patchage. - * Copyright 2008-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/>. - */ +// Copyright 2008-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef PATCHAGE_PORTNAMES_HPP #define PATCHAGE_PORTNAMES_HPP diff --git a/src/PortType.hpp b/src/PortType.hpp index 9db0c1f..97ecaab 100644 --- a/src/PortType.hpp +++ b/src/PortType.hpp @@ -1,22 +1,18 @@ -/* 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/>. - */ +// Copyright 2007-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef PATCHAGE_PORTTYPE_HPP #define PATCHAGE_PORTTYPE_HPP +#include "warnings.hpp" + +PATCHAGE_DISABLE_FMT_WARNINGS +#include <fmt/core.h> +#include <fmt/ostream.h> +PATCHAGE_RESTORE_WARNINGS + +#include <ostream> + namespace patchage { enum class PortType { @@ -27,6 +23,28 @@ enum class PortType { jack_cv, }; +inline std::ostream& +operator<<(std::ostream& os, const PortType port_type) +{ + switch (port_type) { + case PortType::jack_audio: + return os << "JACK audio"; + case PortType::jack_midi: + return os << "JACK MIDI"; + case PortType::alsa_midi: + return os << "ALSA MIDI"; + case PortType::jack_osc: + return os << "JACK OSC"; + case PortType::jack_cv: + return os << "JACK CV"; + } + + PATCHAGE_UNREACHABLE(); +} + } // namespace patchage +template<> +struct fmt::formatter<patchage::PortType> : fmt::ostream_formatter {}; + #endif // PATCHAGE_PORTTYPE_HPP diff --git a/src/Reactor.cpp b/src/Reactor.cpp index b48d85d..eb7300e 100644 --- a/src/Reactor.cpp +++ b/src/Reactor.cpp @@ -1,21 +1,9 @@ -/* 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/>. - */ +// Copyright 2007-2021 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #include "Reactor.hpp" +#include "Action.hpp" #include "Canvas.hpp" #include "CanvasModule.hpp" #include "CanvasPort.hpp" @@ -26,34 +14,35 @@ #include "ILog.hpp" #include "PortID.hpp" #include "Setting.hpp" +#include "SignalDirection.hpp" #include "warnings.hpp" -#include "ganv/Module.hpp" -#include "ganv/Port.hpp" +#include <ganv/Port.hpp> PATCHAGE_DISABLE_FMT_WARNINGS #include <fmt/core.h> -#include <fmt/ostream.h> PATCHAGE_RESTORE_WARNINGS -#include <boost/variant/apply_visitor.hpp> - -#include <ostream> +#include <variant> namespace patchage { -inline std::ostream& -operator<<(std::ostream& os, const ClientType type) +class SettingVisitor { - switch (type) { - case ClientType::jack: - return os << "JACK"; - case ClientType::alsa: - return os << "ALSA"; +public: + explicit SettingVisitor(Configuration& conf) + : _conf{conf} + {} + + template<class S> + void operator()(const S& setting) const + { + _conf.set_setting(setting); } - return os; -} +private: + Configuration& _conf; +}; Reactor::Reactor(Configuration& conf, Drivers& drivers, @@ -66,6 +55,13 @@ Reactor::Reactor(Configuration& conf, {} void +Reactor::operator()(const action::ChangeSetting& action) +{ + const SettingVisitor visitor{_conf}; + std::visit(visitor, action.setting); +} + +void Reactor::operator()(const action::ConnectPorts& action) { if (action.tail.type() == action.head.type()) { @@ -112,7 +108,7 @@ Reactor::operator()(const action::DisconnectPorts& action) if (auto* d = _drivers.driver(action.tail.type())) { d->disconnect(action.tail, action.head); } else { - _log.error(fmt::format("No driver for {}", action.tail.type())); + _log.error(fmt::format("No driver available to disconnect ports")); } } else { _log.error("Unable to disconnect incompatible ports"); @@ -141,7 +137,8 @@ Reactor::operator()(const action::Refresh&) void Reactor::operator()(const action::ResetFontSize&) { - _conf.set<setting::FontSize>(_canvas.get_default_font_size()); + _conf.set<setting::FontSize>( + static_cast<float>(_canvas.get_default_font_size())); } void @@ -162,7 +159,7 @@ void Reactor::operator()(const action::ZoomFull&) { _canvas.zoom_full(); - _conf.set<setting::Zoom>(_canvas.get_zoom()); + _conf.set<setting::Zoom>(static_cast<float>(_canvas.get_zoom())); } void @@ -186,7 +183,7 @@ Reactor::operator()(const action::ZoomOut&) void Reactor::operator()(const Action& action) { - boost::apply_visitor(*this, action); + std::visit(*this, action); } std::string @@ -194,11 +191,11 @@ Reactor::module_name(const ClientID& client) { // Note that split modules always have the same name - if (CanvasModule* mod = find_module(client, SignalDirection::input)) { + if (const CanvasModule* mod = find_module(client, SignalDirection::input)) { return mod->name(); } - if (CanvasModule* mod = find_module(client, SignalDirection::output)) { + if (const CanvasModule* mod = find_module(client, SignalDirection::output)) { return mod->name(); } diff --git a/src/Reactor.hpp b/src/Reactor.hpp index 58b1ffc..a5bc9e9 100644 --- a/src/Reactor.hpp +++ b/src/Reactor.hpp @@ -1,29 +1,17 @@ -/* 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/>. - */ +// Copyright 2007-2021 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef PATCHAGE_REACTOR_HPP #define PATCHAGE_REACTOR_HPP #include "Action.hpp" -#include "SignalDirection.hpp" #include <string> namespace patchage { +enum class SignalDirection; + struct ClientID; struct PortID; @@ -38,21 +26,20 @@ class ILog; class Reactor { public: - using result_type = void; ///< For boost::apply_visitor - explicit Reactor(Configuration& conf, Drivers& drivers, Canvas& canvas, ILog& log); - Reactor(const Reactor&) = delete; + Reactor(const Reactor&) = delete; Reactor& operator=(const Reactor&) = delete; - Reactor(Reactor&&) = delete; + Reactor(Reactor&&) = delete; Reactor& operator=(Reactor&&) = delete; ~Reactor() = default; + void operator()(const action::ChangeSetting& action); void operator()(const action::ConnectPorts& action); void operator()(const action::DecreaseFontSize& action); void operator()(const action::DisconnectClient& action); diff --git a/src/Setting.hpp b/src/Setting.hpp index 90fb124..4bcfc81 100644 --- a/src/Setting.hpp +++ b/src/Setting.hpp @@ -1,18 +1,5 @@ -/* 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/>. - */ +// Copyright 2007-2021 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef PATCHAGE_SETTING_HPP #define PATCHAGE_SETTING_HPP @@ -20,54 +7,81 @@ #include "Coord.hpp" #include "PortType.hpp" -#include <boost/variant/variant.hpp> - #include <cstdint> +#include <variant> namespace patchage { namespace setting { -template<class T> -struct Setting { - using Value = T; +struct AlsaAttached { + bool value{}; +}; + +struct FontSize { + float value{}; +}; + +struct HumanNames { + bool value{}; +}; - Value value{}; +struct JackAttached { + bool value{}; +}; + +struct MessagesHeight { + int value{}; +}; + +struct MessagesVisible { + bool value{}; }; struct PortColor { PortType type{}; - uint32_t value{}; + uint32_t color{}; }; -struct AlsaAttached : Setting<bool> {}; -struct FontSize : Setting<float> {}; -struct HumanNames : Setting<bool> {}; -struct JackAttached : Setting<bool> {}; -struct MessagesHeight : Setting<int> {}; -struct MessagesVisible : Setting<bool> {}; -struct SortedPorts : Setting<bool> {}; -struct SprungLayout : Setting<bool> {}; -struct ToolbarVisible : Setting<bool> {}; -struct WindowLocation : Setting<Coord> {}; -struct WindowSize : Setting<Coord> {}; -struct Zoom : Setting<float> {}; +struct SortedPorts { + bool value{}; +}; + +struct SprungLayout { + bool value{}; +}; + +struct ToolbarVisible { + bool value{}; +}; + +struct WindowLocation { + Coord value{}; +}; + +struct WindowSize { + Coord value{}; +}; + +struct Zoom { + float value{}; +}; } // namespace setting /// A configuration setting -using Setting = boost::variant<setting::AlsaAttached, - setting::FontSize, - setting::HumanNames, - setting::JackAttached, - setting::MessagesHeight, - setting::MessagesVisible, - setting::PortColor, - setting::SortedPorts, - setting::SprungLayout, - setting::ToolbarVisible, - setting::WindowLocation, - setting::WindowSize, - setting::Zoom>; +using Setting = std::variant<setting::AlsaAttached, + setting::FontSize, + setting::HumanNames, + setting::JackAttached, + setting::MessagesHeight, + setting::MessagesVisible, + setting::PortColor, + setting::SortedPorts, + setting::SprungLayout, + setting::ToolbarVisible, + setting::WindowLocation, + setting::WindowSize, + setting::Zoom>; } // namespace patchage diff --git a/src/SignalDirection.hpp b/src/SignalDirection.hpp index 94f5126..84c3cc2 100644 --- a/src/SignalDirection.hpp +++ b/src/SignalDirection.hpp @@ -1,22 +1,18 @@ -/* 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/>. - */ +// Copyright 2007-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef PATCHAGE_SIGNALDIRECTION_HPP #define PATCHAGE_SIGNALDIRECTION_HPP +#include "warnings.hpp" + +PATCHAGE_DISABLE_FMT_WARNINGS +#include <fmt/core.h> +#include <fmt/ostream.h> +PATCHAGE_RESTORE_WARNINGS + +#include <ostream> + namespace patchage { enum class SignalDirection { @@ -25,6 +21,24 @@ enum class SignalDirection { duplex, }; +inline std::ostream& +operator<<(std::ostream& os, const SignalDirection direction) +{ + switch (direction) { + case SignalDirection::input: + return os << "input"; + case SignalDirection::output: + return os << "output"; + case SignalDirection::duplex: + return os << "duplex"; + } + + PATCHAGE_UNREACHABLE(); +} + } // namespace patchage +template<> +struct fmt::formatter<patchage::SignalDirection> : fmt::ostream_formatter {}; + #endif // PATCHAGE_SIGNALDIRECTION_HPP diff --git a/src/TextViewLog.cpp b/src/TextViewLog.cpp index 33b7d22..ad20c37 100644 --- a/src/TextViewLog.cpp +++ b/src/TextViewLog.cpp @@ -1,18 +1,5 @@ -/* 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/>. - */ +// Copyright 2007-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #include "TextViewLog.hpp" @@ -21,6 +8,7 @@ #include <gdkmm/color.h> #include <glibmm/propertyproxy.h> #include <glibmm/refptr.h> +#include <glibmm/ustring.h> #include <gtkmm/enums.h> #include <gtkmm/textbuffer.h> #include <gtkmm/texttag.h> @@ -58,7 +46,7 @@ TextViewLog::TextViewLog(Widget<Gtk::TextView>& text_view) void TextViewLog::info(const std::string& msg) { - Glib::RefPtr<Gtk::TextBuffer> buffer = _text_view->get_buffer(); + const Glib::RefPtr<Gtk::TextBuffer> buffer = _text_view->get_buffer(); buffer->insert(buffer->end(), std::string("\n") + msg); _text_view->scroll_to_mark(buffer->get_insert(), 0); } @@ -66,7 +54,7 @@ TextViewLog::info(const std::string& msg) void TextViewLog::warning(const std::string& msg) { - Glib::RefPtr<Gtk::TextBuffer> buffer = _text_view->get_buffer(); + const Glib::RefPtr<Gtk::TextBuffer> buffer = _text_view->get_buffer(); buffer->insert_with_tag(buffer->end(), std::string("\n") + msg, _warning_tag); _text_view->scroll_to_mark(buffer->get_insert(), 0); } @@ -74,7 +62,7 @@ TextViewLog::warning(const std::string& msg) void TextViewLog::error(const std::string& msg) { - Glib::RefPtr<Gtk::TextBuffer> buffer = _text_view->get_buffer(); + const Glib::RefPtr<Gtk::TextBuffer> buffer = _text_view->get_buffer(); buffer->insert_with_tag(buffer->end(), std::string("\n") + msg, _error_tag); _text_view->scroll_to_mark(buffer->get_insert(), 0); } @@ -82,13 +70,13 @@ TextViewLog::error(const std::string& msg) int TextViewLog::min_height() const { - Glib::RefPtr<Gtk::TextBuffer> buffer = _text_view->get_buffer(); + const Glib::RefPtr<Gtk::TextBuffer> buffer = _text_view->get_buffer(); int y = 0; int line_height = 0; _text_view->get_line_yrange(buffer->begin(), y, line_height); - return line_height + 2 * _text_view->get_pixels_inside_wrap(); + return line_height + (2 * _text_view->get_pixels_inside_wrap()); } } // namespace patchage diff --git a/src/TextViewLog.hpp b/src/TextViewLog.hpp index 5a91853..40d0782 100644 --- a/src/TextViewLog.hpp +++ b/src/TextViewLog.hpp @@ -1,18 +1,5 @@ -/* 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/>. - */ +// Copyright 2007-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef PATCHAGE_TEXTVIEWLOG_HPP #define PATCHAGE_TEXTVIEWLOG_HPP @@ -39,10 +26,10 @@ class TextViewLog : public ILog public: explicit TextViewLog(Widget<Gtk::TextView>& text_view); - TextViewLog(const TextViewLog&) = delete; + TextViewLog(const TextViewLog&) = delete; TextViewLog& operator=(const TextViewLog&) = delete; - TextViewLog(TextViewLog&&) = delete; + TextViewLog(TextViewLog&&) = delete; TextViewLog& operator=(TextViewLog&&) = delete; ~TextViewLog() override = default; diff --git a/src/UIFile.hpp b/src/UIFile.hpp index ee0c4b7..1f2c39f 100644 --- a/src/UIFile.hpp +++ b/src/UIFile.hpp @@ -1,34 +1,19 @@ -/* 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/>. - */ +// Copyright 2007-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef PATCHAGE_UIFILE_HPP #define PATCHAGE_UIFILE_HPP #include "patchage_config.h" -#ifdef PATCHAGE_BINLOC +#if PATCHAGE_BUNDLED # include "binary_location.h" #endif #include <glibmm/refptr.h> #include <gtkmm/builder.h> -#include <fstream> #include <iostream> -#include <sstream> #include <stdexcept> #include <string> @@ -37,7 +22,7 @@ namespace patchage { class UIFile { public: - inline static bool is_readable(const std::string& filename) + static bool is_readable(const std::string& filename) { std::ifstream fs(filename.c_str()); const bool fail = fs.fail(); @@ -47,27 +32,26 @@ public: static Glib::RefPtr<Gtk::Builder> open(const std::string& base_name) { - std::string ui_filename; -#ifdef PATCHAGE_BINLOC + std::string ui_filename = base_name + ".ui"; + +#if PATCHAGE_BUNDLED const std::string bundle = bundle_location(); if (!bundle.empty()) { - ui_filename = bundle + "/" + base_name + ".ui"; - if (is_readable(ui_filename)) { - std::cout << "Loading UI file " << ui_filename << std::endl; - return Gtk::Builder::create_from_file(ui_filename); + const std::string bundle_ui_filename = bundle + "/" + ui_filename; + if (is_readable(bundle_ui_filename)) { + std::cout << "Loading UI file " << bundle_ui_filename << "\n"; + return Gtk::Builder::create_from_file(bundle_ui_filename); } } #endif - ui_filename = std::string(PATCHAGE_DATA_DIR) + "/" + base_name + ".ui"; + + ui_filename = std::string(PATCHAGE_DATA_DIR) + "/" + ui_filename; if (is_readable(ui_filename)) { - std::cout << "Loading UI file " << ui_filename << std::endl; + std::cout << "Loading UI file " << ui_filename << "\n"; return Gtk::Builder::create_from_file(ui_filename); } - std::stringstream ss; - ss << "Unable to find " << base_name << std::endl; - throw std::runtime_error(ss.str()); - return Glib::RefPtr<Gtk::Builder>(); + throw std::runtime_error("Unable to find " + ui_filename); } }; diff --git a/src/Widget.hpp b/src/Widget.hpp index 3d13b91..0f813da 100644 --- a/src/Widget.hpp +++ b/src/Widget.hpp @@ -1,24 +1,11 @@ -/* 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/>. - */ +// Copyright 2007-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef PATCHAGE_WIDGET_HPP #define PATCHAGE_WIDGET_HPP #include <glibmm/refptr.h> -#include <gtkmm/builder.h> // IWYU pragma: keep +#include <gtkmm/builder.h> #include <string> @@ -33,10 +20,10 @@ public: xml->get_widget(name, _me); } - Widget(const Widget&) = delete; + Widget(const Widget&) = delete; Widget& operator=(const Widget&) = delete; - Widget(Widget&&) = delete; + Widget(Widget&&) = delete; Widget& operator=(Widget&&) = delete; ~Widget() = default; diff --git a/src/binary_location.h b/src/binary_location.h index 220c534..e298775 100644 --- a/src/binary_location.h +++ b/src/binary_location.h @@ -1,26 +1,8 @@ -/* This file is part of Patchage. - * Copyright 2008-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 _GNU_SOURCE -# define _GNU_SOURCE -#endif +// Copyright 2008-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #include <dlfcn.h> -#include <climits> #include <cstdlib> #include <string> @@ -30,31 +12,31 @@ namespace patchage { inline std::string binary_location() { - Dl_info dli = {}; - const int ret = dladdr(reinterpret_cast<void*>(&binary_location), &dli); - if (!ret) { - return ""; - } - - char* const bin_loc = realpath(dli.dli_fname, nullptr); - if (!bin_loc) { - return ""; - } - - std::string loc{bin_loc}; - free(bin_loc); - return loc; + Dl_info dli = {}; + const int ret = dladdr(reinterpret_cast<void*>(&binary_location), &dli); + if (!ret) { + return ""; + } + + char* const bin_loc = realpath(dli.dli_fname, nullptr); + if (!bin_loc) { + return ""; + } + + std::string loc{bin_loc}; + free(bin_loc); + return loc; } /** Return the absolute path of the bundle (binary parent directory). */ inline std::string bundle_location() { - const std::string binary = binary_location(); - if (binary.empty()) { - return ""; - } - return binary.substr(0, binary.find_last_of('/')); + const std::string binary = binary_location(); + if (binary.empty()) { + return ""; + } + return binary.substr(0, binary.find_last_of('/')); } } // namespace patchage diff --git a/src/event_to_string.cpp b/src/event_to_string.cpp index c8a6c42..8212b9d 100644 --- a/src/event_to_string.cpp +++ b/src/event_to_string.cpp @@ -1,18 +1,5 @@ -/* 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/>. - */ +// Copyright 2007-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #include "event_to_string.hpp" @@ -28,22 +15,18 @@ PATCHAGE_DISABLE_FMT_WARNINGS #include <fmt/core.h> -#include <fmt/ostream.h> PATCHAGE_RESTORE_WARNINGS -#include <boost/optional/optional.hpp> -#include <boost/variant/apply_visitor.hpp> - -#include <ostream> // IWYU pragma: keep +#include <optional> +#include <ostream> #include <string> +#include <variant> namespace patchage { namespace { struct EventPrinter { - using result_type = std::string; ///< For boost::apply_visitor - std::string operator()(const ClientType type) { switch (type) { @@ -78,44 +61,12 @@ struct EventPrinter { return fmt::format(R"(Remove client "{}")", event.id); } - std::string operator()(const PortType port_type) - { - switch (port_type) { - case PortType::jack_audio: - return "JACK audio"; - case PortType::jack_midi: - return "JACK MIDI"; - case PortType::alsa_midi: - return "ALSA MIDI"; - case PortType::jack_osc: - return "JACK OSC"; - case PortType::jack_cv: - return "JACK CV"; - } - - PATCHAGE_UNREACHABLE(); - } - - std::string operator()(const SignalDirection direction) - { - switch (direction) { - case SignalDirection::input: - return "input"; - case SignalDirection::output: - return "output"; - case SignalDirection::duplex: - return "duplex"; - } - - PATCHAGE_UNREACHABLE(); - } - std::string operator()(const event::PortCreated& event) { - auto result = fmt::format(R"(Add{} {} {} port "{}" ("{}"))", + auto result = fmt::format(R"(Add {}{} {} "{}" ("{}"))", + event.info.type, event.info.is_terminal ? " terminal" : "", - (*this)(event.info.type), - (*this)(event.info.direction), + event.info.direction, event.id, event.info.label); @@ -128,7 +79,7 @@ struct EventPrinter { std::string operator()(const event::PortDestroyed& event) { - return fmt::format(R"("Remove port "{}")", event.id); + return fmt::format(R"(Remove port "{}")", event.id); } std::string operator()(const event::PortsConnected& event) @@ -148,7 +99,7 @@ std::string event_to_string(const Event& event) { EventPrinter printer; - return boost::apply_visitor(printer, event); + return std::visit(printer, event); } std::ostream& diff --git a/src/event_to_string.hpp b/src/event_to_string.hpp index db55733..926065c 100644 --- a/src/event_to_string.hpp +++ b/src/event_to_string.hpp @@ -1,18 +1,5 @@ -/* 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/>. - */ +// Copyright 2007-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef PATCHAGE_EVENT_TO_STRING_HPP #define PATCHAGE_EVENT_TO_STRING_HPP diff --git a/src/handle_event.cpp b/src/handle_event.cpp index fa543e6..4564a27 100644 --- a/src/handle_event.cpp +++ b/src/handle_event.cpp @@ -1,18 +1,5 @@ -/* 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/>. - */ +// Copyright 2007-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #include "handle_event.hpp" @@ -29,12 +16,9 @@ PATCHAGE_DISABLE_FMT_WARNINGS #include <fmt/core.h> -#include <fmt/ostream.h> PATCHAGE_RESTORE_WARNINGS -#include <boost/variant/apply_visitor.hpp> - -#include <iosfwd> +#include <variant> namespace patchage { @@ -43,8 +27,6 @@ namespace { class EventHandler { public: - using result_type = void; ///< For boost::apply_visitor - explicit EventHandler(Configuration& conf, Metadata& metadata, Canvas& canvas, @@ -97,7 +79,7 @@ public: { _metadata.set_port(event.id, event.info); - auto* const port = + const auto* const port = _canvas.create_port(_conf, _metadata, event.id, event.info); if (!port) { @@ -161,7 +143,7 @@ handle_event(Configuration& conf, const Event& event) { EventHandler handler{conf, metadata, canvas, log}; - boost::apply_visitor(handler, event); + std::visit(handler, event); } } // namespace patchage diff --git a/src/handle_event.hpp b/src/handle_event.hpp index 5cf15ef..fae6d78 100644 --- a/src/handle_event.hpp +++ b/src/handle_event.hpp @@ -1,18 +1,5 @@ -/* 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/>. - */ +// Copyright 2007-2021 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef PATCHAGE_HANDLE_EVENT_HPP #define PATCHAGE_HANDLE_EVENT_HPP diff --git a/src/i18n.hpp b/src/i18n.hpp new file mode 100644 index 0000000..ebf8fd1 --- /dev/null +++ b/src/i18n.hpp @@ -0,0 +1,12 @@ +// Copyright 2022 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef PATCHAGE_I18N_HPP +#define PATCHAGE_I18N_HPP + +#include <libintl.h> + +/// Mark a string literal as translatable +#define T(msgid) gettext(msgid) + +#endif // PATCHAGE_I18N_HPP diff --git a/src/jackey.h b/src/jackey.h index 2c0e298..607eadb 100644 --- a/src/jackey.h +++ b/src/jackey.h @@ -1,18 +1,5 @@ -/* - Copyright 2014-2020 David Robillard <d@drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ +// Copyright 2014-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef JACKEY_H #define JACKEY_H diff --git a/src/main.cpp b/src/main.cpp index 499db30..289242f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,18 +1,5 @@ -/* 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/>. - */ +// Copyright 2007-2022 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #ifdef __APPLE__ # include "binary_location.h" @@ -34,6 +21,12 @@ #include <glibmm/ustring.h> #include <gtkmm/main.h> +#if USE_GETTEXT +# include <libintl.h> + +# include <clocale> +#endif + #include <cstring> #include <exception> #include <iostream> @@ -82,16 +75,16 @@ print_usage() std::cout << "Usage: patchage [OPTION]...\n"; std::cout << "Visually connect JACK and ALSA Audio and MIDI ports.\n\n"; std::cout << "Options:\n"; - std::cout << " -h, --help Display this help and exit.\n"; - std::cout << " -A, --no-alsa Do not automatically attach to ALSA.\n"; - std::cout << " -J, --no-jack Do not automatically attack to JACK.\n"; + std::cout << " -h, --help Display this help and exit\n"; + std::cout << " -A, --no-alsa Do not automatically attach to ALSA\n"; + std::cout << " -J, --no-jack Do not automatically attack to JACK\n"; } void print_version() { std::cout << "Patchage " PATCHAGE_VERSION << R"( -Copyright 2007-2020 David Robillard <d@drobilla.net>. +Copyright 2007-2022 David Robillard <d@drobilla.net>. License GPLv3+: <http://gnu.org/licenses/gpl.html>. This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. @@ -107,10 +100,20 @@ main(int argc, char** argv) set_bundle_environment(); #endif +#if USE_GETTEXT + if (!setlocale(LC_ALL, "")) { + std::cerr << "patchage: failed to set locale\n"; + } + + bindtextdomain("patchage", PATCHAGE_LOCALE_DIR); + bind_textdomain_codeset("patchage", "UTF-8"); + textdomain("patchage"); +#endif + try { Glib::thread_init(); - Gtk::Main app(argc, argv); + const Gtk::Main app(argc, argv); ++argv; --argc; @@ -143,12 +146,11 @@ main(int argc, char** argv) patchage::Patchage patchage(options); Gtk::Main::run(*patchage.window()); patchage.save(); - } catch (std::exception& e) { - std::cerr << "patchage: error: " << e.what() << std::endl; + std::cerr << "patchage: error: " << e.what() << "\n"; return 1; } catch (Glib::Exception& e) { - std::cerr << "patchage: error: " << e.what() << std::endl; + std::cerr << "patchage: error: " << e.what() << "\n"; return 1; } diff --git a/src/make_alsa_driver.hpp b/src/make_alsa_driver.hpp index f72da99..7f3b594 100644 --- a/src/make_alsa_driver.hpp +++ b/src/make_alsa_driver.hpp @@ -1,24 +1,10 @@ -/* 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/>. - */ +// Copyright 2007-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef PATCHAGE_MAKE_ALSA_DRIVER_HPP #define PATCHAGE_MAKE_ALSA_DRIVER_HPP #include "Driver.hpp" -#include "patchage_config.h" #include <memory> @@ -26,21 +12,9 @@ namespace patchage { class ILog; -#if defined(HAVE_ALSA) - std::unique_ptr<Driver> make_alsa_driver(ILog& log, Driver::EventSink emit_event); -#else - -inline std::unique_ptr<Driver> -make_alsa_driver(ILog&, Driver::EventSink) -{ - return nullptr; -} - -#endif - } // namespace patchage #endif // PATCHAGE_MAKE_ALSA_DRIVER_HPP diff --git a/src/make_jack_driver.hpp b/src/make_jack_driver.hpp index abd1ba1..79c6eb5 100644 --- a/src/make_jack_driver.hpp +++ b/src/make_jack_driver.hpp @@ -1,24 +1,10 @@ -/* 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/>. - */ +// Copyright 2007-2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef PATCHAGE_MAKE_JACK_DRIVER_HPP #define PATCHAGE_MAKE_JACK_DRIVER_HPP #include "Driver.hpp" -#include "patchage_config.h" #include <memory> @@ -27,21 +13,9 @@ namespace patchage { class AudioDriver; class ILog; -#if defined(PATCHAGE_LIBJACK) || defined(HAVE_JACK_DBUS) - std::unique_ptr<AudioDriver> make_jack_driver(ILog& log, Driver::EventSink emit_event); -#else - -inline std::unique_ptr<AudioDriver> -make_jack_driver(ILog&, Driver::EventSink) -{ - return nullptr; -} - -#endif - } // namespace patchage #endif // PATCHAGE_MAKE_JACK_DRIVER_HPP diff --git a/src/patchage.ui b/src/patchage.ui.in index d86fb80..a7078d5 100644 --- a/src/patchage.ui +++ b/src/patchage.ui.in @@ -5,7 +5,7 @@ <object class="GtkWindow" id="main_win"> <property name="can_focus">False</property> <property name="border_width">1</property> - <property name="title" translatable="yes">Patchage</property> + <property name="title" translatable="no">Patchage</property> <child> <object class="GtkVBox" id="main_vbox"> <property name="visible">True</property> @@ -27,7 +27,7 @@ <object class="GtkMenuItem" id="menu_export_image"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="label" translatable="yes">_Export Image...</property> + <property name="label" translatable="yes">_Export Image…</property> <property name="use_underline">True</property> <accelerator key="e" signal="activate" modifiers="GDK_CONTROL_MASK"/> </object> @@ -64,7 +64,7 @@ <property name="can_focus">False</property> <child> <object class="GtkImageMenuItem" id="menu_jack_connect"> - <property name="label">Connect to _Jack</property> + <property name="label" translatable="yes">Connect to _JACK</property> <property name="visible">True</property> <property name="can_focus">False</property> <property name="use_underline">True</property> @@ -75,7 +75,7 @@ </child> <child> <object class="GtkImageMenuItem" id="menu_jack_disconnect"> - <property name="label">Disconnect from Jack</property> + <property name="label" translatable="yes">Disconnect from JACK</property> <property name="visible">True</property> <property name="sensitive">False</property> <property name="can_focus">False</property> @@ -92,7 +92,7 @@ </child> <child> <object class="GtkImageMenuItem" id="menu_alsa_connect"> - <property name="label">Connect to _Alsa</property> + <property name="label" translatable="yes">Connect to _ALSA</property> <property name="visible">True</property> <property name="can_focus">False</property> <property name="use_underline">True</property> @@ -103,7 +103,7 @@ </child> <child> <object class="GtkImageMenuItem" id="menu_alsa_disconnect"> - <property name="label">Disconnect from ALSA</property> + <property name="label" translatable="yes">Disconnect from ALSA</property> <property name="visible">True</property> <property name="sensitive">False</property> <property name="can_focus">False</property> @@ -269,7 +269,7 @@ </child> <child> <object class="GtkImageMenuItem" id="menu_view_arrange"> - <property name="label">_Arrange</property> + <property name="label" translatable="yes">_Arrange</property> <property name="visible">True</property> <property name="can_focus">False</property> <property name="use_underline">True</property> @@ -284,6 +284,7 @@ <property name="can_focus">False</property> <property name="label" translatable="yes">Sprung Layou_t</property> <property name="use_underline">True</property> + <property name="active">False</property> <accelerator key="t" signal="activate" modifiers="GDK_CONTROL_MASK"/> </object> </child> @@ -338,7 +339,7 @@ <object class="GtkAlignment" id="alignment2"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="tooltip_text" translatable="yes">Jack buffer size and sample rate.</property> + <property name="tooltip_text" translatable="yes">JACK buffer size and sample rate.</property> <property name="yscale">0</property> <child> <object class="GtkHBox" id="hbox4"> @@ -349,8 +350,8 @@ <property name="visible">True</property> <property name="can_focus">True</property> <property name="has_tooltip">True</property> - <property name="tooltip_markup">Jack buffer length in frames</property> - <property name="tooltip_text" translatable="yes">Jack buffer length in frames.</property> + <property name="tooltip_markup">JACK buffer length in frames</property> + <property name="tooltip_text" translatable="yes">JACK buffer length in frames.</property> <property name="border_width">1</property> </object> <packing> @@ -362,7 +363,7 @@ <child> <object class="GtkLabel" id="latency_label"> <property name="can_focus">False</property> - <property name="label" translatable="yes">frames @ ? kHz (? ms)</property> + <property name="label" translatable="yes">frames at ? kHz (? ms)</property> </object> <packing> <property name="expand">False</property> @@ -388,7 +389,7 @@ <object class="GtkLabel" id="dropouts_label"> <property name="can_focus">False</property> <property name="visible">False</property> - <property name="label" translatable="yes"> Dropouts: 0</property> + <property name="label" translatable="yes">Dropouts: {}</property> </object> </child> </object> @@ -500,11 +501,11 @@ <property name="transient_for">main_win</property> <property name="program_name">Patchage</property> <property name="version">@PATCHAGE_VERSION@</property> - <property name="copyright" translatable="yes">© 2005-2020 David Robillard + <property name="copyright" translatable="no">© 2005-2022 David Robillard © 2008 Nedko Arnaudov</property> - <property name="comments" translatable="yes">A JACK and ALSA front-end.</property> + <property name="comments" translatable="yes">A modular patchbay for JACK and ALSA applications.</property> <property name="website">http://drobilla.net/software/patchage</property> - <property name="license" translatable="yes"> GNU GENERAL PUBLIC LICENSE + <property name="license" translatable="no"> GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> diff --git a/src/patchage_config.h b/src/patchage_config.h new file mode 100644 index 0000000..6c4f09f --- /dev/null +++ b/src/patchage_config.h @@ -0,0 +1,112 @@ +// Copyright 2021-2023 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later + +/* + Configuration header that defines reasonable defaults at compile-time. + + This allows configuration from the command-line (usually by the build system) + while still allowing the code to compile "as-is" with reasonable default + features on supported platforms. + + This system is designed so that, ideally, no command-line or build-system + configuration is needed, but automatic feature detection can be disabled or + overridden for maximum control. It should never be necessary to edit the + source code to achieve a given configuration. + + Usage: + + - By default, features are enabled if they can be detected or assumed to be + available from the build environment, unless `PATCHAGE_NO_DEFAULT_CONFIG` + is defined, which disables everything by default. + + - If a symbol like `HAVE_SOMETHING` is defined to non-zero, then the + "something" feature is assumed to be available. + + Code rules: + + - To check for a feature, this header must be included, and the symbol + `USE_SOMETHING` used as a boolean in an `#if` expression. + + - None of the other configuration symbols described here may be used + directly. In particular, this header should be the only place in the + source code that touches `HAVE` symbols. +*/ + +#ifndef PATCHAGE_CONFIG_H +#define PATCHAGE_CONFIG_H + +// Define version unconditionally so a warning will catch a mismatch +#define PATCHAGE_VERSION "1.0.11" + +#if !defined(PATCHAGE_NO_DEFAULT_CONFIG) + +// Classic UNIX: dladdr() +# ifndef HAVE_DLADDR +# ifdef __has_include +# if __has_include(<dlfcn.h>) +# define HAVE_DLADDR 1 +# endif +# elif defined(__unix__) || defined(__APPLE__) +# define HAVE_DLADDR 1 +# endif +# endif + +// GNU gettext() +# ifndef HAVE_GETTEXT +# ifdef __has_include +# if __has_include(<libintl.h>) +# define HAVE_GETTEXT 1 +# endif +# endif +# endif + +// JACK metadata API +# ifndef HAVE_JACK_METADATA +# ifdef __has_include +# if __has_include(<jack/metadata.h>) +# define HAVE_JACK_METADATA 1 +# endif +# endif +# endif + +#endif // !defined(PATCHAGE_NO_DEFAULT_CONFIG) + +/* + Make corresponding USE_FEATURE defines based on the HAVE_FEATURE defines from + above or the command line. The code checks for these using #if (not #ifdef), + so there will be an undefined warning if it checks for an unknown feature, + and this header is always required by any code that checks for features, even + if the build system defines them all. +*/ + +#if defined(HAVE_DLADDR) && HAVE_DLADDR +# define USE_DLADDR 1 +#else +# define USE_DLADDR 0 +#endif + +#if defined(HAVE_GETTEXT) && HAVE_GETTEXT +# define USE_GETTEXT 1 +#else +# define USE_GETTEXT 0 +#endif + +#if defined(HAVE_JACK_METADATA) && HAVE_JACK_METADATA +# define USE_JACK_METADATA 1 +#else +# define USE_JACK_METADATA 0 +#endif + +#if !defined(PATCHAGE_USE_LIGHT_THEME) +# define PATCHAGE_USE_LIGHT_THEME 0 +#endif + +#ifndef PATCHAGE_BUNDLED +# ifdef __APPLE__ +# define PATCHAGE_BUNDLED 1 +# else +# define PATCHAGE_BUNDLED 0 +# endif +#endif + +#endif // PATCHAGE_CONFIG_H diff --git a/src/warnings.hpp b/src/warnings.hpp index e8337a1..ee9b3d8 100644 --- a/src/warnings.hpp +++ b/src/warnings.hpp @@ -1,18 +1,5 @@ -/* This file is part of Patchage. - * Copyright 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/>. - */ +// Copyright 2020 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later #ifndef PATCHAGE_WARNINGS_HPP #define PATCHAGE_WARNINGS_HPP |