diff options
Diffstat (limited to 'src')
63 files changed, 522 insertions, 370 deletions
diff --git a/src/.clang-tidy b/src/.clang-tidy index 8a58aa7b..1d7809c3 100644 --- a/src/.clang-tidy +++ b/src/.clang-tidy @@ -26,5 +26,4 @@ Checks: > -misc-no-recursion, -misc-unused-parameters, -readability-function-cognitive-complexity, - -readability-use-anyofallof, InheritParentConfig: true diff --git a/src/AtomForge.cpp b/src/AtomForge.cpp new file mode 100644 index 00000000..6a62a609 --- /dev/null +++ b/src/AtomForge.cpp @@ -0,0 +1,128 @@ +/* + This file is part of Ingen. + Copyright 2007-2024 David Robillard <http://drobilla.net/> + + Ingen is free software: you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free + Software Foundation, either version 3 of the License, or any later version. + + Ingen 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 Affero General Public License for details. + + You should have received a copy of the GNU Affero General Public License + along with Ingen. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "ingen/AtomForge.hpp" + +#include "lv2/atom/atom.h" +#include "lv2/atom/forge.h" +#include "lv2/atom/util.h" +#include "lv2/urid/urid.h" +#include "sord/sord.h" +#include "sord/sordmm.hpp" + +#include <cassert> +#include <cstring> +#include <utility> + +namespace ingen { + +AtomForge::AtomForge(LV2_URID_Map& map) + : LV2_Atom_Forge{} + , _sratom{sratom_new(&map)} + , _buf{static_cast<LV2_Atom*>(calloc(8, sizeof(LV2_Atom)))} +{ + lv2_atom_forge_init(this, &map); + lv2_atom_forge_set_sink(this, c_append, c_deref, this); +} + +void +AtomForge::read(Sord::World& world, + SordModel* const model, + const SordNode* const node) +{ + sratom_read(_sratom.get(), this, world.c_obj(), model, node); +} + +const LV2_Atom* +AtomForge::atom() const +{ + return _buf.get(); +} + +void +AtomForge::clear() +{ + lv2_atom_forge_set_sink(this, c_append, c_deref, this); + _size = 0; + *_buf = {0U, 0U}; +} + +Sratom& +AtomForge::sratom() +{ + return *_sratom; +} + +intptr_t +AtomForge::append(const void* const data, const uint32_t len) +{ + // Record offset of the start of this write (+1 to avoid null) + const auto ref = static_cast<intptr_t>(_size + 1U); + + // Update size and reallocate if necessary + if (lv2_atom_pad_size(_size + len) > _capacity) { + const size_t new_size = lv2_atom_pad_size(_size + len); + + // Release buffer and try to realloc it + auto* const old = _buf.release(); + auto* const new_buf = static_cast<LV2_Atom*>(realloc(old, new_size)); + if (!new_buf) { + // Failure, reclaim old buffer and signal error to caller + _buf = AtomPtr{old, FreeDeleter<LV2_Atom>{}}; + return 0; + } + + // Adopt new buffer and update capacity to make room for the new data + std::unique_ptr<LV2_Atom, FreeDeleter<LV2_Atom>> ptr{new_buf}; + _capacity = new_size; + _buf = std::move(ptr); + } + + // Append new data + memcpy(reinterpret_cast<uint8_t*>(_buf.get()) + _size, data, len); + _size += len; + return ref; +} + +LV2_Atom* +AtomForge::deref(const intptr_t ref) +{ + /* Make some assumptions and do unnecessary math to appease + -Wcast-align. This is questionable at best, though the forge should + only dereference references to aligned atoms. */ + LV2_Atom* const ptr = _buf.get(); + assert((ref - 1) % sizeof(LV2_Atom) == 0); + return static_cast<LV2_Atom*>(ptr + (ref - 1) / sizeof(LV2_Atom)); + + // Alternatively: + // return (LV2_Atom*)((uint8_t*)_buf.get() + ref - 1); +} + +LV2_Atom_Forge_Ref +AtomForge::c_append(void* const self, + const void* const data, + const uint32_t len) +{ + return static_cast<AtomForge*>(self)->append(data, len); +} + +LV2_Atom* +AtomForge::c_deref(void* const self, const LV2_Atom_Forge_Ref ref) +{ + return static_cast<AtomForge*>(self)->deref(ref); +} + +} // namespace ingen diff --git a/src/AtomWriter.cpp b/src/AtomWriter.cpp index e18b48b8..ce18337f 100644 --- a/src/AtomWriter.cpp +++ b/src/AtomWriter.cpp @@ -293,8 +293,8 @@ AtomWriter::operator()(const Delta& message) * Send a [Copy](http://lv2plug.in/ns/ext/copy#Copy) to copy an object from * its current location (subject) to another (destination). * - * If both the subject and destination are inside Ingen, like block paths, then the old object - * is copied by, for example, creating a new plugin instance. + * If both the subject and destination are inside Ingen, like block paths, then + * the old object is copied by, for example, creating a new plugin instance. * * If the subject is a filename (file URI or atom:Path) and the destination is * inside Ingen, then the subject must be an Ingen graph file or bundle, which @@ -434,7 +434,8 @@ AtomWriter::operator()(const Undo& message) /** @page protocol * @subsection Undo * - * Use [ingen:Redo](http://drobilla.net/ns/ingen#Redo) to redo the last undone change. + * Use [ingen:Redo](http://drobilla.net/ns/ingen#Redo) to redo the last undone + * change. * * @code{.ttl} * [] a ingen:Redo . diff --git a/src/ClashAvoider.cpp b/src/ClashAvoider.cpp index b782bcc7..0ed1da73 100644 --- a/src/ClashAvoider.cpp +++ b/src/ClashAvoider.cpp @@ -62,7 +62,7 @@ ClashAvoider::map_path(const raul::Path& in) // Path without _n suffix std::string base_path_str = in; if (has_offset) { - base_path_str = base_path_str.substr(0, base_path_str.find_last_of('_')); + base_path_str.resize(base_path_str.find_last_of('_')); } raul::Path base_path(base_path_str); @@ -98,12 +98,6 @@ ClashAvoider::map_path(const raul::Path& in) auto o = _offsets.find(base_path); if (o != _offsets.end()) { offset = ++o->second; - } else { - std::string parent_str = in.parent().base(); - parent_str = parent_str.substr(0, parent_str.find_last_of('/')); - if (parent_str.empty()) { - parent_str = "/"; - } } if (offset == 0) { @@ -158,9 +152,9 @@ numeric_suffix_start(const std::string& str) } std::string -ClashAvoider::adjust_name(const raul::Path& old_path, - const raul::Path& new_path, - std::string name) +ClashAvoider::adjust_name(const raul::Path& old_path, + const raul::Path& new_path, + const std::string& name) { const auto name_suffix_start = numeric_suffix_start(name); if (!name_suffix_start) { diff --git a/src/Configuration.cpp b/src/Configuration.cpp index 918bd9d3..b8a717ba 100644 --- a/src/Configuration.cpp +++ b/src/Configuration.cpp @@ -185,7 +185,7 @@ Configuration::parse(int argc, char** argv) std::string name = std::string(argv[i]).substr(2); const char* equals = strchr(argv[i], '='); if (equals) { - name = name.substr(0, name.find('=')); + name.resize(name.find('=')); } const auto o = _options.find(name); @@ -284,8 +284,10 @@ Configuration::save(URIMap& uri_map, } // Create parent directories if necessary - const FilePath dir = path.parent_path(); - if (!std::filesystem::create_directories(dir)) { + const FilePath dir = path.parent_path(); + std::error_code ec; + std::filesystem::create_directories(dir, ec); + if (ec) { throw FileError(fmt("Error creating directory %1% (%2%)", dir, strerror(errno))); } diff --git a/src/LV2Features.cpp b/src/LV2Features.cpp index 7d9003c0..5cdeca44 100644 --- a/src/LV2Features.cpp +++ b/src/LV2Features.cpp @@ -1,6 +1,6 @@ /* This file is part of Ingen. - Copyright 2007-2015 David Robillard <http://drobilla.net/> + Copyright 2007-2024 David Robillard <http://drobilla.net/> Ingen is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free @@ -18,6 +18,7 @@ #include "lv2/core/lv2.h" +#include <algorithm> #include <cstdlib> #include <memory> @@ -58,12 +59,9 @@ LV2Features::is_supported(const std::string& uri) const return true; } - for (const auto& f : _features) { - if (f->uri() == uri) { - return true; - } - } - return false; + return std::any_of(_features.begin(), + _features.end(), + [&uri](const auto& f) { return f->uri() == uri; }); } std::shared_ptr<LV2Features::FeatureArray> diff --git a/src/Log.cpp b/src/Log.cpp index e17e1555..7ace4ce3 100644 --- a/src/Log.cpp +++ b/src/Log.cpp @@ -1,6 +1,6 @@ /* This file is part of Ingen. - Copyright 2007-2016 David Robillard <http://drobilla.net/> + Copyright 2007-2024 David Robillard <http://drobilla.net/> Ingen is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free @@ -39,46 +39,44 @@ void Log::rt_error(const char* msg) { #ifndef NDEBUG - va_list args; - vtprintf(_uris.log_Error, msg, args); + tprintf(_uris.log_Error, msg); #endif } void Log::error(const std::string& msg) { - va_list args; - vtprintf(_uris.log_Error, msg.c_str(), args); + tprintf(_uris.log_Error, msg.c_str()); } void Log::warn(const std::string& msg) { - va_list args; - vtprintf(_uris.log_Warning, msg.c_str(), args); + tprintf(_uris.log_Warning, msg.c_str()); } void Log::info(const std::string& msg) { - va_list args; - vtprintf(_uris.log_Note, msg.c_str(), args); + tprintf(_uris.log_Note, msg.c_str()); } void Log::trace(const std::string& msg) { - va_list args; - vtprintf(_uris.log_Trace, msg.c_str(), args); + tprintf(_uris.log_Trace, msg.c_str()); } -void -Log::print(FILE* stream, const std::string& msg) const +int +Log::tprintf(LV2_URID type, const char* fmt, ...) { - fprintf(stream, "%s", msg.c_str()); - if (_flush) { - fflush(stdout); - } + va_list args; + va_start(args, fmt); + + const int ret = vtprintf(type, fmt, args); + + va_end(args); + return ret; } int @@ -120,11 +118,10 @@ Log::vtprintf(LV2_URID type, const char* fmt, va_list args) static int log_vprintf(LV2_Log_Handle handle, LV2_URID type, const char* fmt, va_list args) { - auto* f = static_cast<Log::Feature::Handle*>(handle); - va_list noargs = {}; + auto* const f = static_cast<Log::Feature::Handle*>(handle); - int ret = f->log->vtprintf(type, f->node->path().c_str(), noargs); - ret += f->log->vtprintf(type, ": ", noargs); + int ret = f->log->tprintf(type, f->node->path().c_str()); + ret += f->log->tprintf(type, ": "); ret += f->log->vtprintf(type, fmt, args); return ret; diff --git a/src/Parser.cpp b/src/Parser.cpp index 2a22c31b..04a10f23 100644 --- a/src/Parser.cpp +++ b/src/Parser.cpp @@ -36,6 +36,7 @@ #include "sord/sord.h" #include "sord/sordmm.hpp" +#include <algorithm> #include <cassert> #include <cstdint> #include <cstring> @@ -633,19 +634,18 @@ Parser::parse_file(ingen::World& world, return false; } - /* Choose the graph to load. If this is a manifest, then there should only - be one, but if this is a graph file, subgraphs will be returned as well. - In this case, choose the one with the file URI. */ - URI uri; - for (const ResourceRecord& r : resources) { - if (r.uri == URI(manifest_path)) { - uri = r.uri; - file_path = r.filename; - break; - } - } + // Try to find the graph with the manifest path for a URI + const auto m = std::find_if(resources.begin(), + resources.end(), + [manifest_path](const auto& r) { + return r.uri == URI(manifest_path); + }); - if (uri.empty()) { + URI uri; + if (m != resources.end()) { + uri = m->uri; + file_path = m->filename; + } else { // Didn't find a graph with the same URI as the file, use the first uri = (*resources.begin()).uri; file_path = (*resources.begin()).filename; diff --git a/src/URI.cpp b/src/URI.cpp index c4020c4d..81dd5686 100644 --- a/src/URI.cpp +++ b/src/URI.cpp @@ -52,14 +52,14 @@ URI::URI(const std::string& str, const URI& base) { } -URI::URI(SerdNode node) +URI::URI(const SerdNode& node) : _uri(SERD_URI_NULL) , _node(serd_node_new_uri_from_node(&node, nullptr, &_uri)) { assert(node.type == SERD_URI); } -URI::URI(SerdNode node, SerdURI uri) : _uri(uri), _node(node) +URI::URI(const SerdNode& node, const SerdURI& uri) : _uri(uri), _node(node) { assert(node.type == SERD_URI); } diff --git a/src/client/BlockModel.cpp b/src/client/BlockModel.cpp index dce30655..8ba446ab 100644 --- a/src/client/BlockModel.cpp +++ b/src/client/BlockModel.cpp @@ -75,23 +75,26 @@ BlockModel::~BlockModel() void BlockModel::remove_port(const std::shared_ptr<PortModel>& port) { - for (auto i = _ports.begin(); i != _ports.end(); ++i) { - if ((*i) == port) { - _ports.erase(i); - break; - } + const auto i = std::find_if(_ports.begin(), + _ports.end(), + [&port](const auto& p) { return p == port; }); + + if (i != _ports.end()) { + _ports.erase(i); + _signal_removed_port.emit(port); } - _signal_removed_port.emit(port); } void BlockModel::remove_port(const raul::Path& port_path) { - for (auto i = _ports.begin(); i != _ports.end(); ++i) { - if ((*i)->path() == port_path) { - _ports.erase(i); - break; - } + const auto i = + std::find_if(_ports.begin(), _ports.end(), [&port_path](const auto& p) { + return p->path() == port_path; + }); + + if (i != _ports.end()) { + _ports.erase(i); } } diff --git a/src/client/ClientStore.cpp b/src/client/ClientStore.cpp index 7cfd439d..66a8d3b6 100644 --- a/src/client/ClientStore.cpp +++ b/src/client/ClientStore.cpp @@ -79,7 +79,7 @@ ClientStore::add_object(const std::shared_ptr<ObjectModel>& object) assert(object->path().is_child_of(parent->path())); object->set_parent(parent); parent->add_child(object); - assert(parent && (object->parent() == parent)); + assert(object->parent() == parent); (*this)[object->path()] = object; _signal_new_object.emit(object); diff --git a/src/client/GraphModel.cpp b/src/client/GraphModel.cpp index 1404f021..0837f738 100644 --- a/src/client/GraphModel.cpp +++ b/src/client/GraphModel.cpp @@ -179,11 +179,4 @@ GraphModel::internal_poly() const return poly.is_valid() ? poly.get<int32_t>() : 1; } -bool -GraphModel::polyphonic() const -{ - const Atom& poly = get_property(_uris.ingen_polyphonic); - return poly.is_valid() && poly.get<int32_t>(); -} - } // namespace ingen::client diff --git a/src/client/PluginModel.cpp b/src/client/PluginModel.cpp index 333bf568..3036f2e8 100644 --- a/src/client/PluginModel.cpp +++ b/src/client/PluginModel.cpp @@ -103,7 +103,7 @@ PluginModel::get_property(const URI& key) const size_t last_delim = last_uri_delim(str); while (last_delim != string::npos && !contains_alpha_after(str, last_delim)) { - str = str.substr(0, last_delim); + str.resize(last_delim); last_delim = last_uri_delim(str); } str = str.substr(last_delim + 1); diff --git a/src/client/PortModel.cpp b/src/client/PortModel.cpp index 73f273c7..46129875 100644 --- a/src/client/PortModel.cpp +++ b/src/client/PortModel.cpp @@ -1,6 +1,6 @@ /* This file is part of Ingen. - Copyright 2007-2015 David Robillard <http://drobilla.net/> + Copyright 2007-2024 David Robillard <http://drobilla.net/> Ingen is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free @@ -22,10 +22,11 @@ #include "ingen/client/ObjectModel.hpp" #include "lv2/urid/urid.h" +#include <algorithm> #include <cstdint> +#include <exception> #include <map> #include <memory> -#include <utility> namespace ingen::client { @@ -60,14 +61,24 @@ PortModel::port_property(const URIs::Quark& uri) const bool PortModel::is_uri() const { - // FIXME: Resource::has_property doesn't work, URI != URID - for (const auto& p : properties()) { - if (p.second.type() == _uris.atom_URID && - static_cast<LV2_URID>(p.second.get<int32_t>()) == _uris.atom_URID) { - return true; - } - } - return false; + return std::any_of( + properties().begin(), properties().end(), [this](const auto& p) { + return (p.second.type() == _uris.atom_URID && + static_cast<LV2_URID>(p.second.template get<int32_t>()) == + _uris.atom_URID); + }); +} + +void +PortModel::add_child(const std::shared_ptr<ObjectModel>&) +{ + std::terminate(); +} + +bool +PortModel::remove_child(const std::shared_ptr<ObjectModel>&) +{ + std::terminate(); } void diff --git a/src/gui/App.hpp b/src/gui/App.hpp index d7776896..36800898 100644 --- a/src/gui/App.hpp +++ b/src/gui/App.hpp @@ -77,6 +77,11 @@ class INGEN_API App public: ~App(); + App(const App&) = delete; + App& operator=(const App&) = delete; + App(App&&) = delete; + App& operator=(App&&) = delete; + void error_message(const std::string& str); void attach(const std::shared_ptr<ingen::Interface>& client); diff --git a/src/gui/BreadCrumbs.cpp b/src/gui/BreadCrumbs.cpp index be613407..982c3b06 100644 --- a/src/gui/BreadCrumbs.cpp +++ b/src/gui/BreadCrumbs.cpp @@ -26,6 +26,7 @@ #include <sigc++/adaptors/bind.h> #include <sigc++/functors/mem_fun.h> +#include <algorithm> #include <string> #include <variant> @@ -46,13 +47,13 @@ BreadCrumbs::BreadCrumbs(App& app) std::shared_ptr<GraphView> BreadCrumbs::view(const raul::Path& path) { - for (const auto& b : _breadcrumbs) { - if (b->path() == path) { - return b->view(); - } - } + const auto b = std::find_if(_breadcrumbs.begin(), + _breadcrumbs.end(), + [&path](const auto* crumb) { + return crumb->path() == path; + }); - return nullptr; + return b == _breadcrumbs.end() ? nullptr : (*b)->view(); } /** Sets up the crumbs to display `path`. @@ -69,7 +70,7 @@ BreadCrumbs::build(const raul::Path& path, if (!_breadcrumbs.empty() && (path.is_parent_of(_full_path) || path == _full_path)) { // Moving to a path we already contain, just switch the active button - for (const auto& b : _breadcrumbs) { + for (auto* b : _breadcrumbs) { if (b->path() == path) { b->set_active(true); if (!b->view()) { @@ -85,7 +86,6 @@ BreadCrumbs::build(const raul::Path& path, } _active_path = path; - _enable_signal = old_enable_signal; } else if (!_breadcrumbs.empty() && path.is_child_of(_full_path)) { // Moving to a child of the full path, append crumbs (preserve cache) @@ -108,7 +108,7 @@ BreadCrumbs::build(const raul::Path& path, suffix = suffix.substr(suffix.find('/') + 1); } - for (const auto& b : _breadcrumbs) { + for (auto* b : _breadcrumbs) { b->set_active(false); } _breadcrumbs.back()->set_active(true); @@ -121,7 +121,7 @@ BreadCrumbs::build(const raul::Path& path, _active_path = path; // Empty existing breadcrumbs - for (const auto& b : _breadcrumbs) { + for (auto* b : _breadcrumbs) { remove(*b); } _breadcrumbs.clear(); @@ -203,15 +203,19 @@ BreadCrumbs::message(const Message& msg) void BreadCrumbs::object_destroyed(const URI& uri) { - for (auto i = _breadcrumbs.begin(); i != _breadcrumbs.end(); ++i) { - if ((*i)->path() == uri.c_str()) { - // Remove all crumbs after the removed one (inclusive) - for (auto j = i; j != _breadcrumbs.end(); ) { - BreadCrumb* bc = *j; - j = _breadcrumbs.erase(j); - remove(*bc); - } - break; + const auto i = std::find_if(_breadcrumbs.begin(), + _breadcrumbs.end(), + [&uri](const auto& b) { + return b->path() == uri.c_str(); + }); + + if (i != _breadcrumbs.end()) { + // Remove all crumbs after the removed one (inclusive) + for (auto j = i; j != _breadcrumbs.end();) { + BreadCrumb* const bc = *j; + + j = _breadcrumbs.erase(j); + remove(*bc); } } } @@ -219,7 +223,7 @@ BreadCrumbs::object_destroyed(const URI& uri) void BreadCrumbs::object_moved(const raul::Path& old_path, const raul::Path& new_path) { - for (const auto& b : _breadcrumbs) { + for (auto* b : _breadcrumbs) { if (b->path() == old_path) { b->set_path(new_path); } diff --git a/src/gui/BreadCrumbs.hpp b/src/gui/BreadCrumbs.hpp index 6501288d..931d2ba8 100644 --- a/src/gui/BreadCrumbs.hpp +++ b/src/gui/BreadCrumbs.hpp @@ -71,7 +71,7 @@ private: { public: BreadCrumb(const raul::Path& path, - const std::shared_ptr<GraphView>& view = nullptr) + const std::shared_ptr<GraphView>& view) : _path(path), _view(view) { assert(!view || view->graph()->path() == path); @@ -81,6 +81,10 @@ private: show_all(); } + explicit BreadCrumb(const raul::Path& path) + : BreadCrumb{path, nullptr} + {} + void set_view(const std::shared_ptr<GraphView>& view) { assert(!view || view->graph()->path() == _path); _view = view; diff --git a/src/gui/ConnectWindow.cpp b/src/gui/ConnectWindow.cpp index b33c3b81..3c9f7e89 100644 --- a/src/gui/ConnectWindow.cpp +++ b/src/gui/ConnectWindow.cpp @@ -440,18 +440,17 @@ ConnectWindow::internal_toggled() void ConnectWindow::next_stage() { - static const char* labels[] = { - "Connecting...", - "Pinging engine...", - "Attaching to engine...", - "Requesting root graph...", - "Waiting for root graph...", - "Connected" - }; - - ++_connect_stage; if (_widgets_loaded) { + static const char* labels[] = { + "Connecting...", + "Pinging engine...", + "Attaching to engine...", + "Requesting root graph...", + "Waiting for root graph...", + "Connected" + }; + _progress_label->set_text(labels[_connect_stage]); } } diff --git a/src/gui/GraphBox.cpp b/src/gui/GraphBox.cpp index 0764e4ed..0cbd7303 100644 --- a/src/gui/GraphBox.cpp +++ b/src/gui/GraphBox.cpp @@ -1,6 +1,6 @@ /* This file is part of Ingen. - Copyright 2007-2017 David Robillard <http://drobilla.net/> + Copyright 2007-2024 David Robillard <http://drobilla.net/> Ingen is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free @@ -91,6 +91,7 @@ # include <webkit/webkit.h> #endif +#include <algorithm> #include <cassert> #include <cstdint> #include <cstdio> @@ -100,7 +101,6 @@ #include <sstream> #include <string> #include <utility> -#include <vector> namespace ingen { @@ -382,12 +382,12 @@ GraphBox::set_graph(const std::shared_ptr<const GraphModel>& graph, _menu_view_control_window->property_sensitive() = false; - for (const auto& p : graph->ports()) { - if (_app->can_control(p.get())) { - _menu_view_control_window->property_sensitive() = true; - break; - } - } + _menu_view_control_window->property_sensitive() = + std::any_of(graph->ports().begin(), + graph->ports().end(), + [this](const auto& p) { + return _app->can_control(p.get()); + }); _menu_parent->property_sensitive() = !!graph->parent(); @@ -425,14 +425,12 @@ GraphBox::graph_port_removed(const std::shared_ptr<const PortModel>& port) return; } - for (const auto& p : _graph->ports()) { - if (p->is_input() && _app->can_control(p.get())) { - _menu_view_control_window->property_sensitive() = true; - return; - } - } - - _menu_view_control_window->property_sensitive() = false; + _menu_view_control_window->property_sensitive() = + std::any_of(_graph->ports().begin(), + _graph->ports().end(), + [this](const auto& p) { + return p->is_input() && _app->can_control(p.get()); + }); } void @@ -885,10 +883,10 @@ GraphBox::event_refresh_activated() void GraphBox::event_fullscreen_toggled() { - // FIXME: ugh, use GTK signals to track state and know for sure - static bool is_fullscreen = false; - if (_window) { + // FIXME: ugh, use GTK signals to track state and know for sure + static bool is_fullscreen = false; + if (!is_fullscreen) { _window->fullscreen(); is_fullscreen = true; diff --git a/src/gui/GraphCanvas.cpp b/src/gui/GraphCanvas.cpp index 6d5c3b5a..7b0fb095 100644 --- a/src/gui/GraphCanvas.cpp +++ b/src/gui/GraphCanvas.cpp @@ -611,14 +611,14 @@ destroy_node(GanvNode* node, void* data) return; } - App* app = static_cast<App*>(data); + const App* app = static_cast<App*>(data); Ganv::Module* module = Glib::wrap(GANV_MODULE(node)); - auto* node_module = dynamic_cast<NodeModule*>(module); + const auto* node_module = dynamic_cast<NodeModule*>(module); if (node_module) { app->interface()->del(node_module->block()->uri()); } else { - auto* port_module = dynamic_cast<GraphPortModule*>(module); + const auto* port_module = dynamic_cast<GraphPortModule*>(module); if (port_module && strcmp(port_module->port()->path().symbol(), "control") && strcmp(port_module->port()->path().symbol(), "notify")) { @@ -630,11 +630,11 @@ destroy_node(GanvNode* node, void* data) static void destroy_arc(GanvEdge* arc, void* data) { - App* app = static_cast<App*>(data); + const App* app = static_cast<App*>(data); Ganv::Edge* arcmm = Glib::wrap(arc); - Port* tail = dynamic_cast<Port*>(arcmm->get_tail()); - Port* head = dynamic_cast<Port*>(arcmm->get_head()); + const Port* tail = dynamic_cast<Port*>(arcmm->get_tail()); + const Port* head = dynamic_cast<Port*>(arcmm->get_head()); app->interface()->disconnect(tail->model()->path(), head->model()->path()); } @@ -659,12 +659,12 @@ serialise_node(GanvNode* node, void* data) } Ganv::Module* module = Glib::wrap(GANV_MODULE(node)); - auto* node_module = dynamic_cast<NodeModule*>(module); + const auto* node_module = dynamic_cast<NodeModule*>(module); if (node_module) { serialiser->serialise(node_module->block()); } else { - auto* port_module = dynamic_cast<GraphPortModule*>(module); + const auto* port_module = dynamic_cast<GraphPortModule*>(module); if (port_module) { serialiser->serialise(port_module->port()); } @@ -679,7 +679,7 @@ serialise_arc(GanvEdge* arc, void* data) return; } - auto* garc = dynamic_cast<gui::Arc*>(Glib::wrap(GANV_EDGE(arc))); + const auto* garc = dynamic_cast<gui::Arc*>(Glib::wrap(GANV_EDGE(arc))); if (garc) { serialiser->serialise_arc(Sord::Node(), garc->model()); } @@ -735,7 +735,7 @@ GraphCanvas::paste() if (base_uri) { std::string base = *base_uri; if (base[base.size() - 1] == '/') { - base = base.substr(0, base.size() - 1); + base.resize(base.size() - 1); } copy_root = uri_to_path(URI(base)); } diff --git a/src/gui/GraphView.hpp b/src/gui/GraphView.hpp index 0b6aee1e..812f2cbc 100644 --- a/src/gui/GraphView.hpp +++ b/src/gui/GraphView.hpp @@ -48,7 +48,7 @@ namespace gui { class App; class GraphCanvas; -/** The graph specific contents of a GraphWindow (ie the canvas and whatever else). +/** The graph specific contents of a GraphWindow (the canvas and whatever else). * * \ingroup GUI */ diff --git a/src/gui/LoadGraphWindow.cpp b/src/gui/LoadGraphWindow.cpp index 794cfe71..b118effb 100644 --- a/src/gui/LoadGraphWindow.cpp +++ b/src/gui/LoadGraphWindow.cpp @@ -237,7 +237,7 @@ raul::Symbol LoadGraphWindow::symbol_from_filename(const Glib::ustring& filename) { std::string symbol_str = Glib::path_get_basename(get_filename()); - symbol_str = symbol_str.substr(0, symbol_str.find('.')); + symbol_str.resize(symbol_str.find('.')); return raul::Symbol::symbolify(symbol_str); } diff --git a/src/gui/NodeMenu.cpp b/src/gui/NodeMenu.cpp index ced303fb..e18ff6b9 100644 --- a/src/gui/NodeMenu.cpp +++ b/src/gui/NodeMenu.cpp @@ -1,6 +1,6 @@ /* This file is part of Ingen. - Copyright 2007-2015 David Robillard <http://drobilla.net/> + Copyright 2007-2024 David Robillard <http://drobilla.net/> Ingen is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free @@ -55,6 +55,7 @@ #include <sigc++/adaptors/bind.h> #include <sigc++/functors/mem_fun.h> +#include <algorithm> #include <cstdint> #include <map> #include <memory> @@ -273,13 +274,11 @@ NodeMenu::on_preset_activated(const std::string& uri) bool NodeMenu::has_control_inputs() { - for (const auto& p : block()->ports()) { - if (p->is_input() && p->is_numeric()) { - return true; - } - } - - return false; + return std::any_of(block()->ports().begin(), + block()->ports().end(), + [](const auto& p) { + return p->is_input() && p->is_numeric(); + }); } } // namespace ingen::gui diff --git a/src/gui/PluginMenu.hpp b/src/gui/PluginMenu.hpp index b2c75ffe..82e2f13b 100644 --- a/src/gui/PluginMenu.hpp +++ b/src/gui/PluginMenu.hpp @@ -50,7 +50,7 @@ namespace gui { class PluginMenu : public Gtk::Menu { public: - PluginMenu(ingen::World& world); + explicit PluginMenu(ingen::World& world); void clear(); void add_plugin(const std::shared_ptr<client::PluginModel>& p); diff --git a/src/gui/ThreadedLoader.hpp b/src/gui/ThreadedLoader.hpp index 83860461..32430277 100644 --- a/src/gui/ThreadedLoader.hpp +++ b/src/gui/ThreadedLoader.hpp @@ -88,7 +88,7 @@ private: save_graph_event(const std::shared_ptr<const client::GraphModel>& model, const URI& uri); - /** Returns nothing and takes no parameters (because they have all been bound) */ + /// Returns nothing and takes no parameters (because they're all bound) using Closure = sigc::slot<void>; void run(); diff --git a/src/gui/WindowFactory.cpp b/src/gui/WindowFactory.cpp index 4fce885c..802fc016 100644 --- a/src/gui/WindowFactory.cpp +++ b/src/gui/WindowFactory.cpp @@ -1,6 +1,6 @@ /* This file is part of Ingen. - Copyright 2007-2015 David Robillard <http://drobilla.net/> + Copyright 2007-2024 David Robillard <http://drobilla.net/> Ingen is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free @@ -36,6 +36,7 @@ #include <sigc++/adaptors/bind.h> #include <sigc++/functors/mem_fun.h> +#include <algorithm> #include <cassert> #include <memory> #include <stdexcept> @@ -93,14 +94,9 @@ WindowFactory::clear() size_t WindowFactory::num_open_graph_windows() { - size_t ret = 0; - for (const auto& w : _graph_windows) { - if (w.second->is_visible()) { - ++ret; - } - } - - return ret; + return std::count_if(_graph_windows.begin(), + _graph_windows.end(), + [](const auto& w) { return w.second->is_visible(); }); } GraphBox* diff --git a/src/meson.build b/src/meson.build index abe6193a..0cea53f1 100644 --- a/src/meson.build +++ b/src/meson.build @@ -2,6 +2,7 @@ # SPDX-License-Identifier: 0BSD OR GPL-3.0-or-later sources = files( + 'AtomForge.cpp', 'AtomReader.cpp', 'AtomWriter.cpp', 'ClashAvoider.cpp', diff --git a/src/runtime_paths.cpp b/src/runtime_paths.cpp index b876ebd4..cca9490d 100644 --- a/src/runtime_paths.cpp +++ b/src/runtime_paths.cpp @@ -44,7 +44,8 @@ static const char* const library_suffix = ".so"; #endif static std::vector<FilePath> -parse_search_path(const char* search_path, std::vector<FilePath> defaults) +parse_search_path(const char* search_path, + const std::vector<FilePath>& defaults) { if (!search_path) { return defaults; diff --git a/src/server/.clang-tidy b/src/server/.clang-tidy index 6990b1fe..a580cc7e 100644 --- a/src/server/.clang-tidy +++ b/src/server/.clang-tidy @@ -6,7 +6,6 @@ Checks: > -bugprone-branch-clone, -bugprone-parent-virtual-call, -bugprone-reserved-identifier, - -bugprone-suspicious-realloc-usage, -bugprone-suspicious-string-compare, -cert-dcl37-c, -cert-dcl51-cpp, diff --git a/src/server/ArcImpl.cpp b/src/server/ArcImpl.cpp index 0b503534..5c8f384b 100644 --- a/src/server/ArcImpl.cpp +++ b/src/server/ArcImpl.cpp @@ -84,32 +84,30 @@ ArcImpl::can_connect(const PortImpl* src, const InputPort* dst) { const ingen::URIs& uris = src->bufs().uris(); return ( - // (Audio | Control | CV) => (Audio | Control | CV) - ( (src->is_a(PortType::ID::CONTROL) || - src->is_a(PortType::ID::AUDIO) || - src->is_a(PortType::ID::CV)) - && (dst->is_a(PortType::ID::CONTROL) - || dst->is_a(PortType::ID::AUDIO) - || dst->is_a(PortType::ID::CV))) + // (Audio | Control | CV) => (Audio | Control | CV) + ((src->is_a(PortType::CONTROL) || src->is_a(PortType::AUDIO) || + src->is_a(PortType::CV)) && + (dst->is_a(PortType::CONTROL) || dst->is_a(PortType::AUDIO) || + dst->is_a(PortType::CV))) - // Equal types - || (src->type() == dst->type() && - src->buffer_type() == dst->buffer_type()) + // Equal types + || + (src->type() == dst->type() && src->buffer_type() == dst->buffer_type()) - // Control => atom:Float Value - || (src->is_a(PortType::ID::CONTROL) && dst->supports(uris.atom_Float)) + // Control => atom:Float Value + || (src->is_a(PortType::CONTROL) && dst->supports(uris.atom_Float)) - // Audio => atom:Sound Value - || (src->is_a(PortType::ID::AUDIO) && dst->supports(uris.atom_Sound)) + // Audio => atom:Sound Value + || (src->is_a(PortType::AUDIO) && dst->supports(uris.atom_Sound)) - // atom:Float Value => Control - || (src->supports(uris.atom_Float) && dst->is_a(PortType::ID::CONTROL)) + // atom:Float Value => Control + || (src->supports(uris.atom_Float) && dst->is_a(PortType::CONTROL)) - // atom:Float Value => CV - || (src->supports(uris.atom_Float) && dst->is_a(PortType::ID::CV)) + // atom:Float Value => CV + || (src->supports(uris.atom_Float) && dst->is_a(PortType::CV)) - // atom:Sound Value => Audio - || (src->supports(uris.atom_Sound) && dst->is_a(PortType::ID::AUDIO))); + // atom:Sound Value => Audio + || (src->supports(uris.atom_Sound) && dst->is_a(PortType::AUDIO))); } } // namespace ingen::server diff --git a/src/server/BlockFactory.cpp b/src/server/BlockFactory.cpp index 4c8dd1d7..124a0f61 100644 --- a/src/server/BlockFactory.cpp +++ b/src/server/BlockFactory.cpp @@ -1,6 +1,6 @@ /* This file is part of Ingen. - Copyright 2007-2015 David Robillard <http://drobilla.net/> + Copyright 2007-2024 David Robillard <http://drobilla.net/> Ingen is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free @@ -148,8 +148,10 @@ BlockFactory::load_lv2_plugins() // Build an array of port type nodes for checking compatibility using Types = std::vector<std::shared_ptr<LilvNode>>; Types types; - for (unsigned t = PortType::ID::AUDIO; t <= PortType::ID::ATOM; ++t) { - const URI uri{PortType(static_cast<PortType::ID>(t)).uri()}; + for (auto t = static_cast<unsigned>(PortType::AUDIO); + t <= static_cast<unsigned>(PortType::ATOM); + ++t) { + const URI uri = port_type_uri(static_cast<PortType>(t)); types.push_back(std::shared_ptr<LilvNode>( lilv_new_uri(_world.lilv_world(), uri.c_str()), lilv_node_free)); } @@ -186,13 +188,13 @@ BlockFactory::load_lv2_plugins() const uint32_t n_ports = lilv_plugin_get_num_ports(lv2_plug); for (uint32_t p = 0; p < n_ports; ++p) { const LilvPort* port = lilv_plugin_get_port_by_index(lv2_plug, p); - supported = false; - for (const auto& t : types) { - if (lilv_port_is_a(lv2_plug, port, t.get())) { - supported = true; - break; - } - } + supported = + std::any_of(types.begin(), + types.end(), + [&lv2_plug, &port](const auto& t) { + return lilv_port_is_a(lv2_plug, port, t.get()); + }); + if (!supported && !lilv_port_has_property(lv2_plug, port, diff --git a/src/server/BlockImpl.cpp b/src/server/BlockImpl.cpp index cae6b252..308f1e78 100644 --- a/src/server/BlockImpl.cpp +++ b/src/server/BlockImpl.cpp @@ -20,6 +20,7 @@ #include "GraphImpl.hpp" #include "PluginImpl.hpp" #include "PortImpl.hpp" +#include "PortType.hpp" #include "RunContext.hpp" #include "ThreadManager.hpp" @@ -202,8 +203,8 @@ BlockImpl::bypass(RunContext& ctx) // Dumb bypass for (const PortType t : { PortType::AUDIO, PortType::CV, PortType::ATOM }) { for (uint32_t i = 0;; ++i) { - PortImpl* in = nth_port_by_type(i, true, t); - PortImpl* out = nth_port_by_type(i, false, t); + const PortImpl* in = nth_port_by_type(i, true, t); + const PortImpl* out = nth_port_by_type(i, false, t); if (!out) { break; // Finished writing all outputs } @@ -240,7 +241,7 @@ BlockImpl::process(RunContext& ctx) // Find earliest offset of a value change SampleCount chunk_end = ctx.nframes(); for (uint32_t i = 0; _ports && i < _ports->size(); ++i) { - PortImpl* const port = _ports->at(i); + const PortImpl* const port = _ports->at(i); if (port->type() == PortType::CONTROL && port->is_input()) { const SampleCount o = port->next_value_offset( offset, ctx.nframes()); @@ -264,7 +265,7 @@ BlockImpl::process(RunContext& ctx) // Emit control port outputs as events for (uint32_t i = 0; _ports && i < _ports->size(); ++i) { - PortImpl* const port = _ports->at(i); + const PortImpl* const port = _ports->at(i); if (port->type() == PortType::CONTROL && port->is_output()) { // TODO: Only emit events when value has actually changed? for (uint32_t v = 0; v < _polyphony; ++v) { diff --git a/src/server/BlockImpl.hpp b/src/server/BlockImpl.hpp index ef76e9bf..0c823219 100644 --- a/src/server/BlockImpl.hpp +++ b/src/server/BlockImpl.hpp @@ -19,7 +19,6 @@ #include "BufferRef.hpp" #include "NodeImpl.hpp" -#include "PortType.hpp" #include "State.hpp" #include "types.hpp" @@ -43,6 +42,9 @@ class Symbol; } // namespace raul namespace ingen { + +enum class PortType; + class Node; namespace server { @@ -125,7 +127,7 @@ public: /** Learn the next incoming MIDI event (for internals) */ virtual void learn() {} - /** Do whatever needs doing in the process thread before process() is called */ + /** Do any necessary preparation in the process thread before process(). */ virtual void pre_process(RunContext& ctx); /** Run block for an entire process cycle (calls run()). */ diff --git a/src/server/Buffer.cpp b/src/server/Buffer.cpp index 553ae92e..68b75931 100644 --- a/src/server/Buffer.cpp +++ b/src/server/Buffer.cpp @@ -18,6 +18,7 @@ #include "BufferFactory.hpp" #include "Engine.hpp" +#include "PortType.hpp" #include "RunContext.hpp" #include "ingen_config.h" @@ -171,7 +172,12 @@ void Buffer::resize(uint32_t capacity) { if (!_external) { - _buf = realloc(_buf, capacity); + void* const new_buf = realloc(_buf, capacity); + if (!new_buf) { + throw std::bad_alloc{}; + } + + _buf = new_buf; _capacity = capacity; clear(); } else { @@ -182,18 +188,18 @@ Buffer::resize(uint32_t capacity) void* Buffer::port_data(PortType port_type, SampleCount offset) { - switch (port_type.id()) { - case PortType::ID::CONTROL: + switch (port_type) { + case PortType::CONTROL: return &_value_buffer->get<LV2_Atom_Float>()->body; - case PortType::ID::CV: - case PortType::ID::AUDIO: + case PortType::CV: + case PortType::AUDIO: if (_type == _factory.uris().atom_Float) { return &get<LV2_Atom_Float>()->body; } else if (_type == _factory.uris().atom_Sound) { return static_cast<Sample*>(_buf) + offset; } break; - case PortType::ID::ATOM: + case PortType::ATOM: if (_type != _factory.uris().atom_Sound) { return _buf; } diff --git a/src/server/Buffer.hpp b/src/server/Buffer.hpp index 8a64e621..5997281e 100644 --- a/src/server/Buffer.hpp +++ b/src/server/Buffer.hpp @@ -19,7 +19,6 @@ #include "BufferFactory.hpp" #include "BufferRef.hpp" -#include "PortType.hpp" #include "server.h" #include "types.hpp" @@ -34,6 +33,8 @@ namespace ingen { +enum class PortType; + class Atom; namespace server { diff --git a/src/server/CompiledGraph.cpp b/src/server/CompiledGraph.cpp index a89623d0..57c4537c 100644 --- a/src/server/CompiledGraph.cpp +++ b/src/server/CompiledGraph.cpp @@ -1,6 +1,6 @@ /* This file is part of Ingen. - Copyright 2015-2017 David Robillard <http://drobilla.net/> + Copyright 2015-2024 David Robillard <http://drobilla.net/> Ingen is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free @@ -61,13 +61,11 @@ public: static bool has_provider_with_many_dependants(const BlockImpl* n) { - for (const auto* p : n->providers()) { - if (p->dependants().size() > 1) { - return true; - } - } - - return false; + return std::any_of(n->providers().begin(), + n->providers().end(), + [](const auto* p) { + return p->dependants().size() > 1; + }); } CompiledGraph::CompiledGraph(GraphImpl* graph) @@ -96,13 +94,11 @@ CompiledGraph::compile(GraphImpl& graph) static size_t num_unvisited_dependants(const BlockImpl* block) { - size_t count = 0; - for (const BlockImpl* b : block->dependants()) { - if (b->get_mark() == BlockImpl::Mark::UNVISITED) { - ++count; - } - } - return count; + return std::count_if(block->dependants().begin(), + block->dependants().end(), + [](const auto* b) { + return b->get_mark() == BlockImpl::Mark::UNVISITED; + }); } static size_t diff --git a/src/server/CompiledGraph.hpp b/src/server/CompiledGraph.hpp index 89aab289..acf7ed88 100644 --- a/src/server/CompiledGraph.hpp +++ b/src/server/CompiledGraph.hpp @@ -46,7 +46,7 @@ public: void run(RunContext& ctx); private: - CompiledGraph(GraphImpl* graph); + explicit CompiledGraph(GraphImpl* graph); using BlockSet = std::set<BlockImpl*>; diff --git a/src/server/ControlBindings.cpp b/src/server/ControlBindings.cpp index e8dd3554..e9002f99 100644 --- a/src/server/ControlBindings.cpp +++ b/src/server/ControlBindings.cpp @@ -249,7 +249,7 @@ ControlBindings::start_learn(PortImpl* port) ThreadManager::assert_thread(THREAD_PRE_PROCESS); Binding* b = _learn_binding.load(); if (!b) { - _learn_binding = new Binding(Type::NULL_CONTROL, port); + _learn_binding = new Binding(); } else { b->port = port; } diff --git a/src/server/ControlBindings.hpp b/src/server/ControlBindings.hpp index a4ed0f94..4c806265 100644 --- a/src/server/ControlBindings.hpp +++ b/src/server/ControlBindings.hpp @@ -60,9 +60,8 @@ public: }; struct Key { - Key(Type t = Type::NULL_CONTROL, int16_t n = 0) noexcept - : type(t), num(n) - {} + Key(Type t, int16_t n) noexcept : type{t}, num{n} {} + Key() noexcept : Key{Type::NULL_CONTROL, 0U} {} bool operator<(const Key& other) const { return ((type < other.type) || @@ -82,7 +81,8 @@ public: /** One binding of a controller to a port. */ struct Binding : public boost::intrusive::set_base_hook<>, public raul::Maid::Disposable { - Binding(Key k=Key(), PortImpl* p=nullptr) : key(k), port(p) {} + Binding(Key k, PortImpl* p) noexcept : key{k}, port{p} {} + Binding() noexcept : Binding{Key{}, nullptr} {} bool operator<(const Binding& rhs) const { return key < rhs.key; } diff --git a/src/server/DuplexPort.cpp b/src/server/DuplexPort.cpp index 941beb10..ce47fa86 100644 --- a/src/server/DuplexPort.cpp +++ b/src/server/DuplexPort.cpp @@ -23,6 +23,7 @@ #include "Engine.hpp" #include "GraphImpl.hpp" #include "NodeImpl.hpp" +#include "PortType.hpp" #include "ingen/Atom.hpp" #include "ingen/Forge.hpp" diff --git a/src/server/DuplexPort.hpp b/src/server/DuplexPort.hpp index 3cc0efba..c06ad85f 100644 --- a/src/server/DuplexPort.hpp +++ b/src/server/DuplexPort.hpp @@ -19,7 +19,6 @@ #include "InputPort.hpp" #include "PortImpl.hpp" -#include "PortType.hpp" #include "server.h" #include "types.hpp" @@ -38,6 +37,8 @@ class Symbol; namespace ingen { +enum class PortType; + class Atom; class Properties; diff --git a/src/server/Engine.cpp b/src/server/Engine.cpp index cc3012d4..c9921889 100644 --- a/src/server/Engine.cpp +++ b/src/server/Engine.cpp @@ -1,6 +1,6 @@ /* This file is part of Ingen. - Copyright 2007-2017 David Robillard <http://drobilla.net/> + Copyright 2007-2024 David Robillard <http://drobilla.net/> Ingen is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free @@ -239,12 +239,11 @@ Engine::emit_notifications(FrameTime end) bool Engine::pending_notifications() { - for (const auto& ctx : _run_contexts) { - if (ctx->pending_notifications()) { - return true; - } - } - return false; + return std::any_of(_run_contexts.begin(), + _run_contexts.end(), + [](const auto& ctx) { + return ctx->pending_notifications(); + }); } bool diff --git a/src/server/GraphImpl.hpp b/src/server/GraphImpl.hpp index 7c3a56df..b09dbb6a 100644 --- a/src/server/GraphImpl.hpp +++ b/src/server/GraphImpl.hpp @@ -99,9 +99,14 @@ public: * Audio thread. * * \param ctx Process context + * * \param bufs New set of buffers - * \param poly Must be < the most recent value passed to prepare_internal_poly. - * \param maid Any objects no longer needed will be pushed to this + * + * \param poly Must be < the most recent value passed to + * prepare_internal_poly. + * + * \param maid Any objects no longer needed will be + * pushed to this */ bool apply_internal_poly(RunContext& ctx, BufferFactory& bufs, diff --git a/src/server/InputPort.cpp b/src/server/InputPort.cpp index 4a464ea8..5d3c4eb7 100644 --- a/src/server/InputPort.cpp +++ b/src/server/InputPort.cpp @@ -23,6 +23,7 @@ #include "BufferRef.hpp" #include "GraphImpl.hpp" #include "NodeImpl.hpp" +#include "PortType.hpp" #include "RunContext.hpp" #include "mix.hpp" diff --git a/src/server/InputPort.hpp b/src/server/InputPort.hpp index ab4c3e54..a90e7390 100644 --- a/src/server/InputPort.hpp +++ b/src/server/InputPort.hpp @@ -19,7 +19,6 @@ #include "ArcImpl.hpp" // IWYU pragma: keep #include "PortImpl.hpp" -#include "PortType.hpp" #include "types.hpp" #include "lv2/urid/urid.h" @@ -37,6 +36,8 @@ class Symbol; namespace ingen { +enum class PortType; + class Atom; namespace server { diff --git a/src/server/JackDriver.cpp b/src/server/JackDriver.cpp index a2a7f951..b1541df1 100644 --- a/src/server/JackDriver.cpp +++ b/src/server/JackDriver.cpp @@ -263,14 +263,14 @@ void JackDriver::rename_port(const raul::Path& old_path, const raul::Path& new_path) { - EnginePort* eport = get_port(old_path); + const EnginePort* eport = get_port(old_path); if (eport) { #if USE_JACK_PORT_RENAME jack_port_rename(_client, static_cast<jack_port_t*>(eport->handle()), new_path.substr(1).c_str()); #else - jack_port_set_name((jack_port_t*)eport->handle(), + jack_port_set_name(static_cast<jack_port_t*>(eport->handle()), new_path.substr(1).c_str()); #endif } @@ -533,15 +533,19 @@ JackDriver::_shutdown_cb() int JackDriver::_block_length_cb(jack_nframes_t nframes) { + const URIs& uris = _engine.world().uris(); + if (_engine.root_graph()) { _block_length = nframes; _seq_size = static_cast<uint32_t>( jack_port_type_get_buffer_size(_client, JACK_DEFAULT_MIDI_TYPE)); _engine.root_graph()->set_buffer_size( - _engine.run_context(), *_engine.buffer_factory(), PortType::AUDIO, + _engine.run_context(), *_engine.buffer_factory(), + uris.atom_Sound, _engine.buffer_factory()->audio_buffer_size(nframes)); _engine.root_graph()->set_buffer_size( - _engine.run_context(), *_engine.buffer_factory(), PortType::ATOM, + _engine.run_context(), *_engine.buffer_factory(), + uris.atom_Sequence, _seq_size); } return 0; diff --git a/src/server/JackDriver.hpp b/src/server/JackDriver.hpp index e811e9c1..d652ebae 100644 --- a/src/server/JackDriver.hpp +++ b/src/server/JackDriver.hpp @@ -28,6 +28,7 @@ #include <boost/intrusive/options.hpp> #include <boost/intrusive/slist.hpp> +#include <jack/transport.h> // IWYU pragma: keep #include <jack/types.h> #include <jack/thread.h> diff --git a/src/server/LV2Block.cpp b/src/server/LV2Block.cpp index c5cd73dc..07d3da48 100644 --- a/src/server/LV2Block.cpp +++ b/src/server/LV2Block.cpp @@ -110,7 +110,7 @@ LV2Block::make_instance(URIs& uris, } for (uint32_t p = 0; p < num_ports(); ++p) { - PortImpl* const port = _ports->at(p); + const PortImpl* const port = _ports->at(p); Buffer* const buffer = (preparing) ? port->prepared_buffer(voice).get() : port->buffer(voice).get(); @@ -693,8 +693,8 @@ get_port_value(const char* port_symbol, uint32_t* size, uint32_t* type) { - auto* const block = static_cast<LV2Block*>(user_data); - auto* const port = block->port_by_symbol(port_symbol); + auto* const block = static_cast<LV2Block*>(user_data); + const auto* const port = block->port_by_symbol(port_symbol); if (port && port->is_input() && port->value().is_valid()) { *size = port->value().size(); diff --git a/src/server/LV2Plugin.cpp b/src/server/LV2Plugin.cpp index ff571d0b..e304e9c0 100644 --- a/src/server/LV2Plugin.cpp +++ b/src/server/LV2Plugin.cpp @@ -71,7 +71,7 @@ LV2Plugin::symbol() const { std::string working = uri(); if (working.back() == '/') { - working = working.substr(0, working.length() - 1); + working.resize(working.length() - 1); } while (!working.empty()) { @@ -82,7 +82,7 @@ LV2Plugin::symbol() const return raul::Symbol::symbolify(symbol); } - working = working.substr(0, last_slash); + working.resize(last_slash); } return raul::Symbol("lv2_symbol"); diff --git a/src/server/NodeImpl.cpp b/src/server/NodeImpl.cpp index f771d953..4461ffc1 100644 --- a/src/server/NodeImpl.cpp +++ b/src/server/NodeImpl.cpp @@ -29,7 +29,7 @@ namespace raul { class Symbol; -} +} // namespace raul namespace ingen::server { diff --git a/src/server/PortImpl.cpp b/src/server/PortImpl.cpp index c7b20f2b..2c9ab3ac 100644 --- a/src/server/PortImpl.cpp +++ b/src/server/PortImpl.cpp @@ -136,13 +136,13 @@ PortImpl::set_type(PortType port_type, LV2_URID buffer_type) remove_property(uris.rdf_type, uris.lv2_CVPort); remove_property(uris.rdf_type, uris.lv2_ControlPort); remove_property(uris.rdf_type, uris.atom_AtomPort); - add_property(uris.rdf_type, world.forge().make_urid(port_type.uri())); + add_property(uris.rdf_type, world.forge().make_urid(port_type_uri(port_type))); // Update audio thread types _type = port_type; _buffer_type = buffer_type; if (!_buffer_type) { - switch (_type.id()) { + switch (_type) { case PortType::CONTROL: _buffer_type = uris.atom_Float; break; @@ -238,7 +238,7 @@ PortImpl::set_voice_value(const RunContext& ctx, FrameTime time, Sample value) { - switch (_type.id()) { + switch (_type) { case PortType::CONTROL: if (buffer(voice)->value()) { const_cast<LV2_Atom_Float*>( @@ -420,7 +420,7 @@ PortImpl::set_is_driver_port(BufferFactory&) void PortImpl::clear_buffers(const RunContext& ctx) { - switch (_type.id()) { + switch (_type) { case PortType::AUDIO: default: for (uint32_t v = 0; v < _poly; ++v) { @@ -453,7 +453,7 @@ PortImpl::monitor(RunContext& ctx, bool send_now) _frames_since_monitor += ctx.nframes(); const bool time_to_send = send_now || _frames_since_monitor >= period; - const bool is_sequence = (_type.id() == PortType::ATOM && + const bool is_sequence = (_type == PortType::ATOM && _buffer_type == _bufs.uris().atom_Sequence); if (!time_to_send && !(is_sequence && _monitored) && (!is_sequence && buffer(0)->value())) { return; @@ -463,7 +463,7 @@ PortImpl::monitor(RunContext& ctx, bool send_now) const URIs& uris = ctx.engine().world().uris(); LV2_URID key = 0; float val = 0.0f; - switch (_type.id()) { + switch (_type) { case PortType::UNKNOWN: break; case PortType::AUDIO: diff --git a/src/server/PortImpl.hpp b/src/server/PortImpl.hpp index 64c3322f..3a1500bc 100644 --- a/src/server/PortImpl.hpp +++ b/src/server/PortImpl.hpp @@ -20,7 +20,6 @@ #include "BufferFactory.hpp" #include "BufferRef.hpp" #include "NodeImpl.hpp" -#include "PortType.hpp" #include "RunContext.hpp" #include "server.h" #include "types.hpp" @@ -42,6 +41,8 @@ class Symbol; namespace ingen { +enum class PortType; + class Properties; namespace server { diff --git a/src/server/PortType.hpp b/src/server/PortType.hpp index 65f87d02..c403ba5b 100644 --- a/src/server/PortType.hpp +++ b/src/server/PortType.hpp @@ -14,81 +14,61 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef INGEN_INTERFACE_PORTTYPE_HPP -#define INGEN_INTERFACE_PORTTYPE_HPP +#ifndef INGEN_ENGINE_PORTTYPE_HPP +#define INGEN_ENGINE_PORTTYPE_HPP #include "ingen/URI.hpp" #include "lv2/atom/atom.h" #include "lv2/core/lv2.h" -#include <cassert> - namespace ingen { -/** The type of a port. - * - * This type refers to the type of the port itself (not necessarily the type - * of its contents). Ports with different types can contain the same type of - * data, but may e.g. have different access semantics. - */ -class PortType -{ -public: - enum ID { - UNKNOWN = 0, - AUDIO = 1, - CONTROL = 2, - CV = 3, - ATOM = 4 - }; +/// The type of a port +enum class PortType { + UNKNOWN, + AUDIO, + CONTROL, + CV, + ATOM, +}; - explicit PortType(const URI& uri) - : _id(UNKNOWN) - { - if (uri == type_uri(AUDIO)) { - _id = AUDIO; - } else if (uri == type_uri(CONTROL)) { - _id = CONTROL; - } else if (uri == type_uri(CV)) { - _id = CV; - } else if (uri == type_uri(ATOM)) { - _id = ATOM; - } +/// Return the URI for `port_type` +inline URI +port_type_uri(const PortType port_type) +{ + switch (port_type) { + case PortType::UNKNOWN: + break; + case PortType::AUDIO: + return URI{LV2_CORE__AudioPort}; + case PortType::CONTROL: + return URI{LV2_CORE__ControlPort}; + case PortType::CV: + return URI{LV2_CORE__CVPort}; + case PortType::ATOM: + return URI{LV2_ATOM__AtomPort}; } - PortType(ID id) noexcept : _id(id) {} - - const URI& uri() const { return type_uri(_id); } - ID id() const { return _id; } - - bool operator==(const ID& id) const { return (_id == id); } - bool operator!=(const ID& id) const { return (_id != id); } - bool operator==(const PortType& type) const { return (_id == type._id); } - bool operator!=(const PortType& type) const { return (_id != type._id); } - bool operator<(const PortType& type) const { return (_id < type._id); } + return URI{"http://www.w3.org/2002/07/owl#Nothing"}; +} - bool is_audio() { return _id == AUDIO; } - bool is_control() { return _id == CONTROL; } - bool is_cv() { return _id == CV; } - bool is_atom() { return _id == ATOM; } - -private: - static const URI& type_uri(unsigned id_num) { - assert(id_num <= ATOM); - static const URI uris[] = { - URI("http://www.w3.org/2002/07/owl#Nothing"), - URI(LV2_CORE__AudioPort), - URI(LV2_CORE__ControlPort), - URI(LV2_CORE__CVPort), - URI(LV2_ATOM__AtomPort) - }; - return uris[id_num]; - } - - ID _id; -}; +/// Return the type with the given `uri`, or #PortType::UNKNOWN +inline PortType +port_type_from_uri(const URI& uri) +{ + static const URI lv2_AudioPort = URI{LV2_CORE__AudioPort}; + static const URI lv2_ControlPort = URI{LV2_CORE__ControlPort}; + static const URI lv2_CVPort = URI{LV2_CORE__CVPort}; + static const URI atom_AtomPort = URI{LV2_ATOM__AtomPort}; + + return (uri == lv2_AudioPort) ? PortType::AUDIO + : (uri == lv2_ControlPort) ? PortType::CONTROL + : (uri == lv2_CVPort) ? PortType::CV + : (uri == atom_AtomPort) ? PortType::ATOM + : PortType::UNKNOWN; +} } // namespace ingen -#endif // INGEN_INTERFACE_PORTTYPE_HPP +#endif // INGEN_ENGINE_PORTTYPE_HPP diff --git a/src/server/PreProcessor.cpp b/src/server/PreProcessor.cpp index 5d9d4660..6cadf53b 100644 --- a/src/server/PreProcessor.cpp +++ b/src/server/PreProcessor.cpp @@ -64,7 +64,7 @@ PreProcessor::event(Event* const ev, Event::Mode mode) /* Note that tail is only used here, not in process(). The head must be checked first here, since if it is null the tail pointer is junk. */ - Event* const head = _head.load(); + const Event* const head = _head.load(); if (!head) { _head = ev; _tail = ev; diff --git a/src/server/SocketListener.hpp b/src/server/SocketListener.hpp index 65df5af5..8979a768 100644 --- a/src/server/SocketListener.hpp +++ b/src/server/SocketListener.hpp @@ -27,7 +27,7 @@ class Engine; class SocketListener { public: - SocketListener(Engine& engine); + explicit SocketListener(Engine& engine); ~SocketListener(); private: diff --git a/src/server/Task.hpp b/src/server/Task.hpp index c665c16f..f2141bd5 100644 --- a/src/server/Task.hpp +++ b/src/server/Task.hpp @@ -39,13 +39,15 @@ public: PARALLEL ///< Elements may be run in any order in parallel }; - Task(Mode mode, BlockImpl* block = nullptr) + Task(Mode mode, BlockImpl* block) : _block(block) , _mode(mode) { assert(mode != Mode::SINGLE || block); } + explicit Task(Mode mode) : Task{mode, nullptr} {} + Task(const Task&) = delete; Task& operator=(const Task&) = delete; diff --git a/src/server/UndoStack.hpp b/src/server/UndoStack.hpp index 8954f05d..58528647 100644 --- a/src/server/UndoStack.hpp +++ b/src/server/UndoStack.hpp @@ -42,7 +42,8 @@ class INGEN_SERVER_API UndoStack : public AtomSink { public: struct Entry { - Entry(time_t t = 0) noexcept : time(t) {} + explicit Entry(time_t t) noexcept : time{t} {} + Entry() noexcept : Entry{0} {} Entry(const Entry& copy) : time(copy.time) diff --git a/src/server/Worker.hpp b/src/server/Worker.hpp index 540347df..e26ff224 100644 --- a/src/server/Worker.hpp +++ b/src/server/Worker.hpp @@ -44,7 +44,7 @@ public: ~Worker(); struct Schedule : public LV2Features::Feature { - Schedule(bool sync) noexcept : synchronous(sync) {} + explicit Schedule(bool sync) noexcept : synchronous(sync) {} const char* uri() const override { return LV2_WORKER__schedule; } diff --git a/src/server/events/CreatePort.cpp b/src/server/events/CreatePort.cpp index 4c054fd9..a4dbbf3f 100644 --- a/src/server/events/CreatePort.cpp +++ b/src/server/events/CreatePort.cpp @@ -23,6 +23,7 @@ #include "Engine.hpp" #include "GraphImpl.hpp" #include "PortImpl.hpp" +#include "PortType.hpp" #include "ingen/Atom.hpp" #include "ingen/Forge.hpp" @@ -55,7 +56,6 @@ CreatePort::CreatePort(Engine& engine, const Properties& properties) : Event(engine, client, id, timestamp) , _path(std::move(path)) - , _port_type(PortType::UNKNOWN) , _properties(properties) { const ingen::URIs& uris = _engine.world().uris(); diff --git a/src/server/events/CreatePort.hpp b/src/server/events/CreatePort.hpp index 6d3e9ca2..acf81dd1 100644 --- a/src/server/events/CreatePort.hpp +++ b/src/server/events/CreatePort.hpp @@ -72,7 +72,7 @@ private: }; raul::Path _path; - PortType _port_type; + PortType _port_type{PortType::UNKNOWN}; LV2_URID _buf_type{0}; GraphImpl* _graph{nullptr}; DuplexPort* _graph_port{nullptr}; diff --git a/src/server/events/Delta.cpp b/src/server/events/Delta.cpp index 3f9e3b9d..96f13ee5 100644 --- a/src/server/events/Delta.cpp +++ b/src/server/events/Delta.cpp @@ -316,8 +316,8 @@ Delta::pre_process(PreProcessContext& ctx) const Property& value = p.second; SpecialType op = SpecialType::NONE; if (obj) { - Resource& resource = *obj; if (value != uris.patch_wildcard) { + Resource& resource = *obj; if (resource.add_property(key, value, value.context())) { _added.emplace(key, value); } diff --git a/src/server/events/DisconnectAll.cpp b/src/server/events/DisconnectAll.cpp index e429e0e6..639b289f 100644 --- a/src/server/events/DisconnectAll.cpp +++ b/src/server/events/DisconnectAll.cpp @@ -34,6 +34,8 @@ #include "ingen/Store.hpp" #include "raul/Path.hpp" +#include <algorithm> +#include <iterator> #include <memory> #include <mutex> #include <set> @@ -68,7 +70,7 @@ DisconnectAll::DisconnectAll(Engine& engine, DisconnectAll::~DisconnectAll() { - for (auto& i : _impls) { + for (auto* i : _impls) { delete i; } } @@ -109,24 +111,31 @@ DisconnectAll::pre_process(PreProcessContext& ctx) } // Create disconnect events to erase adjacent arcs in parent - for (const auto& a : adjacent_arcs(_parent)) { - _impls.push_back( - new Disconnect::Impl(_engine, - _parent, - a->tail(), - dynamic_cast<InputPort*>(a->head()))); - } + const auto& arcs = adjacent_arcs(_parent); + std::transform(arcs.begin(), + arcs.end(), + std::back_inserter(_impls), + [this](const auto& a) { + return new Disconnect::Impl(_engine, + _parent, + a->tail(), + dynamic_cast<InputPort*>(a->head())); + }); // Create disconnect events to erase adjacent arcs in parent's parent if (_port && _parent->parent()) { - auto* const parent_parent = dynamic_cast<GraphImpl*>(_parent->parent()); - for (const auto& a : adjacent_arcs(parent_parent)) { - _impls.push_back( - new Disconnect::Impl(_engine, - parent_parent, - a->tail(), - dynamic_cast<InputPort*>(a->head()))); - } + auto* const grandparent = dynamic_cast<GraphImpl*>(_parent->parent()); + const auto& parent_arcs = adjacent_arcs(grandparent); + + std::transform(parent_arcs.begin(), + parent_arcs.end(), + std::back_inserter(_impls), + [this, grandparent](const auto& a) { + return new Disconnect::Impl(_engine, + grandparent, + a->tail(), + dynamic_cast<InputPort*>(a->head())); + }); } if (!_deleting && ctx.must_compile(*_parent)) { diff --git a/src/server/ingen_lv2.cpp b/src/server/ingen_lv2.cpp index 424a2d7f..3dcdd54d 100644 --- a/src/server/ingen_lv2.cpp +++ b/src/server/ingen_lv2.cpp @@ -65,6 +65,7 @@ #include <cstdint> #include <cstdlib> #include <cstring> +#include <iterator> #include <memory> #include <mutex> #include <set> @@ -216,13 +217,12 @@ public: virtual GraphImpl* root_graph() { return _root_graph; } EnginePort* get_port(const raul::Path& path) override { - for (auto& p : _ports) { - if (p->graph_port()->path() == path) { - return p; - } - } + const auto i = + std::find_if(_ports.begin(), _ports.end(), [&path](const auto& p) { + return p->graph_port()->path() == path; + }); - return nullptr; + return i == _ports.end() ? nullptr : *i; } /** Add a port. Called only during init or restore. */ @@ -318,7 +318,13 @@ public: break; } - buf = realloc(buf, sizeof(LV2_Atom) + atom.size); + void* const new_buf = realloc(buf, sizeof(LV2_Atom) + atom.size); + if (!new_buf) { + _engine.log().rt_error("Failed to allocate for from-UI ring\n"); + break; + } + + buf = new_buf; memcpy(buf, &atom, sizeof(LV2_Atom)); if (!_from_ui.read(atom.size, @@ -461,9 +467,10 @@ find_graphs(const URI& manifest_uri) URI(INGEN__Graph)); Lib::Graphs graphs; - for (const auto& r : resources) { - graphs.push_back(std::make_shared<LV2Graph>(r)); - } + std::transform(resources.begin(), + resources.end(), + std::back_inserter(graphs), + [](const auto& r) { return std::make_shared<LV2Graph>(r); }); return graphs; } @@ -516,13 +523,13 @@ ingen_instantiate(const LV2_Descriptor* descriptor, const Lib::Graphs graphs = find_graphs(URI(reinterpret_cast<const char*>(manifest_node.buf))); serd_node_free(&manifest_node); - const LV2Graph* graph = nullptr; - for (const auto& g : graphs) { - if (g->uri == descriptor->URI) { - graph = g.get(); - break; - } - } + const auto g = std::find_if(graphs.begin(), + graphs.end(), + [&descriptor](const auto& graph) { + return graph->uri == descriptor->URI; + }); + + const LV2Graph* const graph = g == graphs.end() ? nullptr : g->get(); if (!graph) { lv2_log_error(&logger, "could not find graph <%s>\n", descriptor->URI); @@ -615,8 +622,8 @@ ingen_instantiate(const LV2_Descriptor* descriptor, static void ingen_connect_port(LV2_Handle instance, uint32_t port, void* data) { - auto* me = static_cast<IngenPlugin*>(instance); - Engine* engine = static_cast<Engine*>(me->world->engine().get()); + auto* me = static_cast<IngenPlugin*>(instance); + const Engine* engine = static_cast<Engine*>(me->world->engine().get()); const auto driver = std::static_pointer_cast<LV2Driver>(engine->driver()); if (port < driver->ports().size()) { driver->ports().at(port)->set_buffer(data); @@ -672,6 +679,7 @@ ingen_cleanup(LV2_Handle instance) auto world = std::move(me->world); delete me; + world.reset(); } static void |