diff options
Diffstat (limited to 'src')
232 files changed, 9759 insertions, 7749 deletions
diff --git a/src/.clang-tidy b/src/.clang-tidy new file mode 100644 index 00000000..83a09b52 --- /dev/null +++ b/src/.clang-tidy @@ -0,0 +1,32 @@ +Checks: > + -*-avoid-c-arrays, + -*-macro-to-enum, + -*-vararg, + -android-cloexec-*, + -boost-use-ranges, + -bugprone-easily-swappable-parameters, + -bugprone-multi-level-implicit-pointer-conversion, + -bugprone-unchecked-optional-access, + -cert-dcl50-cpp, + -cert-err33-c, + -cert-err34-c, + -clang-analyzer-optin.core.EnumCastOutOfRange, + -clang-analyzer-optin.cplusplus.VirtualCall, + -clang-analyzer-valist.Uninitialized, + -concurrency-mt-unsafe, + -cppcoreguidelines-avoid-non-const-global-variables, + -cppcoreguidelines-no-malloc, + -cppcoreguidelines-owning-memory, + -cppcoreguidelines-pro-bounds-array-to-pointer-decay, + -cppcoreguidelines-pro-bounds-pointer-arithmetic, + -cppcoreguidelines-pro-type-const-cast, + -cppcoreguidelines-pro-type-reinterpret-cast, + -cppcoreguidelines-pro-type-union-access, + -fuchsia-statically-constructed-objects, + -hicpp-no-array-decay, + -hicpp-no-malloc, + -misc-no-recursion, + -misc-unused-parameters, + -readability-function-cognitive-complexity, + -readability-static-accessed-through-instance, +InheritParentConfig: true diff --git a/src/AtomForge.cpp b/src/AtomForge.cpp new file mode 100644 index 00000000..727bd64e --- /dev/null +++ b/src/AtomForge.cpp @@ -0,0 +1,130 @@ +/* + 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 <ingen/memory.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 <sratom/sratom.h> + +#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/AtomReader.cpp b/src/AtomReader.cpp index fc74c5d5..21cb9e40 100644 --- a/src/AtomReader.cpp +++ b/src/AtomReader.cpp @@ -14,31 +14,31 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "ingen/Atom.hpp" -#include "ingen/AtomReader.hpp" -#include "ingen/Interface.hpp" -#include "ingen/Log.hpp" -#include "ingen/Message.hpp" -#include "ingen/Properties.hpp" -#include "ingen/Resource.hpp" -#include "ingen/Status.hpp" -#include "ingen/URI.hpp" -#include "ingen/URIMap.hpp" -#include "ingen/URIs.hpp" -#include "ingen/paths.hpp" -#include "lv2/atom/atom.h" -#include "lv2/atom/util.h" -#include "lv2/urid/urid.h" -#include "raul/Path.hpp" - -#include <boost/optional/optional.hpp> +#include <ingen/AtomReader.hpp> + +#include <ingen/Atom.hpp> +#include <ingen/Interface.hpp> +#include <ingen/Log.hpp> +#include <ingen/Message.hpp> +#include <ingen/Properties.hpp> +#include <ingen/Resource.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIMap.hpp> +#include <ingen/URIs.hpp> +#include <ingen/paths.hpp> +#include <lv2/atom/atom.h> +#include <lv2/atom/util.h> +#include <raul/Path.hpp> #include <cstdint> #include <cstring> +#include <optional> #include <string> namespace ingen { +enum class Status; + AtomReader::AtomReader(URIMap& map, URIs& uris, Log& log, Interface& iface) : _map(map) , _uris(uris) @@ -72,51 +72,57 @@ AtomReader::get_props(const LV2_Atom_Object* obj, const Atom type(sizeof(int32_t), _uris.atom_URID, &obj->body.otype); props.emplace(_uris.rdf_type, type); } - LV2_ATOM_OBJECT_FOREACH(obj, p) { + LV2_ATOM_OBJECT_FOREACH (obj, p) { Atom val; get_atom(&p->value, val); props.emplace(URI(_map.unmap_uri(p->key)), val); } } -boost::optional<URI> +std::optional<URI> AtomReader::atom_to_uri(const LV2_Atom* atom) { if (!atom) { - return boost::optional<URI>(); - } else if (atom->type == _uris.atom_URI) { - const char* str = (const char*)LV2_ATOM_BODY_CONST(atom); + return {}; + } + + if (atom->type == _uris.atom_URI) { + const char* str = static_cast<const char*>(LV2_ATOM_BODY_CONST(atom)); if (URI::is_valid(str)) { return URI(str); - } else { - _log.warn("Invalid URI <%1%>\n", str); } + + _log.warn("Invalid URI <%1%>\n", str); } else if (atom->type == _uris.atom_Path) { - const char* str = (const char*)LV2_ATOM_BODY_CONST(atom); + const char* str = static_cast<const char*>(LV2_ATOM_BODY_CONST(atom)); if (!strncmp(str, "file://", 5)) { return URI(str); - } else { - return URI(std::string("file://") + str); } - } else if (atom->type == _uris.atom_URID) { - const char* str = _map.unmap_uri(((const LV2_Atom_URID*)atom)->body); + + return URI(std::string("file://") + str); + } + + if (atom->type == _uris.atom_URID) { + const char* str = + _map.unmap_uri(reinterpret_cast<const LV2_Atom_URID*>(atom)->body); if (str) { return URI(str); - } else { - _log.warn("Unknown URID %1%\n", str); } + + _log.warn("Unknown URID %1%\n", str); } - return boost::optional<URI>(); + + return {}; } -boost::optional<Raul::Path> +std::optional<raul::Path> AtomReader::atom_to_path(const LV2_Atom* atom) { - boost::optional<URI> uri = atom_to_uri(atom); + std::optional<URI> uri = atom_to_uri(atom); if (uri && uri_is_path(*uri)) { return uri_to_path(*uri); } - return boost::optional<Raul::Path>(); + return {}; } Resource::Graph @@ -124,7 +130,7 @@ AtomReader::atom_to_context(const LV2_Atom* atom) { Resource::Graph ctx = Resource::Graph::DEFAULT; if (atom) { - boost::optional<URI> maybe_uri = atom_to_uri(atom); + std::optional<URI> maybe_uri = atom_to_uri(atom); if (maybe_uri) { ctx = Resource::uri_to_graph(*maybe_uri); } else { @@ -141,7 +147,7 @@ AtomReader::is_message(const URIs& uris, const LV2_Atom* msg) return false; } - const auto* obj = (const LV2_Atom_Object*)msg; + const auto* obj = reinterpret_cast<const LV2_Atom_Object*>(msg); return (obj->body.otype == uris.patch_Get || obj->body.otype == uris.patch_Delete || obj->body.otype == uris.patch_Put || @@ -159,19 +165,19 @@ AtomReader::write(const LV2_Atom* msg, int32_t default_id) return false; } - const auto* obj = (const LV2_Atom_Object*)msg; - const LV2_Atom* subject = nullptr; - const LV2_Atom* number = nullptr; + const auto* const obj = reinterpret_cast<const LV2_Atom_Object*>(msg); + const LV2_Atom* subject = nullptr; + const LV2_Atom* number = nullptr; lv2_atom_object_get(obj, - (LV2_URID)_uris.patch_subject, &subject, - (LV2_URID)_uris.patch_sequenceNumber, &number, + _uris.patch_subject.urid(), &subject, + _uris.patch_sequenceNumber.urid(), &number, nullptr); - const boost::optional<URI> subject_uri = atom_to_uri(subject); + const std::optional<URI> subject_uri = atom_to_uri(subject); const int32_t seq = ((number && number->type == _uris.atom_Int) - ? ((const LV2_Atom_Int*)number)->body + ? reinterpret_cast<const LV2_Atom_Int*>(number)->body : default_id); if (obj->body.otype == _uris.patch_Get) { @@ -182,27 +188,35 @@ AtomReader::write(const LV2_Atom* msg, int32_t default_id) _iface(BundleBegin{seq}); } else if (obj->body.otype == _uris.ingen_BundleEnd) { _iface(BundleEnd{seq}); + } else if (obj->body.otype == _uris.ingen_Undo) { + _iface(Undo{seq}); + } else if (obj->body.otype == _uris.ingen_Redo) { + _iface(Redo{seq}); } else if (obj->body.otype == _uris.patch_Delete) { const LV2_Atom_Object* body = nullptr; - lv2_atom_object_get(obj, (LV2_URID)_uris.patch_body, &body, 0); + lv2_atom_object_get(obj, + _uris.patch_body.urid(), &body, + 0); if (subject_uri && !body) { _iface(Del{seq, *subject_uri}); return true; - } else if (body && body->body.otype == _uris.ingen_Arc) { + } + + if (body && body->body.otype == _uris.ingen_Arc) { const LV2_Atom* tail = nullptr; const LV2_Atom* head = nullptr; const LV2_Atom* incidentTo = nullptr; lv2_atom_object_get(body, - (LV2_URID)_uris.ingen_tail, &tail, - (LV2_URID)_uris.ingen_head, &head, - (LV2_URID)_uris.ingen_incidentTo, &incidentTo, + _uris.ingen_tail.urid(), &tail, + _uris.ingen_head.urid(), &head, + _uris.ingen_incidentTo.urid(), &incidentTo, nullptr); - boost::optional<Raul::Path> subject_path(atom_to_path(subject)); - boost::optional<Raul::Path> tail_path(atom_to_path(tail)); - boost::optional<Raul::Path> head_path(atom_to_path(head)); - boost::optional<Raul::Path> other_path(atom_to_path(incidentTo)); + std::optional<raul::Path> subject_path(atom_to_path(subject)); + std::optional<raul::Path> tail_path(atom_to_path(tail)); + std::optional<raul::Path> head_path(atom_to_path(head)); + std::optional<raul::Path> other_path(atom_to_path(incidentTo)); if (tail_path && head_path) { _iface(Disconnect{seq, *tail_path, *head_path}); } else if (subject_path && other_path) { @@ -216,13 +230,15 @@ AtomReader::write(const LV2_Atom* msg, int32_t default_id) const LV2_Atom_Object* body = nullptr; const LV2_Atom* context = nullptr; lv2_atom_object_get(obj, - (LV2_URID)_uris.patch_body, &body, - (LV2_URID)_uris.patch_context, &context, + _uris.patch_body.urid(), &body, + _uris.patch_context.urid(), &context, 0); if (!body) { _log.warn("Put message has no body\n"); return false; - } else if (!subject_uri) { + } + + if (!subject_uri) { _log.warn("Put message has no subject\n"); return false; } @@ -231,16 +247,16 @@ AtomReader::write(const LV2_Atom* msg, int32_t default_id) LV2_Atom* tail = nullptr; LV2_Atom* head = nullptr; lv2_atom_object_get(body, - (LV2_URID)_uris.ingen_tail, &tail, - (LV2_URID)_uris.ingen_head, &head, + _uris.ingen_tail.urid(), &tail, + _uris.ingen_head.urid(), &head, nullptr); if (!tail || !head) { _log.warn("Arc has no tail or head\n"); return false; } - boost::optional<Raul::Path> tail_path(atom_to_path(tail)); - boost::optional<Raul::Path> head_path(atom_to_path(head)); + std::optional<raul::Path> tail_path(atom_to_path(tail)); + std::optional<raul::Path> head_path(atom_to_path(head)); if (tail_path && head_path) { _iface(Connect{seq, *tail_path, *head_path}); } else { @@ -261,14 +277,17 @@ AtomReader::write(const LV2_Atom* msg, int32_t default_id) const LV2_Atom* value = nullptr; const LV2_Atom* context = nullptr; lv2_atom_object_get(obj, - (LV2_URID)_uris.patch_property, &prop, - (LV2_URID)_uris.patch_value, &value, - (LV2_URID)_uris.patch_context, &context, + _uris.patch_property.urid(), &prop, + _uris.patch_value.urid(), &value, + _uris.patch_context.urid(), &context, 0); - if (!prop || ((const LV2_Atom*)prop)->type != _uris.atom_URID) { + if (!prop || + reinterpret_cast<const LV2_Atom*>(prop)->type != _uris.atom_URID) { _log.warn("Set message missing property\n"); return false; - } else if (!value) { + } + + if (!value) { _log.warn("Set message missing value\n"); return false; } @@ -290,14 +309,16 @@ AtomReader::write(const LV2_Atom* msg, int32_t default_id) const LV2_Atom_Object* add = nullptr; const LV2_Atom* context = nullptr; lv2_atom_object_get(obj, - (LV2_URID)_uris.patch_remove, &remove, - (LV2_URID)_uris.patch_add, &add, - (LV2_URID)_uris.patch_context, &context, + _uris.patch_remove.urid(), &remove, + _uris.patch_add.urid(), &add, + _uris.patch_context.urid(), &context, 0); if (!remove) { _log.warn("Patch message has no remove\n"); return false; - } else if (!add) { + } + + if (!add) { _log.warn("Patch message has no add\n"); return false; } @@ -316,20 +337,20 @@ AtomReader::write(const LV2_Atom* msg, int32_t default_id) return false; } + if (!subject_uri) { + _log.warn("Copy message has non-path subject\n"); + return false; + } + const LV2_Atom* dest = nullptr; - lv2_atom_object_get(obj, (LV2_URID)_uris.patch_destination, &dest, 0); + lv2_atom_object_get(obj, _uris.patch_destination.urid(), &dest, 0); if (!dest) { _log.warn("Copy message has no destination\n"); return false; } - boost::optional<URI> subject_uri(atom_to_uri(subject)); - if (!subject_uri) { - _log.warn("Copy message has non-path subject\n"); - return false; - } - boost::optional<URI> dest_uri(atom_to_uri(dest)); + std::optional<URI> dest_uri(atom_to_uri(dest)); if (!dest_uri) { _log.warn("Copy message has non-URI destination\n"); return false; @@ -343,19 +364,19 @@ AtomReader::write(const LV2_Atom* msg, int32_t default_id) } const LV2_Atom* dest = nullptr; - lv2_atom_object_get(obj, (LV2_URID)_uris.patch_destination, &dest, 0); + lv2_atom_object_get(obj, _uris.patch_destination.urid(), &dest, 0); if (!dest) { _log.warn("Move message has no destination\n"); return false; } - boost::optional<Raul::Path> subject_path(atom_to_path(subject)); + std::optional<raul::Path> subject_path(atom_to_path(subject)); if (!subject_path) { _log.warn("Move message has non-path subject\n"); return false; } - boost::optional<Raul::Path> dest_path(atom_to_path(dest)); + std::optional<raul::Path> dest_path(atom_to_path(dest)); if (!dest_path) { _log.warn("Move message has non-path destination\n"); return false; @@ -363,21 +384,23 @@ AtomReader::write(const LV2_Atom* msg, int32_t default_id) _iface(Move{seq, *subject_path, *dest_path}); } else if (obj->body.otype == _uris.patch_Response) { - const LV2_Atom* seq = nullptr; const LV2_Atom* body = nullptr; lv2_atom_object_get(obj, - (LV2_URID)_uris.patch_sequenceNumber, &seq, - (LV2_URID)_uris.patch_body, &body, + _uris.patch_body.urid(), &body, 0); - if (!seq || seq->type != _uris.atom_Int) { + if (!number || number->type != _uris.atom_Int) { _log.warn("Response message has no sequence number\n"); return false; - } else if (!body || body->type != _uris.atom_Int) { + } + + if (!body || body->type != _uris.atom_Int) { _log.warn("Response message body is not integer\n"); return false; } - _iface(Response{((const LV2_Atom_Int*)seq)->body, - (ingen::Status)((const LV2_Atom_Int*)body)->body, + + _iface(Response{reinterpret_cast<const LV2_Atom_Int*>(number)->body, + static_cast<ingen::Status>( + reinterpret_cast<const LV2_Atom_Int*>(body)->body), subject_uri ? subject_uri->c_str() : ""}); } else { _log.warn("Unknown object type <%1%>\n", diff --git a/src/AtomWriter.cpp b/src/AtomWriter.cpp index 27f224fc..5200cfde 100644 --- a/src/AtomWriter.cpp +++ b/src/AtomWriter.cpp @@ -47,30 +47,29 @@ * manipulating data in this model which resemble HTTP methods. */ -#include "ingen/AtomWriter.hpp" - -#include "ingen/Atom.hpp" -#include "ingen/AtomForge.hpp" -#include "ingen/AtomSink.hpp" -#include "ingen/Message.hpp" -#include "ingen/Properties.hpp" -#include "ingen/Resource.hpp" -#include "ingen/URI.hpp" -#include "ingen/URIMap.hpp" -#include "ingen/URIs.hpp" -#include "ingen/paths.hpp" -#include "lv2/atom/forge.h" -#include "lv2/urid/urid.h" -#include "raul/Path.hpp" -#include "serd/serd.h" - -#include <boost/variant/apply_visitor.hpp> +#include <ingen/AtomWriter.hpp> + +#include <ingen/Atom.hpp> +#include <ingen/AtomForge.hpp> +#include <ingen/AtomSink.hpp> +#include <ingen/Message.hpp> +#include <ingen/Properties.hpp> +#include <ingen/Resource.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIMap.hpp> +#include <ingen/URIs.hpp> +#include <ingen/paths.hpp> +#include <lv2/atom/forge.h> +#include <lv2/urid/urid.h> +#include <raul/Path.hpp> +#include <serd/serd.h> #include <cassert> #include <cstdint> -#include <memory> +#include <map> #include <string> #include <utility> +#include <variant> namespace ingen { @@ -78,9 +77,8 @@ AtomWriter::AtomWriter(URIMap& map, URIs& uris, AtomSink& sink) : _map(map) , _uris(uris) , _sink(sink) - , _forge(map.urid_map_feature()->urid_map) -{ -} + , _forge(map.urid_map()) +{} void AtomWriter::finish_msg() @@ -93,7 +91,7 @@ AtomWriter::finish_msg() void AtomWriter::message(const Message& message) { - boost::apply_visitor(*this, message); + std::visit(*this, message); } /** @page protocol @@ -135,7 +133,8 @@ AtomWriter::operator()(const BundleEnd& message) void AtomWriter::forge_uri(const URI& uri) { - if (serd_uri_string_has_scheme((const uint8_t*)uri.c_str())) { + if (serd_uri_string_has_scheme( + reinterpret_cast<const uint8_t*>(uri.c_str()))) { lv2_atom_forge_urid(&_forge, _map.map_uri(uri.c_str())); } else { lv2_atom_forge_uri(&_forge, uri.c_str(), uri.length()); @@ -157,7 +156,7 @@ AtomWriter::forge_properties(const Properties& properties) } void -AtomWriter::forge_arc(const Raul::Path& tail, const Raul::Path& head) +AtomWriter::forge_arc(const raul::Path& tail, const raul::Path& head) { LV2_Atom_Forge_Frame arc; lv2_atom_forge_object(&_forge, &arc, 0, _uris.ingen_Arc); @@ -295,8 +294,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 @@ -436,7 +435,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 . @@ -503,7 +503,7 @@ AtomWriter::operator()(const Connect& message) LV2_Atom_Forge_Frame msg; forge_request(&msg, _uris.patch_Put, message.seq); lv2_atom_forge_key(&_forge, _uris.patch_subject); - forge_uri(path_to_uri(Raul::Path::lca(message.tail, message.head))); + forge_uri(path_to_uri(raul::Path::lca(message.tail, message.head))); lv2_atom_forge_key(&_forge, _uris.patch_body); forge_arc(message.tail, message.head); lv2_atom_forge_pop(&_forge, &msg); @@ -629,8 +629,7 @@ AtomWriter::operator()(const Response& response) void AtomWriter::operator()(const Error&) -{ -} +{} /** @page protocol * @section loading Loading and Unloading Bundles diff --git a/src/ClashAvoider.cpp b/src/ClashAvoider.cpp index 293b9867..ed4dc91a 100644 --- a/src/ClashAvoider.cpp +++ b/src/ClashAvoider.cpp @@ -14,19 +14,18 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "ingen/ClashAvoider.hpp" -#include "ingen/Store.hpp" -#include "ingen/URI.hpp" -#include "ingen/paths.hpp" -#include "raul/Path.hpp" -#include "raul/Symbol.hpp" - -#include <boost/optional/optional.hpp> +#include <ingen/ClashAvoider.hpp> +#include <ingen/Store.hpp> +#include <ingen/URI.hpp> +#include <ingen/paths.hpp> +#include <raul/Path.hpp> +#include <raul/Symbol.hpp> #include <cassert> #include <cctype> #include <cstdio> #include <cstdlib> +#include <optional> #include <sstream> #include <string> #include <utility> @@ -42,13 +41,13 @@ ClashAvoider::map_uri(const URI& in) { if (uri_is_path(in)) { return path_to_uri(map_path(uri_to_path(in))); - } else { - return in; } + + return in; } -Raul::Path -ClashAvoider::map_path(const Raul::Path& in) +raul::Path +ClashAvoider::map_path(const raul::Path& in) { unsigned offset = 0; bool has_offset = false; @@ -63,86 +62,81 @@ 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); + raul::Path base_path(base_path_str); auto m = _symbol_map.find(in); if (m != _symbol_map.end()) { return m->second; - } else { - using InsertRecord = std::pair<SymbolMap::iterator, bool>; - - // See if parent is mapped - Raul::Path parent = in.parent(); - do { - auto p = _symbol_map.find(parent); - if (p != _symbol_map.end()) { - const Raul::Path mapped = Raul::Path( - p->second.base() + in.substr(parent.base().length())); - InsertRecord i = _symbol_map.emplace(in, mapped); - return i.first->second; + } + + // See if parent is mapped + raul::Path parent = in.parent(); + do { + auto p = _symbol_map.find(parent); + if (p != _symbol_map.end()) { + const auto mapped = raul::Path{p->second.base() + + in.substr(parent.base().length())}; + + auto i = _symbol_map.emplace(in, mapped); + return i.first->second; + } + parent = parent.parent(); + } while (!parent.is_root()); + + if (!exists(in) && _symbol_map.find(in) == _symbol_map.end()) { + // No clash, use symbol unmodified + auto i = _symbol_map.emplace(in, in); + assert(i.second); + return i.first->second; + } + + // Append _2 _3 etc until an unused symbol is found + while (true) { + auto o = _offsets.find(base_path); + if (o != _offsets.end()) { + offset = ++o->second; + } + + if (offset == 0) { + offset = 2; + } + + std::stringstream ss; + ss << base_path << "_" << offset; + if (!exists(raul::Path(ss.str()))) { + std::string name = base_path.symbol(); + if (name.empty()) { + name = "_"; } - parent = parent.parent(); - } while (!parent.is_root()); - if (!exists(in) && _symbol_map.find(in) == _symbol_map.end()) { - // No clash, use symbol unmodified - InsertRecord i = _symbol_map.emplace(in, in); - assert(i.second); + const raul::Symbol sym{name}; + const std::string str{ss.str()}; + + auto i = _symbol_map.emplace(in, raul::Path(str)); + + offset = _store.child_name_offset(in.parent(), sym, false); + _offsets.emplace(base_path, offset); return i.first->second; + } + if (o != _offsets.end()) { + offset = ++o->second; } else { - // Append _2 _3 etc until an unused symbol is found - while (true) { - 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) { - offset = 2; - } - - std::stringstream ss; - ss << base_path << "_" << offset; - if (!exists(Raul::Path(ss.str()))) { - std::string name = base_path.symbol(); - if (name.empty()) { - name = "_"; - } - Raul::Symbol sym(name); - std::string str = ss.str(); - InsertRecord i = _symbol_map.emplace(in, Raul::Path(str)); - offset = _store.child_name_offset(in.parent(), sym, false); - _offsets.emplace(base_path, offset); - return i.first->second; - } else { - if (o != _offsets.end()) { - offset = ++o->second; - } else { - ++offset; - } - } - } + ++offset; } } } bool -ClashAvoider::exists(const Raul::Path& path) const +ClashAvoider::exists(const raul::Path& path) const { return _store.find(path) != _store.end(); } -static boost::optional<size_t> +static std::optional<size_t> numeric_suffix_start(const std::string& str) { if (!isdigit(str[str.length() - 1])) { @@ -158,13 +152,13 @@ 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) { - return name; // No numeric suffix, just re-use old label + return name; // No numeric suffix, just reuse old label } const auto name_suffix = atoi(name.c_str() + *name_suffix_start); @@ -177,11 +171,11 @@ ClashAvoider::adjust_name(const Raul::Path& old_path, const auto offset = new_suffix - old_suffix; return (name.substr(0, *name_suffix_start) + std::to_string(name_suffix + offset)); - } else { - // Add 1 to previous label suffix - return (name.substr(0, *name_suffix_start) + - std::to_string(name_suffix + 1)); } + + // Add 1 to previous label suffix + return (name.substr(0, *name_suffix_start) + + std::to_string(name_suffix + 1)); } } // namespace ingen diff --git a/src/ColorContext.cpp b/src/ColorContext.cpp index 9794e8ce..9706cb81 100644 --- a/src/ColorContext.cpp +++ b/src/ColorContext.cpp @@ -14,10 +14,11 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "ingen/ColorContext.hpp" +#include <ingen/ColorContext.hpp> + #include "ingen_config.h" -#ifdef HAVE_ISATTY +#if USE_ISATTY # include <unistd.h> #else inline int isatty(int fd) { return 0; } @@ -29,7 +30,7 @@ ColorContext::ColorContext(FILE* stream, Color color) : _stream(stream) { if (isatty(fileno(_stream))) { - fprintf(_stream, "\033[0;%dm", (int)color); + fprintf(_stream, "\033[0;%dm", static_cast<int>(color)); } } @@ -41,4 +42,4 @@ ColorContext::~ColorContext() } } -} // namespace ingen +} // namespace ingen diff --git a/src/Configuration.cpp b/src/Configuration.cpp index 5178e97a..9abdc288 100644 --- a/src/Configuration.cpp +++ b/src/Configuration.cpp @@ -14,26 +14,34 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "ingen/Configuration.hpp" -#include "ingen/Forge.hpp" -#include "ingen/URIMap.hpp" -#include "ingen/filesystem.hpp" -#include "ingen/fmt.hpp" -#include "ingen/ingen.h" -#include "ingen/runtime_paths.hpp" -#include "lv2/urid/urid.h" -#include "serd/serd.h" -#include "sord/sord.h" -#include "sord/sordmm.hpp" -#include "sratom/sratom.h" +#include <ingen/Atom.hpp> +#include <ingen/Configuration.hpp> +#include <ingen/FilePath.hpp> +#include <ingen/Forge.hpp> +#include <ingen/URIMap.hpp> +#include <ingen/fmt.hpp> +#include <ingen/ingen.h> +#include <ingen/runtime_paths.hpp> +#include <lv2/urid/urid.h> +#include <serd/serd.h> +#include <sord/sord.h> +#include <sord/sordmm.hpp> +#include <sratom/sratom.h> #include <algorithm> #include <cassert> #include <cerrno> #include <cstdint> +#include <cstdio> #include <cstdlib> #include <cstring> +#include <filesystem> +#include <list> +#include <map> #include <memory> +#include <ostream> +#include <string> +#include <system_error> #include <thread> #include <utility> #include <vector> @@ -54,8 +62,9 @@ Configuration::Configuration(Forge& forge) " ingen -g # Run GUI, connect to running engine\n" " ingen -eg # Run engine and GUI in one process\n" " ingen -eg foo.ingen # Run engine and GUI and load a graph") - , _max_name_length(0) { + static const auto default_n_threads = static_cast<int32_t>(std::max(std::thread::hardware_concurrency(), 1U)); + add("atomicBundles", "atomic-bundles", 'a', "Execute bundles atomically", GLOBAL, forge.Bool, forge.make(false)); add("bufferSize", "buffer-size", 'b', "Buffer size in samples", GLOBAL, forge.Int, forge.make(1024)); add("clientPort", "client-port", 'C', "Client port", GLOBAL, forge.Int, Atom()); @@ -78,7 +87,7 @@ Configuration::Configuration(Forge& forge) add("flushLog", "flush-log", 'f', "Flush logs after every entry", GLOBAL, forge.Bool, forge.make(false)); add("dump", "dump", 'd', "Print debug output", SESSION, forge.Bool, forge.make(false)); add("trace", "trace", 't', "Show LV2 plugin trace messages", SESSION, forge.Bool, forge.make(false)); - add("threads", "threads", 'p', "Number of processing threads", GLOBAL, forge.Int, forge.make(int32_t(std::max(std::thread::hardware_concurrency(), 1U)))); + add("threads", "threads", 'p', "Number of processing threads", GLOBAL, forge.Int, forge.make(default_n_threads)); add("humanNames", "human-names", 0, "Show human names in GUI", GUI, forge.Bool, forge.make(true)); add("portLabels", "port-labels", 0, "Show port labels in GUI", GUI, forge.Bool, forge.make(true)); add("graphDirectory", "graph-directory", 0, "Default directory for opening graphs", GUI, forge.String, Atom()); @@ -110,19 +119,22 @@ Configuration::variable_string(LV2_URID type) const { if (type == _forge.String) { return "=STRING"; - } else if (type == _forge.Int) { + } + + if (type == _forge.Int) { return "=INT"; } + return ""; } void Configuration::print_usage(const std::string& program, std::ostream& os) { - os << "Usage: " << program << " [OPTION]... [GRAPH]" << std::endl; - os << _shortdesc << std::endl << std::endl; - os << _desc << std::endl << std::endl; - os << "Options:" << std::endl; + os << "Usage: " << program << " [OPTION]... [GRAPH]\n"; + os << _shortdesc << "\n\n"; + os << _desc << "\n\n"; + os << "Options:\n"; for (const auto& o : _options) { const Option& option = o.second; os << " "; @@ -131,10 +143,10 @@ Configuration::print_usage(const std::string& program, std::ostream& os) } else { os << " "; } - os.width(_max_name_length + 11); + os.width(static_cast<std::streamsize>(_max_name_length + 11)); os << std::left; os << (std::string("--") + o.first + variable_string(option.type)); - os << option.desc << std::endl; + os << option.desc << "\n"; } } @@ -143,8 +155,8 @@ Configuration::set_value_from_string(Configuration::Option& option, const std::string& value) { if (option.type == _forge.Int) { - char* endptr = nullptr; - int intval = static_cast<int>(strtol(value.c_str(), &endptr, 10)); + char* endptr = nullptr; + const int intval = static_cast<int>(strtol(value.c_str(), &endptr, 10)); if (endptr && *endptr == '\0') { option.value = _forge.make(intval); } else { @@ -155,7 +167,7 @@ Configuration::set_value_from_string(Configuration::Option& option, option.value = _forge.alloc(value.c_str()); assert(option.value.type() == _forge.String); } else if (option.type == _forge.Bool) { - option.value = _forge.make(bool(!strcmp(value.c_str(), "true"))); + option.value = _forge.make(!strcmp(value.c_str(), "true")); assert(option.value.type() == _forge.Bool); } else { throw OptionError(fmt("Bad option type `%1%'", option.name)); @@ -170,7 +182,7 @@ Configuration::parse(int argc, char** argv) for (int i = 1; i < argc; ++i) { if (argv[i][0] != '-' || !strcmp(argv[i], "-")) { // File argument - const Options::iterator o = _options.find("load"); + const auto o = _options.find("load"); if (!o->second.value.is_valid()) { _options.find("load")->second.value = _forge.alloc(argv[i]); } else { @@ -181,17 +193,19 @@ 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 Options::iterator o = _options.find(name); + const auto o = _options.find(name); if (o == _options.end()) { throw OptionError(fmt("Unrecognized option `%1%'", name)); - } else if (o->second.type == _forge.Bool) { // --flag + } + + if (o->second.type == _forge.Bool) { // --flag o->second.value = _forge.make(true); - } else if (equals) { // --opt=val + } else if (equals) { // --opt=val set_value_from_string(o->second, equals + 1); - } else if (++i < argc) { // --opt val + } else if (++i < argc) { // --opt val set_value_from_string(o->second, argv[i]); } else { throw OptionError(fmt("Missing value for `%1%'", name)); @@ -200,22 +214,22 @@ Configuration::parse(int argc, char** argv) // Short option const size_t len = strlen(argv[i]); for (size_t j = 1; j < len; ++j) { - const char letter = argv[i][j]; - const ShortNames::iterator n = _short_names.find(letter); + const char letter = argv[i][j]; + const auto n = _short_names.find(letter); if (n == _short_names.end()) { throw OptionError(fmt("Unrecognized option `%1%'", letter)); } - const Options::iterator o = _options.find(n->second); - if (j < len - 1) { // Non-final POSIX style flag + const auto o = _options.find(n->second); + if (j < len - 1) { // Non-final POSIX style flag if (o->second.type != _forge.Bool) { throw OptionError( fmt("Missing value for `%1%'", letter)); } o->second.value = _forge.make(true); - } else if (o->second.type == _forge.Bool) { // -f + } else if (o->second.type == _forge.Bool) { // -f o->second.value = _forge.make(true); - } else if (++i < argc) { // -v val + } else if (++i < argc) { // -v val set_value_from_string(o->second, argv[i]); } else { throw OptionError(fmt("Missing value for `%1%'", letter)); @@ -228,27 +242,31 @@ Configuration::parse(int argc, char** argv) bool Configuration::load(const FilePath& path) { - if (!filesystem::exists(path)) { + if (!std::filesystem::exists(path)) { return false; } SerdNode node = serd_node_new_file_uri( - (const uint8_t*)path.c_str(), nullptr, nullptr, true); - const std::string uri((const char*)node.buf); + reinterpret_cast<const uint8_t*>(path.c_str()), nullptr, nullptr, true); + + const std::string uri(reinterpret_cast<const char*>(node.buf)); Sord::World world; Sord::Model model(world, uri, SORD_SPO, false); SerdEnv* env = serd_env_new(&node); model.load_file(env, SERD_TURTLE, uri, uri); - Sord::Node nodemm(world, Sord::Node::URI, (const char*)node.buf); - Sord::Node nil; - for (Sord::Iter i = model.find(nodemm, nil, nil); !i.end(); ++i) { - const Sord::Node& pred = i.get_predicate(); - const Sord::Node& obj = i.get_object(); + const Sord::Node nodemm{world, + Sord::Node::URI, + reinterpret_cast<const char*>(node.buf)}; + + const Sord::Node nil; + for (auto i = model.find(nodemm, nil, nil); !i.end(); ++i) { + const auto& pred = i.get_predicate(); + const auto& obj = i.get_object(); if (pred.to_string().substr(0, sizeof(INGEN_NS) - 1) == INGEN_NS) { const std::string key = pred.to_string().substr(sizeof(INGEN_NS) - 1); - const Keys::iterator k = _keys.find(key); + const auto k = _keys.find(key); if (k != _keys.end() && obj.type() == Sord::Node::LITERAL) { set_value_from_string(_options.find(k->second)->second, obj.to_string()); @@ -274,15 +292,17 @@ Configuration::save(URIMap& uri_map, } // Create parent directories if necessary - const FilePath dir = path.parent_path(); - if (!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))); } // Attempt to open file for writing - std::unique_ptr<FILE, decltype(&fclose)> file{fopen(path.c_str(), "w"), - &fclose}; + const std::unique_ptr<FILE, int (*)(FILE*)> file{ + fopen(path.c_str(), "w"), &fclose}; if (!file) { throw FileError(fmt("Failed to open file %1% (%2%)", path, strerror(errno))); @@ -290,31 +310,41 @@ Configuration::save(URIMap& uri_map, // Use the file's URI as the base URI SerdURI base_uri; - SerdNode base = serd_node_new_file_uri( - (const uint8_t*)path.c_str(), nullptr, &base_uri, true); + SerdNode base = + serd_node_new_file_uri(reinterpret_cast<const uint8_t*>(path.c_str()), + nullptr, + &base_uri, + true); // Create environment with ingen prefix SerdEnv* env = serd_env_new(&base); - serd_env_set_prefix_from_strings( - env, (const uint8_t*)"ingen", (const uint8_t*)INGEN_NS); + serd_env_set_prefix_from_strings(env, + reinterpret_cast<const uint8_t*>("ingen"), + reinterpret_cast<const uint8_t*>( + INGEN_NS)); // Create Turtle writer SerdWriter* writer = serd_writer_new( SERD_TURTLE, - (SerdStyle)(SERD_STYLE_RESOLVED|SERD_STYLE_ABBREVIATED), + static_cast<SerdStyle>(SERD_STYLE_RESOLVED|SERD_STYLE_ABBREVIATED), env, &base_uri, serd_file_sink, file.get()); // Write a prefix directive for each prefix in the environment - serd_env_foreach(env, (SerdPrefixSink)serd_writer_set_prefix, writer); + serd_env_foreach(env, + reinterpret_cast<SerdPrefixSink>(serd_writer_set_prefix), + writer); // Create an atom serialiser and connect it to the Turtle writer - Sratom* sratom = sratom_new(&uri_map.urid_map_feature()->urid_map); + Sratom* sratom = sratom_new(&uri_map.urid_map()); sratom_set_pretty_numbers(sratom, true); - sratom_set_sink(sratom, (const char*)base.buf, - (SerdStatementSink)serd_writer_write_statement, nullptr, + sratom_set_sink(sratom, + reinterpret_cast<const char*>(base.buf), + reinterpret_cast<SerdStatementSink>( + serd_writer_write_statement), + nullptr, writer); // Write a statement for each valid option @@ -327,9 +357,9 @@ Configuration::save(URIMap& uri_map, } const std::string key(std::string("ingen:") + o.second.key); - SerdNode pred = serd_node_from_string( - SERD_CURIE, (const uint8_t*)key.c_str()); - sratom_write(sratom, &uri_map.urid_unmap_feature()->urid_unmap, 0, + const SerdNode pred = serd_node_from_string( + SERD_CURIE, reinterpret_cast<const uint8_t*>(key.c_str())); + sratom_write(sratom, &uri_map.urid_unmap(), 0, &base, &pred, value.type(), value.size(), value.get_body()); } @@ -369,9 +399,9 @@ Configuration::option(const std::string& long_name) const auto o = _options.find(long_name); if (o == _options.end()) { return nil; - } else { - return o->second.value; } + + return o->second.value; } bool diff --git a/src/FilePath.cpp b/src/FilePath.cpp deleted file mode 100644 index d16c133c..00000000 --- a/src/FilePath.cpp +++ /dev/null @@ -1,247 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2018 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/FilePath.hpp" - -#include <algorithm> -#include <string> -#include <utility> - -namespace ingen { - -template <typename Char> -static bool -is_sep(const Char chr) -{ -#ifdef USE_WINDOWS_FILE_PATHS - return chr == L'/' || chr == preferred_separator; -#else - return chr == '/'; -#endif -} - -FilePath& -FilePath::operator=(FilePath&& path) noexcept -{ - _str = std::move(path._str); - path.clear(); - return *this; -} - -FilePath& -FilePath::operator=(string_type&& str) -{ - _str = std::move(str); - return *this; -} - -FilePath& -FilePath::operator/=(const FilePath& path) -{ - const FilePath::string_type& str = path.string(); - if (!_str.empty() && !is_sep(_str.back()) && !str.empty() && - !is_sep(str.front())) { - _str += preferred_separator; - } - - _str += str; - return *this; -} - -FilePath& -FilePath::operator+=(const FilePath& path) -{ - return operator+=(path.native()); -} - -FilePath& -FilePath::operator+=(const string_type& str) -{ - _str += str; - return *this; -} - -FilePath& -FilePath::operator+=(const value_type* str) -{ - _str += str; - return *this; -} - -FilePath& -FilePath::operator+=(value_type chr) -{ - _str += chr; - return *this; -} - -FilePath& -FilePath::operator+=(boost::basic_string_view<value_type> sv) -{ - _str.append(sv.data(), sv.size()); - return *this; -} - -FilePath -FilePath::root_name() -{ -#ifdef USE_WINDOWS_FILE_PATHS - if (_str.length() >= 2 && _str[0] >= 'A' && _str[0] <= 'Z' && - _str[1] == ':') { - return FilePath(_str.substr(0, 2)); - } -#endif - - return FilePath(); -} - -FilePath -FilePath::root_directory() const -{ -#ifdef USE_WINDOWS_FILE_PATHS - const auto name = root_name().string(); - return name.empty() ? Path() : Path(name + preferred_separator); -#endif - - return _str[0] == '/' ? FilePath("/") : FilePath(); -} - -FilePath -FilePath::root_path() const -{ -#ifdef USE_WINDOWS_FILE_PATHS - const auto name = root_name(); - return name.empty() ? FilePath() : name / root_directory(); -#endif - return root_directory(); -} - -FilePath -FilePath::relative_path() const -{ - const auto root = root_path(); - return root.empty() ? FilePath() - : FilePath(_str.substr(root.string().length())); -} - -FilePath -FilePath::parent_path() const -{ - if (empty() || *this == root_path()) { - return *this; - } - - const auto first_sep = find_first_sep(); - const auto last_sep = find_last_sep(); - return ((last_sep == std::string::npos || last_sep == first_sep) - ? root_path() - : FilePath(_str.substr(0, last_sep))); -} - -FilePath -FilePath::filename() const -{ - return ((empty() || *this == root_path()) - ? FilePath() - : FilePath(_str.substr(find_last_sep() + 1))); -} - -FilePath -FilePath::stem() const -{ - const auto name = filename(); - const auto dot = name.string().find('.'); - return ((dot == std::string::npos) ? name - : FilePath(name.string().substr(0, dot))); -} - -FilePath -FilePath::extension() const -{ - const auto name = filename().string(); - const auto dot = name.find('.'); - return ((dot == std::string::npos) ? FilePath() - : FilePath(name.substr(dot, dot))); -} - -bool -FilePath::is_absolute() const -{ -#ifdef USE_WINDOWS_FILE_PATHS - return !root_name().empty(); -#else - return !root_directory().empty(); -#endif -} - -std::size_t -FilePath::find_first_sep() const -{ - const auto i = std::find_if(_str.begin(), _str.end(), is_sep<value_type>); - return i == _str.end() ? std::string::npos : (i - _str.begin()); -} - -std::size_t -FilePath::find_last_sep() const -{ - const auto i = std::find_if(_str.rbegin(), _str.rend(), is_sep<value_type>); - return (i == _str.rend() ? std::string::npos - : (_str.length() - 1 - (i - _str.rbegin()))); -} - -bool -operator==(const FilePath& lhs, const FilePath& rhs) noexcept -{ - return lhs.string() == rhs.string(); -} - -bool -operator!=(const FilePath& lhs, const FilePath& rhs) noexcept -{ - return !(lhs == rhs); -} - -bool -operator<(const FilePath& lhs, const FilePath& rhs) noexcept -{ - return lhs.string().compare(rhs.string()) < 0; -} - -bool -operator<=(const FilePath& lhs, const FilePath& rhs) noexcept -{ - return !(rhs < lhs); -} - -bool -operator>(const FilePath& lhs, const FilePath& rhs) noexcept -{ - return rhs < lhs; -} - -bool -operator>=(const FilePath& lhs, const FilePath& rhs) noexcept -{ - return !(lhs < rhs); -} - -FilePath -operator/(const FilePath& lhs, const FilePath& rhs) -{ - return FilePath(lhs) /= rhs; -} - -} // namespace ingen diff --git a/src/Forge.cpp b/src/Forge.cpp index cc1b12c8..8b222c64 100644 --- a/src/Forge.cpp +++ b/src/Forge.cpp @@ -14,14 +14,16 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "ingen/Forge.hpp" -#include "ingen/URI.hpp" -#include "ingen/URIMap.hpp" -#include "lv2/atom/forge.h" -#include "lv2/urid/urid.h" +#include <ingen/Atom.hpp> +#include <ingen/Forge.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIMap.hpp> +#include <lv2/atom/forge.h> +#include <lv2/urid/urid.h> -#include <memory> +#include <cstdint> #include <sstream> +#include <string> namespace ingen { @@ -29,14 +31,14 @@ Forge::Forge(URIMap& map) : LV2_Atom_Forge() , _map(map) { - lv2_atom_forge_init(this, &map.urid_map_feature()->urid_map); + lv2_atom_forge_init(this, &map.urid_map()); } Atom Forge::make_urid(const ingen::URI& u) { const LV2_URID urid = _map.map_uri(u.string()); - return Atom(sizeof(int32_t), URID, &urid); + return {sizeof(int32_t), URID, &urid}; } std::string diff --git a/src/LV2Features.cpp b/src/LV2Features.cpp index cd03cccd..73cc9382 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 @@ -14,11 +14,13 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "ingen/LV2Features.hpp" +#include <ingen/LV2Features.hpp> -#include "lv2/core/lv2.h" +#include <lv2/core/lv2.h> +#include <algorithm> #include <cstdlib> +#include <memory> namespace ingen { @@ -29,17 +31,23 @@ LV2Features::Feature::free_feature(LV2_Feature* feature) free(feature); } +std::shared_ptr<LV2_Feature> +LV2Features::EmptyFeature::feature(World& world, Node* block) +{ + return std::make_shared<LV2_Feature>(LV2_Feature{_uri, nullptr}); +} + void -LV2Features::add_feature(const SPtr<Feature>& feature) +LV2Features::add_feature(const std::shared_ptr<Feature>& feature) { _features.push_back(feature); } LV2Features::FeatureArray::FeatureArray(FeatureVector& features) - : _features(features) + : _features(features) + , _array{static_cast<LV2_Feature**>( + calloc(features.size() + 1, sizeof(LV2_Feature*)))} { - _array = (LV2_Feature**)malloc(sizeof(LV2_Feature*) * (features.size() + 1)); - _array[features.size()] = nullptr; for (size_t i = 0; i < features.size(); ++i) { _array[i] = features[i].get(); } @@ -57,20 +65,17 @@ 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; }); } -SPtr<LV2Features::FeatureArray> +std::shared_ptr<LV2Features::FeatureArray> LV2Features::lv2_features(World& world, Node* node) const { FeatureArray::FeatureVector vec; for (const auto& f : _features) { - SPtr<LV2_Feature> fptr = f->feature(world, node); + const std::shared_ptr<LV2_Feature> fptr = f->feature(world, node); if (fptr) { vec.push_back(fptr); } diff --git a/src/Library.cpp b/src/Library.cpp index a8a7107e..4add6577 100644 --- a/src/Library.cpp +++ b/src/Library.cpp @@ -14,7 +14,8 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "ingen/Library.hpp" +#include <ingen/FilePath.hpp> +#include <ingen/Library.hpp> #ifdef _WIN32 # include <windows.h> diff --git a/src/Log.cpp b/src/Log.cpp index cf18b58c..fbcaeca1 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 @@ -14,73 +14,70 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "ingen/Log.hpp" +#include <ingen/Log.hpp> -#include "ingen/ColorContext.hpp" -#include "ingen/Node.hpp" -#include "ingen/URIs.hpp" -#include "ingen/World.hpp" -#include "lv2/core/lv2.h" -#include "lv2/log/log.h" -#include "lv2/urid/urid.h" -#include "raul/Path.hpp" +#include <ingen/ColorContext.hpp> +#include <ingen/Node.hpp> +#include <ingen/URIs.hpp> +#include <ingen/World.hpp> +#include <lv2/core/lv2.h> +#include <lv2/log/log.h> +#include <lv2/urid/urid.h> +#include <raul/Path.hpp> #include <cstdio> #include <cstdlib> +#include <memory> namespace ingen { Log::Log(LV2_Log_Log* log, URIs& uris) : _log(log) , _uris(uris) - , _flush(false) - , _trace(false) {} 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) +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 @@ -89,26 +86,28 @@ Log::vtprintf(LV2_URID type, const char* fmt, va_list args) int ret = 0; if (type == _uris.log_Trace && !_trace) { return 0; - } else if (_sink) { + } + + if (_sink) { _sink(type, fmt, args); } if (_log) { ret = _log->vprintf(_log->handle, type, fmt, args); } else if (type == _uris.log_Error) { - ColorContext ctx(stderr, ColorContext::Color::RED); + const ColorContext ctx{stderr, ColorContext::Color::RED}; ret = vfprintf(stderr, fmt, args); } else if (type == _uris.log_Warning) { - ColorContext ctx(stderr, ColorContext::Color::YELLOW); + const ColorContext ctx{stderr, ColorContext::Color::YELLOW}; ret = vfprintf(stderr, fmt, args); } else if (type == _uris.log_Note) { - ColorContext ctx(stderr, ColorContext::Color::GREEN); + const ColorContext ctx{stderr, ColorContext::Color::GREEN}; ret = vfprintf(stdout, fmt, args); } else if (_trace && type == _uris.log_Trace) { - ColorContext ctx(stderr, ColorContext::Color::GREEN); + const ColorContext ctx{stderr, ColorContext::Color::GREEN}; ret = vfprintf(stderr, fmt, args); } else { - fprintf(stderr, "Unknown log type %d\n", type); + fprintf(stderr, "Unknown log type %u\n", type); return 0; } if (_flush) { @@ -120,11 +119,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; @@ -148,7 +146,7 @@ free_log_feature(LV2_Feature* feature) { free(feature); } -SPtr<LV2_Feature> +std::shared_ptr<LV2_Feature> Log::Feature::feature(World& world, Node* block) { auto* handle = static_cast<Handle*>(calloc(1, sizeof(Handle))); @@ -162,7 +160,7 @@ Log::Feature::feature(World& world, Node* block) f->URI = LV2_LOG__log; f->data = &handle->lv2_log; - return SPtr<LV2_Feature>(f, &free_log_feature); + return {f, &free_log_feature}; } -} // namespace ingen +} // namespace ingen diff --git a/src/Parser.cpp b/src/Parser.cpp index 5cc1dedd..c03f0abf 100644 --- a/src/Parser.cpp +++ b/src/Parser.cpp @@ -14,41 +14,43 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "ingen/Parser.hpp" - -#include "ingen/Atom.hpp" -#include "ingen/AtomForge.hpp" -#include "ingen/Forge.hpp" -#include "ingen/Interface.hpp" -#include "ingen/Log.hpp" -#include "ingen/Properties.hpp" -#include "ingen/Resource.hpp" -#include "ingen/URI.hpp" -#include "ingen/URIMap.hpp" -#include "ingen/URIs.hpp" -#include "ingen/World.hpp" -#include "ingen/filesystem.hpp" -#include "ingen/paths.hpp" -#include "lv2/atom/atom.h" -#include "lv2/atom/forge.h" -#include "lv2/core/lv2.h" -#include "lv2/urid/urid.h" -#include "raul/Path.hpp" -#include "raul/Symbol.hpp" -#include "serd/serd.h" -#include "sord/sord.h" -#include "sord/sordmm.hpp" - +#include <ingen/Parser.hpp> + +#include <ingen/Atom.hpp> +#include <ingen/AtomForge.hpp> +#include <ingen/FilePath.hpp> +#include <ingen/Forge.hpp> +#include <ingen/Interface.hpp> +#include <ingen/Log.hpp> +#include <ingen/Properties.hpp> +#include <ingen/Resource.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIMap.hpp> +#include <ingen/URIs.hpp> +#include <ingen/World.hpp> +#include <ingen/ingen.h> +#include <ingen/paths.hpp> +#include <lv2/atom/atom.h> +#include <lv2/core/lv2.h> +#include <raul/Path.hpp> +#include <raul/Symbol.hpp> +#include <serd/serd.h> +#include <sord/sord.h> +#include <sord/sordmm.hpp> + +#include <algorithm> #include <cassert> #include <cstdint> #include <cstring> +#include <filesystem> #include <map> #include <set> #include <string> +#include <string_view> #include <utility> -#define NS_RDF "http://www.w3.org/1999/02/22-rdf-syntax-ns#" -#define NS_RDFS "http://www.w3.org/2000/01/rdf-schema#" +#define NS_RDF "http://www.w3.org/1999/02/22-rdf-syntax-ns#" +#define NS_RDFS "http://www.w3.org/2000/01/rdf-schema#" namespace ingen { @@ -57,27 +59,29 @@ Parser::find_resources(Sord::World& world, const URI& manifest_uri, const URI& type_uri) { - const Sord::URI base (world, manifest_uri.string()); - const Sord::URI type (world, type_uri.string()); - const Sord::URI rdf_type (world, NS_RDF "type"); + const Sord::URI base(world, manifest_uri.string()); + const Sord::URI type(world, type_uri.string()); + const Sord::URI rdf_type(world, NS_RDF "type"); const Sord::URI rdfs_seeAlso(world, NS_RDFS "seeAlso"); const Sord::Node nil; - SerdEnv* env = serd_env_new(sord_node_to_serd_node(base.c_obj())); + SerdEnv* env = serd_env_new(sord_node_to_serd_node(base.c_obj())); Sord::Model model(world, manifest_uri.string()); model.load_file(env, SERD_TURTLE, manifest_uri.string()); std::set<ResourceRecord> resources; - for (Sord::Iter i = model.find(nil, rdf_type, type); !i.end(); ++i) { - const Sord::Node resource = i.get_subject(); - const std::string resource_uri = resource.to_c_string(); - Sord::Iter f = model.find(resource, rdfs_seeAlso, nil); - std::string file_path; + for (auto i = model.find(nil, rdf_type, type); !i.end(); ++i) { + const auto resource = i.get_subject(); + auto f = model.find(resource, rdfs_seeAlso, nil); + + std::string file_path; if (!f.end()) { - uint8_t* p = serd_file_uri_parse(f.get_object().to_u_string(), nullptr); - file_path = (const char*)p; + uint8_t* p = + serd_file_uri_parse(f.get_object().to_u_string(), nullptr); + file_path = reinterpret_cast<const char*>(p); serd_free(p); } + resources.insert(ResourceRecord(resource, file_path)); } @@ -85,44 +89,43 @@ Parser::find_resources(Sord::World& world, return resources; } -static boost::optional<Raul::Path> +static std::optional<raul::Path> get_path(const URI& base, const URI& uri) { - const URI relative = uri.make_relative(base); + const URI relative = uri.make_relative(base, base); const std::string uri_str = "/" + relative.string(); - return Raul::Path::is_valid(uri_str) ? Raul::Path(uri_str) - : boost::optional<Raul::Path>(); + return raul::Path::is_valid(uri_str) ? raul::Path(uri_str) + : std::optional<raul::Path>(); } static bool skip_property(ingen::URIs& uris, const Sord::Node& predicate) { - return (predicate == INGEN__file || - predicate == uris.ingen_arc || - predicate == uris.ingen_block || - predicate == uris.lv2_port); + return (predicate == INGEN__file || predicate == uris.ingen_arc || + predicate == uris.ingen_block || predicate == uris.lv2_port); } static Properties -get_properties(ingen::World& world, - Sord::Model& model, - const Sord::Node& subject, - Resource::Graph ctx, - const boost::optional<Properties>& data = {}) +get_properties(ingen::World& world, + Sord::Model& model, + const Sord::Node& subject, + Resource::Graph ctx, + const std::optional<Properties>& data = {}) { - AtomForge forge(world.uri_map().urid_map_feature()->urid_map); + AtomForge forge(world.uri_map().urid_map()); const Sord::Node nil; Properties props; - for (Sord::Iter i = model.find(subject, nil, nil); !i.end(); ++i) { + for (auto i = model.find(subject, nil, nil); !i.end(); ++i) { if (!skip_property(world.uris(), i.get_predicate())) { forge.clear(); - forge.read( - *world.rdf_world(), model.c_obj(), i.get_object().c_obj()); + forge.read(*world.rdf_world(), + model.c_obj(), + i.get_object().c_obj()); const LV2_Atom* atom = forge.atom(); Atom atomm; - atomm = world.forge().alloc( - atom->size, atom->type, LV2_ATOM_BODY_CONST(atom)); + atomm = + Forge::alloc(atom->size, atom->type, LV2_ATOM_BODY_CONST(atom)); props.emplace(i.get_predicate(), Property(atomm, ctx)); } } @@ -147,14 +150,14 @@ get_properties(ingen::World& world, return props; } -using PortRecord = std::pair<Raul::Path, Properties>; +using PortRecord = std::pair<raul::Path, Properties>; -static boost::optional<PortRecord> +static std::optional<PortRecord> get_port(ingen::World& world, Sord::Model& model, const Sord::Node& subject, Resource::Graph ctx, - const Raul::Path& parent, + const raul::Path& parent, uint32_t* index) { const URIs& uris = world.uris(); @@ -164,19 +167,18 @@ get_port(ingen::World& world, // Get index if requested (for Graphs) if (index) { - Properties::const_iterator i = props.find(uris.lv2_index); - if (i == props.end() - || i->second.type() != world.forge().Int - || i->second.get<int32_t>() < 0) { + const auto i = props.find(uris.lv2_index); + if (i == props.end() || i->second.type() != world.forge().Int || + i->second.get<int32_t>() < 0) { world.log().error("Port %1% has no valid index\n", subject); - return boost::optional<PortRecord>(); + return {}; } *index = i->second.get<int32_t>(); } // Get symbol - Properties::const_iterator s = props.find(uris.lv2_symbol); - std::string sym; + auto s = props.find(uris.lv2_symbol); + std::string sym; if (s != props.end() && s->second.type() == world.forge().String) { sym = s->second.ptr<char>(); } else { @@ -184,80 +186,78 @@ get_port(ingen::World& world, const size_t last_slash = subject_str.find_last_of('/'); sym = ((last_slash == std::string::npos) - ? subject_str - : subject_str.substr(last_slash + 1)); + ? subject_str + : subject_str.substr(last_slash + 1)); } - if (!Raul::Symbol::is_valid(sym)) { + if (!raul::Symbol::is_valid(sym)) { world.log().error("Port %1% has invalid symbol `%2%'\n", subject, sym); - return boost::optional<PortRecord>(); + return {}; } - const Raul::Symbol port_sym(sym); - const Raul::Path port_path(parent.child(port_sym)); + const raul::Symbol port_sym(sym); + const raul::Path port_path(parent.child(port_sym)); - props.erase(uris.lv2_symbol); // Don't set symbol property in engine + props.erase(uris.lv2_symbol); // Don't set symbol property in engine return make_pair(port_path, props); } -static boost::optional<Raul::Path> -parse( - World& world, - Interface& target, - Sord::Model& model, - const URI& base_uri, - Sord::Node& subject, - const boost::optional<Raul::Path>& parent = boost::optional<Raul::Path>(), - const boost::optional<Raul::Symbol>& symbol = boost::optional<Raul::Symbol>(), - const boost::optional<Properties>& data = boost::optional<Properties>()); - -static boost::optional<Raul::Path> +static std::optional<raul::Path> +parse(World& world, + Interface& target, + Sord::Model& model, + const URI& base_uri, + Sord::Node& subject, + const std::optional<raul::Path>& parent = std::optional<raul::Path>(), + const std::optional<raul::Symbol>& symbol = std::optional<raul::Symbol>(), + const std::optional<Properties>& data = std::optional<Properties>()); + +static std::optional<raul::Path> parse_graph( - World& world, - Interface& target, - Sord::Model& model, - const URI& base_uri, - const Sord::Node& subject, - Resource::Graph ctx, - const boost::optional<Raul::Path>& parent = boost::optional<Raul::Path>(), - const boost::optional<Raul::Symbol>& symbol = boost::optional<Raul::Symbol>(), - const boost::optional<Properties>& data = boost::optional<Properties>()); - -static boost::optional<Raul::Path> + World& world, + Interface& target, + Sord::Model& model, + const URI& base_uri, + const Sord::Node& subject, + Resource::Graph ctx, + const std::optional<raul::Path>& parent = std::optional<raul::Path>(), + const std::optional<raul::Symbol>& symbol = std::optional<raul::Symbol>(), + const std::optional<Properties>& data = std::optional<Properties>()); + +static std::optional<raul::Path> parse_block( - World& world, - Interface& target, - Sord::Model& model, - const URI& base_uri, - const Sord::Node& subject, - const Raul::Path& path, - const boost::optional<Properties>& data = boost::optional<Properties>()); + World& world, + Interface& target, + Sord::Model& model, + const URI& base_uri, + const Sord::Node& subject, + const raul::Path& path, + const std::optional<Properties>& data = std::optional<Properties>()); static bool -parse_arcs( - World& world, - Interface& target, - Sord::Model& model, - const URI& base_uri, - const Sord::Node& subject, - const Raul::Path& graph); - -static boost::optional<Raul::Path> -parse_block(ingen::World& world, - ingen::Interface& target, - Sord::Model& model, - const URI& base_uri, - const Sord::Node& subject, - const Raul::Path& path, - const boost::optional<Properties>& data) +parse_arcs(World& world, + Interface& target, + Sord::Model& model, + const URI& base_uri, + const Sord::Node& subject, + const raul::Path& graph); + +static std::optional<raul::Path> +parse_block(ingen::World& world, + ingen::Interface& target, + Sord::Model& model, + const URI& base_uri, + const Sord::Node& subject, + const raul::Path& path, + const std::optional<Properties>& data) { const URIs& uris = world.uris(); // Try lv2:prototype and old ingen:prototype for backwards compatibility - const Sord::URI prototype_predicates[] = { - Sord::URI(*world.rdf_world(), uris.lv2_prototype), - Sord::URI(*world.rdf_world(), uris.ingen_prototype) - }; + const Sord::URI prototype_predicates[] = {Sord::URI(*world.rdf_world(), + uris.lv2_prototype), + Sord::URI(*world.rdf_world(), + uris.ingen_prototype)}; // Get prototype Sord::Node prototype; @@ -270,98 +270,111 @@ parse_block(ingen::World& world, if (!prototype.is_valid()) { world.log().error("Block %1% (%2%) missing mandatory lv2:prototype\n", - subject, path); - return boost::optional<Raul::Path>(); + subject, + path); + return {}; } - const auto* type_uri = (const uint8_t*)prototype.to_c_string(); + const auto* type_uri = + reinterpret_cast<const uint8_t*>(prototype.to_c_string()); + if (!serd_uri_string_has_scheme(type_uri) || - !strncmp((const char*)type_uri, "file:", 5)) { + !strncmp(reinterpret_cast<const char*>(type_uri), "file:", 5)) { // Prototype is a file, subgraph SerdURI base_uri_parts; - serd_uri_parse((const uint8_t*)base_uri.c_str(), &base_uri_parts); + serd_uri_parse(reinterpret_cast<const uint8_t*>(base_uri.c_str()), + &base_uri_parts); - SerdURI ignored; - SerdNode sub_uri = serd_node_new_uri_from_string( - type_uri, - &base_uri_parts, - &ignored); + SerdURI ignored; + const SerdNode sub_uri = + serd_node_new_uri_from_string(type_uri, &base_uri_parts, &ignored); - const std::string sub_uri_str = (const char*)sub_uri.buf; - const std::string sub_file = sub_uri_str + "/main.ttl"; + const std::string sub_uri_str = + reinterpret_cast<const char*>(sub_uri.buf); + const std::string sub_file = sub_uri_str + "/main.ttl"; const SerdNode sub_base = serd_node_from_string( - SERD_URI, (const uint8_t*)sub_file.c_str()); + SERD_URI, reinterpret_cast<const uint8_t*>(sub_file.c_str())); Sord::Model sub_model(*world.rdf_world(), sub_file); - SerdEnv* env = serd_env_new(&sub_base); + SerdEnv* env = serd_env_new(&sub_base); sub_model.load_file(env, SERD_TURTLE, sub_file); serd_env_free(env); - Sord::URI sub_node(*world.rdf_world(), sub_file); - parse_graph(world, target, sub_model, sub_base, - sub_node, Resource::Graph::INTERNAL, - path.parent(), Raul::Symbol(path.symbol()), data); - - parse_graph(world, target, model, base_uri, - subject, Resource::Graph::EXTERNAL, - path.parent(), Raul::Symbol(path.symbol()), data); + const Sord::URI sub_node{*world.rdf_world(), sub_file}; + parse_graph(world, + target, + sub_model, + sub_base, + sub_node, + Resource::Graph::INTERNAL, + path.parent(), + raul::Symbol(path.symbol()), + data); + + parse_graph(world, + target, + model, + base_uri, + subject, + Resource::Graph::EXTERNAL, + path.parent(), + raul::Symbol(path.symbol()), + data); } else { // Prototype is non-file URI, plugin Properties props = get_properties( - world, model, subject, Resource::Graph::DEFAULT, data); + world, model, subject, Resource::Graph::DEFAULT, data); props.emplace(uris.rdf_type, uris.forge.make_urid(uris.ingen_Block)); target.put(path_to_uri(path), props); } return path; } -static boost::optional<Raul::Path> -parse_graph(ingen::World& world, - ingen::Interface& target, - Sord::Model& model, - const URI& base_uri, - const Sord::Node& subject, - Resource::Graph ctx, - const boost::optional<Raul::Path>& parent, - const boost::optional<Raul::Symbol>& symbol, - const boost::optional<Properties>& data) +static std::optional<raul::Path> +parse_graph(ingen::World& world, + ingen::Interface& target, + Sord::Model& model, + const URI& base_uri, + const Sord::Node& subject, + Resource::Graph ctx, + const std::optional<raul::Path>& parent, + const std::optional<raul::Symbol>& symbol, + const std::optional<Properties>& data) { const URIs& uris = world.uris(); const Sord::URI ingen_block(*world.rdf_world(), uris.ingen_block); - const Sord::URI lv2_port(*world.rdf_world(), LV2_CORE__port); + const Sord::URI lv2_port(*world.rdf_world(), LV2_CORE__port); const Sord::Node& graph = subject; const Sord::Node nil; // Build graph path and symbol - Raul::Path graph_path; + raul::Path graph_path{"/"}; if (parent && symbol) { graph_path = parent->child(*symbol); } else if (parent) { graph_path = *parent; - } else { - graph_path = Raul::Path("/"); } // Create graph - Properties props = get_properties(world, model, subject, ctx, data); + const Properties props = get_properties(world, model, subject, ctx, data); target.put(path_to_uri(graph_path), props, ctx); // For each port on this graph using PortRecords = std::map<uint32_t, PortRecord>; PortRecords ports; - for (Sord::Iter p = model.find(graph, lv2_port, nil); !p.end(); ++p) { + for (auto p = model.find(graph, lv2_port, nil); !p.end(); ++p) { Sord::Node port = p.get_object(); // Get all properties - uint32_t index = 0; - boost::optional<PortRecord> port_record = get_port( - world, model, port, ctx, graph_path, &index); + uint32_t index = 0; + std::optional<PortRecord> port_record = + get_port(world, model, port, ctx, graph_path, &index); if (!port_record) { world.log().error("Invalid port %1%\n", port); - return boost::optional<Raul::Path>(); + return {}; } // Store port information in ports map @@ -369,50 +382,51 @@ parse_graph(ingen::World& world, ports[index] = *port_record; } else { world.log().error("Ignored port %1% with duplicate index %2%\n", - port, index); + port, + index); } } // Create ports in order by index for (const auto& p : ports) { - target.put(path_to_uri(p.second.first), - p.second.second, - ctx); + target.put(path_to_uri(p.second.first), p.second.second, ctx); } if (ctx != Resource::Graph::INTERNAL) { - return graph_path; // Not parsing graph internals, finished now + return {graph_path}; // Not parsing graph internals, finished now } // For each block in this graph - for (Sord::Iter n = model.find(subject, ingen_block, nil); !n.end(); ++n) { - Sord::Node node = n.get_object(); - URI node_uri = node; + for (auto n = model.find(subject, ingen_block, nil); !n.end(); ++n) { + const Sord::Node node = n.get_object(); + const URI node_uri = node; assert(!node_uri.path().empty() && node_uri.path() != "/"); - const Raul::Path block_path = graph_path.child( - Raul::Symbol(FilePath(node_uri.path()).stem().string())); + const raul::Path block_path = graph_path.child( + raul::Symbol(FilePath(node_uri.path()).stem().string())); // Parse and create block - parse_block(world, target, model, base_uri, node, block_path, - boost::optional<Properties>()); + parse_block( + world, target, model, base_uri, node, block_path, std::nullopt); // For each port on this block - for (Sord::Iter p = model.find(node, lv2_port, nil); !p.end(); ++p) { + for (auto p = model.find(node, lv2_port, nil); !p.end(); ++p) { Sord::Node port = p.get_object(); Resource::Graph subctx = Resource::Graph::DEFAULT; - if (!model.find(node, - Sord::URI(*world.rdf_world(), uris.rdf_type), - Sord::URI(*world.rdf_world(), uris.ingen_Graph)).end()) { + if (!model + .find(node, + Sord::URI(*world.rdf_world(), uris.rdf_type), + Sord::URI(*world.rdf_world(), uris.ingen_Graph)) + .end()) { subctx = Resource::Graph::EXTERNAL; } // Get all properties - boost::optional<PortRecord> port_record = get_port( - world, model, port, subctx, block_path, nullptr); + std::optional<PortRecord> port_record = + get_port(world, model, port, subctx, block_path, nullptr); if (!port_record) { world.log().error("Invalid port %1%\n", port); - return boost::optional<Raul::Path>(); + return {}; } // Create port and/or set all port properties @@ -425,16 +439,16 @@ parse_graph(ingen::World& world, // Now that all ports and blocks exist, create arcs inside graph parse_arcs(world, target, model, base_uri, subject, graph_path); - return graph_path; + return {graph_path}; } static bool -parse_arc(ingen::World& world, - ingen::Interface& target, - Sord::Model& model, - const URI& base_uri, - const Sord::Node& subject, - const Raul::Path& graph) +parse_arc(ingen::World& world, + ingen::Interface& target, + Sord::Model& model, + const URI& base_uri, + const Sord::Node& subject, + const raul::Path& graph) { const URIs& uris = world.uris(); @@ -442,26 +456,28 @@ parse_arc(ingen::World& world, const Sord::URI ingen_head(*world.rdf_world(), uris.ingen_head); const Sord::Node nil; - Sord::Iter t = model.find(subject, ingen_tail, nil); - Sord::Iter h = model.find(subject, ingen_head, nil); + auto t = model.find(subject, ingen_tail, nil); + auto h = model.find(subject, ingen_head, nil); if (t.end()) { world.log().error("Arc has no tail\n"); return false; - } else if (h.end()) { + } + + if (h.end()) { world.log().error("Arc has no head\n"); return false; } - const boost::optional<Raul::Path> tail_path = get_path( - base_uri, t.get_object()); + const std::optional<raul::Path> tail_path = + get_path(base_uri, t.get_object()); if (!tail_path) { world.log().error("Arc tail has invalid URI\n"); return false; } - const boost::optional<Raul::Path> head_path = get_path( - base_uri, h.get_object()); + const std::optional<raul::Path> head_path = + get_path(base_uri, h.get_object()); if (!head_path) { world.log().error("Arc head has invalid URI\n"); return false; @@ -470,7 +486,9 @@ parse_arc(ingen::World& world, if (!(++t).end()) { world.log().error("Arc has multiple tails\n"); return false; - } else if (!(++h).end()) { + } + + if (!(++h).end()) { world.log().error("Arc has multiple heads\n"); return false; } @@ -481,65 +499,70 @@ parse_arc(ingen::World& world, } static bool -parse_arcs(ingen::World& world, - ingen::Interface& target, - Sord::Model& model, - const URI& base_uri, - const Sord::Node& subject, - const Raul::Path& graph) +parse_arcs(ingen::World& world, + ingen::Interface& target, + Sord::Model& model, + const URI& base_uri, + const Sord::Node& subject, + const raul::Path& graph) { const Sord::URI ingen_arc(*world.rdf_world(), world.uris().ingen_arc); const Sord::Node nil; - for (Sord::Iter i = model.find(subject, ingen_arc, nil); !i.end(); ++i) { + for (auto i = model.find(subject, ingen_arc, nil); !i.end(); ++i) { parse_arc(world, target, model, base_uri, i.get_object(), graph); } return true; } -static boost::optional<Raul::Path> -parse(ingen::World& world, - ingen::Interface& target, - Sord::Model& model, - const URI& base_uri, - Sord::Node& subject, - const boost::optional<Raul::Path>& parent, - const boost::optional<Raul::Symbol>& symbol, - const boost::optional<Properties>& data) +static std::optional<raul::Path> +parse(ingen::World& world, + ingen::Interface& target, + Sord::Model& model, + const URI& base_uri, + Sord::Node& subject, + const std::optional<raul::Path>& parent, + const std::optional<raul::Symbol>& symbol, + const std::optional<Properties>& data) { const URIs& uris = world.uris(); - const Sord::URI graph_class (*world.rdf_world(), uris.ingen_Graph); - const Sord::URI block_class (*world.rdf_world(), uris.ingen_Block); - const Sord::URI arc_class (*world.rdf_world(), uris.ingen_Arc); + const Sord::URI graph_class(*world.rdf_world(), uris.ingen_Graph); + const Sord::URI block_class(*world.rdf_world(), uris.ingen_Block); + const Sord::URI arc_class(*world.rdf_world(), uris.ingen_Arc); const Sord::URI internal_class(*world.rdf_world(), uris.ingen_Internal); - const Sord::URI in_port_class (*world.rdf_world(), LV2_CORE__InputPort); + const Sord::URI in_port_class(*world.rdf_world(), LV2_CORE__InputPort); const Sord::URI out_port_class(*world.rdf_world(), LV2_CORE__OutputPort); - const Sord::URI lv2_class (*world.rdf_world(), LV2_CORE__Plugin); - const Sord::URI rdf_type (*world.rdf_world(), uris.rdf_type); + const Sord::URI lv2_class(*world.rdf_world(), LV2_CORE__Plugin); + const Sord::URI rdf_type(*world.rdf_world(), uris.rdf_type); const Sord::Node nil; // Parse explicit subject graph if (subject.is_valid()) { - return parse_graph(world, target, model, base_uri, - subject, Resource::Graph::INTERNAL, - parent, symbol, data); + return parse_graph(world, + target, + model, + base_uri, + subject, + Resource::Graph::INTERNAL, + parent, + symbol, + data); } // Get all subjects and their types (?subject a ?type) - using Subjects = std::map< Sord::Node, std::set<Sord::Node> >; + using Subjects = std::map<Sord::Node, std::set<Sord::Node>>; Subjects subjects; - for (Sord::Iter i = model.find(subject, rdf_type, nil); !i.end(); ++i) { - const Sord::Node& subject = i.get_subject(); + for (auto i = model.find(subject, rdf_type, nil); !i.end(); ++i) { const Sord::Node& rdf_class = i.get_object(); assert(rdf_class.is_uri()); - auto s = subjects.find(subject); + const auto s = subjects.find(i.get_subject()); if (s == subjects.end()) { std::set<Sord::Node> types; types.insert(rdf_class); - subjects.emplace(subject, types); + subjects.emplace(i.get_subject(), types); } else { s->second.insert(rdf_class); } @@ -549,77 +572,82 @@ parse(ingen::World& world, for (const auto& i : subjects) { const Sord::Node& s = i.first; const std::set<Sord::Node>& types = i.second; - boost::optional<Raul::Path> ret; + std::optional<raul::Path> ret; if (types.find(graph_class) != types.end()) { - ret = parse_graph(world, target, model, base_uri, - s, Resource::Graph::INTERNAL, - parent, symbol, data); + ret = parse_graph(world, + target, + model, + base_uri, + s, + Resource::Graph::INTERNAL, + parent, + symbol, + data); } else if (types.find(block_class) != types.end()) { - const Raul::Path rel_path(*get_path(base_uri, s)); - const Raul::Path path = parent ? parent->child(rel_path) : rel_path; + const raul::Path rel_path{*get_path(base_uri, s)}; + const raul::Path path = parent ? parent->child(rel_path) : rel_path; ret = parse_block(world, target, model, base_uri, s, path, data); } else if (types.find(in_port_class) != types.end() || types.find(out_port_class) != types.end()) { - const Raul::Path rel_path(*get_path(base_uri, s)); - const Raul::Path path = parent ? parent->child(rel_path) : rel_path; - const Properties properties = get_properties( - world, model, s, Resource::Graph::DEFAULT, data); + const raul::Path rel_path{*get_path(base_uri, s)}; + const raul::Path path = parent ? parent->child(rel_path) : rel_path; + const Properties properties = + get_properties(world, model, s, Resource::Graph::DEFAULT, data); target.put(path_to_uri(path), properties); ret = path; } else if (types.find(arc_class) != types.end()) { - Raul::Path parent_path(parent ? parent.get() : Raul::Path("/")); + const raul::Path parent_path{parent ? parent.value() : raul::Path("/")}; parse_arc(world, target, model, base_uri, s, parent_path); } else { world.log().error("Subject has no known types\n"); } } - return boost::optional<Raul::Path>(); + return {}; } bool -Parser::parse_file(ingen::World& world, - ingen::Interface& target, - const FilePath& path, - const boost::optional<Raul::Path>& parent, - const boost::optional<Raul::Symbol>& symbol, - const boost::optional<Properties>& data) +Parser::parse_file(ingen::World& world, + ingen::Interface& target, + const FilePath& path, + const std::optional<raul::Path>& parent, + const std::optional<raul::Symbol>& symbol, + const std::optional<Properties>& data) { // Get absolute file path FilePath file_path = path; if (!file_path.is_absolute()) { - file_path = filesystem::current_path() / file_path; + file_path = std::filesystem::current_path() / file_path; } // Find file to use as manifest - const bool is_bundle = filesystem::is_directory(file_path); + const bool is_bundle = std::filesystem::is_directory(file_path); const FilePath manifest_path = - (is_bundle ? file_path / "manifest.ttl" : file_path); + (is_bundle ? file_path / "manifest.ttl" : file_path); - URI manifest_uri(manifest_path); + const URI manifest_uri{manifest_path}; // Find graphs in manifest - const std::set<ResourceRecord> resources = find_resources( - *world.rdf_world(), manifest_uri, URI(INGEN__Graph)); + const std::set<ResourceRecord> resources = + find_resources(*world.rdf_world(), manifest_uri, URI(INGEN__Graph)); if (resources.empty()) { world.log().error("No graphs found in %1%\n", path); 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; @@ -631,13 +659,16 @@ Parser::parse_file(ingen::World& world, } // Initialise parsing environment - const URI file_uri = URI(file_path); - const auto* uri_c_str = (const uint8_t*)uri.c_str(); - SerdNode base_node = serd_node_from_string(SERD_URI, uri_c_str); - SerdEnv* env = serd_env_new(&base_node); + const URI file_uri = URI(file_path); + const auto* uri_c_str = reinterpret_cast<const uint8_t*>(uri.c_str()); + const SerdNode base_node = serd_node_from_string(SERD_URI, uri_c_str); + SerdEnv* env = serd_env_new(&base_node); // Load graph into model - Sord::Model model(*world.rdf_world(), uri.string(), SORD_SPO|SORD_PSO, false); + Sord::Model model(*world.rdf_world(), + uri.string(), + SORD_SPO | SORD_PSO, + false); model.load_file(env, SERD_TURTLE, file_uri); serd_env_free(env); @@ -650,49 +681,50 @@ Parser::parse_file(ingen::World& world, } Sord::Node subject(*world.rdf_world(), Sord::Node::URI, uri.string()); - boost::optional<Raul::Path> parsed_path - = parse(world, target, model, model.base_uri(), - subject, parent, symbol, data); + std::optional<raul::Path> parsed_path = parse( + world, target, model, model.base_uri(), subject, parent, symbol, data); if (parsed_path) { target.set_property(path_to_uri(*parsed_path), URI(INGEN__file), world.forge().alloc_uri(uri.string())); return true; - } else { - world.log().warn("Document URI lost\n"); - return false; } + + world.log().warn("Document URI lost\n"); + return false; } -boost::optional<URI> -Parser::parse_string(ingen::World& world, - ingen::Interface& target, - const std::string& str, - const URI& base_uri, - const boost::optional<Raul::Path>& parent, - const boost::optional<Raul::Symbol>& symbol, - const boost::optional<Properties>& data) +std::optional<URI> +Parser::parse_string(ingen::World& world, + ingen::Interface& target, + const std::string& str, + const URI& base_uri, + const std::optional<raul::Path>& parent, + const std::optional<raul::Symbol>& symbol, + const std::optional<Properties>& data) { // Load string into model - Sord::Model model(*world.rdf_world(), base_uri, SORD_SPO|SORD_PSO, false); + Sord::Model model(*world.rdf_world(), base_uri, SORD_SPO | SORD_PSO, false); SerdEnv* env = serd_env_new(nullptr); if (!base_uri.empty()) { const SerdNode base = serd_node_from_string( - SERD_URI, (const uint8_t*)base_uri.c_str()); + SERD_URI, reinterpret_cast<const uint8_t*>(base_uri.c_str())); serd_env_set_base_uri(env, &base); } model.load_string(env, SERD_TURTLE, str.c_str(), str.length(), base_uri); - URI actual_base((const char*)serd_env_get_base_uri(env, nullptr)->buf); + URI actual_base(reinterpret_cast<const char*>( + serd_env_get_base_uri(env, nullptr)->buf)); + serd_env_free(env); world.log().info("Parsing string (base %1%)\n", base_uri); Sord::Node subject; parse(world, target, model, actual_base, subject, parent, symbol, data); - return actual_base; + return {actual_base}; } } // namespace ingen diff --git a/src/Resource.cpp b/src/Resource.cpp index fca76572..29a82772 100644 --- a/src/Resource.cpp +++ b/src/Resource.cpp @@ -14,11 +14,13 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "ingen/Resource.hpp" +#include <ingen/Resource.hpp> -#include "ingen/Atom.hpp" -#include "ingen/Forge.hpp" -#include "ingen/URIs.hpp" +#include <ingen/Atom.hpp> +#include <ingen/Forge.hpp> +#include <ingen/Properties.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIs.hpp> #include <map> #include <utility> @@ -29,9 +31,8 @@ bool Resource::add_property(const URI& uri, const Atom& value, Graph ctx) { // Ignore duplicate statements - using iterator = Properties::const_iterator; - const std::pair<iterator, iterator> range = _properties.equal_range(uri); - for (iterator i = range.first; i != range.second && i != _properties.end(); ++i) { + const auto range = _properties.equal_range(uri); + for (auto i = range.first; i != range.second && i != _properties.end(); ++i) { if (i->second == value && i->second.context() == ctx) { return false; } @@ -52,29 +53,25 @@ Resource::add_property(const URI& uri, const Atom& value, Graph ctx) const Atom& Resource::set_property(const URI& uri, const Atom& value, Resource::Graph ctx) { + assert(uri != _uris.ingen_activity); // Always ephemeral + // Erase existing property in this context for (auto i = _properties.find(uri); (i != _properties.end()) && (i->first == uri);) { auto next = i; ++next; if (i->second.context() == ctx) { - const auto value = i->second; + const auto old_value = i->second; _properties.erase(i); - on_property_removed(uri, value); + on_property_removed(uri, old_value); } i = next; } - if (uri != _uris.ingen_activity) { - // Insert new property - const Atom& v = _properties.emplace(uri, Property(value, ctx))->second; - on_property(uri, v); - return v; - } else { - // Announce ephemeral activity, but do not store - on_property(uri, value); - return value; - } + // Insert new property + const Atom& v = _properties.emplace(uri, Property(value, ctx))->second; + on_property(uri, v); + return v; } const Atom& @@ -82,7 +79,7 @@ Resource::set_property(const URI& uri, const URIs::Quark& value, Resource::Graph ctx) { - return set_property(uri, value.urid, ctx); + return set_property(uri, value.urid_atom(), ctx); } void @@ -106,8 +103,8 @@ Resource::remove_property(const URI& uri, const Atom& value) void Resource::remove_property(const URI& uri, const URIs::Quark& value) { - remove_property(uri, value.urid); - remove_property(uri, value.uri); + remove_property(uri, value.urid_atom()); + remove_property(uri, value.uri_atom()); } bool @@ -119,8 +116,9 @@ Resource::has_property(const URI& uri, const Atom& value) const bool Resource::has_property(const URI& uri, const URIs::Quark& value) const { - Properties::const_iterator i = _properties.find(uri); - for (; (i != _properties.end()) && (i->first == uri); ++i) { + for (auto i = _properties.find(uri); + (i != _properties.end()) && (i->first == uri); + ++i) { if (value == i->second) { return true; } @@ -138,7 +136,8 @@ const Atom& Resource::get_property(const URI& uri) const { static const Atom nil; - Properties::const_iterator i = _properties.find(uri); + + const auto i = _properties.find(uri); return (i != _properties.end()) ? i->second : nil; } @@ -150,11 +149,10 @@ Resource::type(const URIs& uris, bool& port, bool& is_output) { - using iterator = Properties::const_iterator; - const std::pair<iterator, iterator> types_range = properties.equal_range(uris.rdf_type); + const auto types_range = properties.equal_range(uris.rdf_type); graph = block = port = is_output = false; - for (iterator i = types_range.first; i != types_range.second; ++i) { + for (auto i = types_range.first; i != types_range.second; ++i) { const Atom& atom = i->second; if (atom.type() != uris.forge.URI && atom.type() != uris.forge.URID) { continue; // Non-URI type, ignore garbage data @@ -176,14 +174,14 @@ Resource::type(const URIs& uris, if (graph && block && !port) { // => graph block = false; return true; - } else if (port && (graph || block)) { // nonsense + } + + if (port && (graph || block)) { // nonsense port = false; return false; - } else if (graph || block || port) { // recognized type - return true; - } else { // unknown - return false; } + + return graph || block || port; // recognized type } void @@ -196,7 +194,7 @@ Resource::set_properties(const Properties& props) // Erase existing properties with matching keys for (const auto& p : props) { _properties.erase(p.first); - on_property_removed(p.first, _uris.patch_wildcard.urid); + on_property_removed(p.first, _uris.patch_wildcard.urid_atom()); } // Set new properties diff --git a/src/Serialiser.cpp b/src/Serialiser.cpp index f0b5009e..785e12ba 100644 --- a/src/Serialiser.cpp +++ b/src/Serialiser.cpp @@ -14,120 +14,113 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "ingen/Serialiser.hpp" - -#include "ingen/Arc.hpp" -#include "ingen/Atom.hpp" -#include "ingen/FilePath.hpp" -#include "ingen/Forge.hpp" -#include "ingen/Log.hpp" -#include "ingen/Node.hpp" -#include "ingen/Resource.hpp" -#include "ingen/Store.hpp" -#include "ingen/URI.hpp" -#include "ingen/URIMap.hpp" -#include "ingen/URIs.hpp" -#include "ingen/World.hpp" -#include "ingen/filesystem.hpp" -#include "ingen/runtime_paths.hpp" -#include "ingen/types.hpp" -#include "lv2/core/lv2.h" -#include "lv2/state/state.h" -#include "lv2/ui/ui.h" -#include "lv2/urid/urid.h" -#include "raul/Path.hpp" -#include "raul/Symbol.hpp" -#include "serd/serd.h" -#include "sord/sord.h" -#include "sord/sordmm.hpp" -#include "sratom/sratom.h" +#include <ingen/Serialiser.hpp> + +#include <ingen/Arc.hpp> +#include <ingen/Atom.hpp> +#include <ingen/FilePath.hpp> +#include <ingen/Forge.hpp> +#include <ingen/Log.hpp> +#include <ingen/Node.hpp> +#include <ingen/Properties.hpp> +#include <ingen/Resource.hpp> +#include <ingen/Store.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIMap.hpp> +#include <ingen/URIs.hpp> +#include <ingen/World.hpp> +#include <ingen/ingen.h> +#include <lv2/core/lv2.h> +#include <lv2/state/state.h> +#include <lv2/ui/ui.h> +#include <lv2/urid/urid.h> +#include <raul/Path.hpp> +#include <raul/Symbol.hpp> +#include <serd/serd.h> +#include <sord/sord.h> +#include <sord/sordmm.hpp> +#include <sratom/sratom.h> #include <cassert> #include <cstdint> #include <cstring> -#include <map> +#include <filesystem> +#include <memory> #include <set> #include <stdexcept> #include <string> +#include <string_view> #include <utility> namespace ingen { struct Serialiser::Impl { explicit Impl(World& world) - : _root_path("/") - , _mode(Mode::TO_FILE) - , _world(world) - , _model(nullptr) - , _sratom(sratom_new(&_world.uri_map().urid_map_feature()->urid_map)) + : _root_path("/") + , _world(world) + , _sratom(sratom_new(&_world.uri_map().urid_map())) {} - ~Impl() { - sratom_free(_sratom); - } + ~Impl() { sratom_free(_sratom); } Impl(const Impl&) = delete; - Impl(Impl&&) = delete; + Impl(Impl&&) = delete; Impl& operator=(const Impl&) = delete; Impl& operator=(Impl&&) = delete; enum class Mode { TO_FILE, TO_STRING }; - void start_to_file(const Raul::Path& root, - const FilePath& filename); + void start_to_file(const raul::Path& root, const FilePath& filename); - std::set<const Resource*> serialise_graph(const SPtr<const Node>& graph, - const Sord::Node& graph_id); + std::set<const Resource*> + serialise_graph(const std::shared_ptr<const Node>& graph, + const Sord::Node& graph_id); - void serialise_block(const SPtr<const Node>& block, - const Sord::Node& class_id, - const Sord::Node& block_id); + void serialise_block(const std::shared_ptr<const Node>& block, + const Sord::Node& class_id, + const Sord::Node& block_id); void serialise_port(const Node* port, Resource::Graph context, const Sord::Node& port_id); - void serialise_properties(Sord::Node id, - const Properties& props); + void serialise_properties(Sord::Node id, const Properties& props); - void write_bundle(const SPtr<const Node>& graph, const URI& uri); + void write_bundle(const std::shared_ptr<const Node>& graph, const URI& uri); - Sord::Node path_rdf_node(const Raul::Path& path); + Sord::Node path_rdf_node(const raul::Path& path) const; - void write_manifest(const FilePath& bundle_path, - const SPtr<const Node>& graph); + void write_manifest(const FilePath& bundle_path, + const std::shared_ptr<const Node>& graph); void write_plugins(const FilePath& bundle_path, const std::set<const Resource*>& plugins); - void serialise_arc(const Sord::Node& parent, - const SPtr<const Arc>& arc); + void serialise_arc(const Sord::Node& parent, + const std::shared_ptr<const Arc>& arc); std::string finish(); - Raul::Path _root_path; - Mode _mode; + raul::Path _root_path; + Mode _mode{Mode::TO_FILE}; URI _base_uri; FilePath _basename; World& _world; - Sord::Model* _model; + Sord::Model* _model{nullptr}; Sratom* _sratom; }; -Serialiser::Serialiser(World& world) - : me{make_unique<Impl>(world)} -{} +Serialiser::Serialiser(World& world) : me{std::make_unique<Impl>(world)} {} Serialiser::~Serialiser() = default; void Serialiser::Impl::write_manifest(const FilePath& bundle_path, - const SPtr<const Node>&) + const std::shared_ptr<const Node>&) { const FilePath manifest_path(bundle_path / "manifest.ttl"); - const FilePath binary_path(ingen_module_path("lv2")); - start_to_file(Raul::Path("/"), manifest_path); + start_to_file(raul::Path("/"), manifest_path); Sord::World& world = _model->world(); const URIs& uris = _world.uris(); @@ -157,7 +150,7 @@ Serialiser::Impl::write_plugins(const FilePath& bundle_path, { const FilePath plugins_path(bundle_path / "plugins.ttl"); - start_to_file(Raul::Path("/"), plugins_path); + start_to_file(raul::Path("/"), plugins_path); Sord::World& world = _model->world(); const URIs& uris = _world.uris(); @@ -173,10 +166,12 @@ Serialiser::Impl::write_plugins(const FilePath& bundle_path, if (minor.is_valid() && micro.is_valid()) { _model->add_statement(Sord::URI(world, p->uri()), Sord::URI(world, uris.lv2_minorVersion), - Sord::Literal::integer(world, minor.get<int32_t>())); + Sord::Literal::integer(world, + minor.get<int32_t>())); _model->add_statement(Sord::URI(world, p->uri()), Sord::URI(world, uris.lv2_microVersion), - Sord::Literal::integer(world, micro.get<int32_t>())); + Sord::Literal::integer(world, + micro.get<int32_t>())); } } @@ -184,30 +179,32 @@ Serialiser::Impl::write_plugins(const FilePath& bundle_path, } void -Serialiser::write_bundle(const SPtr<const Node>& graph, const URI& uri) +Serialiser::write_bundle(const std::shared_ptr<const Node>& graph, + const URI& uri) { me->write_bundle(graph, uri); } void -Serialiser::Impl::write_bundle(const SPtr<const Node>& graph, const URI& uri) +Serialiser::Impl::write_bundle(const std::shared_ptr<const Node>& graph, + const URI& uri) { FilePath path(uri.path()); - if (filesystem::exists(path) && !filesystem::is_directory(path)) { + if (std::filesystem::exists(path) && !std::filesystem::is_directory(path)) { path = path.parent_path(); } _world.log().info("Writing bundle %1%\n", path); - filesystem::create_directories(path); + std::filesystem::create_directories(path); const FilePath main_file = path / "main.ttl"; - const Raul::Path old_root_path = _root_path; + const raul::Path old_root_path = _root_path; start_to_file(graph->path(), main_file); - std::set<const Resource*> plugins = serialise_graph( - graph, - Sord::URI(_model->world(), main_file, _base_uri)); + const std::set<const Resource*> plugins = + serialise_graph(graph, + Sord::URI(_model->world(), main_file, _base_uri)); finish(); write_manifest(path, graph); @@ -221,7 +218,7 @@ Serialiser::Impl::write_bundle(const SPtr<const Node>& graph, const URI& uri) * This must be called before any serializing methods. */ void -Serialiser::Impl::start_to_file(const Raul::Path& root, +Serialiser::Impl::start_to_file(const raul::Path& root, const FilePath& filename) { _base_uri = URI(filename); @@ -236,7 +233,7 @@ Serialiser::Impl::start_to_file(const Raul::Path& root, } void -Serialiser::start_to_string(const Raul::Path& root, const URI& base_uri) +Serialiser::start_to_string(const raul::Path& root, const URI& base_uri) { me->_root_path = root; me->_base_uri = base_uri; @@ -245,7 +242,7 @@ Serialiser::start_to_string(const Raul::Path& root, const URI& base_uri) } void -Serialiser::start_to_file(const Raul::Path& root, const FilePath& filename) +Serialiser::start_to_file(const raul::Path& root, const FilePath& filename) { me->start_to_file(root, filename); } @@ -261,10 +258,11 @@ Serialiser::Impl::finish() { std::string ret; if (_mode == Mode::TO_FILE) { - SerdStatus st = _model->write_to_file(_base_uri, SERD_TURTLE); + const SerdStatus st = _model->write_to_file(_base_uri, SERD_TURTLE); if (st) { _world.log().error("Error writing file %1% (%2%)\n", - _base_uri, serd_strerror(st)); + _base_uri, + serd_strerror(st)); } } else { ret = _model->write_to_string(_base_uri, SERD_TURTLE); @@ -278,7 +276,7 @@ Serialiser::Impl::finish() } Sord::Node -Serialiser::Impl::path_rdf_node(const Raul::Path& path) +Serialiser::Impl::path_rdf_node(const raul::Path& path) const { assert(_model); assert(path == _root_path || path.is_child_of(_root_path)); @@ -288,20 +286,25 @@ Serialiser::Impl::path_rdf_node(const Raul::Path& path) } void -Serialiser::serialise(const SPtr<const Node>& object, Resource::Graph context) +Serialiser::serialise(const std::shared_ptr<const Node>& object, + Resource::Graph context) { if (!me->_model) { - throw std::logic_error("serialise called without serialisation in progress"); + throw std::logic_error( + "serialise called without serialisation in progress"); } if (object->graph_type() == Node::GraphType::GRAPH) { me->serialise_graph(object, me->path_rdf_node(object->path())); } else if (object->graph_type() == Node::GraphType::BLOCK) { const Sord::URI plugin_id(me->_model->world(), object->plugin()->uri()); - me->serialise_block(object, plugin_id, me->path_rdf_node(object->path())); + me->serialise_block(object, + plugin_id, + me->path_rdf_node(object->path())); } else if (object->graph_type() == Node::GraphType::PORT) { - me->serialise_port( - object.get(), context, me->path_rdf_node(object->path())); + me->serialise_port(object.get(), + context, + me->path_rdf_node(object->path())); } else { me->serialise_properties(me->path_rdf_node(object->path()), object->properties()); @@ -309,8 +312,8 @@ Serialiser::serialise(const SPtr<const Node>& object, Resource::Graph context) } std::set<const Resource*> -Serialiser::Impl::serialise_graph(const SPtr<const Node>& graph, - const Sord::Node& graph_id) +Serialiser::Impl::serialise_graph(const std::shared_ptr<const Node>& graph, + const Sord::Node& graph_id) { Sord::World& world = _model->world(); const URIs& uris = _world.uris(); @@ -327,9 +330,10 @@ Serialiser::Impl::serialise_graph(const SPtr<const Node>& graph, Sord::URI(world, uris.lv2_extensionData), Sord::URI(world, LV2_STATE__interface)); - _model->add_statement(graph_id, - Sord::URI(world, LV2_UI__ui), - Sord::URI(world, "http://drobilla.net/ns/ingen#GraphUIGtk2")); + _model->add_statement( + graph_id, + Sord::URI(world, LV2_UI__ui), + Sord::URI(world, "http://drobilla.net/ns/ingen#GraphUIGtk2")); // If the graph has no doap:name (required by LV2), use the basename if (graph->properties().find(uris.doap_name) == graph->properties().end()) { @@ -344,29 +348,34 @@ Serialiser::Impl::serialise_graph(const SPtr<const Node>& graph, std::set<const Resource*> plugins; const Store::const_range kids = _world.store()->children_range(graph); - for (Store::const_iterator n = kids.first; n != kids.second; ++n) { + for (auto n = kids.first; n != kids.second; ++n) { if (n->first.parent() != graph->path()) { continue; } if (n->second->graph_type() == Node::GraphType::GRAPH) { - SPtr<Node> subgraph = n->second; + const std::shared_ptr<Node> subgraph = n->second; SerdURI base_uri; - serd_uri_parse((const uint8_t*)_base_uri.c_str(), &base_uri); + serd_uri_parse(reinterpret_cast<const uint8_t*>(_base_uri.c_str()), + &base_uri); - const std::string sub_bundle_path = subgraph->path().substr(1) + ".ingen"; + const std::string sub_bundle_path = + subgraph->path().substr(1) + ".ingen"; SerdURI subgraph_uri; - SerdNode subgraph_node = serd_node_new_uri_from_string( - (const uint8_t*)sub_bundle_path.c_str(), - &base_uri, - &subgraph_uri); + SerdNode subgraph_node = + serd_node_new_uri_from_string(reinterpret_cast<const uint8_t*>( + sub_bundle_path.c_str()), + &base_uri, + &subgraph_uri); - const Sord::URI subgraph_id(world, (const char*)subgraph_node.buf); + const Sord::URI subgraph_id(world, + reinterpret_cast<const char*>( + subgraph_node.buf)); // Save our state - URI my_base_uri = _base_uri; + const URI my_base_uri = _base_uri; Sord::Model* my_model = _model; // Write child bundle within this bundle @@ -382,8 +391,10 @@ Serialiser::Impl::serialise_graph(const SPtr<const Node>& graph, Sord::URI(world, uris.ingen_block), block_id); serialise_block(subgraph, subgraph_id, block_id); + + serd_node_free(&subgraph_node); } else if (n->second->graph_type() == Node::GraphType::BLOCK) { - SPtr<const Node> block = n->second; + const std::shared_ptr<const Node> block = n->second; const Sord::URI class_id(world, block->plugin()->uri()); const Sord::Node block_id(path_rdf_node(n->second->path())); @@ -397,7 +408,7 @@ Serialiser::Impl::serialise_graph(const SPtr<const Node>& graph, } for (uint32_t i = 0; i < graph->num_ports(); ++i) { - Node* p = graph->port(i); + Node* p = graph->port(i); const Sord::Node port_id = path_rdf_node(p->path()); // Ensure lv2:name always exists so Graph is a valid LV2 plugin @@ -421,9 +432,9 @@ Serialiser::Impl::serialise_graph(const SPtr<const Node>& graph, } void -Serialiser::Impl::serialise_block(const SPtr<const Node>& block, - const Sord::Node& class_id, - const Sord::Node& block_id) +Serialiser::Impl::serialise_block(const std::shared_ptr<const Node>& block, + const Sord::Node& class_id, + const Sord::Node& block_id) { const URIs& uris = _world.uris(); @@ -434,7 +445,8 @@ Serialiser::Impl::serialise_block(const SPtr<const Node>& block, Sord::URI(_model->world(), uris.lv2_prototype), class_id); - // Serialise properties, but remove possibly stale state:state (set again below) + // Serialise properties, but remove possibly stale state:state (set again + // below) Properties props = block->properties(); props.erase(uris.state_state); serialise_properties(block_id, props); @@ -442,7 +454,7 @@ Serialiser::Impl::serialise_block(const SPtr<const Node>& block, if (_base_uri.scheme() == "file") { const FilePath base_path = _base_uri.file_path(); const FilePath graph_dir = base_path.parent_path(); - const FilePath state_dir = graph_dir / block->symbol(); + const FilePath state_dir = graph_dir / std::string(block->symbol()); const FilePath state_file = state_dir / "state.ttl"; if (block->save_state(state_dir)) { _model->add_statement(block_id, @@ -466,9 +478,9 @@ Serialiser::Impl::serialise_port(const Node* port, Resource::Graph context, const Sord::Node& port_id) { - URIs& uris = _world.uris(); - Sord::World& world = _model->world(); - Properties props = port->properties(context); + const URIs& uris = _world.uris(); + Sord::World& world = _model->world(); + Properties props = port->properties(context); if (context == Resource::Graph::INTERNAL) { // Always write lv2:symbol for Graph ports (required for lv2:Plugin) @@ -482,14 +494,14 @@ Serialiser::Impl::serialise_port(const Node* port, if (context == Resource::Graph::INTERNAL && port->has_property(uris.rdf_type, uris.lv2_ControlPort) && - port->has_property(uris.rdf_type, uris.lv2_InputPort)) - { + port->has_property(uris.rdf_type, uris.lv2_InputPort)) { const Atom& val = port->get_property(uris.ingen_value); if (val.is_valid()) { props.erase(uris.lv2_default); props.emplace(uris.lv2_default, val); } else { - _world.log().warn("Control input has no value, lv2:default omitted.\n"); + _world.log().warn( + "Control input has no value, lv2:default omitted.\n"); } } else if (context != Resource::Graph::INTERNAL && !port->has_property(uris.rdf_type, uris.lv2_InputPort)) { @@ -500,19 +512,19 @@ Serialiser::Impl::serialise_port(const Node* port, } void -Serialiser::serialise_arc(const Sord::Node& parent, - const SPtr<const Arc>& arc) +Serialiser::serialise_arc(const Sord::Node& parent, + const std::shared_ptr<const Arc>& arc) { - return me->serialise_arc(parent, arc); + me->serialise_arc(parent, arc); } void -Serialiser::Impl::serialise_arc(const Sord::Node& parent, - const SPtr<const Arc>& arc) +Serialiser::Impl::serialise_arc(const Sord::Node& parent, + const std::shared_ptr<const Arc>& arc) { if (!_model) { throw std::logic_error( - "serialise_arc called without serialisation in progress"); + "serialise_arc called without serialisation in progress"); } Sord::World& world = _model->world(); @@ -520,18 +532,12 @@ Serialiser::Impl::serialise_arc(const Sord::Node& parent, const Sord::Node src = path_rdf_node(arc->tail_path()); const Sord::Node dst = path_rdf_node(arc->head_path()); - const Sord::Node arc_id = Sord::Node::blank_id(*_world.rdf_world()); - _model->add_statement(arc_id, - Sord::URI(world, uris.ingen_tail), - src); - _model->add_statement(arc_id, - Sord::URI(world, uris.ingen_head), - dst); + const Sord::Node arc_id = Sord::Node::blank_id(*_world.rdf_world(), "arc"); + _model->add_statement(arc_id, Sord::URI(world, uris.ingen_tail), src); + _model->add_statement(arc_id, Sord::URI(world, uris.ingen_head), dst); if (parent.is_valid()) { - _model->add_statement(parent, - Sord::URI(world, uris.ingen_arc), - arc_id); + _model->add_statement(parent, Sord::URI(world, uris.ingen_arc), arc_id); } else { _model->add_statement(arc_id, Sord::URI(world, uris.rdf_type), @@ -542,24 +548,25 @@ Serialiser::Impl::serialise_arc(const Sord::Node& parent, static bool skip_property(ingen::URIs& uris, const Sord::Node& predicate) { - return (predicate == INGEN__file || - predicate == uris.ingen_arc || - predicate == uris.ingen_block || - predicate == uris.lv2_port); + return (predicate == INGEN__file || predicate == uris.ingen_arc || + predicate == uris.ingen_block || predicate == uris.lv2_port); } void -Serialiser::Impl::serialise_properties(Sord::Node id, - const Properties& props) +Serialiser::Impl::serialise_properties(Sord::Node id, const Properties& props) { - LV2_URID_Unmap* unmap = &_world.uri_map().urid_unmap_feature()->urid_unmap; - SerdNode base = serd_node_from_string(SERD_URI, - (const uint8_t*)_base_uri.c_str()); - SerdEnv* env = serd_env_new(&base); - SordInserter* inserter = sord_inserter_new(_model->c_obj(), env); - - sratom_set_sink(_sratom, _base_uri.c_str(), - (SerdStatementSink)sord_inserter_write_statement, nullptr, + LV2_URID_Unmap* unmap = &_world.uri_map().urid_unmap(); + const SerdNode base = serd_node_from_string( + SERD_URI, reinterpret_cast<const uint8_t*>(_base_uri.c_str())); + + SerdEnv* env = serd_env_new(&base); + SordInserter* inserter = sord_inserter_new(_model->c_obj(), env); + + sratom_set_sink(_sratom, + _base_uri.c_str(), + reinterpret_cast<SerdStatementSink>( + sord_inserter_write_statement), + nullptr, inserter); sratom_set_pretty_numbers(_sratom, true); @@ -568,20 +575,30 @@ Serialiser::Impl::serialise_properties(Sord::Node id, const Sord::URI key(_model->world(), p.first); if (!skip_property(_world.uris(), key)) { if (p.second.type() == _world.uris().atom_URI && - !strncmp((const char*)p.second.get_body(), "ingen:/main/", 13)) { + !strncmp(reinterpret_cast<const char*>(p.second.get_body()), + "ingen:/main/", + 12)) { /* Value is a graph URI relative to the running engine. Chop the prefix and save the path relative to the graph file. This allows saving references to bundle resources. */ - sratom_write(_sratom, unmap, 0, - sord_node_to_serd_node(id.c_obj()), - sord_node_to_serd_node(key.c_obj()), - p.second.type(), p.second.size(), - (const char*)p.second.get_body() + 13); + sratom_write( + _sratom, + unmap, + 0, + sord_node_to_serd_node(id.c_obj()), + sord_node_to_serd_node(key.c_obj()), + p.second.type(), + p.second.size(), + reinterpret_cast<const char*>(p.second.get_body()) + 13); } else { - sratom_write(_sratom, unmap, 0, + sratom_write(_sratom, + unmap, + 0, sord_node_to_serd_node(id.c_obj()), sord_node_to_serd_node(key.c_obj()), - p.second.type(), p.second.size(), p.second.get_body()); + p.second.type(), + p.second.size(), + p.second.get_body()); } } } diff --git a/src/SocketReader.cpp b/src/SocketReader.cpp index 409a1d86..5499fb66 100644 --- a/src/SocketReader.cpp +++ b/src/SocketReader.cpp @@ -14,41 +14,37 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "ingen/SocketReader.hpp" - -#include "ingen/AtomForge.hpp" -#include "ingen/AtomReader.hpp" -#include "ingen/Log.hpp" -#include "ingen/URIMap.hpp" -#include "ingen/World.hpp" -#include "lv2/atom/forge.h" -#include "lv2/urid/urid.h" -#include "raul/Socket.hpp" -#include "sord/sordmm.hpp" +#include <ingen/SocketReader.hpp> + +#include <ingen/AtomForge.hpp> +#include <ingen/AtomReader.hpp> +#include <ingen/Log.hpp> +#include <ingen/URIMap.hpp> +#include <ingen/World.hpp> +#include <lv2/urid/urid.h> +#include <raul/Socket.hpp> +#include <serd/serd.h> +#include <sord/sord.h> +#include <sord/sordmm.hpp> #include <cerrno> #include <cstdint> -#include <cstdio> -#include <cstring> #include <memory> #include <mutex> #include <poll.h> +#include <sys/socket.h> +#include <sys/types.h> #include <utility> namespace ingen { -SocketReader::SocketReader(ingen::World& world, - Interface& iface, - SPtr<Raul::Socket> sock) - : _world(world) - , _iface(iface) - , _env() - , _inserter(nullptr) - , _msg_node(nullptr) - , _socket(std::move(sock)) - , _socket_error(0) - , _exit_flag(false) - , _thread(&SocketReader::run, this) +SocketReader::SocketReader(ingen::World& world, + Interface& iface, + std::shared_ptr<raul::Socket> sock) + : _world(world) + , _iface(iface) + , _socket(std::move(sock)) + , _thread(&SocketReader::run, this) {} SocketReader::~SocketReader() @@ -97,7 +93,7 @@ SocketReader::write_statement(SocketReader* iface, size_t SocketReader::c_recv(void* buf, size_t size, size_t nmemb, void* stream) { - SocketReader* self = (SocketReader*)stream; + auto* self = static_cast<SocketReader*>(stream); const ssize_t c = recv(self->_socket->fd(), buf, size * nmemb, MSG_WAITALL); if (c < 0) { @@ -111,7 +107,7 @@ SocketReader::c_recv(void* buf, size_t size, size_t nmemb, void* stream) int SocketReader::c_err(void* stream) { - SocketReader* self = (SocketReader*)stream; + auto* self = static_cast<SocketReader*>(stream); return self->_socket_error; } @@ -120,7 +116,7 @@ void SocketReader::run() { Sord::World* world = _world.rdf_world(); - LV2_URID_Map& map = _world.uri_map().urid_map_feature()->urid_map; + LV2_URID_Map& map = _world.uri_map().urid_map(); // Set up a forge to build LV2 atoms from model SordNode* base_uri = nullptr; @@ -128,10 +124,11 @@ SocketReader::run() AtomForge forge(map); { // Lock RDF world - std::lock_guard<std::mutex> lock(_world.rdf_mutex()); + const std::lock_guard<std::mutex> lock{_world.rdf_mutex()}; // Use <ingen:/> as base URI, so relative URIs are like bundle paths - base_uri = sord_new_uri(world->c_obj(), (const uint8_t*)"ingen:/"); + base_uri = sord_new_uri(world->c_obj(), + reinterpret_cast<const uint8_t*>("ingen:/")); // Make a model and reader to parse the next Turtle message _env = world->prefixes().c_obj(); @@ -143,14 +140,19 @@ SocketReader::run() SerdReader* reader = serd_reader_new( SERD_TURTLE, this, nullptr, - (SerdBaseSink)set_base_uri, - (SerdPrefixSink)set_prefix, - (SerdStatementSink)write_statement, + reinterpret_cast<SerdBaseSink>(set_base_uri), + reinterpret_cast<SerdPrefixSink>(set_prefix), + reinterpret_cast<SerdStatementSink>(write_statement), nullptr); serd_env_set_base_uri(_env, sord_node_to_serd_node(base_uri)); - serd_reader_start_source_stream( - reader, c_recv, c_err, this, (const uint8_t*)"(socket)", 1); + serd_reader_start_source_stream(reader, + c_recv, + c_err, + this, + reinterpret_cast<const uint8_t*>( + "(socket)"), + 1); // Make an AtomReader to call Ingen Interface methods based on Atom AtomReader ar(_world.uri_map(), _world.uris(), _world.log(), _iface); @@ -165,19 +167,23 @@ SocketReader::run() const int ret = poll(&pfd, 1, -1); if (ret == -1 || (pfd.revents & (POLLERR|POLLHUP|POLLNVAL))) { on_hangup(); - break; // Hangup - } else if (!ret) { - continue; // No data, shouldn't happen + break; // Hangup + } + + if (!ret) { + continue; // No data, shouldn't happen } // Lock RDF world - std::lock_guard<std::mutex> lock(_world.rdf_mutex()); + const std::lock_guard<std::mutex> lock{_world.rdf_mutex()}; // Read until the next '.' - SerdStatus st = serd_reader_read_chunk(reader); + const SerdStatus st = serd_reader_read_chunk(reader); if (st == SERD_FAILURE || !_msg_node) { - continue; // Read nothing, e.g. just whitespace - } else if (st) { + continue; // Read nothing, e.g. just whitespace + } + + if (st) { _world.log().error("Read error: %1%\n", serd_strerror(st)); continue; } @@ -195,7 +201,7 @@ SocketReader::run() } // Lock RDF world - std::lock_guard<std::mutex> lock(_world.rdf_mutex()); + const std::lock_guard<std::mutex> lock{_world.rdf_mutex()}; // Destroy everything sord_inserter_free(_inserter); @@ -205,4 +211,4 @@ SocketReader::run() _socket.reset(); } -} // namespace ingen +} // namespace ingen diff --git a/src/SocketWriter.cpp b/src/SocketWriter.cpp index 910f67f3..7512ecbd 100644 --- a/src/SocketWriter.cpp +++ b/src/SocketWriter.cpp @@ -14,16 +14,18 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "ingen/SocketWriter.hpp" +#include <ingen/SocketWriter.hpp> -#include "ingen/URI.hpp" -#include "raul/Socket.hpp" - -#include <boost/variant/get.hpp> +#include <ingen/Message.hpp> +#include <ingen/TurtleWriter.hpp> +#include <ingen/URI.hpp> +#include <raul/Socket.hpp> +#include <memory> #include <sys/socket.h> #include <sys/types.h> #include <utility> +#include <variant> #ifndef MSG_NOSIGNAL # define MSG_NOSIGNAL 0 @@ -31,10 +33,10 @@ namespace ingen { -SocketWriter::SocketWriter(URIMap& map, - URIs& uris, - const URI& uri, - SPtr<Raul::Socket> sock) +SocketWriter::SocketWriter(URIMap& map, + URIs& uris, + const URI& uri, + std::shared_ptr<raul::Socket> sock) : TurtleWriter(map, uris, uri) , _socket(std::move(sock)) {} @@ -43,7 +45,7 @@ void SocketWriter::message(const Message& message) { TurtleWriter::message(message); - if (boost::get<BundleEnd>(&message)) { + if (std::get_if<BundleEnd>(&message)) { // Send a null byte to indicate end of bundle const char end[] = { 0 }; send(_socket->fd(), end, 1, MSG_NOSIGNAL); @@ -53,7 +55,7 @@ SocketWriter::message(const Message& message) size_t SocketWriter::text_sink(const void* buf, size_t len) { - ssize_t ret = send(_socket->fd(), buf, len, MSG_NOSIGNAL); + const ssize_t ret = send(_socket->fd(), buf, len, MSG_NOSIGNAL); if (ret < 0) { return 0; } diff --git a/src/Store.cpp b/src/Store.cpp index 2373e871..ab8425cb 100644 --- a/src/Store.cpp +++ b/src/Store.cpp @@ -14,14 +14,15 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "ingen/Store.hpp" +#include <ingen/Store.hpp> -#include "ingen/Node.hpp" -#include "raul/Path.hpp" -#include "raul/Symbol.hpp" +#include <ingen/Node.hpp> +#include <raul/Path.hpp> +#include <raul/Symbol.hpp> #include <cassert> #include <cstdint> +#include <memory> #include <sstream> #include <string> @@ -34,7 +35,7 @@ Store::add(Node* o) return; } - emplace(o->path(), SPtr<Node>(o)); + emplace(o->path(), std::shared_ptr<Node>(o)); for (uint32_t i = 0; i < o->num_ports(); ++i) { add(o->port(i)); @@ -66,7 +67,7 @@ Store::find_descendants_end(const iterator parent) Store::const_iterator Store::find_descendants_end(const const_iterator parent) const { - const_iterator descendants_end = parent; + auto descendants_end = parent; ++descendants_end; while (descendants_end != end() && descendants_end->first.is_child_of(parent->first)) { @@ -77,11 +78,11 @@ Store::find_descendants_end(const const_iterator parent) const } Store::const_range -Store::children_range(const SPtr<const Node>& o) const +Store::children_range(const std::shared_ptr<const Node>& o) const { - const const_iterator parent = find(o->path()); + const auto parent = find(o->path()); if (parent != end()) { - const_iterator first_child = parent; + auto first_child = parent; ++first_child; return std::make_pair(first_child, find_descendants_end(parent)); } @@ -92,37 +93,37 @@ void Store::remove(const iterator top, Objects& removed) { if (top != end()) { - const iterator descendants_end = find_descendants_end(top); + const auto descendants_end = find_descendants_end(top); removed.insert(top, descendants_end); erase(top, descendants_end); } } void -Store::rename(const iterator top, const Raul::Path& new_path) +Store::rename(const iterator top, const raul::Path& new_path) { - const Raul::Path old_path = top->first; + const raul::Path old_path = top->first; // Remove the object and all its descendants Objects removed; remove(top, removed); // Rename all the removed objects - for (Objects::const_iterator i = removed.begin(); i != removed.end(); ++i) { - const Raul::Path path = (i->first == old_path) + for (const auto& r : removed) { + const auto path = (r.first == old_path) ? new_path : new_path.child( - Raul::Path(i->first.substr(old_path.base().length() - 1))); + raul::Path(r.first.substr(old_path.base().length() - 1))); - i->second->set_path(path); - assert(find(path) == end()); // Shouldn't be dropping objects! - emplace(path, i->second); + r.second->set_path(path); + assert(find(path) == end()); // Shouldn't be dropping objects! + emplace(path, r.second); } } unsigned -Store::child_name_offset(const Raul::Path& parent, - const Raul::Symbol& symbol, +Store::child_name_offset(const raul::Path& parent, + const raul::Symbol& symbol, bool allow_zero) const { unsigned offset = 0; @@ -133,14 +134,13 @@ Store::child_name_offset(const Raul::Path& parent, if (offset > 0) { ss << "_" << offset; } - if (find(parent.child(Raul::Symbol(ss.str()))) == end() && + + if (find(parent.child(raul::Symbol(ss.str()))) == end() && (allow_zero || offset > 0)) { break; - } else if (offset == 0) { - offset = 2; - } else { - ++offset; } + + offset = (offset == 0) ? 2 : (offset + 1); } return offset; diff --git a/src/StreamWriter.cpp b/src/StreamWriter.cpp index d8a93a0b..c40389e4 100644 --- a/src/StreamWriter.cpp +++ b/src/StreamWriter.cpp @@ -14,10 +14,11 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "ingen/StreamWriter.hpp" +#include <ingen/StreamWriter.hpp> -#include "ingen/ColorContext.hpp" -#include "ingen/URI.hpp" +#include <ingen/ColorContext.hpp> +#include <ingen/TurtleWriter.hpp> +#include <ingen/URI.hpp> namespace ingen { @@ -34,7 +35,7 @@ StreamWriter::StreamWriter(URIMap& map, size_t StreamWriter::text_sink(const void* buf, size_t len) { - ColorContext ctx(_stream, _color); + const ColorContext ctx{_stream, _color}; return fwrite(buf, 1, len, _stream); } diff --git a/src/TurtleWriter.cpp b/src/TurtleWriter.cpp index 1deb2e13..e19c14e2 100644 --- a/src/TurtleWriter.cpp +++ b/src/TurtleWriter.cpp @@ -14,12 +14,19 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "ingen/TurtleWriter.hpp" +#include <ingen/TurtleWriter.hpp> -#include "ingen/URIMap.hpp" -#include "lv2/atom/atom.h" +#include <ingen/AtomWriter.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIMap.hpp> +#include <ingen/ingen.h> +#include <lv2/atom/atom.h> +#include <serd/serd.h> +#include <sratom/sratom.h> -#define USTR(s) ((const uint8_t*)(s)) +#include <utility> + +#define USTR(s) reinterpret_cast<const uint8_t*>(s) namespace ingen { @@ -33,25 +40,23 @@ c_text_sink(const void* buf, size_t len, void* stream) static SerdStatus write_prefix(void* handle, const SerdNode* name, const SerdNode* uri) { - serd_writer_set_prefix((SerdWriter*)handle, name, uri); + serd_writer_set_prefix(static_cast<SerdWriter*>(handle), name, uri); return SERD_SUCCESS; } TurtleWriter::TurtleWriter(URIMap& map, URIs& uris, URI uri) - : AtomWriter(map, uris, *this) - , _map(map) - , _sratom(sratom_new(&map.urid_map_feature()->urid_map)) - , _base(SERD_NODE_NULL) - , _base_uri(SERD_URI_NULL) - , _uri(std::move(uri)) - , _wrote_prefixes(false) + : AtomWriter{map, uris, *this} + , _map{map} + , _sratom{sratom_new(&map.urid_map())} + , _base{serd_node_from_string(SERD_URI, USTR("ingen:/"))} + , _env{serd_env_new(&_base)} + , _uri{std::move(uri)} { // Use <ingen:/> as base URI, so relative URIs are like bundle paths - _base = serd_node_from_string(SERD_URI, (const uint8_t*)"ingen:/"); - serd_uri_parse(_base.buf, &_base_uri); + + serd_uri_parse(USTR("ingen:/"), &_base_uri); // Set up serialisation environment - _env = serd_env_new(&_base); serd_env_set_prefix_from_strings(_env, USTR("atom"), USTR("http://lv2plug.in/ns/ext/atom#")); serd_env_set_prefix_from_strings(_env, USTR("doap"), USTR("http://usefulinc.com/ns/doap#")); serd_env_set_prefix_from_strings(_env, USTR("ingen"), USTR(INGEN_NS)); @@ -64,9 +69,10 @@ TurtleWriter::TurtleWriter(URIMap& map, URIs& uris, URI uri) serd_env_set_prefix_from_strings(_env, USTR("xsd"), USTR("http://www.w3.org/2001/XMLSchema#")); // Make a Turtle writer that writes to text_sink + // NOLINTNEXTLINE(cppcoreguidelines-prefer-member-initializer) _writer = serd_writer_new( SERD_TURTLE, - (SerdStyle)(SERD_STYLE_RESOLVED|SERD_STYLE_ABBREVIATED|SERD_STYLE_CURIED), + static_cast<SerdStyle>(SERD_STYLE_RESOLVED|SERD_STYLE_ABBREVIATED|SERD_STYLE_CURIED), _env, &_base_uri, c_text_sink, @@ -74,9 +80,9 @@ TurtleWriter::TurtleWriter(URIMap& map, URIs& uris, URI uri) // Configure sratom to write directly to the writer (and thus text_sink) sratom_set_sink(_sratom, - (const char*)_base.buf, - (SerdStatementSink)serd_writer_write_statement, - (SerdEndSink)serd_writer_end_anon, + reinterpret_cast<const char*>(_base.buf), + reinterpret_cast<SerdStatementSink>(serd_writer_write_statement), + reinterpret_cast<SerdEndSink>(serd_writer_end_anon), _writer); } @@ -96,7 +102,7 @@ TurtleWriter::write(const LV2_Atom* msg, int32_t) _wrote_prefixes = true; } - sratom_write(_sratom, &_map.urid_unmap_feature()->urid_unmap, 0, + sratom_write(_sratom, &_map.urid_unmap(), 0, nullptr, nullptr, msg->type, msg->size, LV2_ATOM_BODY_CONST(msg)); serd_writer_finish(_writer); return true; diff --git a/src/URI.cpp b/src/URI.cpp index f7b64209..3161b7d2 100644 --- a/src/URI.cpp +++ b/src/URI.cpp @@ -14,69 +14,72 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "ingen/URI.hpp" +#include <ingen/URI.hpp> -#include "ingen/FilePath.hpp" +#include <ingen/FilePath.hpp> +#include <serd/serd.h> +#include <sord/sordmm.hpp> #include <cassert> namespace ingen { -URI::URI() - : _uri(SERD_URI_NULL) - , _node(SERD_NODE_NULL) -{} +URI::URI() : _uri(SERD_URI_NULL), _node(SERD_NODE_NULL) {} URI::URI(const std::string& str) - : _uri(SERD_URI_NULL) - , _node(serd_node_new_uri_from_string((const uint8_t*)str.c_str(), + : _uri(SERD_URI_NULL) + , _node(serd_node_new_uri_from_string(reinterpret_cast<const uint8_t*>( + str.c_str()), nullptr, &_uri)) -{} +{ +} URI::URI(const char* str) - : _uri(SERD_URI_NULL) - , _node(serd_node_new_uri_from_string((const uint8_t*)str, nullptr, &_uri)) -{} + : _uri(SERD_URI_NULL) + , _node(serd_node_new_uri_from_string(reinterpret_cast<const uint8_t*>(str), + nullptr, + &_uri)) +{ +} URI::URI(const std::string& str, const URI& base) - : _uri(SERD_URI_NULL) - , _node(serd_node_new_uri_from_string((const uint8_t*)str.c_str(), + : _uri(SERD_URI_NULL) + , _node(serd_node_new_uri_from_string(reinterpret_cast<const uint8_t*>( + str.c_str()), &base._uri, &_uri)) -{} - -URI::URI(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) + : _uri(SERD_URI_NULL) + , _node(serd_node_new_uri_from_node(&node, nullptr, &_uri)) { assert(node.type == SERD_URI); } -URI::URI(const Sord::Node& node) - : URI(*node.to_serd_node()) +URI::URI(const SerdNode& node, const SerdURI& uri) : _uri(uri), _node(node) { + assert(node.type == SERD_URI); } +URI::URI(const Sord::Node& node) : URI(*node.to_serd_node()) {} + URI::URI(const FilePath& path) - : _uri(SERD_URI_NULL) - , _node(serd_node_new_file_uri((const uint8_t*)path.c_str(), - nullptr, - &_uri, - true)) -{} + : _uri(SERD_URI_NULL) + , _node( + serd_node_new_file_uri(reinterpret_cast<const uint8_t*>(path.c_str()), + nullptr, + &_uri, + true)) +{ +} URI::URI(const URI& uri) - : _uri(SERD_URI_NULL) - , _node(serd_node_new_uri(&uri._uri, nullptr, &_uri)) -{} + : _uri(SERD_URI_NULL), _node(serd_node_new_uri(&uri._uri, nullptr, &_uri)) +{ +} URI& URI::operator=(const URI& uri) @@ -89,9 +92,7 @@ URI::operator=(const URI& uri) return *this; } -URI::URI(URI&& uri) noexcept - : _uri(uri._uri) - , _node(uri._node) +URI::URI(URI&& uri) noexcept : _uri(uri._uri), _node(uri._node) { uri._node = SERD_NODE_NULL; uri._uri = SERD_URI_NULL; @@ -100,6 +101,8 @@ URI::URI(URI&& uri) noexcept URI& URI::operator=(URI&& uri) noexcept { + serd_node_free(&_node); + _node = uri._node; _uri = uri._uri; uri._node = SERD_NODE_NULL; @@ -115,9 +118,21 @@ URI::~URI() URI URI::make_relative(const URI& base) const { - SerdURI uri; - SerdNode node = serd_node_new_relative_uri(&_uri, &base._uri, nullptr, &uri); - return URI(node, uri); + SerdURI uri; + const SerdNode node = + serd_node_new_relative_uri(&_uri, &base._uri, nullptr, &uri); + + return {node, uri}; +} + +URI +URI::make_relative(const URI& base, const URI& root) const +{ + SerdURI uri; + const SerdNode node = + serd_node_new_relative_uri(&_uri, &base._uri, &root._uri, &uri); + + return {node, uri}; } -} // namespace ingen +} // namespace ingen diff --git a/src/URIMap.cpp b/src/URIMap.cpp index 0d43deed..25764762 100644 --- a/src/URIMap.cpp +++ b/src/URIMap.cpp @@ -14,11 +14,11 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "ingen/URIMap.hpp" +#include <ingen/URIMap.hpp> -#include "ingen/Log.hpp" -#include "ingen/URI.hpp" -#include "lv2/urid/urid.h" +#include <ingen/Log.hpp> +#include <ingen/URI.hpp> +#include <lv2/urid/urid.h> #include <cassert> #include <cstdint> @@ -29,21 +29,20 @@ namespace ingen { URIMap::URIMap(Log& log, LV2_URID_Map* map, LV2_URID_Unmap* unmap) : _urid_map_feature(new URIDMapFeature(this, map, log)) , _urid_unmap_feature(new URIDUnmapFeature(this, unmap)) -{ -} +{} URIMap::URIDMapFeature::URIDMapFeature(URIMap* map, LV2_URID_Map* impl, Log& log) - : Feature(LV2_URID__map, &urid_map) - , urid_map() - , log(log) + : Feature(LV2_URID__map, &_urid_map) + , _urid_map() + , _log(log) { if (impl) { - urid_map = *impl; + _urid_map = *impl; } else { - urid_map.map = default_map; - urid_map.handle = map; + _urid_map.map = default_map; + _urid_map.handle = map; } } @@ -51,9 +50,9 @@ LV2_URID URIMap::URIDMapFeature::default_map(LV2_URID_Map_Handle h, const char* c_uri) { - auto* const map((URIMap*)h); - std::string uri(c_uri); - std::lock_guard<std::mutex> lock(map->_mutex); + auto* const map{static_cast<URIMap*>(h)}; + std::string uri{c_uri}; + const std::lock_guard<std::mutex> lock{map->_mutex}; auto record = map->_map.emplace(uri, map->_map.size() + 1); const auto id = record.first->second; @@ -69,22 +68,23 @@ LV2_URID URIMap::URIDMapFeature::map(const char* uri) { if (!URI::is_valid(uri)) { - log.error("Attempt to map invalid URI <%1%>\n", uri); + _log.error("Attempt to map invalid URI <%1%>\n", uri); return 0; } - return urid_map.map(urid_map.handle, uri); + + return _urid_map.map(_urid_map.handle, uri); } URIMap::URIDUnmapFeature::URIDUnmapFeature(URIMap* map, LV2_URID_Unmap* impl) - : Feature(LV2_URID__unmap, &urid_unmap) - , urid_unmap() + : Feature(LV2_URID__unmap, &_urid_unmap) + , _urid_unmap() { if (impl) { - urid_unmap = *impl; + _urid_unmap = *impl; } else { - urid_unmap.unmap = default_unmap; - urid_unmap.handle = map; + _urid_unmap.unmap = default_unmap; + _urid_unmap.handle = map; } } @@ -92,8 +92,8 @@ const char* URIMap::URIDUnmapFeature::default_unmap(LV2_URID_Unmap_Handle h, LV2_URID urid) { - auto* const map((URIMap*)h); - std::lock_guard<std::mutex> lock(map->_mutex); + auto* const map{static_cast<URIMap*>(h)}; + const std::lock_guard<std::mutex> lock{map->_mutex}; return (urid > 0 && urid <= map->_unmap.size() ? map->_unmap[urid - 1].c_str() @@ -101,9 +101,9 @@ URIMap::URIDUnmapFeature::default_unmap(LV2_URID_Unmap_Handle h, } const char* -URIMap::URIDUnmapFeature::unmap(LV2_URID urid) +URIMap::URIDUnmapFeature::unmap(LV2_URID urid) const { - return urid_unmap.unmap(urid_unmap.handle, urid); + return _urid_unmap.unmap(_urid_unmap.handle, urid); } uint32_t diff --git a/src/URIs.cpp b/src/URIs.cpp index dfe6b867..49eb1707 100644 --- a/src/URIs.cpp +++ b/src/URIs.cpp @@ -14,55 +14,57 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "ingen/URIs.hpp" +#include <ingen/URIs.hpp> -#include "ingen/Forge.hpp" -#include "ingen/ingen.h" -#include "lv2/atom/atom.h" -#include "lv2/buf-size/buf-size.h" -#include "lv2/core/lv2.h" -#include "lv2/log/log.h" -#include "lv2/midi/midi.h" -#include "lv2/morph/morph.h" -#include "lv2/options/options.h" -#include "lv2/parameters/parameters.h" -#include "lv2/patch/patch.h" -#include "lv2/port-props/port-props.h" -#include "lv2/presets/presets.h" -#include "lv2/resize-port/resize-port.h" -#include "lv2/state/state.h" -#include "lv2/time/time.h" -#include "lv2/worker/worker.h" +#include <ingen/Forge.hpp> +#include <ingen/URI.hpp> +#include <ingen/ingen.h> +#include <lilv/lilv.h> +#include <lv2/atom/atom.h> +#include <lv2/buf-size/buf-size.h> +#include <lv2/core/lv2.h> +#include <lv2/log/log.h> +#include <lv2/midi/midi.h> +#include <lv2/morph/morph.h> +#include <lv2/options/options.h> +#include <lv2/parameters/parameters.h> +#include <lv2/patch/patch.h> +#include <lv2/port-props/port-props.h> +#include <lv2/presets/presets.h> +#include <lv2/resize-port/resize-port.h> +#include <lv2/state/state.h> +#include <lv2/time/time.h> +#include <lv2/worker/worker.h> namespace ingen { -URIs::Quark::Quark(Forge& forge, +URIs::Quark::Quark(Forge& ingen_forge, URIMap*, LilvWorld* lworld, const char* str) : URI(str) - , urid(forge.make_urid(URI(str))) - , uri(forge.alloc_uri(str)) - , lnode(lilv_new_uri(lworld, str)) + , _urid_atom(ingen_forge.make_urid(URI(str))) + , _uri_atom(ingen_forge.alloc_uri(str)) + , _lilv_node(lilv_new_uri(lworld, str)) {} URIs::Quark::Quark(const Quark& copy) : URI(copy) - , urid(copy.urid) - , uri(copy.uri) - , lnode(lilv_node_duplicate(copy.lnode)) + , _urid_atom(copy._urid_atom) + , _uri_atom(copy._uri_atom) + , _lilv_node(lilv_node_duplicate(copy._lilv_node)) {} URIs::Quark::~Quark() { - lilv_node_free(lnode); + lilv_node_free(_lilv_node); } #define NS_RDF "http://www.w3.org/1999/02/22-rdf-syntax-ns#" #define NS_RDFS "http://www.w3.org/2000/01/rdf-schema#" -URIs::URIs(Forge& forge, URIMap* map, LilvWorld* lworld) - : forge(forge) +URIs::URIs(Forge& ingen_forge, URIMap* map, LilvWorld* lworld) + : forge(ingen_forge) , atom_AtomPort (forge, map, lworld, LV2_ATOM__AtomPort) , atom_Bool (forge, map, lworld, LV2_ATOM__Bool) , atom_Chunk (forge, map, lworld, LV2_ATOM__Chunk) @@ -155,6 +157,7 @@ URIs::URIs(Forge& forge, URIMap* map, LilvWorld* lworld) , midi_binding (forge, map, lworld, LV2_MIDI__binding) , midi_controllerNumber (forge, map, lworld, LV2_MIDI__controllerNumber) , midi_noteNumber (forge, map, lworld, LV2_MIDI__noteNumber) + , midi_channel (forge, map, lworld, LV2_MIDI__channel) , morph_AutoMorphPort (forge, map, lworld, LV2_MORPH__AutoMorphPort) , morph_MorphPort (forge, map, lworld, LV2_MORPH__MorphPort) , morph_currentType (forge, map, lworld, LV2_MORPH__currentType) diff --git a/src/World.cpp b/src/World.cpp index 41e69826..7e643002 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -14,36 +14,35 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "ingen/World.hpp" - -#include "ingen/Atom.hpp" -#include "ingen/Configuration.hpp" -#include "ingen/DataAccess.hpp" -#include "ingen/EngineBase.hpp" -#include "ingen/FilePath.hpp" -#include "ingen/Forge.hpp" -#include "ingen/InstanceAccess.hpp" -#include "ingen/LV2Features.hpp" -#include "ingen/Library.hpp" -#include "ingen/Log.hpp" -#include "ingen/Module.hpp" -#include "ingen/Parser.hpp" -#include "ingen/Serialiser.hpp" -#include "ingen/URI.hpp" -#include "ingen/URIMap.hpp" -#include "ingen/URIs.hpp" -#include "ingen/ingen.h" -#include "ingen/runtime_paths.hpp" -#include "lilv/lilv.h" -#include "lv2/log/log.h" -#include "lv2/urid/urid.h" -#include "sord/sordmm.hpp" +#include <ingen/World.hpp> + +#include <ingen/Atom.hpp> +#include <ingen/Configuration.hpp> +#include <ingen/DataAccess.hpp> +#include <ingen/EngineBase.hpp> +#include <ingen/Forge.hpp> +#include <ingen/InstanceAccess.hpp> +#include <ingen/LV2Features.hpp> +#include <ingen/Library.hpp> +#include <ingen/Log.hpp> +#include <ingen/Module.hpp> +#include <ingen/Parser.hpp> +#include <ingen/Serialiser.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIMap.hpp> +#include <ingen/URIs.hpp> +#include <ingen/ingen.h> +#include <ingen/runtime_paths.hpp> +#include <lilv/lilv.h> +#include <lv2/log/log.h> +#include <lv2/urid/urid.h> +#include <sord/sordmm.hpp> #include <cstdint> +#include <filesystem> #include <list> #include <map> #include <memory> -#include <sstream> #include <string> #include <utility> @@ -68,38 +67,38 @@ ingen_load_library(Log& log, const string& name) const auto path = ingen_module_path(name); if (path.empty()) { log.error("Failed to find %1% (%2%)\n", - name, Library::get_last_error()); + name, + Library::get_last_error()); return nullptr; } - UPtr<Library> library = make_unique<Library>(path); + log.info("Loading module %1%\n", path); + + std::unique_ptr<Library> library = std::make_unique<Library>(path); if (*library) { return library; } log.error("Unable to load %1% from %2% (%3%)\n", - name, path, Library::get_last_error()); + name, + path, + Library::get_last_error()); return nullptr; } -class World::Impl { +class World::Impl +{ public: - Impl(LV2_URID_Map* map, - LV2_URID_Unmap* unmap, - LV2_Log_Log* lv2_log) - : argc(nullptr) - , argv(nullptr) - , lv2_features(nullptr) - , rdf_world(new Sord::World()) - , lilv_world(lilv_world_new(), lilv_world_free) - , uri_map(log, map, unmap) - , forge(uri_map) - , uris(forge, &uri_map, lilv_world.get()) - , lv2_log() - , conf(forge) - , log(lv2_log, uris) + Impl(LV2_URID_Map* map, LV2_URID_Unmap* unmap, LV2_Log_Log* log_feature) + : lv2_features(new LV2Features()) + , rdf_world(new Sord::World()) + , lilv_world(lilv_world_new(), lilv_world_free) + , uri_map(log, map, unmap) + , forge(uri_map) + , uris(forge, &uri_map, lilv_world.get()) + , conf(forge) + , log(log_feature, uris) { - lv2_features = new LV2Features(); lv2_features->add_feature(uri_map.urid_map_feature()); lv2_features->add_feature(uri_map.urid_unmap_feature()); lv2_features->add_feature(std::make_shared<InstanceAccess>()); @@ -108,25 +107,28 @@ public: lilv_world_load_all(lilv_world.get()); // Set up RDF namespaces - rdf_world->add_prefix("atom", "http://lv2plug.in/ns/ext/atom#"); - rdf_world->add_prefix("doap", "http://usefulinc.com/ns/doap#"); + rdf_world->add_prefix("atom", "http://lv2plug.in/ns/ext/atom#"); + rdf_world->add_prefix("doap", "http://usefulinc.com/ns/doap#"); rdf_world->add_prefix("ingen", INGEN_NS); - rdf_world->add_prefix("lv2", "http://lv2plug.in/ns/lv2core#"); - rdf_world->add_prefix("midi", "http://lv2plug.in/ns/ext/midi#"); - rdf_world->add_prefix("owl", "http://www.w3.org/2002/07/owl#"); + rdf_world->add_prefix("lv2", "http://lv2plug.in/ns/lv2core#"); + rdf_world->add_prefix("midi", "http://lv2plug.in/ns/ext/midi#"); + rdf_world->add_prefix("owl", "http://www.w3.org/2002/07/owl#"); rdf_world->add_prefix("patch", "http://lv2plug.in/ns/ext/patch#"); - rdf_world->add_prefix("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#"); - rdf_world->add_prefix("rdfs", "http://www.w3.org/2000/01/rdf-schema#"); - rdf_world->add_prefix("xsd", "http://www.w3.org/2001/XMLSchema#"); + rdf_world->add_prefix("rdf", + "http://www.w3.org/1999/02/22-rdf-syntax-ns#"); + rdf_world->add_prefix("rdfs", "http://www.w3.org/2000/01/rdf-schema#"); + rdf_world->add_prefix("xsd", "http://www.w3.org/2001/XMLSchema#"); // Load internal 'plugin' information into lilv world - LilvNode* rdf_type = lilv_new_uri( - lilv_world.get(), "http://www.w3.org/1999/02/22-rdf-syntax-ns#type"); - LilvNode* ingen_Plugin = lilv_new_uri( - lilv_world.get(), INGEN__Plugin); - LilvNodes* internals = lilv_world_find_nodes( - lilv_world.get(), nullptr, rdf_type, ingen_Plugin); - LILV_FOREACH(nodes, i, internals) { + LilvNode* rdf_type = + lilv_new_uri(lilv_world.get(), + "http://www.w3.org/1999/02/22-rdf-syntax-ns#type"); + LilvNode* ingen_Plugin = lilv_new_uri(lilv_world.get(), INGEN__Plugin); + LilvNodes* internals = lilv_world_find_nodes(lilv_world.get(), + nullptr, + rdf_type, + ingen_Plugin); + LILV_FOREACH (nodes, i, internals) { const LilvNode* internal = lilv_nodes_get(internals, i); lilv_world_load_resource(lilv_world.get(), internal); } @@ -164,44 +166,45 @@ public: } Impl(const Impl&) = delete; - Impl(Impl&&) = delete; + Impl(Impl&&) = delete; Impl& operator=(const Impl&) = delete; Impl& operator=(Impl&&) = delete; using Modules = std::map<std::string, Module*>; Modules modules; - using InterfaceFactories = std::map<const std::string, World::InterfaceFactory>; + using InterfaceFactories = + std::map<const std::string, World::InterfaceFactory>; InterfaceFactories interface_factories; using ScriptRunner = bool (*)(World& world, const char* filename); using ScriptRunners = std::map<const std::string, ScriptRunner>; ScriptRunners script_runners; - using LilvWorldUPtr = std::unique_ptr<LilvWorld, decltype(&lilv_world_free)>; - - int* argc; - char*** argv; - LV2Features* lv2_features; - UPtr<Sord::World> rdf_world; - LilvWorldUPtr lilv_world; - URIMap uri_map; - Forge forge; - URIs uris; - LV2_Log_Log* lv2_log; - Configuration conf; - Log log; - SPtr<Interface> interface; - SPtr<EngineBase> engine; - SPtr<Serialiser> serialiser; - SPtr<Parser> parser; - SPtr<Store> store; - std::mutex rdf_mutex; - std::string jack_uuid; + using LilvWorldUPtr = + std::unique_ptr<LilvWorld, decltype(&lilv_world_free)>; + + int* argc{nullptr}; + char*** argv{nullptr}; + LV2Features* lv2_features; + std::unique_ptr<Sord::World> rdf_world; + LilvWorldUPtr lilv_world; + URIMap uri_map; + Forge forge; + URIs uris; + Configuration conf; + Log log; + std::shared_ptr<Interface> interface; + std::shared_ptr<EngineBase> engine; + std::shared_ptr<Serialiser> serialiser; + std::shared_ptr<Parser> parser; + std::shared_ptr<Store> store; + std::mutex rdf_mutex; + std::string jack_uuid; }; World::World(LV2_URID_Map* map, LV2_URID_Unmap* unmap, LV2_Log_Log* log) - : _impl(new Impl(map, unmap, log)) + : _impl(new Impl(map, unmap, log)) { _impl->serialiser = std::make_shared<Serialiser>(*this); _impl->parser = std::make_shared<Parser>(); @@ -230,30 +233,108 @@ World::load_configuration(int& argc, char**& argv) _impl->log.set_trace(_impl->conf.option("trace").get<int32_t>()); } -void World::set_engine(const SPtr<EngineBase>& e) { _impl->engine = e; } -void World::set_interface(const SPtr<Interface>& i) { _impl->interface = i; } -void World::set_store(const SPtr<Store>& s) { _impl->store = s; } +void +World::set_engine(const std::shared_ptr<EngineBase>& e) +{ + _impl->engine = e; +} -SPtr<EngineBase> World::engine() { return _impl->engine; } -SPtr<Interface> World::interface() { return _impl->interface; } -SPtr<Parser> World::parser() { return _impl->parser; } -SPtr<Serialiser> World::serialiser() { return _impl->serialiser; } -SPtr<Store> World::store() { return _impl->store; } +void +World::set_interface(const std::shared_ptr<Interface>& i) +{ + _impl->interface = i; +} -int& World::argc() { return *_impl->argc; } -char**& World::argv() { return *_impl->argv; } -Configuration& World::conf() { return _impl->conf; } -Log& World::log() { return _impl->log; } +void +World::set_store(const std::shared_ptr<Store>& s) +{ + _impl->store = s; +} -std::mutex& World::rdf_mutex() { return _impl->rdf_mutex; } +std::shared_ptr<EngineBase> +World::engine() +{ + return _impl->engine; +} +std::shared_ptr<Interface> +World::interface() +{ + return _impl->interface; +} +std::shared_ptr<Parser> +World::parser() +{ + return _impl->parser; +} +std::shared_ptr<Serialiser> +World::serialiser() +{ + return _impl->serialiser; +} +std::shared_ptr<Store> +World::store() +{ + return _impl->store; +} -Sord::World* World::rdf_world() { return _impl->rdf_world.get(); } -LilvWorld* World::lilv_world() { return _impl->lilv_world.get(); } +int& +World::argc() +{ + return *_impl->argc; +} +char**& +World::argv() +{ + return *_impl->argv; +} +Configuration& +World::conf() +{ + return _impl->conf; +} +Log& +World::log() +{ + return _impl->log; +} + +std::mutex& +World::rdf_mutex() +{ + return _impl->rdf_mutex; +} + +Sord::World* +World::rdf_world() +{ + return _impl->rdf_world.get(); +} +LilvWorld* +World::lilv_world() +{ + return _impl->lilv_world.get(); +} -LV2Features& World::lv2_features() { return *_impl->lv2_features; } -Forge& World::forge() { return _impl->forge; } -URIs& World::uris() { return _impl->uris; } -URIMap& World::uri_map() { return _impl->uri_map; } +LV2Features& +World::lv2_features() +{ + return *_impl->lv2_features; +} +Forge& +World::forge() +{ + return _impl->forge; +} +URIs& +World::uris() +{ + return _impl->uris; +} +URIMap& +World::uri_map() +{ + return _impl->uri_map; +} bool World::load_module(const char* name) @@ -262,11 +343,14 @@ World::load_module(const char* name) if (i != _impl->modules.end()) { return true; } - log().info("Loading %1% module\n", name); + std::unique_ptr<ingen::Library> lib = ingen_load_library(log(), name); + ingen::Module* (*module_load)() = - lib ? (ingen::Module* (*)())lib->get_function("ingen_module_load") - : nullptr; + lib ? reinterpret_cast<ingen::Module* (*)()>( + lib->get_function("ingen_module_load")) + : nullptr; + if (module_load) { Module* module = module_load(); if (module) { @@ -278,7 +362,8 @@ World::load_module(const char* name) } log().error("Failed to load module `%1%' (%2%)\n", - name, lib->get_last_error()); + name, + lib->get_last_error()); return false; } @@ -297,14 +382,15 @@ World::run_module(const char* name) /** Get an interface for a remote engine at `engine_uri` */ -SPtr<Interface> -World::new_interface(const URI& engine_uri, const SPtr<Interface>& respondee) +std::shared_ptr<Interface> +World::new_interface(const URI& engine_uri, + const std::shared_ptr<Interface>& respondee) { - const Impl::InterfaceFactories::const_iterator i = - _impl->interface_factories.find(std::string(engine_uri.scheme())); + const auto i = + _impl->interface_factories.find(std::string{engine_uri.scheme()}); if (i == _impl->interface_factories.end()) { log().warn("Unknown URI scheme `%1%'\n", engine_uri.scheme()); - return SPtr<Interface>(); + return nullptr; } return i->second(*this, engine_uri, respondee); @@ -314,7 +400,7 @@ World::new_interface(const URI& engine_uri, const SPtr<Interface>& respondee) bool World::run(const std::string& mime_type, const std::string& filename) { - const Impl::ScriptRunners::const_iterator i = _impl->script_runners.find(mime_type); + const auto i = _impl->script_runners.find(mime_type); if (i == _impl->script_runners.end()) { log().warn("Unknown script MIME type `%1%'\n", mime_type); return false; @@ -324,7 +410,8 @@ World::run(const std::string& mime_type, const std::string& filename) } void -World::add_interface_factory(const std::string& scheme, InterfaceFactory factory) +World::add_interface_factory(const std::string& scheme, + InterfaceFactory factory) { _impl->interface_factories.emplace(scheme, factory); } diff --git a/src/client/.clang-tidy b/src/client/.clang-tidy new file mode 100644 index 00000000..2561514f --- /dev/null +++ b/src/client/.clang-tidy @@ -0,0 +1,3 @@ +Checks: > + -google-readability-todo, +InheritParentConfig: true diff --git a/src/client/BlockModel.cpp b/src/client/BlockModel.cpp index f9eaa26e..beef0117 100644 --- a/src/client/BlockModel.cpp +++ b/src/client/BlockModel.cpp @@ -14,50 +14,58 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "ingen/client/BlockModel.hpp" - -#include "ingen/URIs.hpp" -#include "ingen/World.hpp" -#include "ingen/client/PortModel.hpp" - +#include <ingen/client/BlockModel.hpp> + +#include <ingen/Atom.hpp> +#include <ingen/Forge.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIs.hpp> +#include <ingen/client/ObjectModel.hpp> +#include <ingen/client/PluginModel.hpp> +#include <ingen/client/PortModel.hpp> +#include <lilv/lilv.h> +#include <lv2/core/lv2.h> +#include <raul/Path.hpp> +#include <raul/Symbol.hpp> + +#include <sigc++/signal.h> + +#include <algorithm> #include <cassert> #include <cmath> #include <cstdlib> #include <cstring> +#include <memory> #include <string> - -namespace ingen { -namespace client { - -BlockModel::BlockModel(URIs& uris, - const SPtr<PluginModel>& plugin, - const Raul::Path& path) - : ObjectModel(uris, path) - , _plugin_uri(plugin->uri()) - , _plugin(plugin) - , _num_values(0) - , _min_values(nullptr) - , _max_values(nullptr) -{ -} - -BlockModel::BlockModel(URIs& uris, - const URI& plugin_uri, - const Raul::Path& path) - : ObjectModel(uris, path) - , _plugin_uri(plugin_uri) - , _num_values(0) - , _min_values(nullptr) - , _max_values(nullptr) -{ -} +#include <utility> + +namespace ingen::client { + +BlockModel::BlockModel(URIs& uris, + const std::shared_ptr<PluginModel>& plugin, + const raul::Path& path) + : ObjectModel(uris, path) + , _plugin_uri(plugin->uri()) + , _plugin(plugin) + , _num_values(0) + , _min_values(nullptr) + , _max_values(nullptr) +{} + +BlockModel::BlockModel(URIs& uris, URI plugin_uri, const raul::Path& path) + : ObjectModel(uris, path) + , _plugin_uri(std::move(plugin_uri)) + , _num_values(0) + , _min_values(nullptr) + , _max_values(nullptr) +{} BlockModel::BlockModel(const BlockModel& copy) : ObjectModel(copy) , _plugin_uri(copy._plugin_uri) , _num_values(copy._num_values) - , _min_values((float*)malloc(sizeof(float) * _num_values)) - , _max_values((float*)malloc(sizeof(float) * _num_values)) + , _min_values(static_cast<float*>(malloc(sizeof(float) * _num_values))) + , _max_values(static_cast<float*>(malloc(sizeof(float) * _num_values))) { memcpy(_min_values, copy._min_values, sizeof(float) * _num_values); memcpy(_max_values, copy._max_values, sizeof(float) * _num_values); @@ -69,25 +77,28 @@ BlockModel::~BlockModel() } void -BlockModel::remove_port(const SPtr<PortModel>& port) +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) +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); } } @@ -103,26 +114,26 @@ BlockModel::clear() } void -BlockModel::add_child(const SPtr<ObjectModel>& c) +BlockModel::add_child(const std::shared_ptr<ObjectModel>& c) { assert(c->parent().get() == this); //ObjectModel::add_child(c); - SPtr<PortModel> pm = dynamic_ptr_cast<PortModel>(c); + auto pm = std::dynamic_pointer_cast<PortModel>(c); assert(pm); add_port(pm); } bool -BlockModel::remove_child(const SPtr<ObjectModel>& c) +BlockModel::remove_child(const std::shared_ptr<ObjectModel>& c) { assert(c->path().is_child_of(path())); assert(c->parent().get() == this); //bool ret = ObjectModel::remove_child(c); - SPtr<PortModel> pm = dynamic_ptr_cast<PortModel>(c); + auto pm = std::dynamic_pointer_cast<PortModel>(c); assert(pm); remove_port(pm); @@ -131,7 +142,7 @@ BlockModel::remove_child(const SPtr<ObjectModel>& c) } void -BlockModel::add_port(const SPtr<PortModel>& pm) +BlockModel::add_port(const std::shared_ptr<PortModel>& pm) { assert(pm); assert(pm->path().is_child_of(path())); @@ -144,18 +155,18 @@ BlockModel::add_port(const SPtr<PortModel>& pm) _signal_new_port.emit(pm); } -SPtr<const PortModel> -BlockModel::get_port(const Raul::Symbol& symbol) const +std::shared_ptr<const PortModel> +BlockModel::get_port(const raul::Symbol& symbol) const { for (auto p : _ports) { if (p->symbol() == symbol) { return p; } } - return SPtr<PortModel>(); + return std::shared_ptr<PortModel>(); } -SPtr<const PortModel> +std::shared_ptr<const PortModel> BlockModel::get_port(uint32_t index) const { return _ports[index]; @@ -170,10 +181,11 @@ BlockModel::port(uint32_t index) const } void -BlockModel::default_port_value_range(const SPtr<const PortModel>& port, - float& min, - float& max, - uint32_t srate) const +BlockModel::default_port_value_range( + const std::shared_ptr<const PortModel>& port, + float& min, + float& max, + uint32_t srate) const { // Default control values min = 0.0; @@ -198,22 +210,23 @@ BlockModel::default_port_value_range(const SPtr<const PortModel>& port, } if (port->port_property(_uris.lv2_sampleRate)) { - min *= srate; - max *= srate; + const auto frate = static_cast<float>(srate); + min *= frate; + max *= frate; } } void -BlockModel::port_value_range(const SPtr<const PortModel>& port, - float& min, - float& max, - uint32_t srate) const +BlockModel::port_value_range(const std::shared_ptr<const PortModel>& port, + float& min, + float& max, + uint32_t srate) const { assert(port->parent().get() == this); default_port_value_range(port, min, max); - // Possibly overriden + // Possibly overridden const Atom& min_atom = port->get_property(_uris.lv2_minimum); const Atom& max_atom = port->get_property(_uris.lv2_maximum); if (min_atom.type() == _uris.forge.Float) { @@ -224,12 +237,13 @@ BlockModel::port_value_range(const SPtr<const PortModel>& port, } if (max <= min) { - max = min + 1.0; + max = min + 1.0f; } if (port->port_property(_uris.lv2_sampleRate)) { - min *= srate; - max *= srate; + const auto frate = static_cast<float>(srate); + min *= frate; + max *= frate; } } @@ -239,15 +253,17 @@ BlockModel::label() const const Atom& name_property = get_property(_uris.lv2_name); if (name_property.type() == _uris.forge.String) { return name_property.ptr<char>(); - } else if (plugin_model()) { + } + + if (plugin_model()) { return plugin_model()->human_name(); - } else { - return symbol().c_str(); } + + return symbol().c_str(); } std::string -BlockModel::port_label(const SPtr<const PortModel>& port) const +BlockModel::port_label(const std::shared_ptr<const PortModel>& port) const { const Atom& name = port->get_property(URI(LV2_CORE__name)); if (name.is_valid() && name.type() == _uris.forge.String) { @@ -274,9 +290,9 @@ BlockModel::port_label(const SPtr<const PortModel>& port) const } void -BlockModel::set(const SPtr<ObjectModel>& model) +BlockModel::set(const std::shared_ptr<ObjectModel>& model) { - SPtr<BlockModel> block = dynamic_ptr_cast<BlockModel>(model); + auto block = std::dynamic_pointer_cast<BlockModel>(model); if (block) { _plugin_uri = block->_plugin_uri; _plugin = block->_plugin; @@ -285,5 +301,4 @@ BlockModel::set(const SPtr<ObjectModel>& model) ObjectModel::set(model); } -} // namespace client -} // namespace ingen +} // namespace ingen::client diff --git a/src/client/ClientStore.cpp b/src/client/ClientStore.cpp index a42efd16..9f224db3 100644 --- a/src/client/ClientStore.cpp +++ b/src/client/ClientStore.cpp @@ -14,30 +14,42 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "ingen/client/ClientStore.hpp" - -#include "ingen/Log.hpp" -#include "ingen/client/ArcModel.hpp" -#include "ingen/client/BlockModel.hpp" -#include "ingen/client/GraphModel.hpp" -#include "ingen/client/ObjectModel.hpp" -#include "ingen/client/PluginModel.hpp" -#include "ingen/client/PortModel.hpp" -#include "ingen/client/SigClientInterface.hpp" - -#include <boost/variant/apply_visitor.hpp> +#include <ingen/client/ClientStore.hpp> + +#include <ingen/Atom.hpp> +#include <ingen/Forge.hpp> +#include <ingen/Log.hpp> +#include <ingen/Message.hpp> +#include <ingen/Properties.hpp> +#include <ingen/Resource.hpp> +#include <ingen/Store.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIs.hpp> +#include <ingen/client/ArcModel.hpp> +#include <ingen/client/BlockModel.hpp> +#include <ingen/client/GraphModel.hpp> +#include <ingen/client/ObjectModel.hpp> +#include <ingen/client/PluginModel.hpp> +#include <ingen/client/PortModel.hpp> +#include <ingen/client/SigClientInterface.hpp> +#include <ingen/paths.hpp> +#include <raul/Path.hpp> +#include <sigc++/signal.h> + +#include <sigc++/functors/mem_fun.h> #include <cassert> #include <cstdint> +#include <memory> #include <string> #include <utility> +#include <variant> -namespace ingen { -namespace client { +namespace ingen::client { -ClientStore::ClientStore(URIs& uris, - Log& log, - SPtr<SigClientInterface> emitter) +ClientStore::ClientStore(URIs& uris, + Log& log, + const std::shared_ptr<SigClientInterface>& emitter) : _uris(uris) , _log(log) , _emitter(emitter) @@ -57,21 +69,21 @@ ClientStore::clear() } void -ClientStore::add_object(SPtr<ObjectModel> object) +ClientStore::add_object(const std::shared_ptr<ObjectModel>& object) { // If we already have "this" object, merge the existing one into the new // one (with precedence to the new values). auto existing = find(object->path()); if (existing != end()) { - dynamic_ptr_cast<ObjectModel>(existing->second)->set(object); + std::dynamic_pointer_cast<ObjectModel>(existing->second)->set(object); } else { if (!object->path().is_root()) { - SPtr<ObjectModel> parent = _object(object->path().parent()); + const std::shared_ptr<ObjectModel> parent = _object(object->path().parent()); if (parent) { 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); @@ -84,26 +96,26 @@ ClientStore::add_object(SPtr<ObjectModel> object) } } - for (auto p : object->properties()) { + for (const auto& p : object->properties()) { object->signal_property().emit(p.first, p.second); } } -SPtr<ObjectModel> -ClientStore::remove_object(const Raul::Path& path) +std::shared_ptr<ObjectModel> +ClientStore::remove_object(const raul::Path& path) { // Find the object, the "top" of the tree to remove - const iterator top = find(path); + const auto top = find(path); if (top == end()) { - return SPtr<ObjectModel>(); + return nullptr; } - SPtr<ObjectModel> object = dynamic_ptr_cast<ObjectModel>(top->second); + auto object = std::dynamic_pointer_cast<ObjectModel>(top->second); // Remove object and any adjacent arcs from parent if applicable if (object && object->parent()) { - SPtr<PortModel> port = dynamic_ptr_cast<PortModel>(object); - if (port && dynamic_ptr_cast<GraphModel>(port->parent())) { + auto port = std::dynamic_pointer_cast<PortModel>(object); + if (port && std::dynamic_pointer_cast<GraphModel>(port->parent())) { disconnect_all(port->parent()->path(), path); if (port->parent()->parent()) { disconnect_all(port->parent()->parent()->path(), path); @@ -129,69 +141,69 @@ ClientStore::remove_object(const Raul::Path& path) return object; } -SPtr<PluginModel> +std::shared_ptr<PluginModel> ClientStore::_plugin(const URI& uri) { - const Plugins::iterator i = _plugins->find(uri); - return (i == _plugins->end()) ? SPtr<PluginModel>() : (*i).second; + const auto i = _plugins->find(uri); + return (i == _plugins->end()) ? std::shared_ptr<PluginModel>() : (*i).second; } -SPtr<PluginModel> +std::shared_ptr<PluginModel> ClientStore::_plugin(const Atom& uri) { /* FIXME: Should probably be stored with URIs rather than strings, to make this a fast case. */ - const Plugins::iterator i = _plugins->find(URI(_uris.forge.str(uri, false))); - return (i == _plugins->end()) ? SPtr<PluginModel>() : (*i).second; + const auto i = _plugins->find(URI(_uris.forge.str(uri, false))); + return (i == _plugins->end()) ? std::shared_ptr<PluginModel>() : (*i).second; } -SPtr<const PluginModel> +std::shared_ptr<const PluginModel> ClientStore::plugin(const URI& uri) const { return const_cast<ClientStore*>(this)->_plugin(uri); } -SPtr<ObjectModel> -ClientStore::_object(const Raul::Path& path) +std::shared_ptr<ObjectModel> +ClientStore::_object(const raul::Path& path) { - const iterator i = find(path); + const auto i = find(path); if (i == end()) { - return SPtr<ObjectModel>(); - } else { - SPtr<ObjectModel> model = dynamic_ptr_cast<ObjectModel>(i->second); - assert(model); - assert(model->path().is_root() || model->parent()); - return model; + return nullptr; } + + auto model = std::dynamic_pointer_cast<ObjectModel>(i->second); + assert(model); + assert(model->path().is_root() || model->parent()); + return model; } -SPtr<const ObjectModel> -ClientStore::object(const Raul::Path& path) const +std::shared_ptr<const ObjectModel> +ClientStore::object(const raul::Path& path) const { return const_cast<ClientStore*>(this)->_object(path); } -SPtr<Resource> +std::shared_ptr<Resource> ClientStore::_resource(const URI& uri) { if (uri_is_path(uri)) { return _object(uri_to_path(uri)); - } else { - return _plugin(uri); } + + return _plugin(uri); } -SPtr<const Resource> +std::shared_ptr<const Resource> ClientStore::resource(const URI& uri) const { return const_cast<ClientStore*>(this)->_resource(uri); } void -ClientStore::add_plugin(SPtr<PluginModel> pm) +ClientStore::add_plugin(const std::shared_ptr<PluginModel>& pm) { - SPtr<PluginModel> existing = _plugin(pm->uri()); + const std::shared_ptr<PluginModel> existing = _plugin(pm->uri()); if (existing) { existing->set(pm); } else { @@ -225,7 +237,7 @@ ClientStore::operator()(const Copy&) void ClientStore::operator()(const Move& msg) { - const iterator top = find(msg.old_path); + const auto top = find(msg.old_path); if (top != end()) { rename(top, msg.new_path); } @@ -234,29 +246,30 @@ ClientStore::operator()(const Move& msg) void ClientStore::message(const Message& msg) { - boost::apply_visitor(*this, msg); + std::visit(*this, msg); } void ClientStore::operator()(const Put& msg) { - using Iterator = Properties::const_iterator; - const auto& uri = msg.uri; const auto& properties = msg.properties; - bool is_graph, is_block, is_port, is_output; + bool is_block = false; + bool is_graph = false; + bool is_output = false; + bool is_port = false; Resource::type(uris(), properties, is_graph, is_block, is_port, is_output); // Check for specially handled types - const Iterator t = properties.find(_uris.rdf_type); + const auto t = properties.find(_uris.rdf_type); if (t != properties.end()) { const Atom& type(t->second); if (_uris.pset_Preset == type) { - const Iterator p = properties.find(_uris.lv2_appliesTo); - const Iterator l = properties.find(_uris.rdfs_label); - SPtr<PluginModel> plug; + const auto p = properties.find(_uris.lv2_appliesTo); + const auto l = properties.find(_uris.rdfs_label); + std::shared_ptr<PluginModel> plug; if (p == properties.end()) { _log.error("Preset <%1%> with no plugin\n", uri.c_str()); } else if (l == properties.end()) { @@ -270,10 +283,12 @@ ClientStore::operator()(const Put& msg) plug->add_preset(uri, l->second.ptr<char>()); } return; - } else if (_uris.ingen_Graph == type) { + } + + if (_uris.ingen_Graph == type) { is_graph = true; } else if (_uris.ingen_Internal == type || _uris.lv2_Plugin == type) { - SPtr<PluginModel> p(new PluginModel(uris(), uri, type, properties)); + const std::shared_ptr<PluginModel> p{new PluginModel(uris(), uri, type, properties)}; add_plugin(p); return; } @@ -284,9 +299,9 @@ ClientStore::operator()(const Put& msg) return; } - const Raul::Path path(uri_to_path(uri)); + const raul::Path path(uri_to_path(uri)); - SPtr<ObjectModel> obj = dynamic_ptr_cast<ObjectModel>(_object(path)); + auto obj = std::dynamic_pointer_cast<ObjectModel>(_object(path)); if (obj) { obj->set_properties(properties); return; @@ -297,7 +312,7 @@ ClientStore::operator()(const Put& msg) } if (is_graph) { - SPtr<GraphModel> model(new GraphModel(uris(), path)); + const std::shared_ptr<GraphModel> model{new GraphModel(uris(), path)}; model->set_properties(properties); add_object(model); } else if (is_block) { @@ -306,33 +321,35 @@ ClientStore::operator()(const Put& msg) p = properties.find(_uris.ingen_prototype); } - SPtr<PluginModel> plug; + std::shared_ptr<PluginModel> plug; if (p->second.is_valid() && (p->second.type() == _uris.forge.URI || p->second.type() == _uris.forge.URID)) { - const URI uri(_uris.forge.str(p->second, false)); - if (!(plug = _plugin(uri))) { - plug = SPtr<PluginModel>( - new PluginModel(uris(), uri, Atom(), Properties())); + const URI plugin_uri(_uris.forge.str(p->second, false)); + if (!(plug = _plugin(plugin_uri))) { + plug = std::make_shared<PluginModel>(uris(), + plugin_uri, + Atom(), + Properties()); add_plugin(plug); } - SPtr<BlockModel> bm(new BlockModel(uris(), plug, path)); + const std::shared_ptr<BlockModel> bm{new BlockModel(uris(), plug, path)}; bm->set_properties(properties); add_object(bm); } else { _log.warn("Block %1% has no prototype\n", path.c_str()); } } else if (is_port) { - PortModel::Direction pdir = (is_output) + const PortModel::Direction pdir = (is_output) ? PortModel::Direction::OUTPUT : PortModel::Direction::INPUT; - uint32_t index = 0; - const Iterator i = properties.find(_uris.lv2_index); + uint32_t index = 0; + const auto i = properties.find(_uris.lv2_index); if (i != properties.end() && i->second.type() == _uris.forge.Int) { index = i->second.get<int32_t>(); } - SPtr<PortModel> p(new PortModel(uris(), path, index, pdir)); + const std::shared_ptr<PortModel> p{new PortModel(uris(), path, index, pdir)}; p->set_properties(properties); add_object(p); } else { @@ -354,9 +371,9 @@ ClientStore::operator()(const Delta& msg) return; } - const Raul::Path path(uri_to_path(uri)); + const raul::Path path(uri_to_path(uri)); - SPtr<ObjectModel> obj = _object(path); + const std::shared_ptr<ObjectModel> obj = _object(path); if (obj) { obj->remove_properties(msg.remove); obj->add_properties(msg.add); @@ -377,7 +394,7 @@ ClientStore::operator()(const SetProperty& msg) predicate.c_str(), _uris.forge.str(value, false)); return; } - SPtr<Resource> subject = _resource(subject_uri); + const std::shared_ptr<Resource> subject = _resource(subject_uri); if (subject) { if (predicate == _uris.ingen_activity) { /* Activity is transient, trigger any live actions (like GUI @@ -387,7 +404,7 @@ ClientStore::operator()(const SetProperty& msg) subject->set_property(predicate, value, msg.ctx); } } else { - SPtr<PluginModel> plugin = _plugin(subject_uri); + const std::shared_ptr<PluginModel> plugin = _plugin(subject_uri); if (plugin) { plugin->set_property(predicate, value); } else if (predicate != _uris.ingen_activity) { @@ -397,26 +414,26 @@ ClientStore::operator()(const SetProperty& msg) } } -SPtr<GraphModel> -ClientStore::connection_graph(const Raul::Path& tail_path, - const Raul::Path& head_path) +std::shared_ptr<GraphModel> +ClientStore::connection_graph(const raul::Path& tail_path, + const raul::Path& head_path) { - SPtr<GraphModel> graph; + std::shared_ptr<GraphModel> graph; if (tail_path.parent() == head_path.parent()) { - graph = dynamic_ptr_cast<GraphModel>(_object(tail_path.parent())); + graph = std::dynamic_pointer_cast<GraphModel>(_object(tail_path.parent())); } if (!graph && tail_path.parent() == head_path.parent().parent()) { - graph = dynamic_ptr_cast<GraphModel>(_object(tail_path.parent())); + graph = std::dynamic_pointer_cast<GraphModel>(_object(tail_path.parent())); } if (!graph && tail_path.parent().parent() == head_path.parent()) { - graph = dynamic_ptr_cast<GraphModel>(_object(head_path.parent())); + graph = std::dynamic_pointer_cast<GraphModel>(_object(head_path.parent())); } if (!graph) { - graph = dynamic_ptr_cast<GraphModel>(_object(tail_path.parent().parent())); + graph = std::dynamic_pointer_cast<GraphModel>(_object(tail_path.parent().parent())); } if (!graph) { @@ -428,21 +445,21 @@ ClientStore::connection_graph(const Raul::Path& tail_path, } bool -ClientStore::attempt_connection(const Raul::Path& tail_path, - const Raul::Path& head_path) +ClientStore::attempt_connection(const raul::Path& tail_path, + const raul::Path& head_path) { - SPtr<PortModel> tail = dynamic_ptr_cast<PortModel>(_object(tail_path)); - SPtr<PortModel> head = dynamic_ptr_cast<PortModel>(_object(head_path)); + auto tail = std::dynamic_pointer_cast<PortModel>(_object(tail_path)); + auto head = std::dynamic_pointer_cast<PortModel>(_object(head_path)); if (tail && head) { - SPtr<GraphModel> graph = connection_graph(tail_path, head_path); - SPtr<ArcModel> arc(new ArcModel(tail, head)); + const std::shared_ptr<GraphModel> graph = connection_graph(tail_path, head_path); + const std::shared_ptr<ArcModel> arc(new ArcModel(tail, head)); graph->add_arc(arc); return true; - } else { - _log.warn("Failed to connect %1% => %2%\n", tail_path, head_path); - return false; } + + _log.warn("Failed to connect %1% => %2%\n", tail_path, head_path); + return false; } void @@ -454,9 +471,9 @@ ClientStore::operator()(const Connect& msg) void ClientStore::operator()(const Disconnect& msg) { - SPtr<PortModel> tail = dynamic_ptr_cast<PortModel>(_object(msg.tail)); - SPtr<PortModel> head = dynamic_ptr_cast<PortModel>(_object(msg.head)); - SPtr<GraphModel> graph = connection_graph(msg.tail, msg.head); + auto tail = std::dynamic_pointer_cast<PortModel>(_object(msg.tail)); + auto head = std::dynamic_pointer_cast<PortModel>(_object(msg.head)); + auto graph = connection_graph(msg.tail, msg.head); if (graph) { graph->remove_arc(tail.get(), head.get()); } @@ -465,8 +482,8 @@ ClientStore::operator()(const Disconnect& msg) void ClientStore::operator()(const DisconnectAll& msg) { - SPtr<GraphModel> graph = dynamic_ptr_cast<GraphModel>(_object(msg.graph)); - SPtr<ObjectModel> object = _object(msg.path); + auto graph = std::dynamic_pointer_cast<GraphModel>(_object(msg.graph)); + auto object = _object(msg.path); if (!graph || !object) { _log.error("Bad disconnect all notification %1% in %2%\n", @@ -475,8 +492,8 @@ ClientStore::operator()(const DisconnectAll& msg) } const GraphModel::Arcs arcs = graph->arcs(); - for (auto a : arcs) { - SPtr<ArcModel> arc = dynamic_ptr_cast<ArcModel>(a.second); + for (const auto& a : arcs) { + auto arc = std::dynamic_pointer_cast<ArcModel>(a.second); if (arc->tail()->parent() == object || arc->head()->parent() == object || arc->tail()->path() == msg.path @@ -486,5 +503,4 @@ ClientStore::operator()(const DisconnectAll& msg) } } -} // namespace client -} // namespace ingen +} // namespace ingen::client diff --git a/src/client/GraphModel.cpp b/src/client/GraphModel.cpp index 90ab2964..fe119361 100644 --- a/src/client/GraphModel.cpp +++ b/src/client/GraphModel.cpp @@ -14,50 +14,65 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "ingen/client/GraphModel.hpp" - -#include "ingen/URIs.hpp" -#include "ingen/client/ArcModel.hpp" -#include "ingen/client/BlockModel.hpp" -#include "ingen/client/ClientStore.hpp" +#include <ingen/client/GraphModel.hpp> + +#include <ingen/Atom.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIs.hpp> +#include <ingen/client/ArcModel.hpp> +#include <ingen/client/BlockModel.hpp> +#include <ingen/client/ObjectModel.hpp> +#include <ingen/client/PortModel.hpp> +#include <raul/Path.hpp> +#include <sigc++/signal.h> #include <cassert> +#include <map> +#include <memory> #include <string> #include <utility> namespace ingen { -namespace client { +class Node; +} // namespace ingen + +namespace ingen::client { + +GraphModel::GraphModel(URIs& uris, const raul::Path& graph_path) + : BlockModel{uris, static_cast<const URI&>(uris.ingen_Graph), graph_path} +{ +} void -GraphModel::add_child(const SPtr<ObjectModel>& c) +GraphModel::add_child(const std::shared_ptr<ObjectModel>& c) { assert(c->parent().get() == this); - SPtr<PortModel> pm = dynamic_ptr_cast<PortModel>(c); + auto pm = std::dynamic_pointer_cast<PortModel>(c); if (pm) { add_port(pm); return; } - SPtr<BlockModel> bm = dynamic_ptr_cast<BlockModel>(c); + auto bm = std::dynamic_pointer_cast<BlockModel>(c); if (bm) { _signal_new_block.emit(bm); } } bool -GraphModel::remove_child(const SPtr<ObjectModel>& o) +GraphModel::remove_child(const std::shared_ptr<ObjectModel>& o) { assert(o->path().is_child_of(path())); assert(o->parent().get() == this); - SPtr<PortModel> pm = dynamic_ptr_cast<PortModel>(o); + auto pm = std::dynamic_pointer_cast<PortModel>(o); if (pm) { remove_arcs_on(pm); remove_port(pm); } - SPtr<BlockModel> bm = dynamic_ptr_cast<BlockModel>(o); + auto bm = std::dynamic_pointer_cast<BlockModel>(o); if (bm) { _signal_removed_block.emit(bm); } @@ -66,21 +81,21 @@ GraphModel::remove_child(const SPtr<ObjectModel>& o) } void -GraphModel::remove_arcs_on(const SPtr<PortModel>& p) +GraphModel::remove_arcs_on(const std::shared_ptr<PortModel>& p) { // Remove any connections which referred to this object, // since they can't possibly exist anymore - for (auto j = _arcs.begin(); j != _arcs.end();) { + for (auto j = _graph_arcs.begin(); j != _graph_arcs.end();) { auto next = j; ++next; - SPtr<ArcModel> arc = dynamic_ptr_cast<ArcModel>(j->second); + auto arc = std::dynamic_pointer_cast<ArcModel>(j->second); if (arc->tail_path().parent() == p->path() || arc->tail_path() == p->path() || arc->head_path().parent() == p->path() || arc->head_path() == p->path()) { _signal_removed_arc.emit(arc); - _arcs.erase(j); // Cuts our reference + _graph_arcs.erase(j); // Cuts our reference } j = next; } @@ -89,23 +104,23 @@ GraphModel::remove_arcs_on(const SPtr<PortModel>& p) void GraphModel::clear() { - _arcs.clear(); + _graph_arcs.clear(); BlockModel::clear(); - assert(_arcs.empty()); + assert(_graph_arcs.empty()); assert(_ports.empty()); } -SPtr<ArcModel> +std::shared_ptr<ArcModel> GraphModel::get_arc(const Node* tail, const Node* head) { - auto i = _arcs.find(std::make_pair(tail, head)); - if (i != _arcs.end()) { - return dynamic_ptr_cast<ArcModel>(i->second); - } else { - return SPtr<ArcModel>(); + auto i = _graph_arcs.find(std::make_pair(tail, head)); + if (i != _graph_arcs.end()) { + return std::dynamic_pointer_cast<ArcModel>(i->second); } + + return nullptr; } /** Add a connection to this graph. @@ -116,7 +131,7 @@ GraphModel::get_arc(const Node* tail, const Node* head) * this graph is a fatal error. */ void -GraphModel::add_arc(const SPtr<ArcModel>& arc) +GraphModel::add_arc(const std::shared_ptr<ArcModel>& arc) { // Store should have 'resolved' the connection already assert(arc); @@ -130,15 +145,16 @@ GraphModel::add_arc(const SPtr<ArcModel>& arc) assert(arc->head()->parent().get() == this || arc->head()->parent()->parent().get() == this); - SPtr<ArcModel> existing = get_arc( + const std::shared_ptr<ArcModel> existing = get_arc( arc->tail().get(), arc->head().get()); if (existing) { assert(arc->tail() == existing->tail()); assert(arc->head() == existing->head()); } else { - _arcs.emplace(std::make_pair(arc->tail().get(), arc->head().get()), - arc); + _graph_arcs.emplace(std::make_pair(arc->tail().get(), + arc->head().get()), + arc); _signal_new_arc.emit(arc); } } @@ -146,11 +162,11 @@ GraphModel::add_arc(const SPtr<ArcModel>& arc) void GraphModel::remove_arc(const Node* tail, const Node* head) { - auto i = _arcs.find(std::make_pair(tail, head)); - if (i != _arcs.end()) { - SPtr<ArcModel> arc = dynamic_ptr_cast<ArcModel>(i->second); + auto i = _graph_arcs.find(std::make_pair(tail, head)); + if (i != _graph_arcs.end()) { + auto arc = std::dynamic_pointer_cast<ArcModel>(i->second); _signal_removed_arc.emit(arc); - _arcs.erase(i); + _graph_arcs.erase(i); } } @@ -168,12 +184,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 client -} // namespace ingen +} // namespace ingen::client diff --git a/src/client/ObjectModel.cpp b/src/client/ObjectModel.cpp index b1a27590..4baa895c 100644 --- a/src/client/ObjectModel.cpp +++ b/src/client/ObjectModel.cpp @@ -14,33 +14,38 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "ingen/client/ObjectModel.hpp" - -#include "ingen/Node.hpp" -#include "ingen/URIs.hpp" +#include <ingen/client/ObjectModel.hpp> + +#include <ingen/Atom.hpp> +#include <ingen/Node.hpp> +#include <ingen/Properties.hpp> +#include <ingen/Resource.hpp> +#include <ingen/URIs.hpp> +#include <ingen/paths.hpp> +#include <raul/Path.hpp> +#include <raul/Symbol.hpp> +#include <sigc++/signal.h> #include <cassert> #include <cstdint> +#include <map> #include <string> #include <utility> -namespace ingen { -namespace client { +namespace ingen::client { -ObjectModel::ObjectModel(URIs& uris, const Raul::Path& path) +ObjectModel::ObjectModel(URIs& uris, const raul::Path& path) : Node(uris, path) , _path(path) , _symbol((path == "/") ? "root" : path.symbol()) -{ -} +{} ObjectModel::ObjectModel(const ObjectModel& copy) : Node(copy) , _parent(copy._parent) , _path(copy._path) , _symbol(copy._symbol) -{ -} +{} bool ObjectModel::is_a(const URIs::Quark& type) const @@ -81,34 +86,33 @@ ObjectModel::polyphonic() const * `o` as correct. The paths of the two models MUST be equal. */ void -ObjectModel::set(const SPtr<ObjectModel>& o) +ObjectModel::set(const std::shared_ptr<ObjectModel>& o) { assert(_path == o->path()); if (o->_parent) { _parent = o->_parent; } - for (auto v : o->properties()) { + for (const auto& v : o->properties()) { Resource::set_property(v.first, v.second); _signal_property.emit(v.first, v.second); } } void -ObjectModel::set_path(const Raul::Path& p) +ObjectModel::set_path(const raul::Path& p) { _path = p; - _symbol = Raul::Symbol(p.is_root() ? "root" : p.symbol()); + _symbol = raul::Symbol(p.is_root() ? "root" : p.symbol()); set_uri(path_to_uri(p)); _signal_moved.emit(); } void -ObjectModel::set_parent(const SPtr<ObjectModel>& p) +ObjectModel::set_parent(const std::shared_ptr<ObjectModel>& p) { assert(_path.is_child_of(p->path())); _parent = p; } -} // namespace client -} // namespace ingen +} // namespace ingen::client diff --git a/src/client/PluginModel.cpp b/src/client/PluginModel.cpp index f0e3c3a0..f4dfccd2 100644 --- a/src/client/PluginModel.cpp +++ b/src/client/PluginModel.cpp @@ -14,26 +14,29 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "ingen/client/PluginModel.hpp" - -#include "ingen/Atom.hpp" -#include "ingen/client/GraphModel.hpp" -#include "ingen/client/PluginUI.hpp" -#include "raul/Path.hpp" -#include "ingen_config.h" - -#include <boost/optional/optional.hpp> +#include <ingen/client/PluginModel.hpp> + +#include <ingen/Atom.hpp> +#include <ingen/Forge.hpp> +#include <ingen/Properties.hpp> +#include <ingen/Resource.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIs.hpp> +#include <ingen/client/PluginUI.hpp> +#include <lilv/lilv.h> +#include <lv2/core/lv2.h> +#include <raul/Symbol.hpp> +#include <sigc++/signal.h> #include <cctype> #include <cstring> -#include <iosfwd> +#include <memory> #include <string> #include <utility> using std::string; -namespace ingen { -namespace client { +namespace ingen::client { LilvWorld* PluginModel::_lilv_world = nullptr; const LilvPlugins* PluginModel::_lilv_plugins = nullptr; @@ -46,13 +49,12 @@ PluginModel::PluginModel(URIs& uris, const Properties& properties) : Resource(uris, uri) , _type(type) - , _fetched(false) { if (!_type.is_valid()) { if (uri.string().find("ingen-internals") != string::npos) { - _type = uris.ingen_Internal.urid; + _type = uris.ingen_Internal.urid_atom(); } else { - _type = uris.lv2_Plugin.urid; // Assume LV2 and hope for the best... + _type = uris.lv2_Plugin.urid_atom(); // Assume LV2 and hope for the best... } } @@ -107,38 +109,44 @@ 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); - std::string symbol = Raul::Symbol::symbolify(str); + const std::string symbol = raul::Symbol::symbolify(str); set_property(_uris.lv2_symbol, _uris.forge.alloc(symbol)); return get_property(key); } if (_lilv_plugin) { - boost::optional<const Atom&> ret; - LilvNode* lv2_pred = lilv_new_uri(_lilv_world, key.c_str()); - LilvNodes* values = lilv_plugin_get_value(_lilv_plugin, lv2_pred); + const Atom* ret = nullptr; + LilvNode* lv2_pred = lilv_new_uri(_lilv_world, key.c_str()); + LilvNodes* values = lilv_plugin_get_value(_lilv_plugin, lv2_pred); lilv_node_free(lv2_pred); - LILV_FOREACH(nodes, i, values) { - const LilvNode* val = lilv_nodes_get(values, i); - if (lilv_node_is_uri(val)) { - ret = set_property( - key, _uris.forge.make_urid(URI(lilv_node_as_uri(val)))); + LILV_FOREACH (nodes, i, values) { + const LilvNode* value = lilv_nodes_get(values, i); + if (lilv_node_is_uri(value)) { + ret = &set_property( + key, _uris.forge.make_urid(URI(lilv_node_as_uri(value)))); break; - } else if (lilv_node_is_string(val)) { - ret = set_property( - key, _uris.forge.alloc(lilv_node_as_string(val))); + } + + if (lilv_node_is_string(value)) { + ret = &set_property( + key, _uris.forge.alloc(lilv_node_as_string(value))); break; - } else if (lilv_node_is_float(val)) { - ret = set_property( - key, _uris.forge.make(lilv_node_as_float(val))); + } + + if (lilv_node_is_float(value)) { + ret = &set_property( + key, _uris.forge.make(lilv_node_as_float(value))); break; - } else if (lilv_node_is_int(val)) { - ret = set_property( - key, _uris.forge.make(lilv_node_as_int(val))); + } + + if (lilv_node_is_int(value)) { + ret = &set_property( + key, _uris.forge.make(lilv_node_as_int(value))); break; } } @@ -153,7 +161,7 @@ PluginModel::get_property(const URI& key) const } void -PluginModel::set(SPtr<PluginModel> p) +PluginModel::set(const std::shared_ptr<PluginModel>& p) { _type = p->_type; @@ -161,7 +169,7 @@ PluginModel::set(SPtr<PluginModel> p) _lilv_plugin = p->_lilv_plugin; } - for (auto v : p->properties()) { + for (const auto& v : p->properties()) { Resource::set_property(v.first, v.second); _signal_property.emit(v.first, v.second); } @@ -176,15 +184,15 @@ PluginModel::add_preset(const URI& uri, const std::string& label) _signal_preset.emit(uri, label); } -Raul::Symbol +raul::Symbol PluginModel::default_block_symbol() const { const Atom& name_atom = get_property(_uris.lv2_symbol); if (name_atom.is_valid() && name_atom.type() == _uris.forge.String) { - return Raul::Symbol::symbolify(name_atom.ptr<char>()); - } else { - return Raul::Symbol("_"); + return raul::Symbol::symbolify(name_atom.ptr<char>()); } + + return raul::Symbol("_"); } string @@ -193,18 +201,18 @@ PluginModel::human_name() const const Atom& name_atom = get_property(_uris.doap_name); if (name_atom.type() == _uris.forge.String) { return name_atom.ptr<char>(); - } else { - return default_block_symbol().c_str(); } + + return default_block_symbol().c_str(); } string -PluginModel::port_human_name(uint32_t i) const +PluginModel::port_human_name(const uint32_t index) const { if (_lilv_plugin) { - const LilvPort* port = lilv_plugin_get_port_by_index(_lilv_plugin, i); + const LilvPort* port = lilv_plugin_get_port_by_index(_lilv_plugin, index); LilvNode* name = lilv_port_get_name(_lilv_plugin, port); - const string ret(lilv_node_as_string(name)); + string ret(lilv_node_as_string(name)); lilv_node_free(name); return ret; } @@ -212,14 +220,14 @@ PluginModel::port_human_name(uint32_t i) const } PluginModel::ScalePoints -PluginModel::port_scale_points(uint32_t i) const +PluginModel::port_scale_points(const uint32_t index) const { // TODO: Non-float scale points ScalePoints points; if (_lilv_plugin) { - const LilvPort* port = lilv_plugin_get_port_by_index(_lilv_plugin, i); + const LilvPort* port = lilv_plugin_get_port_by_index(_lilv_plugin, index); LilvScalePoints* sp = lilv_port_get_scale_points(_lilv_plugin, port); - LILV_FOREACH(scale_points, i, sp) { + LILV_FOREACH (scale_points, i, sp) { const LilvScalePoint* p = lilv_scale_points_get(sp, i); points.emplace( lilv_node_as_float(lilv_scale_point_get_value(p)), @@ -241,12 +249,12 @@ PluginModel::has_ui() const return false; } -SPtr<PluginUI> -PluginModel::ui(ingen::World& world, - SPtr<const BlockModel> block) const +std::shared_ptr<PluginUI> +PluginModel::ui(ingen::World& world, + const std::shared_ptr<const BlockModel>& block) const { if (!_lilv_plugin) { - return SPtr<PluginUI>(); + return nullptr; } return PluginUI::create(world, block, _lilv_plugin); @@ -258,9 +266,9 @@ heading(const std::string& text, bool html, unsigned level) if (html) { const std::string tag = std::string("h") + std::to_string(level); return std::string("<") + tag + ">" + text + "</" + tag + ">\n"; - } else { - return text + ":\n\n"; } + + return text + ":\n\n"; } static std::string @@ -268,13 +276,13 @@ link(const std::string& addr, bool html) { if (html) { return std::string("<a href=\"") + addr + "\">" + addr + "</a>"; - } else { - return addr; } + + return addr; } std::string -PluginModel::get_documentation(const LilvNode* subject, bool html) const +PluginModel::get_documentation(const LilvNode* subject, bool html) { std::string doc; @@ -358,5 +366,4 @@ PluginModel::set_lilv_world(LilvWorld* world) _lilv_plugins = lilv_world_get_all_plugins(_lilv_world); } -} // namespace client -} // namespace ingen +} // namespace ingen::client diff --git a/src/client/PluginUI.cpp b/src/client/PluginUI.cpp index a997d716..c4aa748f 100644 --- a/src/client/PluginUI.cpp +++ b/src/client/PluginUI.cpp @@ -14,33 +14,44 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "ingen/client/PluginUI.hpp" - -#include "ingen/Interface.hpp" -#include "ingen/Log.hpp" -#include "ingen/URIs.hpp" -#include "ingen/client/BlockModel.hpp" -#include "ingen/client/PortModel.hpp" -#include "lv2/atom/atom.h" -#include "lv2/ui/ui.h" +#include <ingen/client/PluginUI.hpp> + +#include <ingen/Atom.hpp> +#include <ingen/Forge.hpp> +#include <ingen/LV2Features.hpp> +#include <ingen/Log.hpp> +#include <ingen/Resource.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIs.hpp> +#include <ingen/World.hpp> +#include <ingen/client/BlockModel.hpp> +#include <ingen/client/PortModel.hpp> +#include <lilv/lilv.h> +#include <lv2/atom/atom.h> +#include <lv2/core/lv2.h> +#include <lv2/ui/ui.h> +#include <raul/Symbol.hpp> +#include <suil/suil.h> + +#include <sigc++/signal.h> #include <cstring> +#include <memory> #include <string> #include <utility> -namespace ingen { -namespace client { +namespace ingen::client { SuilHost* PluginUI::ui_host = nullptr; -static SPtr<const PortModel> +static std::shared_ptr<const PortModel> get_port(PluginUI* ui, uint32_t port_index) { if (port_index >= ui->block()->ports().size()) { ui->world().log().error("%1% UI tried to access invalid port %2%\n", ui->block()->plugin()->uri().c_str(), port_index); - return SPtr<const PortModel>(); + return nullptr; } return ui->block()->ports()[port_index]; } @@ -52,9 +63,9 @@ lv2_ui_write(SuilController controller, uint32_t format, const void* buffer) { - PluginUI* const ui = (PluginUI*)controller; - const URIs& uris = ui->world().uris(); - SPtr<const PortModel> port = get_port(ui, port_index); + auto* const ui = static_cast<PluginUI*>(controller); + const URIs& uris = ui->world().uris(); + auto port = get_port(ui, port_index); if (!port) { return; } @@ -67,10 +78,10 @@ lv2_ui_write(SuilController controller, ui->block()->plugin()->uri().c_str()); return; } - const float value = *(const float*)buffer; + const float value = *static_cast<const float*>(buffer); if (port->value().type() == uris.atom_Float && value == port->value().get<float>()) { - return; // Ignore feedback + return; // Ignore feedback } ui->signal_property_changed()( @@ -79,10 +90,11 @@ lv2_ui_write(SuilController controller, ui->world().forge().make(value), Resource::Graph::DEFAULT); - } else if (format == uris.atom_eventTransfer.urid.get<LV2_URID>()) { - const LV2_Atom* atom = (const LV2_Atom*)buffer; - Atom val = ui->world().forge().alloc( - atom->size, atom->type, LV2_ATOM_BODY_CONST(atom)); + } else if (format == uris.atom_eventTransfer.urid()) { + const auto* atom = static_cast<const LV2_Atom*>(buffer); + const Atom val = + Forge::alloc(atom->size, atom->type, LV2_ATOM_BODY_CONST(atom)); + ui->signal_property_changed()(port->uri(), uris.ingen_activity, val, @@ -97,7 +109,7 @@ lv2_ui_write(SuilController controller, static uint32_t lv2_ui_port_index(SuilController controller, const char* port_symbol) { - PluginUI* const ui = (PluginUI*)controller; + auto* const ui = static_cast<PluginUI*>(controller); const BlockModel::Ports& ports = ui->block()->ports(); for (uint32_t i = 0; i < ports.size(); ++i) { @@ -114,8 +126,8 @@ lv2_ui_subscribe(SuilController controller, uint32_t protocol, const LV2_Feature* const* features) { - PluginUI* const ui = (PluginUI*)controller; - SPtr<const PortModel> port = get_port(ui, port_index); + auto* const ui = static_cast<PluginUI*>(controller); + const std::shared_ptr<const PortModel> port = get_port(ui, port_index); if (!port) { return 1; } @@ -135,8 +147,8 @@ lv2_ui_unsubscribe(SuilController controller, uint32_t protocol, const LV2_Feature* const* features) { - PluginUI* const ui = (PluginUI*)controller; - SPtr<const PortModel> port = get_port(ui, port_index); + auto* const ui = static_cast<PluginUI*>(controller); + auto port = get_port(ui, port_index); if (!port) { return 1; } @@ -150,24 +162,22 @@ lv2_ui_unsubscribe(SuilController controller, return 0; } -PluginUI::PluginUI(ingen::World& world, - SPtr<const BlockModel> block, - LilvUIs* uis, - const LilvUI* ui, - const LilvNode* ui_type) - : _world(world) - , _block(std::move(block)) - , _instance(nullptr) - , _uis(uis) - , _ui(ui) - , _ui_node(lilv_node_duplicate(lilv_ui_get_uri(ui))) - , _ui_type(lilv_node_duplicate(ui_type)) -{ -} +PluginUI::PluginUI(ingen::World& world, + std::shared_ptr<const BlockModel> block, + LilvUIs* uis, + const LilvUI* ui, + const LilvNode* ui_type) + : _world(world) + , _block(std::move(block)) + , _uis(uis) + , _ui(ui) + , _ui_node(lilv_node_duplicate(lilv_ui_get_uri(ui))) + , _ui_type(lilv_node_duplicate(ui_type)) +{} PluginUI::~PluginUI() { - for (uint32_t i : _subscribed_ports) { + for (const uint32_t i : _subscribed_ports) { lv2_ui_unsubscribe(this, i, 0, nullptr); } suil_instance_free(_instance); @@ -177,10 +187,10 @@ PluginUI::~PluginUI() lilv_world_unload_resource(_world.lilv_world(), lilv_ui_get_uri(_ui)); } -SPtr<PluginUI> -PluginUI::create(ingen::World& world, - SPtr<const BlockModel> block, - const LilvPlugin* plugin) +std::shared_ptr<PluginUI> +PluginUI::create(ingen::World& world, + const std::shared_ptr<const BlockModel>& block, + const LilvPlugin* plugin) { if (!PluginUI::ui_host) { PluginUI::ui_host = suil_host_new(lv2_ui_write, @@ -196,7 +206,7 @@ PluginUI::create(ingen::World& world, LilvUIs* uis = lilv_plugin_get_uis(plugin); const LilvUI* ui = nullptr; const LilvNode* ui_type = nullptr; - LILV_FOREACH(uis, u, uis) { + LILV_FOREACH (uis, u, uis) { const LilvUI* this_ui = lilv_uis_get(uis, u); if (lilv_ui_is_supported(this_ui, suil_ui_supported, @@ -210,11 +220,11 @@ PluginUI::create(ingen::World& world, if (!ui) { lilv_node_free(gtk_ui); - return SPtr<PluginUI>(); + return nullptr; } // Create the PluginUI, but don't instantiate yet - SPtr<PluginUI> ret(new PluginUI(world, block, uis, ui, ui_type)); + std::shared_ptr<PluginUI> ret(new PluginUI(world, block, uis, ui, ui_type)); ret->_features = world.lv2_features().lv2_features( world, const_cast<BlockModel*>(block.get())); @@ -238,7 +248,7 @@ PluginUI::instantiate() LilvNode* ui_plugin = lilv_new_uri(lworld, LV2_UI__plugin); LilvNodes* notes = lilv_world_find_nodes( lworld, lilv_ui_get_uri(_ui), ui_portNotification, nullptr); - LILV_FOREACH(nodes, n, notes) { + LILV_FOREACH (nodes, n, notes) { const LilvNode* note = lilv_nodes_get(notes, n); const LilvNode* sym = lilv_world_get(lworld, note, uris.lv2_symbol, nullptr); const LilvNode* plug = lilv_world_get(lworld, note, ui_plugin, nullptr); @@ -253,7 +263,7 @@ PluginUI::instantiate() plugin_uri, lilv_node_as_string(_ui_node)); } else if (!strcmp(lilv_node_as_uri(plug), plugin_uri.c_str())) { // Notification is valid and for this plugin - uint32_t index = lv2_ui_port_index(this, lilv_node_as_string(sym)); + const uint32_t index = lv2_ui_port_index(this, lilv_node_as_string(sym)); if (index != LV2UI_INVALID_PORT_INDEX) { lv2_ui_subscribe(this, index, 0, nullptr); _subscribed_ports.insert(index); @@ -287,7 +297,7 @@ PluginUI::instantiate() if (!_instance) { _world.log().error("Failed to instantiate LV2 UI\n"); // Cancel any subscriptions - for (uint32_t i : _subscribed_ports) { + for (const uint32_t i : _subscribed_ports) { lv2_ui_unsubscribe(this, i, 0, nullptr); } return false; @@ -299,7 +309,7 @@ PluginUI::instantiate() SuilWidget PluginUI::get_widget() { - return (SuilWidget*)suil_instance_get_widget(_instance); + return suil_instance_get_widget(_instance); } void @@ -337,5 +347,4 @@ PluginUI::is_resizable() const return !fs_matches && !nrs_matches; } -} // namespace client -} // namespace ingen +} // namespace ingen::client diff --git a/src/client/PortModel.cpp b/src/client/PortModel.cpp index 6b2d011f..14a5297e 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 @@ -14,14 +14,22 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "ingen/client/BlockModel.hpp" -#include "ingen/client/PortModel.hpp" +#include <ingen/client/PortModel.hpp> +#include <ingen/Properties.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIs.hpp> +#include <ingen/client/ObjectModel.hpp> +#include <lv2/urid/urid.h> +#include <sigc++/signal.h> + +#include <algorithm> #include <cstdint> -#include <utility> +#include <exception> +#include <map> +#include <memory> -namespace ingen { -namespace client { +namespace ingen::client { void PortModel::on_property(const URI& uri, const Atom& value) @@ -54,22 +62,32 @@ PortModel::port_property(const URIs::Quark& uri) const bool PortModel::is_uri() const { - // FIXME: Resource::has_property doesn't work, URI != URID - for (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 -PortModel::set(const SPtr<ObjectModel>& model) +PortModel::set(const std::shared_ptr<ObjectModel>& model) { ObjectModel::set(model); - SPtr<PortModel> port = dynamic_ptr_cast<PortModel>(model); + auto port = std::dynamic_pointer_cast<PortModel>(model); if (port) { _index = port->_index; _direction = port->_direction; @@ -77,5 +95,4 @@ PortModel::set(const SPtr<ObjectModel>& model) } } -} // namespace client -} // namespace ingen +} // namespace ingen::client diff --git a/src/client/ingen_client.cpp b/src/client/ingen_client.cpp index f76fae0b..88619115 100644 --- a/src/client/ingen_client.cpp +++ b/src/client/ingen_client.cpp @@ -14,20 +14,22 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "ingen/Module.hpp" -#include "ingen/World.hpp" -#include "ingen_config.h" +#include <ingen/Module.hpp> -struct IngenClientModule : public ingen::Module { +namespace ingen::client { + +struct ClientModule : public ingen::Module { void load(ingen::World& world) override {} }; +} // namespace ingen::client + extern "C" { -ingen::Module* +INGEN_MODULE_EXPORT ingen::Module* ingen_module_load() { - return new IngenClientModule(); + return new ingen::client::ClientModule(); } } // extern "C" diff --git a/src/client/meson.build b/src/client/meson.build new file mode 100644 index 00000000..7c040634 --- /dev/null +++ b/src/client/meson.build @@ -0,0 +1,50 @@ +# Copyright 2022 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: 0BSD OR GPL-3.0-or-later + +################ +# Dependencies # +################ + +sigcpp_dep = dependency('sigc++-2.0', include_type: 'system') + +########## +# Module # +########## + +client_sources = files( + 'BlockModel.cpp', + 'ClientStore.cpp', + 'GraphModel.cpp', + 'ObjectModel.cpp', + 'PluginModel.cpp', + 'PluginUI.cpp', + 'PortModel.cpp', + 'ingen_client.cpp', +) + +client_dependencies = [ + boost_dep, + ingen_dep, + lilv_dep, + lv2_dep, + raul_dep, + sigcpp_dep, + suil_dep, +] + +libingen_client = shared_library( + 'ingen_client', + client_sources, + cpp_args: cpp_suppressions + platform_defines + ['-DINGEN_CLIENT_INTERNAL'], + dependencies: client_dependencies, + gnu_symbol_visibility: 'hidden', + implicit_include_directories: false, + include_directories: ingen_include_dirs, + install: true, + install_dir: ingen_module_dir, +) + +ingen_client_dep = declare_dependency( + dependencies: client_dependencies, + link_with: libingen_client, +) diff --git a/src/client/wscript b/src/client/wscript deleted file mode 100644 index 394c9e4d..00000000 --- a/src/client/wscript +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env python - - -def build(bld): - obj = bld(features = 'cxx cxxshlib', - cflags = ['-fvisibility=hidden'], - includes = ['../..'], - export_includes = ['../..'], - name = 'libingen_client', - target = 'ingen_client', - install_path = '${LIBDIR}', - use = 'libingen', - uselib = 'GLIBMM LV2 LILV SUIL RAUL SERD SORD SIGCPP') - - obj.source = ''' - BlockModel.cpp - ClientStore.cpp - GraphModel.cpp - ObjectModel.cpp - PluginModel.cpp - PluginUI.cpp - PortModel.cpp - ingen_client.cpp - ''' diff --git a/src/gui/.clang-tidy b/src/gui/.clang-tidy new file mode 100644 index 00000000..99bd2aba --- /dev/null +++ b/src/gui/.clang-tidy @@ -0,0 +1,29 @@ +Checks: > + -*-narrowing-conversions, + -android-cloexec-*, + -bugprone-branch-clone, + -bugprone-exception-escape, + -bugprone-macro-parentheses, + -bugprone-parent-virtual-call, + -bugprone-reserved-identifier, + -bugprone-suspicious-string-compare, + -cert-dcl21-cpp, + -cert-dcl37-c, + -cert-dcl51-cpp, + -cert-err58-cpp, + -cert-str34-c, + -clang-analyzer-core.CallAndMessage, + -cppcoreguidelines-macro-usage, + -cppcoreguidelines-pro-bounds-constant-array-index, + -cppcoreguidelines-pro-type-static-cast-downcast, + -cppcoreguidelines-pro-type-vararg, + -cppcoreguidelines-slicing, + -google-default-arguments, + -google-readability-todo, + -google-runtime-int, + -google-runtime-references, + -hicpp-multiway-paths-covered, + -hicpp-vararg, + -llvm-header-guard, + -readability-convert-member-functions-to-static, +InheritParentConfig: true diff --git a/src/gui/App.cpp b/src/gui/App.cpp index dfa34998..260afdba 100644 --- a/src/gui/App.cpp +++ b/src/gui/App.cpp @@ -18,74 +18,78 @@ #include "ConnectWindow.hpp" #include "GraphTreeWindow.hpp" -#include "GraphWindow.hpp" -#include "LoadPluginWindow.hpp" #include "MessagesWindow.hpp" -#include "NodeModule.hpp" #include "Port.hpp" #include "RDFS.hpp" #include "Style.hpp" -#include "SubgraphModule.hpp" #include "ThreadedLoader.hpp" #include "WidgetFactory.hpp" #include "WindowFactory.hpp" #include "rgba.hpp" -#include "ganv/Edge.hpp" -#include "ingen/Configuration.hpp" -#include "ingen/EngineBase.hpp" -#include "ingen/Interface.hpp" -#include "ingen/Log.hpp" -#include "ingen/QueuedInterface.hpp" -#include "ingen/StreamWriter.hpp" -#include "ingen/World.hpp" -#include "ingen/client/ClientStore.hpp" -#include "ingen/client/GraphModel.hpp" -#include "ingen/client/ObjectModel.hpp" -#include "ingen/client/PortModel.hpp" -#include "ingen/client/SigClientInterface.hpp" -#include "ingen/runtime_paths.hpp" -#include "lilv/lilv.h" -#include "raul/Path.hpp" -#include "suil/suil.h" - -#include <boost/variant/get.hpp> -#include <gtk/gtkwindow.h> +#include <ingen/Atom.hpp> +#include <ingen/ColorContext.hpp> +#include <ingen/Configuration.hpp> +#include <ingen/EngineBase.hpp> +#include <ingen/Forge.hpp> +#include <ingen/Interface.hpp> +#include <ingen/Log.hpp> +#include <ingen/Message.hpp> +#include <ingen/Properties.hpp> +#include <ingen/QueuedInterface.hpp> +#include <ingen/Resource.hpp> +#include <ingen/Status.hpp> +#include <ingen/StreamWriter.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIs.hpp> +#include <ingen/World.hpp> +#include <ingen/client/ClientStore.hpp> +#include <ingen/client/PluginModel.hpp> +#include <ingen/client/PortModel.hpp> +#include <ingen/client/SigClientInterface.hpp> +#include <ingen/fmt.hpp> +#include <ingen/runtime_paths.hpp> +#include <lilv/lilv.h> +#include <lv2/urid/urid.h> +#include <suil/suil.h> + +#include <glib.h> +#include <glibmm/main.h> +#include <glibmm/miscutils.h> +#include <glibmm/propertyproxy.h> +#include <glibmm/ustring.h> +#include <gtk/gtk.h> +#include <gtkmm/aboutdialog.h> +#include <gtkmm/dialog.h> +#include <gtkmm/enums.h> +#include <gtkmm/main.h> +#include <gtkmm/messagedialog.h> +#include <gtkmm/rc.h> #include <gtkmm/stock.h> +#include <gtkmm/widget.h> +#include <sigc++/functors/mem_fun.h> +#include <sigc++/functors/slot.h> +#include <algorithm> #include <cassert> -#include <fstream> +#include <cstdarg> +#include <cstdio> +#include <exception> +#include <iostream> +#include <map> +#include <memory> #include <string> #include <utility> +#include <variant> -namespace Raul { class Deletable; } - -namespace ingen { - -namespace client { class PluginModel; } - -using namespace client; - -namespace gui { - -class Port; +namespace ingen::gui { Gtk::Main* App::_main = nullptr; App::App(ingen::World& world) - : _style(new Style(*this)) - , _about_dialog(nullptr) - , _window_factory(new WindowFactory(*this)) - , _world(world) - , _sample_rate(48000) - , _block_length(1024) - , _n_threads(1) - , _mean_run_load(0.0f) - , _min_run_load(0.0f) - , _max_run_load(0.0f) - , _enable_signal(true) - , _requested_plugins(false) - , _is_plugin(false) + : _style(new Style(*this)) + , _window_factory(new WindowFactory(*this)) + , _world(world) { _world.conf().load_default("ingen", "gui.ttl"); @@ -99,11 +103,13 @@ App::App(ingen::World& world) _about_dialog->property_program_name() = "Ingen"; _about_dialog->property_logo_icon_name() = "ingen"; - PluginModel::set_rdf_world(*world.rdf_world()); - PluginModel::set_lilv_world(world.lilv_world()); + client::PluginModel::set_rdf_world(*world.rdf_world()); + client::PluginModel::set_lilv_world(world.lilv_world()); - using namespace std::placeholders; - world.log().set_sink(std::bind(&MessagesWindow::log, _messages_window, _1, _2, _3)); + world.log().set_sink( + [this](const LV2_URID type, const char* fmt, va_list args) { + return _messages_window->log(type, fmt, args); + }); } App::~App() @@ -112,7 +118,7 @@ App::~App() delete _window_factory; } -SPtr<App> +std::shared_ptr<App> App::create(ingen::World& world) { suil_init(&world.argc(), &world.argv(), SUIL_ARG_NONE); @@ -128,7 +134,7 @@ App::create(ingen::World& world) _main = new Gtk::Main(&world.argc(), &world.argv()); } - auto app = SPtr<App>{new App(world)}; + auto app = std::shared_ptr<App>(new App(world)); // Load configuration settings app->style()->load_settings(); @@ -151,16 +157,16 @@ App::run() // with 'ingen -egl' we'd get a bunch of notifications about load // immediately before even knowing about the root graph or plugins) while (!_connect_window->attached()) { - if (_main->iteration()) { + if (Gtk::Main::iteration()) { break; } } - _main->run(); + Gtk::Main::run(); } void -App::attach(SPtr<ingen::Interface> client) +App::attach(const std::shared_ptr<ingen::Interface>& client) { assert(!_client); assert(!_store); @@ -171,21 +177,26 @@ App::attach(SPtr<ingen::Interface> client) } _client = client; - _store = SPtr<ClientStore>(new ClientStore(_world.uris(), _world.log(), sig_client())); - _loader = SPtr<ThreadedLoader>(new ThreadedLoader(*this, _world.interface())); + + _store = std::make_shared<client::ClientStore>(_world.uris(), + _world.log(), + sig_client()); + + _loader = std::make_shared<ThreadedLoader>(*this, _world.interface()); + if (!_world.store()) { _world.set_store(_store); } if (_world.conf().option("dump").get<int32_t>()) { - _dumper = SPtr<StreamWriter>(new StreamWriter(_world.uri_map(), - _world.uris(), - URI("ingen:/client"), - stderr, - ColorContext::Color::CYAN)); + _dumper = std::make_shared<StreamWriter>(_world.uri_map(), + _world.uris(), + URI("ingen:/client"), + stderr, + ColorContext::Color::CYAN); sig_client()->signal_message().connect( - sigc::mem_fun(*_dumper.get(), &StreamWriter::message)); + sigc::mem_fun(*_dumper, &StreamWriter::message)); } _graph_tree_window->init(*this, *_store); @@ -202,7 +213,7 @@ App::detach() _loader.reset(); _store.reset(); _client.reset(); - _world.set_interface(SPtr<Interface>()); + _world.set_interface(nullptr); } } @@ -215,17 +226,17 @@ App::request_plugins_if_necessary() } } -SPtr<SigClientInterface> +std::shared_ptr<client::SigClientInterface> App::sig_client() { - SPtr<QueuedInterface> qi = dynamic_ptr_cast<QueuedInterface>(_client); + auto qi = std::dynamic_pointer_cast<QueuedInterface>(_client); if (qi) { - return dynamic_ptr_cast<SigClientInterface>(qi->sink()); + return std::dynamic_pointer_cast<client::SigClientInterface>(qi->sink()); } - return dynamic_ptr_cast<SigClientInterface>(_client); + return std::dynamic_pointer_cast<client::SigClientInterface>(_client); } -SPtr<Serialiser> +std::shared_ptr<Serialiser> App::serialiser() { return _world.serialiser(); @@ -234,13 +245,13 @@ App::serialiser() void App::message(const Message& msg) { - if (const Response* const r = boost::get<Response>(&msg)) { + if (const Response* const r = std::get_if<Response>(&msg)) { response(r->id, r->status, r->subject); - } else if (const Error* const e = boost::get<Error>(&msg)) { + } else if (const Error* const e = std::get_if<Error>(&msg)) { error_message(e->message); - } else if (const Put* const p = boost::get<Put>(&msg)) { + } else if (const Put* const p = std::get_if<Put>(&msg)) { put(p->uri, p->properties, p->ctx); - } else if (const SetProperty* const s = boost::get<SetProperty>(&msg)) { + } else if (const SetProperty* const s = std::get_if<SetProperty>(&msg)) { property_change(s->subject, s->predicate, s->value, s->ctx); } } @@ -312,7 +323,9 @@ App::property_change(const URI& subject, { if (subject != URI("ingen:/engine")) { return; - } else if (key == uris().param_sampleRate && value.type() == forge().Int) { + } + + if (key == uris().param_sampleRate && value.type() == forge().Int) { _sample_rate = value.get<int32_t>(); } else if (key == uris().bufsz_maxBlockLength && value.type() == forge().Int) { _block_length = value.get<int32_t>(); @@ -354,7 +367,7 @@ App::status_text() const return fmt( "%2.1f kHz / %.1f ms, %s, %s DSP", (_sample_rate / 1e3f), - (_block_length * 1e3f / (float)_sample_rate), + (_block_length * 1e3f / static_cast<float>(_sample_rate)), ((_n_threads == 1) ? "1 thread" : fmt("%1% threads", _n_threads)), fraction_label(_max_run_load)); } @@ -362,7 +375,7 @@ App::status_text() const void App::port_activity(Port* port) { - std::pair<ActivityPorts::iterator, bool> inserted = _activity_ports.emplace(port, false); + const auto inserted = _activity_ports.emplace(port, false); if (inserted.second) { inserted.first->second = false; } @@ -428,7 +441,7 @@ App::gtk_main_iteration() return false; } } else { - dynamic_ptr_cast<QueuedInterface>(_client)->emit(); + std::dynamic_pointer_cast<QueuedInterface>(_client)->emit(); } _enable_signal = true; @@ -495,5 +508,4 @@ App::sample_rate() const return _sample_rate; } -} // namespace gui -} // namespace ingen +} // namespace ingen::gui diff --git a/src/gui/App.hpp b/src/gui/App.hpp index 13c46414..0138f25a 100644 --- a/src/gui/App.hpp +++ b/src/gui/App.hpp @@ -17,47 +17,51 @@ #ifndef INGEN_GUI_APP_HPP #define INGEN_GUI_APP_HPP -#include "ingen/Atom.hpp" -#include "ingen/Message.hpp" -#include "ingen/Resource.hpp" -#include "ingen/Status.hpp" -#include "ingen/World.hpp" -#include "ingen/ingen.h" -#include "ingen/types.hpp" -#include "lilv/lilv.h" -#include "raul/Deletable.hpp" - -#include <gtkmm/aboutdialog.h> -#include <gtkmm/main.h> -#include <gtkmm/window.h> - -#include <unordered_map> +#include <ingen/Message.hpp> +#include <ingen/Properties.hpp> +#include <ingen/Resource.hpp> +#include <ingen/URI.hpp> +#include <ingen/World.hpp> +#include <ingen/ingen.h> +#include <lilv/lilv.h> + +#include <sigc++/signal.h> + +#include <cstdint> +#include <memory> #include <string> +#include <unordered_map> + +namespace Gtk { +class AboutDialog; +class Main; +class Widget; +class Window; +} // namespace Gtk namespace ingen { +enum class Status; + +class Atom; +class Forge; class Interface; class Log; -class Port; class Serialiser; class StreamWriter; -class World; +class URIs; namespace client { class ClientStore; -class GraphModel; -class PluginModel; class PortModel; class SigClientInterface; -} +} // namespace client namespace gui { class ConnectWindow; -class GraphCanvas; -class GraphTreeView; class GraphTreeWindow; class MessagesWindow; class Port; @@ -73,9 +77,14 @@ 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(SPtr<ingen::Interface> client); + void attach(const std::shared_ptr<ingen::Interface>& client); void detach(); @@ -94,7 +103,7 @@ public: bool signal() const { return _enable_signal; } void enable_signals(bool b) { _enable_signal = b; } bool disable_signals() { - bool old = _enable_signal; + const bool old = _enable_signal; _enable_signal = false; return old; } @@ -118,17 +127,17 @@ public: Style* style() const { return _style; } WindowFactory* window_factory() const { return _window_factory; } - ingen::Forge& forge() const { return _world.forge(); } - SPtr<ingen::Interface> interface() const { return _world.interface(); } - SPtr<ingen::Interface> client() const { return _client; } - SPtr<client::ClientStore> store() const { return _store; } - SPtr<ThreadedLoader> loader() const { return _loader; } + ingen::Forge& forge() const { return _world.forge(); } + std::shared_ptr<ingen::Interface> interface() const { return _world.interface(); } + std::shared_ptr<ingen::Interface> client() const { return _client; } + std::shared_ptr<client::ClientStore> store() const { return _store; } + std::shared_ptr<ThreadedLoader> loader() const { return _loader; } - SPtr<client::SigClientInterface> sig_client(); + std::shared_ptr<client::SigClientInterface> sig_client(); - SPtr<Serialiser> serialiser(); + std::shared_ptr<Serialiser> serialiser(); - static SPtr<App> create(ingen::World& world); + static std::shared_ptr<App> create(ingen::World& world); void run(); @@ -136,9 +145,9 @@ public: sigc::signal<void, const std::string&> signal_status_text_changed; - inline ingen::World& world() const { return _world; } - inline ingen::URIs& uris() const { return _world.uris(); } - inline ingen::Log& log() const { return _world.log(); } + ingen::World& world() const { return _world; } + ingen::URIs& uris() const { return _world.uris(); } + ingen::Log& log() const { return _world.log(); } protected: explicit App(ingen::World& world); @@ -159,35 +168,35 @@ protected: static Gtk::Main* _main; - SPtr<ingen::Interface> _client; - SPtr<client::ClientStore> _store; - SPtr<ThreadedLoader> _loader; - SPtr<StreamWriter> _dumper; + std::shared_ptr<ingen::Interface> _client; + std::shared_ptr<client::ClientStore> _store; + std::shared_ptr<ThreadedLoader> _loader; + std::shared_ptr<StreamWriter> _dumper; Style* _style; - ConnectWindow* _connect_window; - MessagesWindow* _messages_window; - GraphTreeWindow* _graph_tree_window; - Gtk::AboutDialog* _about_dialog; - WindowFactory* _window_factory; + ConnectWindow* _connect_window = nullptr; + MessagesWindow* _messages_window = nullptr; + GraphTreeWindow* _graph_tree_window = nullptr; + Gtk::AboutDialog* _about_dialog = nullptr; + WindowFactory* _window_factory = nullptr; ingen::World& _world; - int32_t _sample_rate; - int32_t _block_length; - int32_t _n_threads; - float _mean_run_load; - float _min_run_load; - float _max_run_load; + int32_t _sample_rate{48000}; + int32_t _block_length{1024}; + int32_t _n_threads{1}; + float _mean_run_load{0.0f}; + float _min_run_load{0.0f}; + float _max_run_load{0.0f}; std::string _status_text; using ActivityPorts = std::unordered_map<Port*, bool>; ActivityPorts _activity_ports; - bool _enable_signal; - bool _requested_plugins; - bool _is_plugin; + bool _enable_signal{true}; + bool _requested_plugins{false}; + bool _is_plugin{false}; }; } // namespace gui diff --git a/src/gui/Arc.cpp b/src/gui/Arc.cpp index d811bd22..c13cf4a7 100644 --- a/src/gui/Arc.cpp +++ b/src/gui/Arc.cpp @@ -16,24 +16,30 @@ #include "Arc.hpp" -#include "ingen/client/ArcModel.hpp" -#include "ingen/client/BlockModel.hpp" +#include <ganv/Edge.hpp> +#include <ingen/URI.hpp> +#include <ingen/client/ArcModel.hpp> +#include <ingen/client/BlockModel.hpp> +#include <ingen/client/ObjectModel.hpp> +#include <ingen/client/PortModel.hpp> + +#include <glib-object.h> + +#include <memory> #define NS_INTERNALS "http://drobilla.net/ns/ingen-internals#" -namespace ingen { -namespace gui { +namespace ingen::gui { -Arc::Arc(Ganv::Canvas& canvas, - SPtr<const client::ArcModel> model, - Ganv::Node* src, - Ganv::Node* dst) - : Ganv::Edge(canvas, src, dst) - , _arc_model(model) +Arc::Arc(Ganv::Canvas& canvas, + const std::shared_ptr<const client::ArcModel>& model, + Ganv::Node* src, + Ganv::Node* dst) + : Ganv::Edge(canvas, src, dst), _arc_model(model) { - SPtr<const client::ObjectModel> tparent = model->tail()->parent(); - SPtr<const client::BlockModel> tparent_block; - if ((tparent_block = dynamic_ptr_cast<const client::BlockModel>(tparent))) { + const std::shared_ptr<const client::ObjectModel> tparent = model->tail()->parent(); + std::shared_ptr<const client::BlockModel> tparent_block; + if ((tparent_block = std::dynamic_pointer_cast<const client::BlockModel>(tparent))) { if (tparent_block->plugin_uri() == NS_INTERNALS "BlockDelay") { g_object_set(_gobj, "dash-length", 4.0, nullptr); set_constraining(false); @@ -41,5 +47,4 @@ Arc::Arc(Ganv::Canvas& canvas, } } -} // namespace gui -} // namespace ingen +} // namespace ingen::gui diff --git a/src/gui/Arc.hpp b/src/gui/Arc.hpp index 453985fc..ad1bc6f2 100644 --- a/src/gui/Arc.hpp +++ b/src/gui/Arc.hpp @@ -17,14 +17,20 @@ #ifndef INGEN_GUI_ARC_HPP #define INGEN_GUI_ARC_HPP -#include "ganv/Edge.hpp" -#include "ingen/types.hpp" +#include <ganv/Edge.hpp> -#include <cassert> +#include <memory> + +namespace Ganv { +class Canvas; +class Node; +} // namespace Ganv namespace ingen { -namespace client { class ArcModel; } +namespace client { +class ArcModel; +} // namespace client namespace gui { @@ -35,15 +41,15 @@ namespace gui { class Arc : public Ganv::Edge { public: - Arc(Ganv::Canvas& canvas, - SPtr<const client::ArcModel> model, - Ganv::Node* src, - Ganv::Node* dst); + Arc(Ganv::Canvas& canvas, + const std::shared_ptr<const client::ArcModel>& model, + Ganv::Node* src, + Ganv::Node* dst); - SPtr<const client::ArcModel> model() const { return _arc_model; } + std::shared_ptr<const client::ArcModel> model() const { return _arc_model; } private: - SPtr<const client::ArcModel> _arc_model; + std::shared_ptr<const client::ArcModel> _arc_model; }; } // namespace gui diff --git a/src/gui/BreadCrumbs.cpp b/src/gui/BreadCrumbs.cpp index 33b2c4b3..5bd4d30a 100644 --- a/src/gui/BreadCrumbs.cpp +++ b/src/gui/BreadCrumbs.cpp @@ -17,23 +17,29 @@ #include "BreadCrumbs.hpp" #include "App.hpp" +#include "GraphView.hpp" -#include "ingen/client/SigClientInterface.hpp" +#include <ingen/Message.hpp> +#include <ingen/URI.hpp> +#include <ingen/client/GraphModel.hpp> +#include <ingen/client/SigClientInterface.hpp> +#include <raul/Path.hpp> +#include <raul/Symbol.hpp> -#include <boost/variant/get.hpp> +#include <sigc++/adaptors/bind.h> +#include <sigc++/functors/mem_fun.h> +#include <algorithm> #include <string> +#include <variant> -namespace ingen { -namespace gui { +namespace ingen::gui { using std::string; BreadCrumbs::BreadCrumbs(App& app) - : Gtk::HBox() - , _active_path("/") + : _active_path("/") , _full_path("/") - , _enable_signal(true) { app.sig_client()->signal_message().connect( sigc::mem_fun(this, &BreadCrumbs::message)); @@ -41,16 +47,16 @@ BreadCrumbs::BreadCrumbs(App& app) set_can_focus(false); } -SPtr<GraphView> -BreadCrumbs::view(const Raul::Path& path) +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 SPtr<GraphView>(); + return b == _breadcrumbs.end() ? nullptr : (*b)->view(); } /** Sets up the crumbs to display `path`. @@ -59,21 +65,22 @@ BreadCrumbs::view(const Raul::Path& path) * children preserved. */ void -BreadCrumbs::build(Raul::Path path, SPtr<GraphView> view) +BreadCrumbs::build(const raul::Path& path, + const std::shared_ptr<GraphView>& view) { - bool old_enable_signal = _enable_signal; + const bool old_enable_signal = _enable_signal; _enable_signal = false; 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()) { b->set_view(view); } - // views are expensive, having two around for the same graph is a bug + // Views are expensive, having two around is a bug assert(b->view() == view); } else { @@ -82,71 +89,70 @@ BreadCrumbs::build(Raul::Path path, SPtr<GraphView> view) } _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, just append crumbs (preserve view cache) + // Moving to a child of the full path, append crumbs (preserve cache) string suffix = path.substr(_full_path.length()); - while (suffix.length() > 0) { + while (!suffix.empty()) { if (suffix[0] == '/') { suffix = suffix.substr(1); } - const string name = suffix.substr(0, suffix.find("/")); - _full_path = _full_path.child(Raul::Symbol(name)); + const string name = suffix.substr(0, suffix.find('/')); + _full_path = _full_path.child(raul::Symbol(name)); BreadCrumb* but = create_crumb(_full_path, view); pack_start(*but, false, false, 1); _breadcrumbs.push_back(but); but->show(); - if (suffix.find("/") == string::npos) { + if (suffix.find('/') == string::npos) { break; - } else { - suffix = suffix.substr(suffix.find("/")+1); } + + suffix = suffix.substr(suffix.find('/') + 1); } - for (const auto& b : _breadcrumbs) { + for (auto* b : _breadcrumbs) { b->set_active(false); } _breadcrumbs.back()->set_active(true); } else { - // Rebuild from scratch - // Getting here is bad unless absolutely necessary, since the GraphView cache is lost + /* Rebuild from scratch. Getting here is bad unless absolutely + necessary, since the GraphView cache is lost. */ _full_path = path; _active_path = path; // Empty existing breadcrumbs - for (const auto& b : _breadcrumbs) { + for (auto* b : _breadcrumbs) { remove(*b); } _breadcrumbs.clear(); // Add root - BreadCrumb* root_but = create_crumb(Raul::Path("/"), view); + BreadCrumb* root_but = create_crumb(raul::Path("/"), view); pack_start(*root_but, false, false, 1); _breadcrumbs.push_front(root_but); root_but->set_active(root_but->path() == _active_path); - Raul::Path working_path("/"); + raul::Path working_path("/"); string suffix = path.substr(1); - while (suffix.length() > 0) { + while (!suffix.empty()) { if (suffix[0] == '/') { suffix = suffix.substr(1); } - const string name = suffix.substr(0, suffix.find("/")); - working_path = working_path.child(Raul::Symbol(name)); + const string name = suffix.substr(0, suffix.find('/')); + working_path = working_path.child(raul::Symbol(name)); BreadCrumb* but = create_crumb(working_path, view); pack_start(*but, false, false, 1); _breadcrumbs.push_back(but); but->set_active(working_path == _active_path); but->show(); - if (suffix.find("/") == string::npos) { + if (suffix.find('/') == string::npos) { break; - } else { - suffix = suffix.substr(suffix.find("/")+1); } + + suffix = suffix.substr(suffix.find('/')+1); } } @@ -157,13 +163,11 @@ BreadCrumbs::build(Raul::Path path, SPtr<GraphView> view) * match, otherwise ignoring `view`. */ BreadCrumbs::BreadCrumb* -BreadCrumbs::create_crumb(const Raul::Path& path, - SPtr<GraphView> view) +BreadCrumbs::create_crumb(const raul::Path& path, + const std::shared_ptr<GraphView>& view) { - BreadCrumb* but = manage( - new BreadCrumb(path, - ((view && path == view->graph()->path()) - ? view : SPtr<GraphView>()))); + BreadCrumb* but = manage(new BreadCrumb( + path, ((view && path == view->graph()->path()) ? view : nullptr))); but->signal_toggled().connect( sigc::bind(sigc::mem_fun(this, &BreadCrumbs::breadcrumb_clicked), @@ -194,7 +198,7 @@ BreadCrumbs::breadcrumb_clicked(BreadCrumb* crumb) void BreadCrumbs::message(const Message& msg) { - if (const Del* const del = boost::get<Del>(&msg)) { + if (const Del* const del = std::get_if<Del>(&msg)) { object_destroyed(del->uri); } } @@ -202,28 +206,31 @@ 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); } } } void -BreadCrumbs::object_moved(const Raul::Path& old_path, const Raul::Path& new_path) +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); } } } -} // namespace gui -} // namespace ingen +} // namespace ingen::gui diff --git a/src/gui/BreadCrumbs.hpp b/src/gui/BreadCrumbs.hpp index 63872a78..89a339f2 100644 --- a/src/gui/BreadCrumbs.hpp +++ b/src/gui/BreadCrumbs.hpp @@ -19,21 +19,26 @@ #include "GraphView.hpp" -#include "ingen/Message.hpp" -#include "ingen/client/GraphModel.hpp" -#include "ingen/types.hpp" -#include "raul/Path.hpp" +#include <ingen/Message.hpp> +#include <ingen/URI.hpp> +#include <ingen/client/GraphModel.hpp> +#include <raul/Path.hpp> +#include <glibmm/ustring.h> #include <gtkmm/box.h> #include <gtkmm/label.h> +#include <gtkmm/object.h> #include <gtkmm/togglebutton.h> +#include <sigc++/signal.h> #include <cassert> #include <list> +#include <memory> #include <string> -namespace ingen { -namespace gui { +namespace ingen::gui { + +class App; /** Collection of breadcrumb buttons forming a path. * This doubles as a cache for GraphViews. @@ -45,11 +50,12 @@ class BreadCrumbs : public Gtk::HBox public: explicit BreadCrumbs(App& app); - SPtr<GraphView> view(const Raul::Path& path); + std::shared_ptr<GraphView> view(const raul::Path& path); - void build(Raul::Path path, SPtr<GraphView> view); + void build(const raul::Path& path, const std::shared_ptr<GraphView>& view); - sigc::signal<void, const Raul::Path&, SPtr<GraphView> > signal_graph_selected; + sigc::signal<void, const raul::Path&, std::shared_ptr<GraphView>> + signal_graph_selected; private: /** Breadcrumb button. @@ -64,9 +70,9 @@ private: class BreadCrumb : public Gtk::ToggleButton { public: - BreadCrumb(const Raul::Path& path, SPtr<GraphView> view = SPtr<GraphView>()) - : _path(path) - , _view(view) + BreadCrumb(const raul::Path& path, + const std::shared_ptr<GraphView>& view) + : _path(path), _view(view) { assert(!view || view->graph()->path() == path); set_border_width(0); @@ -75,15 +81,19 @@ private: show_all(); } - void set_view(SPtr<GraphView> view) { + 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; } - const Raul::Path& path() const { return _path; } - SPtr<GraphView> view() const { return _view; } + const raul::Path& path() const { return _path; } + std::shared_ptr<GraphView> view() const { return _view; } - void set_path(const Raul::Path& path) { + void set_path(const raul::Path& path) { remove(); const char* text = (path.is_root()) ? "/" : path.symbol(); Gtk::Label* lab = manage(new Gtk::Label(text)); @@ -91,31 +101,31 @@ private: lab->show(); add(*lab); - if (_view && _view->graph()->path() != path) + if (_view && _view->graph()->path() != path) { _view.reset(); + } } private: - Raul::Path _path; - SPtr<GraphView> _view; + raul::Path _path; + std::shared_ptr<GraphView> _view; }; - BreadCrumb* create_crumb(const Raul::Path& path, - SPtr<GraphView> view = SPtr<GraphView>()); + BreadCrumb* create_crumb(const raul::Path& path, + const std::shared_ptr<GraphView>& view = nullptr); void breadcrumb_clicked(BreadCrumb* crumb); void message(const Message& msg); void object_destroyed(const URI& uri); - void object_moved(const Raul::Path& old_path, const Raul::Path& new_path); + void object_moved(const raul::Path& old_path, const raul::Path& new_path); - Raul::Path _active_path; - Raul::Path _full_path; - bool _enable_signal; + raul::Path _active_path; + raul::Path _full_path; + bool _enable_signal{true}; std::list<BreadCrumb*> _breadcrumbs; }; -} // namespace gui -} // namespace ingen +} // namespace ingen::gui #endif // INGEN_GUI_BREADCRUMBS_HPP diff --git a/src/gui/ConnectWindow.cpp b/src/gui/ConnectWindow.cpp index 209475e0..edafdfa4 100644 --- a/src/gui/ConnectWindow.cpp +++ b/src/gui/ConnectWindow.cpp @@ -17,69 +17,71 @@ #include "ConnectWindow.hpp" #include "App.hpp" +#include "Window.hpp" #include "WindowFactory.hpp" -#include "ingen/Configuration.hpp" -#include "ingen/EngineBase.hpp" -#include "ingen/Interface.hpp" -#include "ingen/Log.hpp" -#include "ingen/Module.hpp" -#include "ingen/QueuedInterface.hpp" -#include "ingen/World.hpp" -#include "ingen/client/ClientStore.hpp" -#include "ingen/client/GraphModel.hpp" -#include "ingen/client/SigClientInterface.hpp" -#include "ingen/client/SocketClient.hpp" -#include "ingen_config.h" -#include "raul/Process.hpp" - -#include <boost/variant/get.hpp> +#include <ingen/Atom.hpp> +#include <ingen/Configuration.hpp> +#include <ingen/EngineBase.hpp> +#include <ingen/Forge.hpp> +#include <ingen/Interface.hpp> +#include <ingen/Log.hpp> +#include <ingen/Message.hpp> +#include <ingen/QueuedInterface.hpp> +#include <ingen/Status.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIs.hpp> +#include <ingen/World.hpp> +#include <ingen/client/ClientStore.hpp> +#include <ingen/client/GraphModel.hpp> +#include <ingen/client/SigClientInterface.hpp> +#include <ingen/client/SocketClient.hpp> +#include <ingen/fmt.hpp> +#include <ingen/paths.hpp> +#include <raul/Path.hpp> +#include <raul/Process.hpp> + #include <glib.h> +#include <glibmm/main.h> +#include <glibmm/ustring.h> +#include <gtkmm/builder.h> +#include <gtkmm/button.h> +#include <gtkmm/dialog.h> +#include <gtkmm/entry.h> +#include <gtkmm/enums.h> +#include <gtkmm/image.h> +#include <gtkmm/label.h> +#include <gtkmm/main.h> +#include <gtkmm/progressbar.h> +#include <gtkmm/radiobutton.h> +#include <gtkmm/spinbutton.h> #include <gtkmm/stock.h> +#include <sigc++/adaptors/bind.h> +#include <sigc++/functors/mem_fun.h> +#include <sigc++/functors/slot.h> +#include <sigc++/signal.h> #include <limits> +#include <memory> #include <string> +#include <sys/time.h> #include <utility> +#include <variant> -using namespace ingen::client; - -namespace ingen { -namespace gui { +namespace ingen::gui { ConnectWindow::ConnectWindow(BaseObjectType* cobject, Glib::RefPtr<Gtk::Builder> xml) : Dialog(cobject) , _xml(std::move(xml)) - , _icon(nullptr) - , _progress_bar(nullptr) - , _progress_label(nullptr) - , _url_entry(nullptr) - , _server_radio(nullptr) - , _port_spinbutton(nullptr) - , _launch_radio(nullptr) - , _internal_radio(nullptr) - , _activate_button(nullptr) - , _deactivate_button(nullptr) - , _disconnect_button(nullptr) - , _connect_button(nullptr) - , _quit_button(nullptr) - , _mode(Mode::CONNECT_REMOTE) - , _connect_uri("unix:///tmp/ingen.sock") - , _ping_id(-1) - , _attached(false) - , _finished_connecting(false) - , _widgets_loaded(false) - , _connect_stage(0) - , _quit_flag(false) -{ -} +{} void ConnectWindow::message(const Message& msg) { - if (const Response* const r = boost::get<Response>(&msg)) { + if (const Response* const r = std::get_if<Response>(&msg)) { ingen_response(r->id, r->status, r->subject); - } else if (const Error* const e = boost::get<Error>(&msg)) { + } else if (const Error* const e = std::get_if<Error>(&msg)) { error(e->message); } } @@ -111,7 +113,7 @@ ConnectWindow::start(App& app, ingen::World& world) } set_connected_to(world.interface()); - connect(bool(world.interface())); + connect(!!world.interface()); } void @@ -129,7 +131,7 @@ ConnectWindow::ingen_response(int32_t id, } void -ConnectWindow::set_connected_to(SPtr<ingen::Interface> engine) +ConnectWindow::set_connected_to(const std::shared_ptr<ingen::Interface>& engine) { _app->world().set_interface(engine); @@ -195,10 +197,10 @@ ConnectWindow::connect_remote(const URI& uri) { ingen::World& world = _app->world(); - SPtr<SigClientInterface> sci(new SigClientInterface()); - SPtr<QueuedInterface> qi(new QueuedInterface(sci)); + auto sci = std::make_shared<client::SigClientInterface>(); + auto qi = std::make_shared<QueuedInterface>(sci); - SPtr<ingen::Interface> iface(world.new_interface(uri, qi)); + const std::shared_ptr<ingen::Interface> iface{world.new_interface(uri, qi)}; if (iface) { world.set_interface(iface); _app->attach(qi); @@ -216,10 +218,10 @@ ConnectWindow::connect(bool existing) if (_app->client()) { error("Already connected"); return; - } else if (_attached) { - _attached = false; } + _attached = false; + set_connecting_widget_states(); _connect_stage = 0; @@ -230,7 +232,7 @@ ConnectWindow::connect(bool existing) if (existing) { uri_str = world.interface()->uri(); _connect_stage = 1; - SPtr<client::SocketClient> client = dynamic_ptr_cast<client::SocketClient>( + auto client = std::dynamic_pointer_cast<client::SocketClient>( world.interface()); if (client) { _app->attach(client->respondee()); @@ -254,7 +256,7 @@ ConnectWindow::connect(bool existing) const std::string port = std::to_string(_port_spinbutton->get_value_as_int()); const char* cmd[] = { "ingen", "-e", "-E", port.c_str(), nullptr }; - if (!Raul::Process::launch(cmd)) { + if (!raul::Process::launch(cmd)) { error("Failed to launch engine process"); return; } @@ -266,10 +268,14 @@ ConnectWindow::connect(bool existing) if (!world.load_module("server")) { error("Failed to load server module"); return; - } else if (!world.load_module("jack")) { + } + + if (!world.load_module("jack")) { error("Failed to load jack module"); return; - } else if (!world.engine()->activate()) { + } + + if (!world.engine()->activate()) { error("Failed to activate engine"); return; } @@ -291,7 +297,7 @@ ConnectWindow::disconnect() _attached = false; _app->detach(); - set_connected_to(SPtr<ingen::Interface>()); + set_connected_to(nullptr); if (!_widgets_loaded) { return; @@ -437,18 +443,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]); } } @@ -463,7 +468,7 @@ ConnectWindow::gtk_callback() } // Timing stuff for repeated attach attempts - timeval now; + timeval now = {}; gettimeofday(&now, nullptr); static const timeval start = now; static timeval last = now; @@ -471,8 +476,8 @@ ConnectWindow::gtk_callback() // Show if attempted connection goes on for a noticeable amount of time if (!is_visible()) { - const float ms_since_start = (now.tv_sec - start.tv_sec) * 1000.0f + - (now.tv_usec - start.tv_usec) * 0.001f; + const float ms_since_start = ((now.tv_sec - start.tv_sec) * 1000.0f) + + ((now.tv_usec - start.tv_usec) * 0.001f); if (ms_since_start > 500) { present(); set_connecting_widget_states(); @@ -480,12 +485,12 @@ ConnectWindow::gtk_callback() } if (_connect_stage == 0) { - const float ms_since_last = (now.tv_sec - last.tv_sec) * 1000.0f + - (now.tv_usec - last.tv_usec) * 0.001f; + const float ms_since_last = ((now.tv_sec - last.tv_sec) * 1000.0f) + + ((now.tv_usec - last.tv_usec) * 0.001f); if (ms_since_last >= 250) { last = now; if (_mode == Mode::INTERNAL) { - SPtr<SigClientInterface> client(new SigClientInterface()); + auto client = std::make_shared<client::SigClientInterface>(); _app->world().interface()->set_respondee(client); _app->attach(client); _app->register_callbacks(); @@ -510,8 +515,8 @@ ConnectWindow::gtk_callback() if (_attached) { next_stage(); } else { - const float ms_since_last = (now.tv_sec - last.tv_sec) * 1000.0f + - (now.tv_usec - last.tv_usec) * 0.001f; + const float ms_since_last = ((now.tv_sec - last.tv_sec) * 1000.0f) + + ((now.tv_usec - last.tv_usec) * 0.001f); if (attempts > 10) { error("Failed to ping engine"); _connect_stage = -1; @@ -527,8 +532,8 @@ ConnectWindow::gtk_callback() next_stage(); } else if (_connect_stage == 4) { if (!_app->store()->empty()) { - SPtr<const GraphModel> root = dynamic_ptr_cast<const GraphModel>( - _app->store()->object(Raul::Path("/"))); + auto root = std::dynamic_pointer_cast<const client::GraphModel>( + _app->store()->object(raul::Path("/"))); if (root) { set_connected_to(_app->interface()); _app->window_factory()->present_graph(root); @@ -557,9 +562,9 @@ ConnectWindow::gtk_callback() _progress_label->set_text(std::string("Disconnected")); } return false; - } else { - return true; } + + return true; } void @@ -569,5 +574,4 @@ ConnectWindow::quit() Gtk::Main::quit(); } -} // namespace gui -} // namespace ingen +} // namespace ingen::gui diff --git a/src/gui/ConnectWindow.hpp b/src/gui/ConnectWindow.hpp index 882e0142..cd9059e1 100644 --- a/src/gui/ConnectWindow.hpp +++ b/src/gui/ConnectWindow.hpp @@ -19,24 +19,30 @@ #include "Window.hpp" -#include "ingen/Message.hpp" -#include "ingen/types.hpp" -#include "lilv/lilv.h" +#include <ingen/Message.hpp> +#include <ingen/URI.hpp> +#include <glibmm/refptr.h> #include <gtkmm/builder.h> -#include <gtkmm/button.h> -#include <gtkmm/entry.h> -#include <gtkmm/image.h> -#include <gtkmm/label.h> -#include <gtkmm/progressbar.h> -#include <gtkmm/radiobutton.h> -#include <gtkmm/spinbutton.h> #include <cstdint> +#include <memory> #include <string> +namespace Gtk { +class Button; +class Entry; +class Image; +class Label; +class ProgressBar; +class RadioButton; +class SpinButton; +} // namespace Gtk + namespace ingen { +enum class Status; + class Interface; class World; @@ -57,7 +63,7 @@ public: ConnectWindow(BaseObjectType* cobject, Glib::RefPtr<Gtk::Builder> xml); - void set_connected_to(SPtr<ingen::Interface> engine); + void set_connected_to(const std::shared_ptr<ingen::Interface>& engine); void start(App& app, ingen::World& world); bool attached() const { return _finished_connecting; } @@ -94,28 +100,28 @@ private: const Glib::RefPtr<Gtk::Builder> _xml; - Gtk::Image* _icon; - Gtk::ProgressBar* _progress_bar; - Gtk::Label* _progress_label; - Gtk::Entry* _url_entry; - Gtk::RadioButton* _server_radio; - Gtk::SpinButton* _port_spinbutton; - Gtk::RadioButton* _launch_radio; - Gtk::RadioButton* _internal_radio; - Gtk::Button* _activate_button; - Gtk::Button* _deactivate_button; - Gtk::Button* _disconnect_button; - Gtk::Button* _connect_button; - Gtk::Button* _quit_button; - - Mode _mode; - URI _connect_uri; - int32_t _ping_id; - bool _attached; - bool _finished_connecting; - bool _widgets_loaded; - int _connect_stage; - bool _quit_flag; + Gtk::Image* _icon{nullptr}; + Gtk::ProgressBar* _progress_bar{nullptr}; + Gtk::Label* _progress_label{nullptr}; + Gtk::Entry* _url_entry{nullptr}; + Gtk::RadioButton* _server_radio{nullptr}; + Gtk::SpinButton* _port_spinbutton{nullptr}; + Gtk::RadioButton* _launch_radio{nullptr}; + Gtk::RadioButton* _internal_radio{nullptr}; + Gtk::Button* _activate_button{nullptr}; + Gtk::Button* _deactivate_button{nullptr}; + Gtk::Button* _disconnect_button{nullptr}; + Gtk::Button* _connect_button{nullptr}; + Gtk::Button* _quit_button{nullptr}; + + Mode _mode{Mode::CONNECT_REMOTE}; + URI _connect_uri{"unix:///tmp/ingen.sock"}; + int32_t _ping_id{-1}; + bool _attached{false}; + bool _finished_connecting{false}; + bool _widgets_loaded{false}; + int _connect_stage{0}; + bool _quit_flag{false}; }; } // namespace gui diff --git a/src/gui/GraphBox.cpp b/src/gui/GraphBox.cpp index 5ce54d99..47c567e3 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 @@ -14,6 +14,8 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ +#include "GraphBox.hpp" + #include "App.hpp" #include "BreadCrumbs.hpp" #include "ConnectWindow.hpp" @@ -21,38 +23,93 @@ #include "GraphTreeWindow.hpp" #include "GraphView.hpp" #include "GraphWindow.hpp" -#include "LoadGraphWindow.hpp" -#include "LoadPluginWindow.hpp" #include "MessagesWindow.hpp" -#include "NewSubgraphWindow.hpp" -#include "Style.hpp" #include "ThreadedLoader.hpp" #include "WidgetFactory.hpp" #include "WindowFactory.hpp" #include "ingen_config.h" -#include "ingen/Configuration.hpp" -#include "ingen/Interface.hpp" -#include "ingen/Log.hpp" -#include "ingen/client/ClientStore.hpp" -#include "ingen/client/GraphModel.hpp" -#include "ingen/fmt.hpp" - -#include <boost/format.hpp> +#include <ganv/canvas.h> +#include <ingen/Atom.hpp> +#include <ingen/Configuration.hpp> +#include <ingen/Forge.hpp> +#include <ingen/Interface.hpp> +#include <ingen/Properties.hpp> +#include <ingen/Resource.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIs.hpp> +#include <ingen/World.hpp> +#include <ingen/client/BlockModel.hpp> +#include <ingen/client/ClientStore.hpp> +#include <ingen/client/GraphModel.hpp> +#include <ingen/client/ObjectModel.hpp> +#include <ingen/client/PluginModel.hpp> +#include <ingen/client/PortModel.hpp> +#include <ingen/fmt.hpp> +#include <raul/Path.hpp> +#include <raul/Symbol.hpp> + +#include <gdk/gdk.h> +#include <glib.h> #include <glib/gstdio.h> +#include <glibmm/convert.h> #include <glibmm/fileutils.h> +#include <glibmm/miscutils.h> +#include <glibmm/propertyproxy.h> +#include <glibmm/refptr.h> +#include <glibmm/ustring.h> +#include <gtkmm/alignment.h> +#include <gtkmm/box.h> +#include <gtkmm/builder.h> +#include <gtkmm/button.h> +#include <gtkmm/checkbutton.h> +#include <gtkmm/checkmenuitem.h> +#include <gtkmm/clipboard.h> +#include <gtkmm/container.h> +#include <gtkmm/dialog.h> +#include <gtkmm/enums.h> +#include <gtkmm/filechooser.h> +#include <gtkmm/filechooserdialog.h> +#include <gtkmm/filefilter.h> +#include <gtkmm/label.h> +#include <gtkmm/menuitem.h> +#include <gtkmm/messagedialog.h> +#include <gtkmm/object.h> +#include <gtkmm/paned.h> +#include <gtkmm/scrolledwindow.h> +#include <gtkmm/statusbar.h> #include <gtkmm/stock.h> -#ifdef HAVE_WEBKIT -#include <webkit/webkit.h> +#include <gtkmm/textbuffer.h> +#include <gtkmm/textview.h> +#include <gtkmm/toolitem.h> +#include <gtkmm/widget.h> +#include <sigc++/adaptors/retype_return.h> +#include <sigc++/connection.h> +#include <sigc++/functors/mem_fun.h> +#include <sigc++/signal.h> + +#if USE_WEBKIT +# include <webkit/webkit.h> #endif +#include <algorithm> #include <cassert> +#include <cstdint> +#include <cstdio> +#include <limits> +#include <map> +#include <memory> #include <sstream> #include <string> +#include <utility> namespace ingen { -using namespace client; +using client::BlockModel; +using client::GraphModel; +using client::ObjectModel; +using client::PluginModel; +using client::PortModel; namespace gui { @@ -63,11 +120,6 @@ static const int STATUS_CONTEXT_HOVER = 2; GraphBox::GraphBox(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& xml) : Gtk::VBox(cobject) - , _app(nullptr) - , _window(nullptr) - , _breadcrumbs(nullptr) - , _has_shown_documentation(false) - , _enable_signal(true) { property_visible() = false; @@ -176,7 +228,7 @@ GraphBox::GraphBox(BaseObjectType* cobject, _menu_view_graph_properties->signal_activate().connect( sigc::mem_fun(this, &GraphBox::event_show_properties)); - Glib::RefPtr<Gtk::Clipboard> clipboard = Gtk::Clipboard::get(); + const Glib::RefPtr<Gtk::Clipboard> clipboard = Gtk::Clipboard::get(); clipboard->signal_owner_change().connect( sigc::mem_fun(this, &GraphBox::event_clipboard_changed)); @@ -194,21 +246,25 @@ GraphBox::~GraphBox() delete _breadcrumbs; } -SPtr<GraphBox> -GraphBox::create(App& app, SPtr<const GraphModel> graph) +std::shared_ptr<GraphBox> +GraphBox::create(App& app, const std::shared_ptr<const GraphModel>& graph) { GraphBox* result = nullptr; - Glib::RefPtr<Gtk::Builder> xml = WidgetFactory::create("graph_win"); + const Glib::RefPtr<Gtk::Builder> xml = WidgetFactory::create("graph_win"); xml->get_widget_derived("graph_win_vbox", result); + if (!result) { + return {}; + } + result->init_box(app); - result->set_graph(graph, SPtr<GraphView>()); + result->set_graph(graph, nullptr); if (app.is_plugin()) { result->_menu_close->set_sensitive(false); result->_menu_quit->set_sensitive(false); } - return SPtr<GraphBox>(result); + return std::shared_ptr<GraphBox>(result); } void @@ -248,13 +304,14 @@ GraphBox::set_status_text(const std::string& text) } void -GraphBox::set_graph_from_path(const Raul::Path& path, SPtr<GraphView> view) +GraphBox::set_graph_from_path(const raul::Path& path, + const std::shared_ptr<GraphView>& view) { if (view) { assert(view->graph()->path() == path); _app->window_factory()->present_graph(view->graph(), _window, view); } else { - SPtr<const GraphModel> model = dynamic_ptr_cast<const GraphModel>( + auto model = std::dynamic_pointer_cast<const GraphModel>( _app->store()->object(path)); if (model) { _app->window_factory()->present_graph(model, _window); @@ -267,8 +324,8 @@ GraphBox::set_graph_from_path(const Raul::Path& path, SPtr<GraphView> view) * If `view` is null, a new view will be created. */ void -GraphBox::set_graph(SPtr<const GraphModel> graph, - SPtr<GraphView> view) +GraphBox::set_graph(const std::shared_ptr<const GraphModel>& graph, + const std::shared_ptr<GraphView>& view) { if (!graph || graph == _graph) { return; @@ -307,11 +364,11 @@ GraphBox::set_graph(SPtr<const GraphModel> graph, // Add view to our alignment if (_view->get_parent()) { - _view->get_parent()->remove(*_view.get()); + _view->get_parent()->remove(*_view); } _alignment->remove(); - _alignment->add(*_view.get()); + _alignment->add(*_view); if (_breadcrumbs->get_parent()) { _breadcrumbs->get_parent()->remove(*_breadcrumbs); @@ -326,14 +383,14 @@ GraphBox::set_graph(SPtr<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() = bool(graph->parent()); + _menu_parent->property_sensitive() = !!graph->parent(); new_port_connection = graph->signal_new_port().connect( sigc::mem_fun(this, &GraphBox::graph_port_added)); @@ -355,7 +412,7 @@ GraphBox::set_graph(SPtr<const GraphModel> graph, } void -GraphBox::graph_port_added(SPtr<const PortModel> port) +GraphBox::graph_port_added(const std::shared_ptr<const PortModel>& port) { if (port->is_input() && _app->can_control(port.get())) { _menu_view_control_window->property_sensitive() = true; @@ -363,20 +420,18 @@ GraphBox::graph_port_added(SPtr<const PortModel> port) } void -GraphBox::graph_port_removed(SPtr<const PortModel> port) +GraphBox::graph_port_removed(const std::shared_ptr<const PortModel>& port) { if (!(port->is_input() && _app->can_control(port.get()))) { 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 @@ -397,7 +452,7 @@ GraphBox::set_documentation(const std::string& doc, bool html) _doc_scrolledwindow->hide(); return; } -#ifdef HAVE_WEBKIT +#if USE_WEBKIT WebKitWebView* view = WEBKIT_WEB_VIEW(webkit_web_view_new()); webkit_web_view_load_html_string(view, doc.c_str(), ""); Gtk::Widget* widget = Gtk::manage(Glib::wrap(GTK_WIDGET(view))); @@ -425,7 +480,7 @@ GraphBox::show_status(const ObjectModel* model) show_port_status(port, port->value()); } else if ((block = dynamic_cast<const BlockModel*>(model))) { - const PluginModel* plugin = dynamic_cast<const PluginModel*>(block->plugin()); + const auto* plugin = dynamic_cast<const PluginModel*>(block->plugin()); if (plugin) { msg << fmt(" (%1%)", plugin->human_name()); } @@ -441,7 +496,7 @@ GraphBox::show_port_status(const PortModel* port, const Atom& value) const BlockModel* parent = dynamic_cast<const BlockModel*>(port->parent().get()); if (parent) { - const PluginModel* plugin = dynamic_cast<const PluginModel*>(parent->plugin()); + const auto* plugin = dynamic_cast<const PluginModel*>(parent->plugin()); if (plugin) { const std::string& human_name = plugin->port_human_name(port->index()); if (!human_name.empty()) { @@ -482,7 +537,7 @@ GraphBox::event_show_engine() void GraphBox::event_clipboard_changed(GdkEventOwnerChange* ev) { - Glib::RefPtr<Gtk::Clipboard> clipboard = Gtk::Clipboard::get(); + const Glib::RefPtr<Gtk::Clipboard> clipboard = Gtk::Clipboard::get(); _menu_paste->set_sensitive(clipboard->wait_is_text_available()); } @@ -591,8 +646,8 @@ GraphBox::event_save_as() filename += ".ingen"; basename += ".ingen"; } else if (filename.substr(filename.length() - 4) == ".ttl") { - const Glib::ustring dir = Glib::path_get_dirname(filename); - if (dir.substr(dir.length() - 6) != ".ingen") { + const Glib::ustring dirname = Glib::path_get_dirname(filename); + if (dirname.substr(dirname.length() - 6) != ".ingen") { error("<b>File does not appear to be in an Ingen bundle."); } } else if (filename.substr(filename.length() - 6) != ".ingen") { @@ -602,7 +657,7 @@ GraphBox::event_save_as() const std::string symbol(basename.substr(0, basename.find('.'))); - if (!Raul::Symbol::is_valid(symbol)) { + if (!raul::Symbol::is_valid(symbol)) { error( "<b>Ingen bundle names must be valid symbols.</b>", "All characters must be _, a-z, A-Z, or 0-9, but the first may not be 0-9."); @@ -664,24 +719,23 @@ GraphBox::event_export_image() dialog.set_transient_for(*_window); } - using Types = std::map<std::string, std::string>; - Types types; + std::map<std::string, std::string> types; types["*.dot"] = "Graphviz DOT"; types["*.pdf"] = "Portable Document Format"; types["*.ps"] = "PostScript"; types["*.svg"] = "Scalable Vector Graphics"; - for (Types::const_iterator t = types.begin(); t != types.end(); ++t) { + for (const auto& t : types) { Gtk::FileFilter filt; - filt.add_pattern(t->first); - filt.set_name(t->second); + filt.add_pattern(t.first); + filt.set_name(t.second); dialog.add_filter(filt); - if (t->first == "*.pdf") { + if (t.first == "*.pdf") { dialog.set_filter(filt); } } - Gtk::CheckButton* bg_but = new Gtk::CheckButton("Draw _Background", true); - Gtk::Alignment* extra = new Gtk::Alignment(1.0, 0.5, 0.0, 0.0); + auto* bg_but = new Gtk::CheckButton("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)); extra->show_all(); @@ -813,7 +867,9 @@ GraphBox::event_arrange() void GraphBox::event_parent_activated() { - SPtr<client::GraphModel> parent = dynamic_ptr_cast<client::GraphModel>(_graph->parent()); + auto parent = + std::dynamic_pointer_cast<client::GraphModel>(_graph->parent()); + if (parent) { _app->window_factory()->present_graph(parent, _window); } @@ -828,10 +884,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; @@ -873,7 +929,7 @@ GraphBox::event_animate_signals_toggled() _app->interface()->set_property( URI("ingen:/clients/this"), _app->uris().ingen_broadcast, - _app->forge().make((bool)_menu_animate_signals->get_active())); + _app->forge().make(_menu_animate_signals->get_active())); } void diff --git a/src/gui/GraphBox.hpp b/src/gui/GraphBox.hpp index 93599e0b..07962a3d 100644 --- a/src/gui/GraphBox.hpp +++ b/src/gui/GraphBox.hpp @@ -17,47 +17,52 @@ #ifndef INGEN_GUI_GRAPH_BOX_HPP #define INGEN_GUI_GRAPH_BOX_HPP -#include <string> +#include <ingen/ingen.h> +#include <gdk/gdk.h> +#include <glibmm/ustring.h> #include <gtkmm/alignment.h> #include <gtkmm/box.h> -#include <gtkmm/builder.h> -#include <gtkmm/menushell.h> -#include <gtkmm/messagedialog.h> -#include <gtkmm/paned.h> #include <gtkmm/scrolledwindow.h> -#include <gtkmm/statusbar.h> +#include <sigc++/connection.h> -#include "ingen/ingen.h" -#include "ingen/types.hpp" +#include <memory> +#include <string> -#include "Window.hpp" +namespace Glib { +template <class T> class RefPtr; +} // namespace Glib -namespace Raul { -class Atom; +namespace Gtk { +class Builder; +class CheckMenuItem; +class HPaned; +class Label; +class MenuItem; +class Statusbar; +} // namespace Gtk + +namespace raul { class Path; -} +} // namespace raul namespace ingen { +class Atom; class URI; namespace client { class GraphModel; class PortModel; class ObjectModel; -} +} // namespace client namespace gui { +class App; class BreadCrumbs; -class LoadGraphBox; -class LoadPluginWindow; -class NewSubgraphWindow; -class GraphDescriptionWindow; class GraphView; class GraphWindow; -class SubgraphModule; /** A window for a graph. * @@ -68,37 +73,39 @@ class INGEN_API GraphBox : public Gtk::VBox public: GraphBox(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& xml); - ~GraphBox(); - static SPtr<GraphBox> create( - App& app, SPtr<const client::GraphModel> graph); + ~GraphBox() override; + + static std::shared_ptr<GraphBox> + create(App& app, const std::shared_ptr<const client::GraphModel>& graph); void init_box(App& app); void set_status_text(const std::string& text); - void set_graph(SPtr<const client::GraphModel> graph, - SPtr<GraphView> view); + void set_graph(const std::shared_ptr<const client::GraphModel>& graph, + const std::shared_ptr<GraphView>& view); void set_window(GraphWindow* win) { _window = win; } bool documentation_is_visible() { return _doc_scrolledwindow->is_visible(); } void set_documentation(const std::string& doc, bool html); - SPtr<const client::GraphModel> graph() const { return _graph; } - SPtr<GraphView> view() const { return _view; } + std::shared_ptr<const client::GraphModel> graph() const { return _graph; } + std::shared_ptr<GraphView> view() const { return _view; } void show_port_status(const client::PortModel* port, const Atom& value); - void set_graph_from_path(const Raul::Path& path, SPtr<GraphView> view); + void set_graph_from_path(const raul::Path& path, + const std::shared_ptr<GraphView>& view); void object_entered(const client::ObjectModel* model); void object_left(const client::ObjectModel* model); private: - void graph_port_added(SPtr<const client::PortModel> port); - void graph_port_removed(SPtr<const client::PortModel> port); + void graph_port_added(const std::shared_ptr<const client::PortModel>& port); + void graph_port_removed(const std::shared_ptr<const client::PortModel>& port); void property_changed(const URI& predicate, const Atom& value); void show_status(const client::ObjectModel* model); @@ -143,59 +150,59 @@ private: void event_show_engine(); void event_clipboard_changed(GdkEventOwnerChange* ev); - App* _app; - SPtr<const client::GraphModel> _graph; - SPtr<GraphView> _view; - GraphWindow* _window; + App* _app = nullptr; + std::shared_ptr<const client::GraphModel> _graph; + std::shared_ptr<GraphView> _view; + GraphWindow* _window = nullptr; sigc::connection new_port_connection; sigc::connection removed_port_connection; sigc::connection edit_mode_connection; - Gtk::MenuItem* _menu_import; - Gtk::MenuItem* _menu_save; - Gtk::MenuItem* _menu_save_as; - Gtk::MenuItem* _menu_export_image; - Gtk::MenuItem* _menu_redo; - Gtk::MenuItem* _menu_undo; - Gtk::MenuItem* _menu_cut; - Gtk::MenuItem* _menu_copy; - Gtk::MenuItem* _menu_paste; - Gtk::MenuItem* _menu_delete; - Gtk::MenuItem* _menu_select_all; - Gtk::MenuItem* _menu_close; - Gtk::MenuItem* _menu_quit; - Gtk::CheckMenuItem* _menu_animate_signals; - Gtk::CheckMenuItem* _menu_sprung_layout; - Gtk::CheckMenuItem* _menu_human_names; - Gtk::CheckMenuItem* _menu_show_port_names; - Gtk::CheckMenuItem* _menu_show_doc_pane; - Gtk::CheckMenuItem* _menu_show_status_bar; - Gtk::MenuItem* _menu_zoom_in; - Gtk::MenuItem* _menu_zoom_out; - Gtk::MenuItem* _menu_zoom_normal; - Gtk::MenuItem* _menu_zoom_full; - Gtk::MenuItem* _menu_increase_font_size; - Gtk::MenuItem* _menu_decrease_font_size; - Gtk::MenuItem* _menu_normal_font_size; - Gtk::MenuItem* _menu_parent; - Gtk::MenuItem* _menu_refresh; - Gtk::MenuItem* _menu_fullscreen; - Gtk::MenuItem* _menu_arrange; - Gtk::MenuItem* _menu_view_engine_window; - Gtk::MenuItem* _menu_view_control_window; - Gtk::MenuItem* _menu_view_graph_properties; - Gtk::MenuItem* _menu_view_messages_window; - Gtk::MenuItem* _menu_view_graph_tree_window; - Gtk::MenuItem* _menu_help_about; - - Gtk::Alignment* _alignment; - BreadCrumbs* _breadcrumbs; - Gtk::Statusbar* _status_bar; - Gtk::Label* _status_label; - - Gtk::HPaned* _doc_paned; - Gtk::ScrolledWindow* _doc_scrolledwindow; + Gtk::MenuItem* _menu_import = nullptr; + Gtk::MenuItem* _menu_save = nullptr; + Gtk::MenuItem* _menu_save_as = nullptr; + Gtk::MenuItem* _menu_export_image = nullptr; + Gtk::MenuItem* _menu_redo = nullptr; + Gtk::MenuItem* _menu_undo = nullptr; + Gtk::MenuItem* _menu_cut = nullptr; + Gtk::MenuItem* _menu_copy = nullptr; + Gtk::MenuItem* _menu_paste = nullptr; + Gtk::MenuItem* _menu_delete = nullptr; + Gtk::MenuItem* _menu_select_all = nullptr; + Gtk::MenuItem* _menu_close = nullptr; + Gtk::MenuItem* _menu_quit = nullptr; + Gtk::CheckMenuItem* _menu_animate_signals = nullptr; + Gtk::CheckMenuItem* _menu_sprung_layout = nullptr; + Gtk::CheckMenuItem* _menu_human_names = nullptr; + Gtk::CheckMenuItem* _menu_show_port_names = nullptr; + Gtk::CheckMenuItem* _menu_show_doc_pane = nullptr; + Gtk::CheckMenuItem* _menu_show_status_bar = nullptr; + Gtk::MenuItem* _menu_zoom_in = nullptr; + Gtk::MenuItem* _menu_zoom_out = nullptr; + Gtk::MenuItem* _menu_zoom_normal = nullptr; + Gtk::MenuItem* _menu_zoom_full = nullptr; + Gtk::MenuItem* _menu_increase_font_size = nullptr; + Gtk::MenuItem* _menu_decrease_font_size = nullptr; + Gtk::MenuItem* _menu_normal_font_size = nullptr; + Gtk::MenuItem* _menu_parent = nullptr; + Gtk::MenuItem* _menu_refresh = nullptr; + Gtk::MenuItem* _menu_fullscreen = nullptr; + Gtk::MenuItem* _menu_arrange = nullptr; + Gtk::MenuItem* _menu_view_engine_window = nullptr; + Gtk::MenuItem* _menu_view_control_window = nullptr; + Gtk::MenuItem* _menu_view_graph_properties = nullptr; + Gtk::MenuItem* _menu_view_messages_window = nullptr; + Gtk::MenuItem* _menu_view_graph_tree_window = nullptr; + Gtk::MenuItem* _menu_help_about = nullptr; + + Gtk::Alignment* _alignment = nullptr; + BreadCrumbs* _breadcrumbs = nullptr; + Gtk::Statusbar* _status_bar = nullptr; + Gtk::Label* _status_label = nullptr; + + Gtk::HPaned* _doc_paned = nullptr; + Gtk::ScrolledWindow* _doc_scrolledwindow = nullptr; sigc::connection _entered_connection; sigc::connection _left_connection; @@ -203,8 +210,8 @@ private: /** Invisible bin used to store breadcrumbs when not shown by a view */ Gtk::Alignment _breadcrumb_bin; - bool _has_shown_documentation; - bool _enable_signal; + bool _has_shown_documentation = false; + bool _enable_signal = true; }; } // namespace gui diff --git a/src/gui/GraphCanvas.cpp b/src/gui/GraphCanvas.cpp index 40a0c675..3090186a 100644 --- a/src/gui/GraphCanvas.cpp +++ b/src/gui/GraphCanvas.cpp @@ -14,13 +14,12 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ +#include "GraphCanvas.hpp" + #include "App.hpp" #include "Arc.hpp" -#include "GraphCanvas.hpp" #include "GraphPortModule.hpp" #include "GraphWindow.hpp" -#include "LoadPluginWindow.hpp" -#include "NewSubgraphWindow.hpp" #include "NodeModule.hpp" #include "PluginMenu.hpp" #include "Port.hpp" @@ -29,35 +28,89 @@ #include "WidgetFactory.hpp" #include "WindowFactory.hpp" -#include "ganv/Canvas.hpp" -#include "ganv/Circle.hpp" -#include "ingen/ClashAvoider.hpp" -#include "ingen/Configuration.hpp" -#include "ingen/Interface.hpp" -#include "ingen/Log.hpp" -#include "ingen/Serialiser.hpp" -#include "ingen/World.hpp" -#include "ingen/client/BlockModel.hpp" -#include "ingen/client/ClientStore.hpp" -#include "ingen/client/GraphModel.hpp" -#include "ingen/client/PluginModel.hpp" -#include "ingen/ingen.h" -#include "lv2/atom/atom.h" - -#include <boost/optional/optional.hpp> +#include <ganv/Canvas.hpp> +#include <ganv/Edge.hpp> +#include <ganv/Module.hpp> +#include <ganv/Node.hpp> +#include <ganv/Port.hpp> +#include <ganv/canvas.h> +#include <ganv/edge.h> +#include <ganv/module.h> +#include <ganv/types.h> +#include <ingen/Arc.hpp> +#include <ingen/Atom.hpp> +#include <ingen/ClashAvoider.hpp> +#include <ingen/Configuration.hpp> +#include <ingen/Forge.hpp> +#include <ingen/Interface.hpp> +#include <ingen/Log.hpp> +#include <ingen/Node.hpp> +#include <ingen/Parser.hpp> +#include <ingen/Properties.hpp> +#include <ingen/Resource.hpp> +#include <ingen/Serialiser.hpp> +#include <ingen/Store.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIs.hpp> +#include <ingen/World.hpp> +#include <ingen/client/ArcModel.hpp> +#include <ingen/client/BlockModel.hpp> +#include <ingen/client/ClientStore.hpp> +#include <ingen/client/GraphModel.hpp> +#include <ingen/client/ObjectModel.hpp> +#include <ingen/client/PluginModel.hpp> +#include <ingen/client/PortModel.hpp> +#include <ingen/paths.hpp> +#include <raul/Path.hpp> +#include <raul/Symbol.hpp> +#include <sord/sordmm.hpp> + +#include <gdk/gdk.h> +#include <gdk/gdkkeysyms-compat.h> +#include <gdkmm/window.h> +#include <glib.h> +#include <glibmm/refptr.h> +#include <glibmm/ustring.h> +#include <gtkmm/builder.h> +#include <gtkmm/checkmenuitem.h> +#include <gtkmm/clipboard.h> +#include <gtkmm/enums.h> +#include <gtkmm/image.h> +#include <gtkmm/layout.h> +#include <gtkmm/menu.h> +#include <gtkmm/menu_elems.h> +#include <gtkmm/menuitem.h> +#include <gtkmm/object.h> #include <gtkmm/stock.h> +#include <gtkmm/stockid.h> +#include <sigc++/adaptors/bind.h> +#include <sigc++/functors/mem_fun.h> +#include <sigc++/signal.h> #include <algorithm> #include <cassert> +#include <cstdio> +#include <cstring> +#include <initializer_list> +#include <limits> #include <map> +#include <memory> +#include <mutex> +#include <optional> #include <set> +#include <sstream> #include <string> +#include <vector> using std::string; namespace ingen { -using namespace client; +using client::ArcModel; +using client::BlockModel; +using client::GraphModel; +using client::PluginModel; +using client::PortModel; namespace gui { @@ -67,30 +120,21 @@ port_order(const GanvPort* a, const GanvPort* b, void* data) const Port* pa = dynamic_cast<const Port*>(Glib::wrap(a)); const Port* pb = dynamic_cast<const Port*>(Glib::wrap(b)); if (pa && pb) { - return ((int)pa->model()->index() - (int)pb->model()->index()); + return (static_cast<int>(pa->model()->index()) - + static_cast<int>(pb->model()->index())); } return 0; } -GraphCanvas::GraphCanvas(App& app, - SPtr<const GraphModel> graph, - int width, - int height) - : Canvas(width, height) - , _app(app) - , _graph(std::move(graph)) - , _auto_position_count(0) - , _menu_x(0) - , _menu_y(0) - , _paste_count(0) - , _menu(nullptr) - , _internal_menu(nullptr) - , _plugin_menu(nullptr) - , _human_names(true) - , _show_port_names(true) - , _menu_dirty(false) -{ - Glib::RefPtr<Gtk::Builder> xml = WidgetFactory::create("canvas_menu"); +GraphCanvas::GraphCanvas(App& app, + std::shared_ptr<const GraphModel> graph, + int width, + int height) + : Canvas(width, height) + , _app(app) + , _graph(std::move(graph)) +{ + const Glib::RefPtr<Gtk::Builder> xml = WidgetFactory::create("canvas_menu"); xml->get_widget("canvas_menu", _menu); xml->get_widget("canvas_menu_add_audio_input", _menu_add_audio_input); @@ -209,7 +253,7 @@ GraphCanvas::build_menus() _menu->reorder_child(*internal_menu_item, 4); } - // Build skeleton LV2 plugin class heirarchy for 'Plugin' menu + // Build skeleton LV2 plugin class hierarchy for 'Plugin' menu if (_plugin_menu) { _plugin_menu->clear(); } else { @@ -225,9 +269,9 @@ GraphCanvas::build_menus() sigc::mem_fun(this, &GraphCanvas::load_plugin)); } - // Add known plugins to menu heirarchy - SPtr<const ClientStore::Plugins> plugins = _app.store()->plugins(); - for (const auto& p : *plugins.get()) { + // Add known plugins to menu hierarchy + auto plugins = _app.store()->plugins(); + for (const auto& p : *plugins) { add_plugin(p.second); } @@ -240,8 +284,8 @@ GraphCanvas::build() const Store::const_range kids = _app.store()->children_range(_graph); // Create modules for blocks - for (Store::const_iterator i = kids.first; i != kids.second; ++i) { - SPtr<BlockModel> block = dynamic_ptr_cast<BlockModel>(i->second); + for (auto i = kids.first; i != kids.second; ++i) { + auto block = std::dynamic_pointer_cast<BlockModel>(i->second); if (block && block->parent() == _graph) { add_block(block); } @@ -254,22 +298,22 @@ GraphCanvas::build() // Create arcs for (const auto& a : _graph->arcs()) { - connection(dynamic_ptr_cast<ArcModel>(a.second)); + connection(std::dynamic_pointer_cast<ArcModel>(a.second)); } } static void show_module_human_names(GanvNode* node, void* data) { - bool b = *(bool*)data; + const bool b = *static_cast<bool*>(data); if (GANV_IS_MODULE(node)) { Ganv::Module* module = Glib::wrap(GANV_MODULE(node)); - NodeModule* nmod = dynamic_cast<NodeModule*>(module); + auto* nmod = dynamic_cast<NodeModule*>(module); if (nmod) { nmod->show_human_names(b); } - GraphPortModule* pmod = dynamic_cast<GraphPortModule*>(module); + auto* pmod = dynamic_cast<GraphPortModule*>(module); if (pmod) { pmod->show_human_names(b); } @@ -291,7 +335,7 @@ ensure_port_labels(GanvNode* node, void* data) if (GANV_IS_MODULE(node)) { Ganv::Module* module = Glib::wrap(GANV_MODULE(node)); for (Ganv::Port* p : *module) { - ingen::gui::Port* port = dynamic_cast<ingen::gui::Port*>(p); + auto* port = dynamic_cast<ingen::gui::Port*>(p); if (port) { port->ensure_label(); } @@ -307,7 +351,7 @@ GraphCanvas::show_port_names(bool b) } void -GraphCanvas::add_plugin(const SPtr<PluginModel>& p) +GraphCanvas::add_plugin(const std::shared_ptr<PluginModel>& p) { if (_internal_menu && _app.uris().ingen_Internal == p->type()) { _internal_menu->items().push_back( @@ -327,10 +371,10 @@ GraphCanvas::remove_plugin(const URI& uri) } void -GraphCanvas::add_block(const SPtr<const BlockModel>& bm) +GraphCanvas::add_block(const std::shared_ptr<const BlockModel>& bm) { - SPtr<const GraphModel> pm = dynamic_ptr_cast<const GraphModel>(bm); - NodeModule* module; + auto pm = std::dynamic_pointer_cast<const GraphModel>(bm); + NodeModule* module = nullptr; if (pm) { module = SubgraphModule::create(*this, pm, _human_names); } else { @@ -345,7 +389,7 @@ GraphCanvas::add_block(const SPtr<const BlockModel>& bm) } void -GraphCanvas::remove_block(const SPtr<const BlockModel>& bm) +GraphCanvas::remove_block(const std::shared_ptr<const BlockModel>& bm) { auto i = _views.find(bm); @@ -360,7 +404,7 @@ GraphCanvas::remove_block(const SPtr<const BlockModel>& bm) } void -GraphCanvas::add_port(const SPtr<const PortModel>& pm) +GraphCanvas::add_port(const std::shared_ptr<const PortModel>& pm) { GraphPortModule* view = GraphPortModule::create(*this, pm); _views.emplace(pm, view); @@ -368,7 +412,7 @@ GraphCanvas::add_port(const SPtr<const PortModel>& pm) } void -GraphCanvas::remove_port(const SPtr<const PortModel>& pm) +GraphCanvas::remove_port(const std::shared_ptr<const PortModel>& pm) { auto i = _views.find(pm); @@ -386,24 +430,24 @@ GraphCanvas::remove_port(const SPtr<const PortModel>& pm) } Ganv::Port* -GraphCanvas::get_port_view(const SPtr<PortModel>& port) +GraphCanvas::get_port_view(const std::shared_ptr<PortModel>& port) { Ganv::Module* module = _views[port]; // Port on this graph if (module) { - GraphPortModule* ppm = dynamic_cast<GraphPortModule*>(module); + auto* ppm = dynamic_cast<GraphPortModule*>(module); return ppm ? *ppm->begin() : dynamic_cast<Ganv::Port*>(module); - } else { - module = dynamic_cast<NodeModule*>(_views[port->parent()]); - if (module) { - for (const auto& p : *module) { - gui::Port* pv = dynamic_cast<gui::Port*>(p); - if (pv && pv->model() == port) { - return pv; - } + } + + module = dynamic_cast<NodeModule*>(_views[port->parent()]); + if (module) { + for (auto* p : *module) { + auto* pv = dynamic_cast<gui::Port*>(p); + if (pv && pv->model() == port) { + return pv; } } } @@ -413,7 +457,7 @@ GraphCanvas::get_port_view(const SPtr<PortModel>& port) /** Called when a connection is added to the model. */ void -GraphCanvas::connection(const SPtr<const ArcModel>& arc) +GraphCanvas::connection(const std::shared_ptr<const ArcModel>& arc) { Ganv::Port* const tail = get_port_view(arc->tail()); Ganv::Port* const head = get_port_view(arc->head()); @@ -428,7 +472,7 @@ GraphCanvas::connection(const SPtr<const ArcModel>& arc) /** Called when a connection is removed from the model. */ void -GraphCanvas::disconnection(const SPtr<const ArcModel>& arc) +GraphCanvas::disconnection(const std::shared_ptr<const ArcModel>& arc) { Ganv::Port* const tail = get_port_view(arc->tail()); Ganv::Port* const head = get_port_view(arc->head()); @@ -436,9 +480,9 @@ GraphCanvas::disconnection(const SPtr<const ArcModel>& arc) if (tail && head) { remove_edge_between(tail, head); if (arc->head()->is_a(_app.uris().lv2_AudioPort)) { - gui::Port* const h = dynamic_cast<gui::Port*>(head); + auto* const h = dynamic_cast<gui::Port*>(head); if (h) { - h->activity(_app.forge().make(0.0f)); // Reset peaks + h->activity(_app.forge().make(0.0f)); // Reset peaks } } } else { @@ -490,8 +534,8 @@ GraphCanvas::auto_menu_position(int& x, int& y, bool& push_in) *_app.window_factory()->graph_window(_graph), 64, 64, _menu_x, _menu_y); - int origin_x; - int origin_y; + int origin_x = 0; + int origin_y = 0; widget().get_window()->get_origin(origin_x, origin_y); _menu_x += origin_x; _menu_y += origin_y; @@ -518,8 +562,8 @@ GraphCanvas::on_event(GdkEvent* event) case GDK_BUTTON_PRESS: if (event->button.button == 3) { _auto_position_count = 1; - _menu_x = (int)event->button.x_root; - _menu_y = (int)event->button.y_root; + _menu_x = static_cast<int>(event->button.x_root); + _menu_y = static_cast<int>(event->button.y_root); show_menu(false, event->button.button, event->button.time); ret = true; } @@ -537,6 +581,7 @@ GraphCanvas::on_event(GdkEvent* event) case GDK_space: case GDK_Menu: show_menu(true, 3, event->key.time); + break; default: break; } break; @@ -569,14 +614,14 @@ destroy_node(GanvNode* node, void* data) return; } - App* app = (App*)data; + const App* app = static_cast<App*>(data); Ganv::Module* module = Glib::wrap(GANV_MODULE(node)); - NodeModule* 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 { - GraphPortModule* 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")) { @@ -588,11 +633,11 @@ destroy_node(GanvNode* node, void* data) static void destroy_arc(GanvEdge* arc, void* data) { - App* app = (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()); } @@ -611,18 +656,18 @@ GraphCanvas::destroy_selection() static void serialise_node(GanvNode* node, void* data) { - Serialiser* serialiser = (Serialiser*)data; + auto* serialiser = static_cast<Serialiser*>(data); if (!GANV_IS_MODULE(node)) { return; } Ganv::Module* module = Glib::wrap(GANV_MODULE(node)); - NodeModule* node_module = dynamic_cast<NodeModule*>(module); + const auto* node_module = dynamic_cast<NodeModule*>(module); if (node_module) { serialiser->serialise(node_module->block()); } else { - GraphPortModule* port_module = dynamic_cast<GraphPortModule*>(module); + const auto* port_module = dynamic_cast<GraphPortModule*>(module); if (port_module) { serialiser->serialise(port_module->port()); } @@ -632,12 +677,12 @@ serialise_node(GanvNode* node, void* data) static void serialise_arc(GanvEdge* arc, void* data) { - Serialiser* serialiser = (Serialiser*)data; + auto* serialiser = static_cast<Serialiser*>(data); if (!GANV_IS_EDGE(arc)) { return; } - gui::Arc* 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()); } @@ -646,7 +691,7 @@ serialise_arc(GanvEdge* arc, void* data) void GraphCanvas::copy_selection() { - std::lock_guard<std::mutex> lock(_app.world().rdf_mutex()); + const std::lock_guard<std::mutex> lock{_app.world().rdf_mutex()}; Serialiser serialiser(_app.world()); serialiser.start_to_string(_graph->path(), _graph->base_uri()); @@ -654,7 +699,7 @@ GraphCanvas::copy_selection() for_each_selected_node(serialise_node, &serialiser); for_each_selected_edge(serialise_arc, &serialiser); - Glib::RefPtr<Gtk::Clipboard> clipboard = Gtk::Clipboard::get(); + const Glib::RefPtr<Gtk::Clipboard> clipboard = Gtk::Clipboard::get(); clipboard->set_text(serialiser.finish()); _paste_count = 0; } @@ -662,14 +707,12 @@ GraphCanvas::copy_selection() void GraphCanvas::paste() { - using PropIter = Properties::const_iterator; - - std::lock_guard<std::mutex> lock(_app.world().rdf_mutex()); + const std::lock_guard<std::mutex> lock{_app.world().rdf_mutex()}; const Glib::ustring str = Gtk::Clipboard::get()->wait_for_text(); - SPtr<Parser> parser = _app.loader()->parser(); + auto parser = _app.loader()->parser(); const URIs& uris = _app.uris(); - const Raul::Path& parent = _graph->path(); + const raul::Path& parent = _graph->path(); if (!parser) { _app.log().error("Unable to load parser, paste unavailable\n"); return; @@ -681,21 +724,21 @@ GraphCanvas::paste() ++_paste_count; // Make a client store to serve as clipboard - ClientStore clipboard(_app.world().uris(), _app.log()); + client::ClientStore clipboard(_app.world().uris(), _app.log()); clipboard.set_plugins(_app.store()->plugins()); clipboard.put(main_uri(), {{uris.rdf_type, Property(uris.ingen_Graph)}}); // Parse clipboard text into clipboard store - boost::optional<URI> base_uri = parser->parse_string( + std::optional<URI> base_uri = parser->parse_string( _app.world(), clipboard, str, main_uri()); // Figure out the copy graph base path - Raul::Path copy_root("/"); + raul::Path copy_root("/"); 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)); } @@ -704,7 +747,7 @@ GraphCanvas::paste() float min_x = std::numeric_limits<float>::max(); float min_y = std::numeric_limits<float>::max(); for (const auto& c : clipboard) { - if (c.first.parent() == Raul::Path("/")) { + if (c.first.parent() == raul::Path("/")) { const Atom& x = c.second->get_property(uris.ingen_canvasX); const Atom& y = c.second->get_property(uris.ingen_canvasY); if (x.type() == uris.atom_Float) { @@ -717,7 +760,10 @@ GraphCanvas::paste() } // Find canvas paste origin based on pointer position - int widget_point_x, widget_point_y, scroll_x, scroll_y; + int widget_point_x = 0; + int widget_point_y = 0; + int scroll_x = 0; + int scroll_y = 0; widget().get_pointer(widget_point_x, widget_point_y); get_scroll_offsets(scroll_x, scroll_y); const int paste_x = widget_point_x + scroll_x + (20.0f * _paste_count); @@ -726,16 +772,17 @@ GraphCanvas::paste() _app.interface()->bundle_begin(); // Put each top level object in the clipboard store - ClashAvoider avoider(*_app.store().get()); + ClashAvoider avoider(*_app.store()); for (const auto& c : clipboard) { - if (c.first.is_root() || c.first.parent() != Raul::Path("/")) { + if (c.first.is_root() || c.first.parent() != raul::Path("/")) { continue; } - const SPtr<Node> node = c.second; - const Raul::Path& old_path = copy_root.child(node->path()); + const auto node = c.second; + const raul::Path& old_path = copy_root.child(node->path()); const URI& old_uri = path_to_uri(old_path); - const Raul::Path& new_path = avoider.map_path(parent.child(node->path())); + const raul::Path& new_path = + avoider.map_path(parent.child(node->path())); // Copy properties, except those that should not be inherited in copies Properties props = node->properties(); @@ -758,8 +805,8 @@ GraphCanvas::paste() } // Set coordinates so paste origin is at the mouse pointer - PropIter xi = node->properties().find(uris.ingen_canvasX); - PropIter yi = node->properties().find(uris.ingen_canvasY); + const auto xi = node->properties().find(uris.ingen_canvasX); + const auto yi = node->properties().find(uris.ingen_canvasY); if (xi != node->properties().end()) { const float x = xi->second.get<float>() - min_x + paste_x; props.insert({xi->first, Property(_app.forge().make(x), @@ -776,7 +823,7 @@ GraphCanvas::paste() } // Connect objects - for (auto a : clipboard.object(Raul::Path("/"))->arcs()) { + for (const auto& a : clipboard.object(raul::Path("/"))->arcs()) { _app.interface()->connect( avoider.map_path(parent.child(a.second->tail_path())), avoider.map_path(parent.child(a.second->head_path()))); @@ -799,12 +846,12 @@ GraphCanvas::generate_port_name( snprintf(num_buf, sizeof(num_buf), "%u", i); symbol = sym_base + "_"; symbol += num_buf; - if (!_graph->get_port(Raul::Symbol::symbolify(symbol))) { + if (!_graph->get_port(raul::Symbol::symbolify(symbol))) { break; } } - assert(Raul::Path::is_valid(string("/") + symbol)); + assert(raul::Path::is_valid(string("/") + symbol)); name.append(" ").append(num_buf); } @@ -815,9 +862,10 @@ GraphCanvas::menu_add_port(const string& sym_base, const URI& type, bool is_output) { - string sym, name; + string sym; + string name; generate_port_name(sym_base, sym, name_base, name); - const Raul::Path& path = _graph->path().child(Raul::Symbol(sym)); + const raul::Path& path = _graph->path().child(raul::Symbol(sym)); const URIs& uris = _app.uris(); @@ -830,29 +878,29 @@ GraphCanvas::menu_add_port(const string& sym_base, uris.rdf_type, Property(is_output ? uris.lv2_OutputPort : uris.lv2_InputPort)); props.emplace(uris.lv2_index, - _app.forge().make(int32_t(_graph->num_ports()))); + _app.forge().make(static_cast<int32_t>(_graph->num_ports()))); props.emplace(uris.lv2_name, _app.forge().alloc(name.c_str())); _app.interface()->put(path_to_uri(path), props); } void -GraphCanvas::load_plugin(WPtr<PluginModel> weak_plugin) +GraphCanvas::load_plugin(const std::weak_ptr<PluginModel>& weak_plugin) { - SPtr<PluginModel> plugin = weak_plugin.lock(); + auto plugin = weak_plugin.lock(); if (!plugin) { return; } - Raul::Symbol symbol = plugin->default_block_symbol(); - unsigned offset = _app.store()->child_name_offset(_graph->path(), symbol); + raul::Symbol symbol = plugin->default_block_symbol(); + const unsigned offset = _app.store()->child_name_offset(_graph->path(), symbol); if (offset != 0) { std::stringstream ss; ss << symbol << "_" << offset; - symbol = Raul::Symbol(ss.str()); + symbol = raul::Symbol(ss.str()); } const URIs& uris = _app.uris(); - const Raul::Path path = _graph->path().child(symbol); + const raul::Path path = _graph->path().child(symbol); // FIXME: polyphony? Properties props = get_initial_data(); @@ -866,8 +914,8 @@ GraphCanvas::load_plugin(WPtr<PluginModel> weak_plugin) void GraphCanvas::get_new_module_location(double& x, double& y) { - int scroll_x; - int scroll_y; + int scroll_x = 0; + int scroll_y = 0; get_scroll_offsets(scroll_x, scroll_y); x = scroll_x + 20; y = scroll_y + 20; @@ -879,9 +927,11 @@ GraphCanvas::get_initial_data(Resource::Graph ctx) Properties result; const URIs& uris = _app.uris(); result.emplace(uris.ingen_canvasX, - Property(_app.forge().make((float)_menu_x), ctx)); + Property(_app.forge().make(static_cast<float>(_menu_x)), + ctx)); result.emplace(uris.ingen_canvasY, - Property(_app.forge().make((float)_menu_y), ctx)); + Property(_app.forge().make(static_cast<float>(_menu_y)), + ctx)); return result; } diff --git a/src/gui/GraphCanvas.hpp b/src/gui/GraphCanvas.hpp index 7aa4bb98..38f3ab08 100644 --- a/src/gui/GraphCanvas.hpp +++ b/src/gui/GraphCanvas.hpp @@ -17,27 +17,48 @@ #ifndef INGEN_GUI_GRAPHCANVAS_HPP #define INGEN_GUI_GRAPHCANVAS_HPP -#include "NodeModule.hpp" +#include <ganv/Canvas.hpp> +#include <ingen/Properties.hpp> +#include <ingen/Resource.hpp> +#include <ingen/URI.hpp> +#include <lilv/lilv.h> +#include <raul/Path.hpp> -#include "ganv/Canvas.hpp" -#include "ganv/Module.hpp" -#include "ingen/Node.hpp" -#include "ingen/client/ArcModel.hpp" -#include "ingen/types.hpp" -#include "lilv/lilv.h" -#include "raul/Path.hpp" +#include <gdk/gdk.h> -#include <string> +#include <cstdint> #include <map> +#include <memory> #include <set> +#include <string> +#include <utility> + +namespace Ganv { +class Module; +class Node; +class Port; +} // namespace Ganv + +namespace Gtk { +class CheckMenuItem; +class Menu; +class MenuItem; +} // namespace Gtk namespace ingen { -namespace client { class GraphModel; } +namespace client { +class ArcModel; +class BlockModel; +class GraphModel; +class ObjectModel; +class PluginModel; +class PortModel; +} // namespace client namespace gui { -class NodeModule; +class App; class PluginMenu; /** Graph canvas widget. @@ -47,12 +68,12 @@ class PluginMenu; class GraphCanvas : public Ganv::Canvas { public: - GraphCanvas(App& app, - SPtr<const client::GraphModel> graph, - int width, - int height); + GraphCanvas(App& app, + std::shared_ptr<const client::GraphModel> graph, + int width, + int height); - virtual ~GraphCanvas() {} + ~GraphCanvas() override = default; App& app() { return _app; } @@ -61,14 +82,14 @@ public: void show_port_names(bool b); bool show_port_names() const { return _show_port_names; } - void add_plugin(const SPtr<client::PluginModel>& p); + void add_plugin(const std::shared_ptr<client::PluginModel>& p); void remove_plugin(const URI& uri); - void add_block(const SPtr<const client::BlockModel>& bm); - void remove_block(const SPtr<const client::BlockModel>& bm); - void add_port(const SPtr<const client::PortModel>& pm); - void remove_port(const SPtr<const client::PortModel>& pm); - void connection(const SPtr<const client::ArcModel>& arc); - void disconnection(const SPtr<const client::ArcModel>& arc); + void add_block(const std::shared_ptr<const client::BlockModel>& bm); + void remove_block(const std::shared_ptr<const client::BlockModel>& bm); + void add_port(const std::shared_ptr<const client::PortModel>& pm); + void remove_port(const std::shared_ptr<const client::PortModel>& pm); + void connection(const std::shared_ptr<const client::ArcModel>& arc); + void disconnection(const std::shared_ptr<const client::ArcModel>& arc); void get_new_module_location(double& x, double& y); @@ -96,7 +117,7 @@ private: void menu_new_graph(); void menu_load_graph(); void menu_properties(); - void load_plugin(WPtr<client::PluginModel> weak_plugin); + void load_plugin(const std::weak_ptr<client::PluginModel>& weak_plugin); void build_menus(); @@ -106,7 +127,7 @@ private: Properties get_initial_data(Resource::Graph ctx=Resource::Graph::DEFAULT); - Ganv::Port* get_port_view(const SPtr<client::PortModel>& port); + Ganv::Port* get_port_view(const std::shared_ptr<client::PortModel>& port); void connect(Ganv::Node* tail, Ganv::Node* head); @@ -114,42 +135,42 @@ private: void disconnect(Ganv::Node* tail, Ganv::Node* head); - App& _app; - SPtr<const client::GraphModel> _graph; + App& _app; + std::shared_ptr<const client::GraphModel> _graph; - using Views = std::map<SPtr<const client::ObjectModel>, Ganv::Module*>; + using Views = std::map<std::shared_ptr<const client::ObjectModel>, Ganv::Module*>; Views _views; - int _auto_position_count; + int _auto_position_count{0}; std::pair<int, int> _auto_position_scroll_offsets; - int _menu_x; - int _menu_y; - int _paste_count; + int _menu_x{0}; + int _menu_y{0}; + int _paste_count{0}; // Track pasted objects so they can be selected when they arrive - std::set<Raul::Path> _pastees; - - Gtk::Menu* _menu; - Gtk::Menu* _internal_menu; - PluginMenu* _plugin_menu; - Gtk::MenuItem* _menu_add_audio_input; - Gtk::MenuItem* _menu_add_audio_output; - Gtk::MenuItem* _menu_add_control_input; - Gtk::MenuItem* _menu_add_control_output; - Gtk::MenuItem* _menu_add_cv_input; - Gtk::MenuItem* _menu_add_cv_output; - Gtk::MenuItem* _menu_add_event_input; - Gtk::MenuItem* _menu_add_event_output; - Gtk::MenuItem* _menu_load_plugin; - Gtk::MenuItem* _menu_load_graph; - Gtk::MenuItem* _menu_new_graph; - Gtk::MenuItem* _menu_properties; - Gtk::CheckMenuItem* _menu_edit; - - bool _human_names; - bool _show_port_names; - bool _menu_dirty; + std::set<raul::Path> _pastees; + + Gtk::Menu* _menu = nullptr; + Gtk::Menu* _internal_menu = nullptr; + PluginMenu* _plugin_menu = nullptr; + Gtk::MenuItem* _menu_add_audio_input = nullptr; + Gtk::MenuItem* _menu_add_audio_output = nullptr; + Gtk::MenuItem* _menu_add_control_input = nullptr; + Gtk::MenuItem* _menu_add_control_output = nullptr; + Gtk::MenuItem* _menu_add_cv_input = nullptr; + Gtk::MenuItem* _menu_add_cv_output = nullptr; + Gtk::MenuItem* _menu_add_event_input = nullptr; + Gtk::MenuItem* _menu_add_event_output = nullptr; + Gtk::MenuItem* _menu_load_plugin = nullptr; + Gtk::MenuItem* _menu_load_graph = nullptr; + Gtk::MenuItem* _menu_new_graph = nullptr; + Gtk::MenuItem* _menu_properties = nullptr; + Gtk::CheckMenuItem* _menu_edit = nullptr; + + bool _human_names = true; + bool _show_port_names = true; + bool _menu_dirty = false; }; } // namespace gui diff --git a/src/gui/GraphPortModule.cpp b/src/gui/GraphPortModule.cpp index 1947f355..cd471d97 100644 --- a/src/gui/GraphPortModule.cpp +++ b/src/gui/GraphPortModule.cpp @@ -14,41 +14,47 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ +#include "GraphPortModule.hpp" + #include "App.hpp" -#include "Style.hpp" #include "GraphCanvas.hpp" -#include "GraphPortModule.hpp" -#include "GraphWindow.hpp" #include "Port.hpp" -#include "PortMenu.hpp" -#include "RenameWindow.hpp" -#include "WidgetFactory.hpp" -#include "WindowFactory.hpp" -#include "ingen/Configuration.hpp" -#include "ingen/Interface.hpp" -#include "ingen/client/BlockModel.hpp" -#include "ingen/client/GraphModel.hpp" +#include <ganv/Module.hpp> +#include <ingen/Atom.hpp> +#include <ingen/Configuration.hpp> +#include <ingen/Forge.hpp> +#include <ingen/Interface.hpp> +#include <ingen/Properties.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIs.hpp> +#include <ingen/World.hpp> +#include <ingen/client/GraphModel.hpp> +#include <ingen/client/PortModel.hpp> +#include <raul/Symbol.hpp> + +#include <sigc++/functors/mem_fun.h> +#include <sigc++/signal.h> #include <cassert> +#include <cstdint> +#include <map> +#include <memory> #include <string> #include <utility> -namespace ingen { - -using namespace client; - -namespace gui { +namespace ingen::gui { -GraphPortModule::GraphPortModule(GraphCanvas& canvas, - const SPtr<const client::PortModel>& model) - : Ganv::Module(canvas, "", 0, 0, false) // FIXME: coords? - , _model(model) - , _port(nullptr) +GraphPortModule::GraphPortModule( + GraphCanvas& canvas, + const std::shared_ptr<const client::PortModel>& model) + : Ganv::Module(canvas, "", 0, 0, false) // FIXME: coords? + , _model(model) { assert(model); - assert(dynamic_ptr_cast<const GraphModel>(model->parent())); + assert( + std::dynamic_pointer_cast<const client::GraphModel>(model->parent())); set_stacked(model->polyphonic()); if (model->is_input() && !model->is_numeric()) { @@ -63,10 +69,11 @@ GraphPortModule::GraphPortModule(GraphCanvas& canvas, } GraphPortModule* -GraphPortModule::create(GraphCanvas& canvas, const SPtr<const PortModel>& model) +GraphPortModule::create(GraphCanvas& canvas, + const std::shared_ptr<const client::PortModel>& model) { - GraphPortModule* ret = new GraphPortModule(canvas, model); - Port* port = Port::create(canvas.app(), *ret, model, true); + auto* ret = new GraphPortModule(canvas, model); + Port* port = Port::create(canvas.app(), *ret, model, true); ret->set_port(port); if (model->is_numeric()) { @@ -83,7 +90,7 @@ GraphPortModule::create(GraphCanvas& canvas, const SPtr<const PortModel>& model) App& GraphPortModule::app() const { - return ((GraphCanvas*)canvas())->app(); + return static_cast<GraphCanvas*>(canvas())->app(); } bool @@ -134,9 +141,9 @@ GraphPortModule::property_changed(const URI& key, const Atom& value) const URIs& uris = app().uris(); if (value.type() == uris.forge.Float) { if (key == uris.ingen_canvasX) { - move_to(value.get<float>(), get_y()); + move_to(static_cast<double>(value.get<float>()), get_y()); } else if (key == uris.ingen_canvasY) { - move_to(get_x(), value.get<float>()); + move_to(get_x(), static_cast<double>(value.get<float>())); } } else if (value.type() == uris.forge.String) { if (key == uris.lv2_name && @@ -161,5 +168,4 @@ GraphPortModule::set_selected(gboolean b) } } -} // namespace gui -} // namespace ingen +} // namespace ingen::gui diff --git a/src/gui/GraphPortModule.hpp b/src/gui/GraphPortModule.hpp index cad3bfc5..a8091f38 100644 --- a/src/gui/GraphPortModule.hpp +++ b/src/gui/GraphPortModule.hpp @@ -17,24 +17,28 @@ #ifndef INGEN_GUI_GRAPHPORTMODULE_HPP #define INGEN_GUI_GRAPHPORTMODULE_HPP -#include "Port.hpp" +#include <ganv/Module.hpp> +#include <ingen/URI.hpp> -#include "ganv/Module.hpp" +#include <gdk/gdk.h> +#include <glib.h> +#include <memory> #include <string> -namespace Raul { class Atom; } +namespace ingen { + +class Atom; -namespace ingen { namespace client { +namespace client { class PortModel; -} } +} // namespace client -namespace ingen { namespace gui { +class App; class GraphCanvas; class Port; -class PortMenu; /** A "module" to represent a graph's port on its own canvas. * @@ -46,7 +50,8 @@ class GraphPortModule : public Ganv::Module { public: static GraphPortModule* - create(GraphCanvas& canvas, const SPtr<const client::PortModel>& model); + create(GraphCanvas& canvas, + const std::shared_ptr<const client::PortModel>& model); App& app() const; @@ -55,11 +60,11 @@ public: void set_name(const std::string& n); - SPtr<const client::PortModel> port() const { return _model; } + std::shared_ptr<const client::PortModel> port() const { return _model; } protected: - GraphPortModule(GraphCanvas& canvas, - const SPtr<const client::PortModel>& model); + GraphPortModule(GraphCanvas& canvas, + const std::shared_ptr<const client::PortModel>& model); bool show_menu(GdkEventButton* ev); void set_selected(gboolean b) override; @@ -68,8 +73,8 @@ protected: void property_changed(const URI& key, const Atom& value); - SPtr<const client::PortModel> _model; - Port* _port; + std::shared_ptr<const client::PortModel> _model; + Port* _port{nullptr}; }; } // namespace gui diff --git a/src/gui/GraphTreeWindow.cpp b/src/gui/GraphTreeWindow.cpp index 68f6e392..1d141271 100644 --- a/src/gui/GraphTreeWindow.cpp +++ b/src/gui/GraphTreeWindow.cpp @@ -14,27 +14,51 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "App.hpp" #include "GraphTreeWindow.hpp" -#include "SubgraphModule.hpp" + +#include "App.hpp" +#include "Window.hpp" #include "WindowFactory.hpp" -#include "ingen/Interface.hpp" -#include "ingen/Log.hpp" -#include "ingen/client/ClientStore.hpp" -#include "ingen/client/GraphModel.hpp" -#include "raul/Path.hpp" + +#include <ingen/Atom.hpp> +#include <ingen/Forge.hpp> +#include <ingen/Interface.hpp> +#include <ingen/Log.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIs.hpp> +#include <ingen/client/ClientStore.hpp> +#include <ingen/client/GraphModel.hpp> +#include <ingen/client/ObjectModel.hpp> +#include <raul/Path.hpp> +#include <raul/Symbol.hpp> + +#include <glibmm/propertyproxy.h> +#include <gtkmm/builder.h> +#include <gtkmm/cellrenderer.h> +#include <gtkmm/cellrenderertoggle.h> +#include <gtkmm/object.h> +#include <gtkmm/treeiter.h> +#include <gtkmm/treepath.h> +#include <gtkmm/treeviewcolumn.h> +#include <sigc++/adaptors/bind.h> +#include <sigc++/functors/mem_fun.h> +#include <sigc++/signal.h> + +#include <cassert> +#include <cstdint> +#include <memory> +#include <string> namespace ingen { -using namespace client; +using client::GraphModel; +using client::ObjectModel; namespace gui { GraphTreeWindow::GraphTreeWindow(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& xml) : Window(cobject) - , _app(nullptr) - , _enable_signal(true) { xml->get_widget_derived("graphs_treeview", _graphs_treeview); @@ -50,7 +74,7 @@ GraphTreeWindow::GraphTreeWindow(BaseObjectType* cobject, _graphs_treeview->append_column(*name_col); _graphs_treeview->append_column(*enabled_col); - Gtk::CellRendererToggle* enabled_renderer = dynamic_cast<Gtk::CellRendererToggle*>( + auto* enabled_renderer = dynamic_cast<Gtk::CellRendererToggle*>( _graphs_treeview->get_column_cell_renderer(1)); enabled_renderer->property_activatable() = true; @@ -65,28 +89,28 @@ GraphTreeWindow::GraphTreeWindow(BaseObjectType* cobject, } void -GraphTreeWindow::init(App& app, ClientStore& store) +GraphTreeWindow::init(App& app, client::ClientStore& store) { - _app = &app; + init_window(app); store.signal_new_object().connect( sigc::mem_fun(this, &GraphTreeWindow::new_object)); } void -GraphTreeWindow::new_object(const SPtr<ObjectModel>& object) +GraphTreeWindow::new_object(const std::shared_ptr<ObjectModel>& object) { - SPtr<GraphModel> graph = dynamic_ptr_cast<GraphModel>(object); + auto graph = std::dynamic_pointer_cast<GraphModel>(object); if (graph) { add_graph(graph); } } void -GraphTreeWindow::add_graph(const SPtr<GraphModel>& pm) +GraphTreeWindow::add_graph(const std::shared_ptr<GraphModel>& pm) { if (!pm->parent()) { - Gtk::TreeModel::iterator iter = _graph_treestore->append(); - Gtk::TreeModel::Row row = *iter; + const auto iter = _graph_treestore->append(); + auto row = *iter; if (pm->path().is_root()) { row[_graph_tree_columns.name_col] = _app->interface()->uri().string(); } else { @@ -96,12 +120,13 @@ GraphTreeWindow::add_graph(const SPtr<GraphModel>& pm) row[_graph_tree_columns.graph_model_col] = pm; _graphs_treeview->expand_row(_graph_treestore->get_path(iter), true); } else { - Gtk::TreeModel::Children children = _graph_treestore->children(); - Gtk::TreeModel::iterator c = find_graph(children, pm->parent()); + const auto& children = _graph_treestore->children(); + auto c = find_graph(children, pm->parent()); if (c != children.end()) { - Gtk::TreeModel::iterator iter = _graph_treestore->append(c->children()); - Gtk::TreeModel::Row row = *iter; + const auto iter = _graph_treestore->append(c->children()); + auto row = *iter; + row[_graph_tree_columns.name_col] = pm->symbol().c_str(); row[_graph_tree_columns.enabled_col] = pm->enabled(); row[_graph_tree_columns.graph_model_col] = pm; @@ -123,24 +148,26 @@ GraphTreeWindow::add_graph(const SPtr<GraphModel>& pm) } void -GraphTreeWindow::remove_graph(const SPtr<GraphModel>& pm) +GraphTreeWindow::remove_graph(const std::shared_ptr<GraphModel>& pm) { - Gtk::TreeModel::iterator i = find_graph(_graph_treestore->children(), pm); + const auto i = find_graph(_graph_treestore->children(), pm); if (i != _graph_treestore->children().end()) { _graph_treestore->erase(i); } } Gtk::TreeModel::iterator -GraphTreeWindow::find_graph(Gtk::TreeModel::Children root, - const SPtr<client::ObjectModel>& graph) +GraphTreeWindow::find_graph(Gtk::TreeModel::Children root, + const std::shared_ptr<client::ObjectModel>& graph) { - for (Gtk::TreeModel::iterator c = root.begin(); c != root.end(); ++c) { - SPtr<GraphModel> pm = (*c)[_graph_tree_columns.graph_model_col]; + for (auto c = root.begin(); c != root.end(); ++c) { + const std::shared_ptr<GraphModel> pm = (*c)[_graph_tree_columns.graph_model_col]; if (graph == pm) { return c; - } else if (!(*c)->children().empty()) { - Gtk::TreeModel::iterator ret = find_graph(c->children(), graph); + } + + if (!(*c)->children().empty()) { + auto ret = find_graph(c->children(), graph); if (ret != c->children().end()) { return ret; } @@ -154,10 +181,12 @@ GraphTreeWindow::find_graph(Gtk::TreeModel::Children root, void GraphTreeWindow::show_graph_menu(GdkEventButton* ev) { - Gtk::TreeModel::iterator active = _graph_tree_selection->get_selected(); + const auto active = _graph_tree_selection->get_selected(); if (active) { - Gtk::TreeModel::Row row = *active; - SPtr<GraphModel> pm = row[_graph_tree_columns.graph_model_col]; + auto row = *active; + auto col = _graph_tree_columns.graph_model_col; + + const std::shared_ptr<GraphModel>& pm = row[col]; if (pm) { _app->log().warn("TODO: graph menu from tree window"); } @@ -168,9 +197,10 @@ void GraphTreeWindow::event_graph_activated(const Gtk::TreeModel::Path& path, Gtk::TreeView::Column* col) { - Gtk::TreeModel::iterator active = _graph_treestore->get_iter(path); - Gtk::TreeModel::Row row = *active; - SPtr<GraphModel> pm = row[_graph_tree_columns.graph_model_col]; + const auto active = _graph_treestore->get_iter(path); + auto row = *active; + + const std::shared_ptr<GraphModel> pm = row[_graph_tree_columns.graph_model_col]; _app->window_factory()->present_graph(pm); } @@ -178,31 +208,32 @@ GraphTreeWindow::event_graph_activated(const Gtk::TreeModel::Path& path, void GraphTreeWindow::event_graph_enabled_toggled(const Glib::ustring& path_str) { - Gtk::TreeModel::Path path(path_str); - Gtk::TreeModel::iterator active = _graph_treestore->get_iter(path); - Gtk::TreeModel::Row row = *active; + const Gtk::TreeModel::Path path{path_str}; + auto active = _graph_treestore->get_iter(path); + auto row = *active; - SPtr<GraphModel> pm = row[_graph_tree_columns.graph_model_col]; + const std::shared_ptr<GraphModel> pm = row[_graph_tree_columns.graph_model_col]; assert(pm); if (_enable_signal) { _app->set_property(pm->uri(), _app->uris().ingen_enabled, - _app->forge().make((bool)!pm->enabled())); + _app->forge().make(!pm->enabled())); } } void -GraphTreeWindow::graph_property_changed(const URI& key, - const Atom& value, - const SPtr<GraphModel>& graph) +GraphTreeWindow::graph_property_changed( + const URI& key, + const Atom& value, + const std::shared_ptr<GraphModel>& graph) { const URIs& uris = _app->uris(); _enable_signal = false; if (key == uris.ingen_enabled && value.type() == uris.forge.Bool) { - Gtk::TreeModel::iterator i = find_graph(_graph_treestore->children(), graph); + const auto i = find_graph(_graph_treestore->children(), graph); if (i != _graph_treestore->children().end()) { - Gtk::TreeModel::Row row = *i; + auto row = *i; row[_graph_tree_columns.enabled_col] = value.get<int32_t>(); } else { _app->log().error("Unable to find graph %1%\n", graph->path()); @@ -212,15 +243,13 @@ GraphTreeWindow::graph_property_changed(const URI& key, } void -GraphTreeWindow::graph_moved(const SPtr<GraphModel>& graph) +GraphTreeWindow::graph_moved(const std::shared_ptr<GraphModel>& graph) { _enable_signal = false; - Gtk::TreeModel::iterator i - = find_graph(_graph_treestore->children(), graph); - + auto i = find_graph(_graph_treestore->children(), graph); if (i != _graph_treestore->children().end()) { - Gtk::TreeModel::Row row = *i; + auto row = *i; row[_graph_tree_columns.name_col] = graph->symbol().c_str(); } else { _app->log().error("Unable to find graph %1%\n", graph->path()); diff --git a/src/gui/GraphTreeWindow.hpp b/src/gui/GraphTreeWindow.hpp index c1ea53c2..6f33f258 100644 --- a/src/gui/GraphTreeWindow.hpp +++ b/src/gui/GraphTreeWindow.hpp @@ -19,20 +19,36 @@ #include "Window.hpp" -#include <gtkmm/builder.h> +#include <ingen/URI.hpp> + +#include <gdk/gdk.h> +#include <glibmm/refptr.h> +#include <glibmm/ustring.h> #include <gtkmm/treemodel.h> +#include <gtkmm/treemodelcolumn.h> +#include <gtkmm/treeselection.h> #include <gtkmm/treestore.h> #include <gtkmm/treeview.h> -namespace Raul { class Path; } +#include <memory> + +namespace Gtk { +class Builder; +} // namespace Gtk namespace ingen { -namespace client { class ClientStore; class ObjectModel; } +class Atom; + +namespace client { +class ClientStore; +class ObjectModel; +class GraphModel; +} // namespace client namespace gui { -class GraphWindow; +class App; class GraphTreeView; /** Window with a TreeView of all loaded graphs. @@ -47,16 +63,17 @@ public: void init(App& app, client::ClientStore& store); - void new_object(const SPtr<client::ObjectModel>& object); + void new_object(const std::shared_ptr<client::ObjectModel>& object); - void graph_property_changed(const URI& key, - const Atom& value, - const SPtr<client::GraphModel>& graph); + void + graph_property_changed(const URI& key, + const Atom& value, + const std::shared_ptr<client::GraphModel>& graph); - void graph_moved(const SPtr<client::GraphModel>& graph); + void graph_moved(const std::shared_ptr<client::GraphModel>& graph); - void add_graph(const SPtr<client::GraphModel>& pm); - void remove_graph(const SPtr<client::GraphModel>& pm); + void add_graph(const std::shared_ptr<client::GraphModel>& pm); + void remove_graph(const std::shared_ptr<client::GraphModel>& pm); void show_graph_menu(GdkEventButton* ev); protected: @@ -65,30 +82,28 @@ protected: void event_graph_enabled_toggled(const Glib::ustring& path_str); - Gtk::TreeModel::iterator find_graph( - Gtk::TreeModel::Children root, - const SPtr<client::ObjectModel>& graph); + Gtk::TreeModel::iterator + find_graph(Gtk::TreeModel::Children root, + const std::shared_ptr<client::ObjectModel>& graph); - GraphTreeView* _graphs_treeview; + GraphTreeView* _graphs_treeview{nullptr}; - struct GraphTreeModelColumns : public Gtk::TreeModel::ColumnRecord - { + struct GraphTreeModelColumns : public Gtk::TreeModel::ColumnRecord { GraphTreeModelColumns() { add(name_col); add(enabled_col); add(graph_model_col); } - Gtk::TreeModelColumn<Glib::ustring> name_col; - Gtk::TreeModelColumn<bool> enabled_col; - Gtk::TreeModelColumn<SPtr<client::GraphModel> > graph_model_col; + Gtk::TreeModelColumn<Glib::ustring> name_col; + Gtk::TreeModelColumn<bool> enabled_col; + Gtk::TreeModelColumn<std::shared_ptr<client::GraphModel>> graph_model_col; }; - App* _app; GraphTreeModelColumns _graph_tree_columns; Glib::RefPtr<Gtk::TreeStore> _graph_treestore; Glib::RefPtr<Gtk::TreeSelection> _graph_tree_selection; - bool _enable_signal; + bool _enable_signal{true}; }; /** Derived TreeView class to support context menus for graphs */ @@ -98,24 +113,23 @@ public: GraphTreeView(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& xml) : Gtk::TreeView(cobject) - , _window(nullptr) {} void set_window(GraphTreeWindow* win) { _window = win; } bool on_button_press_event(GdkEventButton* ev) override { - bool ret = Gtk::TreeView::on_button_press_event(ev); + const bool ret = Gtk::TreeView::on_button_press_event(ev); - if ((ev->type == GDK_BUTTON_PRESS) && (ev->button == 3)) + if ((ev->type == GDK_BUTTON_PRESS) && (ev->button == 3)) { _window->show_graph_menu(ev); + } return ret; } private: - GraphTreeWindow* _window; - -}; // struct GraphTreeView + GraphTreeWindow* _window{nullptr}; +}; } // namespace gui } // namespace ingen diff --git a/src/gui/GraphView.cpp b/src/gui/GraphView.cpp index 36c6caed..8d1e1777 100644 --- a/src/gui/GraphView.cpp +++ b/src/gui/GraphView.cpp @@ -14,32 +14,49 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ +#include "GraphView.hpp" + #include "App.hpp" -#include "LoadPluginWindow.hpp" -#include "NewSubgraphWindow.hpp" #include "GraphCanvas.hpp" -#include "GraphTreeWindow.hpp" -#include "GraphView.hpp" #include "WidgetFactory.hpp" -#include "ingen/Interface.hpp" -#include "ingen/client/GraphModel.hpp" +#include <ingen/Atom.hpp> +#include <ingen/Forge.hpp> +#include <ingen/Properties.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIs.hpp> +#include <ingen/client/GraphModel.hpp> + +#include <glibmm/propertyproxy.h> +#include <glibmm/refptr.h> +#include <gtkmm/adjustment.h> +#include <gtkmm/builder.h> +#include <gtkmm/enums.h> +#include <gtkmm/layout.h> +#include <gtkmm/scrolledwindow.h> +#include <gtkmm/spinbutton.h> +#include <gtkmm/toggletoolbutton.h> +#include <gtkmm/toolbar.h> +#include <gtkmm/toolitem.h> +#include <sigc++/functors/mem_fun.h> +#include <sigc++/signal.h> #include <cassert> -#include <fstream> +#include <cstdint> +#include <map> +#include <memory> +#include <string> +#include <utility> namespace ingen { -using namespace client; +using client::GraphModel; namespace gui { GraphView::GraphView(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& xml) : Gtk::Box(cobject) - , _app(nullptr) - , _breadcrumb_container(nullptr) - , _enable_signal(true) { property_visible() = false; @@ -66,14 +83,14 @@ GraphView::init(App& app) } void -GraphView::set_graph(const SPtr<const GraphModel>& graph) +GraphView::set_graph(const std::shared_ptr<const GraphModel>& graph) { assert(!_canvas); // FIXME: remove assert(_breadcrumb_container); // ensure created _graph = graph; - _canvas = SPtr<GraphCanvas>(new GraphCanvas(*_app, graph, 1600*2, 1200*2)); + _canvas = std::make_shared<GraphCanvas>(*_app, graph, 1600*2, 1200*2); _canvas->build(); _canvas_scrolledwindow->add(_canvas->widget()); @@ -100,15 +117,21 @@ GraphView::set_graph(const SPtr<const GraphModel>& graph) _canvas->widget().grab_focus(); } -SPtr<GraphView> -GraphView::create(App& app, const SPtr<const GraphModel>& graph) +std::shared_ptr<GraphView> +GraphView::create(App& app, const std::shared_ptr<const GraphModel>& graph) { - GraphView* result = nullptr; - Glib::RefPtr<Gtk::Builder> xml = WidgetFactory::create("warehouse_win"); + GraphView* result = nullptr; + const Glib::RefPtr<Gtk::Builder> xml = + WidgetFactory::create("warehouse_win"); + xml->get_widget_derived("graph_view_box", result); + if (!result) { + return nullptr; + } + result->init(app); result->set_graph(graph); - return SPtr<GraphView>(result); + return std::shared_ptr<GraphView>(result); } void @@ -120,14 +143,14 @@ GraphView::process_toggled() _app->set_property(_graph->uri(), _app->uris().ingen_enabled, - _app->forge().make((bool)_process_but->get_active())); + _app->forge().make(_process_but->get_active())); } void GraphView::poly_changed() { const int poly = _poly_spin->get_value_as_int(); - if (_enable_signal && poly != (int)_graph->internal_poly()) { + if (_enable_signal && poly != static_cast<int>(_graph->internal_poly())) { _app->set_property(_graph->uri(), _app->uris().ingen_polyphony, _app->forge().make(poly)); diff --git a/src/gui/GraphView.hpp b/src/gui/GraphView.hpp index 457a5f76..812f2cbc 100644 --- a/src/gui/GraphView.hpp +++ b/src/gui/GraphView.hpp @@ -17,18 +17,22 @@ #ifndef INGEN_GUI_GRAPHVIEW_HPP #define INGEN_GUI_GRAPHVIEW_HPP -#include "ingen/types.hpp" - #include <gtkmm/box.h> -#include <gtkmm/builder.h> -#include <gtkmm/scrolledwindow.h> -#include <gtkmm/spinbutton.h> -#include <gtkmm/toggletoolbutton.h> -#include <gtkmm/toolbar.h> -#include <gtkmm/toolitem.h> -#include <gtkmm/toolitem.h> -namespace Raul { class Atom; } +#include <memory> + +namespace Glib { +template <class T> class RefPtr; +} // namespace Glib + +namespace Gtk { +class Builder; +class ScrolledWindow; +class SpinButton; +class ToggleToolButton; +class ToolItem; +class Toolbar; +} // namespace Gtk namespace ingen { @@ -36,22 +40,15 @@ class Atom; class URI; namespace client { -class PortModel; -class MetadataModel; class GraphModel; -class ObjectModel; -} +} // namespace client namespace gui { class App; -class LoadPluginWindow; -class NewSubgraphWindow; class GraphCanvas; -class GraphDescriptionWindow; -class SubgraphModule; -/** 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 */ @@ -61,19 +58,23 @@ public: GraphView(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& xml); - ~GraphView(); + ~GraphView() override; void init(App& app); - SPtr<GraphCanvas> canvas() const { return _canvas; } - SPtr<const client::GraphModel> graph() const { return _graph; } - Gtk::ToolItem* breadcrumb_container() const { return _breadcrumb_container; } + std::shared_ptr<GraphCanvas> canvas() const { return _canvas; } + std::shared_ptr<const client::GraphModel> graph() const { return _graph; } + + Gtk::ToolItem* breadcrumb_container() const + { + return _breadcrumb_container; + } - static SPtr<GraphView> - create(App& app, const SPtr<const client::GraphModel>& graph); + static std::shared_ptr<GraphView> + create(App& app, const std::shared_ptr<const client::GraphModel>& graph); private: - void set_graph(const SPtr<const client::GraphModel>& graph); + void set_graph(const std::shared_ptr<const client::GraphModel>& graph); void process_toggled(); void poly_changed(); @@ -81,18 +82,18 @@ private: void property_changed(const URI& predicate, const Atom& value); - App* _app; + App* _app = nullptr; - SPtr<const client::GraphModel> _graph; - SPtr<GraphCanvas> _canvas; + std::shared_ptr<const client::GraphModel> _graph; + std::shared_ptr<GraphCanvas> _canvas; - Gtk::ScrolledWindow* _canvas_scrolledwindow; - Gtk::Toolbar* _toolbar; - Gtk::ToggleToolButton* _process_but; - Gtk::SpinButton* _poly_spin; - Gtk::ToolItem* _breadcrumb_container; + Gtk::ScrolledWindow* _canvas_scrolledwindow = nullptr; + Gtk::Toolbar* _toolbar = nullptr; + Gtk::ToggleToolButton* _process_but = nullptr; + Gtk::SpinButton* _poly_spin = nullptr; + Gtk::ToolItem* _breadcrumb_container = nullptr; - bool _enable_signal; + bool _enable_signal = true; }; } // namespace gui diff --git a/src/gui/GraphWindow.cpp b/src/gui/GraphWindow.cpp index 086886ef..a6978e46 100644 --- a/src/gui/GraphWindow.cpp +++ b/src/gui/GraphWindow.cpp @@ -14,25 +14,24 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "ingen/client/ClientStore.hpp" -#include "ingen/client/GraphModel.hpp" +#include "GraphWindow.hpp" -#include "App.hpp" +#include "GraphBox.hpp" #include "GraphCanvas.hpp" #include "GraphView.hpp" -#include "GraphWindow.hpp" -#include "WindowFactory.hpp" +#include "Window.hpp" + +#include <glibmm/propertyproxy.h> +#include <glibmm/refptr.h> +#include <gtkmm/builder.h> +#include <gtkmm/layout.h> +#include <gtkmm/window.h> -namespace ingen { -namespace gui { +namespace ingen::gui { GraphWindow::GraphWindow(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& xml) : Window(cobject) - , _box(nullptr) - , _position_stored(false) - , _x(0) - , _y(0) { property_visible() = false; @@ -81,5 +80,4 @@ GraphWindow::on_key_press_event(GdkEventKey* event) return Gtk::Window::on_key_press_event(event); } -} // namespace gui -} // namespace ingen +} // namespace ingen::gui diff --git a/src/gui/GraphWindow.hpp b/src/gui/GraphWindow.hpp index e3d30d4c..9936b5df 100644 --- a/src/gui/GraphWindow.hpp +++ b/src/gui/GraphWindow.hpp @@ -20,17 +20,27 @@ #include "GraphBox.hpp" #include "Window.hpp" -#include "ingen/types.hpp" - -#include <gtkmm/builder.h> +#include <gdk/gdk.h> +#include <memory> #include <string> +namespace Glib { +template <class T> class RefPtr; +} // namespace Glib + +namespace Gtk { +class Builder; +} // namespace Gtk + namespace ingen { +class Atom; + namespace client { class GraphModel; -} +class PortModel; +} // namespace client namespace gui { @@ -44,12 +54,16 @@ public: GraphWindow(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& xml); - ~GraphWindow(); + ~GraphWindow() override; void init_window(App& app) override; - SPtr<const client::GraphModel> graph() const { return _box->graph(); } - GraphBox* box() const { return _box; } + std::shared_ptr<const client::GraphModel> graph() const + { + return _box->graph(); + } + + GraphBox* box() const { return _box; } bool documentation_is_visible() { return _box->documentation_is_visible(); } @@ -68,10 +82,10 @@ protected: bool on_key_press_event(GdkEventKey* event) override; private: - GraphBox* _box; - bool _position_stored; - int _x; - int _y; + GraphBox* _box{nullptr}; + bool _position_stored{false}; + int _x{0}; + int _y{0}; }; } // namespace gui diff --git a/src/gui/LoadGraphWindow.cpp b/src/gui/LoadGraphWindow.cpp index 62c68b04..5124face 100644 --- a/src/gui/LoadGraphWindow.cpp +++ b/src/gui/LoadGraphWindow.cpp @@ -17,36 +17,55 @@ #include "LoadGraphWindow.hpp" #include "App.hpp" -#include "GraphView.hpp" -#include "Style.hpp" #include "ThreadedLoader.hpp" -#include "ingen/Configuration.hpp" -#include "ingen/Interface.hpp" -#include "ingen/client/BlockModel.hpp" -#include "ingen/client/ClientStore.hpp" -#include "ingen/client/GraphModel.hpp" -#include "ingen/runtime_paths.hpp" - -#include <boost/optional/optional.hpp> +#include <ingen/Atom.hpp> +#include <ingen/Configuration.hpp> +#include <ingen/FilePath.hpp> +#include <ingen/Forge.hpp> +#include <ingen/Properties.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIs.hpp> +#include <ingen/World.hpp> +#include <ingen/client/ClientStore.hpp> +#include <ingen/client/GraphModel.hpp> +#include <ingen/runtime_paths.hpp> +#include <raul/Path.hpp> +#include <raul/Symbol.hpp> + +#include <glibmm/fileutils.h> #include <glibmm/miscutils.h> +#include <glibmm/propertyproxy.h> +#include <glibmm/refptr.h> +#include <glibmm/slisthandle.h> +#include <gtkmm/builder.h> +#include <gtkmm/button.h> +#include <gtkmm/entry.h> +#include <gtkmm/filefilter.h> +#include <gtkmm/label.h> +#include <gtkmm/radiobutton.h> +#include <gtkmm/spinbutton.h> +#include <gtkmm/window.h> +#include <sigc++/adaptors/bind.h> +#include <sigc++/functors/mem_fun.h> #include <list> -#include <ostream> +#include <map> +#include <memory> +#include <optional> +#include <sstream> #include <string> #include <utility> namespace ingen { -using namespace client; +using client::GraphModel; namespace gui { LoadGraphWindow::LoadGraphWindow(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& xml) : Gtk::FileChooserDialog(cobject) - , _app(nullptr) - , _merge_ports(false) { xml->get_widget("load_graph_symbol_label", _symbol_label); xml->get_widget("load_graph_symbol_entry", _symbol_entry); @@ -97,9 +116,9 @@ LoadGraphWindow::LoadGraphWindow(BaseObjectType* cobject, } void -LoadGraphWindow::present(const SPtr<const GraphModel>& graph, - bool import, - const Properties& data) +LoadGraphWindow::present(const std::shared_ptr<const GraphModel>& graph, + bool import, + const Properties& data) { _import = import; set_graph(graph); @@ -117,7 +136,7 @@ LoadGraphWindow::present(const SPtr<const GraphModel>& graph, * This function MUST be called before using the window in any way! */ void -LoadGraphWindow::set_graph(const SPtr<const GraphModel>& graph) +LoadGraphWindow::set_graph(const std::shared_ptr<const GraphModel>& graph) { _graph = graph; _symbol_entry->set_text(""); @@ -169,8 +188,8 @@ LoadGraphWindow::ok_clicked() if (_import) { // If unset load_graph will load value - boost::optional<Raul::Path> parent; - boost::optional<Raul::Symbol> symbol; + std::optional<raul::Path> parent; + std::optional<raul::Symbol> symbol; if (!_graph->path().is_root()) { parent = _graph->path().parent(); symbol = _graph->symbol(); @@ -180,17 +199,17 @@ LoadGraphWindow::ok_clicked() true, FilePath(get_filename()), parent, symbol, _initial_data); } else { - std::list<Glib::ustring> uri_list = get_filenames(); - for (auto u : uri_list) { + const std::list<Glib::ustring> uri_list = get_filenames(); + for (const auto& u : uri_list) { // Cascade Atom& x = _initial_data.find(uris.ingen_canvasX)->second; x = _app->forge().make(x.get<float>() + 20.0f); Atom& y = _initial_data.find(uris.ingen_canvasY)->second; y = _app->forge().make(y.get<float>() + 20.0f); - Raul::Symbol symbol(symbol_from_filename(u)); + raul::Symbol symbol(symbol_from_filename(u)); if (uri_list.size() == 1 && !_symbol_entry->get_text().empty()) { - symbol = Raul::Symbol::symbolify(_symbol_entry->get_text()); + symbol = raul::Symbol::symbolify(_symbol_entry->get_text()); } symbol = avoid_symbol_clash(symbol); @@ -215,27 +234,27 @@ LoadGraphWindow::cancel_clicked() hide(); } -Raul::Symbol +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('.')); - return Raul::Symbol::symbolify(symbol_str); + symbol_str.resize(symbol_str.find('.')); + return raul::Symbol::symbolify(symbol_str); } -Raul::Symbol -LoadGraphWindow::avoid_symbol_clash(const Raul::Symbol& symbol) +raul::Symbol +LoadGraphWindow::avoid_symbol_clash(const raul::Symbol& symbol) { - unsigned offset = _app->store()->child_name_offset( + const unsigned offset = _app->store()->child_name_offset( _graph->path(), symbol); if (offset != 0) { std::stringstream ss; ss << symbol << "_" << offset; - return Raul::Symbol(ss.str()); - } else { - return symbol; + return raul::Symbol(ss.str()); } + + return symbol; } void diff --git a/src/gui/LoadGraphWindow.hpp b/src/gui/LoadGraphWindow.hpp index a2217d83..bfa2590e 100644 --- a/src/gui/LoadGraphWindow.hpp +++ b/src/gui/LoadGraphWindow.hpp @@ -17,20 +17,32 @@ #ifndef INGEN_GUI_LOADGRAPHWINDOW_HPP #define INGEN_GUI_LOADGRAPHWINDOW_HPP -#include "ingen/Node.hpp" -#include "ingen/types.hpp" +#include <ingen/Properties.hpp> +#include <raul/Symbol.hpp> -#include <gtkmm/builder.h> -#include <gtkmm/button.h> -#include <gtkmm/entry.h> +#include <glibmm/ustring.h> #include <gtkmm/filechooserdialog.h> -#include <gtkmm/label.h> -#include <gtkmm/radiobutton.h> -#include <gtkmm/spinbutton.h> + +#include <memory> + +namespace Glib { +template <class T> class RefPtr; +} // namespace Glib + +namespace Gtk { +class Builder; +class Button; +class Entry; +class Label; +class RadioButton; +class SpinButton; +} // namespace Gtk namespace ingen { -namespace client { class GraphModel; } +namespace client { +class GraphModel; +} // namespace client namespace gui { @@ -50,11 +62,11 @@ public: void init(App& app) { _app = &app; } - void set_graph(const SPtr<const client::GraphModel>& graph); + void set_graph(const std::shared_ptr<const client::GraphModel>& graph); - void present(const SPtr<const client::GraphModel>& graph, - bool import, - const Properties& data); + void present(const std::shared_ptr<const client::GraphModel>& graph, + bool import, + const Properties& data); protected: void on_show() override; @@ -67,28 +79,28 @@ private: void cancel_clicked(); void ok_clicked(); - Raul::Symbol symbol_from_filename(const Glib::ustring& filename); - Raul::Symbol avoid_symbol_clash(const Raul::Symbol& symbol); + raul::Symbol symbol_from_filename(const Glib::ustring& filename); + raul::Symbol avoid_symbol_clash(const raul::Symbol& symbol); - App* _app; + App* _app = nullptr; Properties _initial_data; - SPtr<const client::GraphModel> _graph; - - Gtk::Label* _symbol_label; - Gtk::Entry* _symbol_entry; - Gtk::Label* _ports_label; - Gtk::RadioButton* _merge_ports_radio; - Gtk::RadioButton* _insert_ports_radio; - Gtk::RadioButton* _poly_voices_radio; - Gtk::RadioButton* _poly_from_file_radio; - Gtk::SpinButton* _poly_spinbutton; - Gtk::Button* _ok_button; - Gtk::Button* _cancel_button; - - bool _import; - bool _merge_ports; + std::shared_ptr<const client::GraphModel> _graph; + + Gtk::Label* _symbol_label = nullptr; + Gtk::Entry* _symbol_entry = nullptr; + Gtk::Label* _ports_label = nullptr; + Gtk::RadioButton* _merge_ports_radio = nullptr; + Gtk::RadioButton* _insert_ports_radio = nullptr; + Gtk::RadioButton* _poly_voices_radio = nullptr; + Gtk::RadioButton* _poly_from_file_radio = nullptr; + Gtk::SpinButton* _poly_spinbutton = nullptr; + Gtk::Button* _ok_button = nullptr; + Gtk::Button* _cancel_button = nullptr; + + bool _import = false; + bool _merge_ports = false; }; } // namespace gui diff --git a/src/gui/LoadPluginWindow.cpp b/src/gui/LoadPluginWindow.cpp index bb84f96f..3d8b2cd5 100644 --- a/src/gui/LoadPluginWindow.cpp +++ b/src/gui/LoadPluginWindow.cpp @@ -14,36 +14,66 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "App.hpp" -#include "GraphCanvas.hpp" -#include "GraphView.hpp" -#include "GraphWindow.hpp" #include "LoadPluginWindow.hpp" -#include "ingen_config.h" -#include "ingen/Interface.hpp" -#include "ingen/client/ClientStore.hpp" -#include "ingen/client/GraphModel.hpp" +#include "App.hpp" +#include "Window.hpp" + +#include <ingen/Atom.hpp> +#include <ingen/Forge.hpp> +#include <ingen/Interface.hpp> +#include <ingen/Properties.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIs.hpp> +#include <ingen/client/ClientStore.hpp> +#include <ingen/client/GraphModel.hpp> +#include <ingen/client/PluginModel.hpp> +#include <ingen/paths.hpp> +#include <lilv/lilv.h> +#include <raul/Path.hpp> +#include <raul/Symbol.hpp> + +#include <gdk/gdkkeysyms-compat.h> +#include <glibmm/listhandle.h> +#include <glibmm/propertyproxy.h> +#include <glibmm/ustring.h> +#include <gtkmm/builder.h> +#include <gtkmm/button.h> +#include <gtkmm/checkbutton.h> +#include <gtkmm/combobox.h> +#include <gtkmm/enums.h> +#include <gtkmm/messagedialog.h> +#include <gtkmm/object.h> +#include <gtkmm/treeiter.h> +#include <gtkmm/treepath.h> +#include <gtkmm/treeview.h> +#include <gtkmm/treeviewcolumn.h> +#include <gtkmm/window.h> +#include <sigc++/adaptors/bind.h> +#include <sigc++/functors/mem_fun.h> +#include <sigc++/signal.h> -#include <string> -#include <cstddef> -#include <cassert> #include <algorithm> +#include <cctype> +#include <cstddef> +#include <memory> +#include <sstream> +#include <string> +#include <utility> using std::string; namespace ingen { -using namespace client; +using client::ClientStore; +using client::GraphModel; +using client::PluginModel; namespace gui { LoadPluginWindow::LoadPluginWindow(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& xml) : Window(cobject) - , _name_offset(0) - , _has_shown(false) - , _refresh_list(true) { xml->get_widget("load_plugin_plugins_treeview", _plugins_treeview); xml->get_widget("load_plugin_polyphonic_checkbutton", _polyphonic_checkbutton); @@ -77,8 +107,9 @@ LoadPluginWindow::LoadPluginWindow(BaseObjectType* cobject, _criteria_liststore = Gtk::ListStore::create(_criteria_columns); _filter_combo->set_model(_criteria_liststore); - Gtk::TreeModel::iterator iter = _criteria_liststore->append(); - Gtk::TreeModel::Row row = *iter; + auto iter = _criteria_liststore->append(); + auto row = *iter; + row[_criteria_columns._col_label] = "Name contains"; row[_criteria_columns._col_criteria] = CriteriaColumns::Criteria::NAME; _filter_combo->set_active(iter); @@ -125,8 +156,8 @@ LoadPluginWindow::LoadPluginWindow(BaseObjectType* cobject, } void -LoadPluginWindow::present(SPtr<const GraphModel> graph, - Properties data) +LoadPluginWindow::present(const std::shared_ptr<const GraphModel>& graph, + const Properties& data) { set_graph(graph); _initial_data = data; @@ -142,9 +173,9 @@ LoadPluginWindow::name_changed() // Toggle add button sensitivity according name legality if (_selection->get_selected_rows().size() == 1) { const string sym = _name_entry->get_text(); - if (!Raul::Symbol::is_valid(sym)) { + if (!raul::Symbol::is_valid(sym)) { _add_button->property_sensitive() = false; - } else if (_app->store()->find(_graph->path().child(Raul::Symbol(sym))) + } else if (_app->store()->find(_graph->path().child(raul::Symbol(sym))) != _app->store()->end()) { _add_button->property_sensitive() = false; } else { @@ -164,7 +195,7 @@ LoadPluginWindow::name_cleared(Gtk::EntryIconPosition pos, const GdkEventButton* * This function MUST be called before using the window in any way! */ void -LoadPluginWindow::set_graph(SPtr<const GraphModel> graph) +LoadPluginWindow::set_graph(const std::shared_ptr<const GraphModel>& graph) { if (_graph) { _graph = graph; @@ -199,12 +230,13 @@ LoadPluginWindow::on_show() } void -LoadPluginWindow::set_plugins(SPtr<const ClientStore::Plugins> plugins) +LoadPluginWindow::set_plugins( + const std::shared_ptr<const ClientStore::Plugins>& plugins) { _rows.clear(); _plugins_liststore->clear(); - for (const auto& p : *plugins.get()) { + for (const auto& p : *plugins) { add_plugin(p.second); } @@ -213,7 +245,7 @@ LoadPluginWindow::set_plugins(SPtr<const ClientStore::Plugins> plugins) } void -LoadPluginWindow::new_plugin(SPtr<const PluginModel> pm) +LoadPluginWindow::new_plugin(const std::shared_ptr<const PluginModel>& pm) { if (is_visible()) { add_plugin(pm); @@ -223,7 +255,7 @@ LoadPluginWindow::new_plugin(SPtr<const PluginModel> pm) } static std::string -get_project_name(SPtr<const PluginModel> plugin) +get_project_name(const std::shared_ptr<const PluginModel>& plugin) { std::string name; if (plugin->lilv_plugin()) { @@ -249,7 +281,7 @@ get_project_name(SPtr<const PluginModel> plugin) } static std::string -get_author_name(SPtr<const PluginModel> plugin) +get_author_name(const std::shared_ptr<const PluginModel>& plugin) { std::string name; if (plugin->lilv_plugin()) { @@ -263,8 +295,8 @@ get_author_name(SPtr<const PluginModel> plugin) } void -LoadPluginWindow::set_row(Gtk::TreeModel::Row& row, - SPtr<const PluginModel> plugin) +LoadPluginWindow::set_row(Gtk::TreeModel::Row& row, + const std::shared_ptr<const PluginModel>& plugin) { const URIs& uris = _app->uris(); const Atom& name = plugin->get_property(uris.doap_name); @@ -294,14 +326,14 @@ LoadPluginWindow::set_row(Gtk::TreeModel::Row& row, } void -LoadPluginWindow::add_plugin(SPtr<const PluginModel> plugin) +LoadPluginWindow::add_plugin(const std::shared_ptr<const PluginModel>& plugin) { if (plugin->lilv_plugin() && lilv_plugin_is_replaced(plugin->lilv_plugin())) { return; } - Gtk::TreeModel::iterator iter = _plugins_liststore->append(); - Gtk::TreeModel::Row row = *iter; + auto iter = _plugins_liststore->append(); + auto row = *iter; _rows.emplace(plugin->uri(), iter); set_row(row, plugin); @@ -323,20 +355,22 @@ LoadPluginWindow::plugin_activated(const Gtk::TreeModel::Path& path, void LoadPluginWindow::plugin_selection_changed() { - size_t n_selected = _selection->get_selected_rows().size(); + const size_t n_selected = _selection->get_selected_rows().size(); if (n_selected == 0) { _name_offset = 0; _name_entry->set_text(""); _name_entry->set_sensitive(false); } else if (n_selected == 1) { - Gtk::TreeModel::iterator iter = _plugins_liststore->get_iter( - *_selection->get_selected_rows().begin()); + auto iter = _plugins_liststore->get_iter( + *_selection->get_selected_rows().begin()); if (iter) { - Gtk::TreeModel::Row row = *iter; - SPtr<const PluginModel> p = row.get_value( - _plugins_columns._col_plugin); - _name_offset = _app->store()->child_name_offset( - _graph->path(), p->default_block_symbol()); + auto row = *iter; + auto p = row.get_value(_plugins_columns._col_plugin); + + _name_offset = + _app->store()->child_name_offset(_graph->path(), + p->default_block_symbol()); + _name_entry->set_text(generate_module_name(p, _name_offset)); _name_entry->set_sensitive(true); } else { @@ -357,8 +391,9 @@ LoadPluginWindow::plugin_selection_changed() * sends the notification back. */ string -LoadPluginWindow::generate_module_name(SPtr<const PluginModel> plugin, - int offset) +LoadPluginWindow::generate_module_name( + const std::shared_ptr<const PluginModel>& plugin, + int offset) { std::stringstream ss; ss << plugin->default_block_symbol(); @@ -371,17 +406,17 @@ LoadPluginWindow::generate_module_name(SPtr<const PluginModel> plugin, void LoadPluginWindow::load_plugin(const Gtk::TreeModel::iterator& iter) { - const URIs& uris = _app->uris(); - Gtk::TreeModel::Row row = *iter; - SPtr<const PluginModel> plugin = row.get_value(_plugins_columns._col_plugin); - bool polyphonic = _polyphonic_checkbutton->get_active(); - string name = _name_entry->get_text(); + const URIs& uris = _app->uris(); + auto row = *iter; + auto plugin = row.get_value(_plugins_columns._col_plugin); + const bool polyphonic = _polyphonic_checkbutton->get_active(); + string name = _name_entry->get_text(); if (name.empty()) { name = generate_module_name(plugin, _name_offset); } - if (name.empty() || !Raul::Symbol::is_valid(name)) { + if (name.empty() || !raul::Symbol::is_valid(name)) { Gtk::MessageDialog dialog( *this, "Unable to choose a default name, please provide one", @@ -389,8 +424,8 @@ LoadPluginWindow::load_plugin(const Gtk::TreeModel::iterator& iter) dialog.run(); } else { - Raul::Path path = _graph->path().child(Raul::Symbol::symbolify(name)); - Properties props = _initial_data; + const raul::Path path = _graph->path().child(raul::Symbol::symbolify(name)); + Properties props = _initial_data; props.emplace(uris.rdf_type, Property(uris.ingen_Block)); props.emplace(uris.lv2_prototype, _app->forge().make_urid(plugin->uri())); props.emplace(uris.ingen_polyphonic, _app->forge().make(polyphonic)); @@ -425,8 +460,8 @@ LoadPluginWindow::filter_changed() transform(search.begin(), search.end(), search.begin(), ::toupper); // Get selected criteria - const Gtk::TreeModel::Row row = *(_filter_combo->get_active()); - CriteriaColumns::Criteria criteria = row[_criteria_columns._col_criteria]; + const auto row = *(_filter_combo->get_active()); + const CriteriaColumns::Criteria criteria = row[_criteria_columns._col_criteria]; string field; @@ -435,9 +470,9 @@ LoadPluginWindow::filter_changed() size_t num_visible = 0; const URIs& uris = _app->uris(); - for (const auto& p : *_app->store()->plugins().get()) { - const SPtr<PluginModel> plugin = p.second; - const Atom& name = plugin->get_property(uris.doap_name); + for (const auto& p : *_app->store()->plugins()) { + const auto plugin = p.second; + const Atom& name = plugin->get_property(uris.doap_name); switch (criteria) { case CriteriaColumns::Criteria::NAME: @@ -485,9 +520,9 @@ LoadPluginWindow::on_key_press_event(GdkEventKey* event) if (event->keyval == GDK_w && event->state & GDK_CONTROL_MASK) { hide(); return true; - } else { - return Gtk::Window::on_key_press_event(event); } + + return Gtk::Window::on_key_press_event(event); } void @@ -497,7 +532,7 @@ LoadPluginWindow::plugin_property_changed(const URI& plugin, { const URIs& uris = _app->uris(); if (predicate == uris.doap_name) { - Rows::const_iterator i = _rows.find(plugin); + const auto i = _rows.find(plugin); if (i != _rows.end() && value.type() == uris.forge.String) { (*i->second)[_plugins_columns._col_name] = value.ptr<char>(); } diff --git a/src/gui/LoadPluginWindow.hpp b/src/gui/LoadPluginWindow.hpp index 31843dde..eab48913 100644 --- a/src/gui/LoadPluginWindow.hpp +++ b/src/gui/LoadPluginWindow.hpp @@ -19,26 +19,43 @@ #include "Window.hpp" -#include "ingen/Node.hpp" -#include "ingen/client/ClientStore.hpp" -#include "ingen/types.hpp" -#include "ingen_config.h" +#include <ingen/Properties.hpp> +#include <ingen/URI.hpp> +#include <ingen/client/ClientStore.hpp> -#include <gtkmm/builder.h> -#include <gtkmm/combobox.h> +#include <gdk/gdk.h> +#include <glibmm/refptr.h> +#include <gtkmm/entry.h> #include <gtkmm/liststore.h> #include <gtkmm/treemodel.h> -#include <gtkmm/treeview.h> +#include <gtkmm/treemodelcolumn.h> +#include <gtkmm/treeselection.h> #include <map> +#include <memory> #include <string> +namespace Glib { +class ustring; +} // namespace Glib + +namespace Gtk { +class Builder; +class Button; +class CheckButton; +class ComboBox; +class TreeView; +class TreeViewColumn; +} // namespace Gtk + namespace ingen { +class Atom; + namespace client { class GraphModel; class PluginModel; -} +} // namespace client namespace gui { @@ -54,13 +71,15 @@ public: LoadPluginWindow(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& xml); - void set_graph(SPtr<const client::GraphModel> graph); - void set_plugins(SPtr<const client::ClientStore::Plugins> plugins); + void set_graph(const std::shared_ptr<const client::GraphModel>& graph); + + void set_plugins( + const std::shared_ptr<const client::ClientStore::Plugins>& plugins); - void add_plugin(SPtr<const client::PluginModel> plugin); + void add_plugin(const std::shared_ptr<const client::PluginModel>& plugin); - void present(SPtr<const client::GraphModel> graph, - Properties data); + void present(const std::shared_ptr<const client::GraphModel>& graph, + const Properties& data); protected: void on_show() override; @@ -68,7 +87,8 @@ protected: private: /** Columns for the plugin list */ - class ModelColumns : public Gtk::TreeModel::ColumnRecord { + class ModelColumns : public Gtk::TreeModel::ColumnRecord + { public: ModelColumns() { add(_col_name); @@ -86,11 +106,12 @@ private: Gtk::TreeModelColumn<Glib::ustring> _col_uri; // Not displayed: - Gtk::TreeModelColumn< SPtr<const client::PluginModel> > _col_plugin; + Gtk::TreeModelColumn<std::shared_ptr<const client::PluginModel>> _col_plugin; }; /** Column for the filter criteria combo box. */ - class CriteriaColumns : public Gtk::TreeModel::ColumnRecord { + class CriteriaColumns : public Gtk::TreeModel::ColumnRecord + { public: enum class Criteria { NAME, TYPE, PROJECT, AUTHOR, URI, }; @@ -109,10 +130,10 @@ private: void name_changed(); void name_cleared(Gtk::EntryIconPosition pos, const GdkEventButton* event); - void set_row(Gtk::TreeModel::Row& row, - SPtr<const client::PluginModel> plugin); + void set_row(Gtk::TreeModel::Row& row, + const std::shared_ptr<const client::PluginModel>& plugin); - void new_plugin(SPtr<const client::PluginModel> pm); + void new_plugin(const std::shared_ptr<const client::PluginModel>& pm); void plugin_property_changed(const URI& plugin, const URI& predicate, @@ -121,14 +142,15 @@ private: void plugin_activated(const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn* col); void plugin_selection_changed(); - std::string generate_module_name(SPtr<const client::PluginModel> plugin, - int offset=0); + static std::string generate_module_name( + const std::shared_ptr<const client::PluginModel>& plugin, + int offset = 0); void load_plugin(const Gtk::TreeModel::iterator& iter); Properties _initial_data; - SPtr<const client::GraphModel> _graph; + std::shared_ptr<const client::GraphModel> _graph; using Rows = std::map<URI, Gtk::TreeModel::iterator>; Rows _rows; @@ -141,17 +163,17 @@ private: Glib::RefPtr<Gtk::TreeSelection> _selection; - int _name_offset; // see comments for generate_plugin_name - - bool _has_shown; - bool _refresh_list; - Gtk::TreeView* _plugins_treeview; - Gtk::CheckButton* _polyphonic_checkbutton; - Gtk::Entry* _name_entry; - Gtk::Button* _close_button; - Gtk::Button* _add_button; - Gtk::ComboBox* _filter_combo; - Gtk::Entry* _search_entry; + int _name_offset = 0; // see comments for generate_plugin_name + + bool _has_shown = false; + bool _refresh_list = true; + Gtk::TreeView* _plugins_treeview = nullptr; + Gtk::CheckButton* _polyphonic_checkbutton = nullptr; + Gtk::Entry* _name_entry = nullptr; + Gtk::Button* _close_button = nullptr; + Gtk::Button* _add_button = nullptr; + Gtk::ComboBox* _filter_combo = nullptr; + Gtk::Entry* _search_entry = nullptr; }; } // namespace gui diff --git a/src/gui/MessagesWindow.cpp b/src/gui/MessagesWindow.cpp index 84d29679..993fbb33 100644 --- a/src/gui/MessagesWindow.cpp +++ b/src/gui/MessagesWindow.cpp @@ -17,16 +17,30 @@ #include "MessagesWindow.hpp" #include "App.hpp" - -#include "ingen/URIs.hpp" +#include "Window.hpp" +#include "ingen_config.h" + +#include <ingen/URIs.hpp> +#include <lv2/urid/urid.h> + +#include <gdkmm/color.h> +#include <glibmm/propertyproxy.h> +#include <glibmm/ustring.h> +#include <gtkmm/builder.h> +#include <gtkmm/button.h> +#include <gtkmm/enums.h> +#include <gtkmm/textbuffer.h> +#include <gtkmm/texttagtable.h> +#include <gtkmm/textview.h> +#include <sigc++/functors/mem_fun.h> #include <cstdio> #include <cstdlib> #include <string> #include <utility> -namespace ingen { -namespace gui { +namespace ingen::gui { + using std::string; MessagesWindow::MessagesWindow(BaseObjectType* cobject, @@ -41,8 +55,8 @@ MessagesWindow::MessagesWindow(BaseObjectType* cobject, _close_button->signal_clicked().connect(sigc::mem_fun(this, &Window::hide)); for (int s = Gtk::STATE_NORMAL; s <= Gtk::STATE_INSENSITIVE; ++s) { - _textview->modify_base((Gtk::StateType)s, Gdk::Color("#000000")); - _textview->modify_text((Gtk::StateType)s, Gdk::Color("#EEEEEC")); + _textview->modify_base(static_cast<Gtk::StateType>(s), Gdk::Color("#000000")); + _textview->modify_text(static_cast<Gtk::StateType>(s), Gdk::Color("#EEEEEC")); } } @@ -70,7 +84,7 @@ MessagesWindow::init_window(App& app) void MessagesWindow::post_error(const string& msg) { - Glib::RefPtr<Gtk::TextBuffer> text_buf = _textview->get_buffer(); + const Glib::RefPtr<Gtk::TextBuffer> text_buf = _textview->get_buffer(); text_buf->insert_with_tag(text_buf->end(), msg, _error_tag); text_buf->insert(text_buf->end(), "\n"); @@ -87,9 +101,9 @@ MessagesWindow::post_error(const string& msg) int MessagesWindow::log(LV2_URID type, const char* fmt, va_list args) { - std::lock_guard<std::mutex> lock(_mutex); + const std::lock_guard<std::mutex> lock{_mutex}; -#ifdef HAVE_VASPRINTF +#if USE_VASPRINTF char* buf = nullptr; const int len = vasprintf(&buf, fmt, args); #else @@ -107,10 +121,11 @@ void MessagesWindow::flush() { while (true) { - LV2_URID type; + LV2_URID type = 0; std::string line; + { - std::lock_guard<std::mutex> lock(_mutex); + const std::lock_guard<std::mutex> lock{_mutex}; if (!_stream.rdbuf()->in_avail()) { return; } @@ -118,7 +133,7 @@ MessagesWindow::flush() std::getline(_stream, line, '\0'); } - Glib::RefPtr<Gtk::TextBuffer> text_buf = _textview->get_buffer(); + const Glib::RefPtr<Gtk::TextBuffer> text_buf = _textview->get_buffer(); auto t = _tags.find(type); if (t != _tags.end()) { @@ -136,10 +151,9 @@ MessagesWindow::flush() void MessagesWindow::clear_clicked() { - Glib::RefPtr<Gtk::TextBuffer> text_buf = _textview->get_buffer(); + const Glib::RefPtr<Gtk::TextBuffer> text_buf = _textview->get_buffer(); text_buf->erase(text_buf->begin(), text_buf->end()); _clear_button->set_sensitive(false); } -} // namespace gui -} // namespace ingen +} // namespace ingen::gui diff --git a/src/gui/MessagesWindow.hpp b/src/gui/MessagesWindow.hpp index add87455..0a70e76c 100644 --- a/src/gui/MessagesWindow.hpp +++ b/src/gui/MessagesWindow.hpp @@ -19,11 +19,10 @@ #include "Window.hpp" -#include "lv2/log/log.h" +#include <lv2/urid/urid.h> -#include <gtkmm/builder.h> -#include <gtkmm/button.h> -#include <gtkmm/textview.h> +#include <glibmm/refptr.h> +#include <gtkmm/texttag.h> #include <cstdarg> #include <map> @@ -31,8 +30,13 @@ #include <sstream> #include <string> -namespace ingen { -namespace gui { +namespace Gtk { +class Builder; +class Button; +class TextView; +} // namespace Gtk + +namespace ingen::gui { /** Messages Window. * @@ -59,15 +63,14 @@ private: std::mutex _mutex; std::stringstream _stream; - Gtk::TextView* _textview; - Gtk::Button* _clear_button; - Gtk::Button* _close_button; + Gtk::TextView* _textview{nullptr}; + Gtk::Button* _clear_button{nullptr}; + Gtk::Button* _close_button{nullptr}; Glib::RefPtr<Gtk::TextTag> _error_tag; std::map< LV2_URID, Glib::RefPtr<Gtk::TextTag> > _tags; }; -} // namespace gui -} // namespace ingen +} // namespace ingen::gui #endif // INGEN_GUI_MESSAGESWINDOW_HPP diff --git a/src/gui/NewSubgraphWindow.cpp b/src/gui/NewSubgraphWindow.cpp index 228bd91c..3d6bf019 100644 --- a/src/gui/NewSubgraphWindow.cpp +++ b/src/gui/NewSubgraphWindow.cpp @@ -17,17 +17,38 @@ #include "NewSubgraphWindow.hpp" #include "App.hpp" -#include "GraphView.hpp" - -#include "ingen/Interface.hpp" -#include "ingen/client/ClientStore.hpp" -#include "ingen/client/GraphModel.hpp" +#include "Window.hpp" + +#include <ingen/Forge.hpp> +#include <ingen/Interface.hpp> +#include <ingen/Properties.hpp> +#include <ingen/Resource.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIs.hpp> +#include <ingen/client/ClientStore.hpp> +#include <ingen/client/GraphModel.hpp> +#include <ingen/paths.hpp> +#include <raul/Path.hpp> +#include <raul/Symbol.hpp> + +#include <glibmm/propertyproxy.h> +#include <glibmm/refptr.h> +#include <glibmm/ustring.h> +#include <gtkmm/adjustment.h> +#include <gtkmm/builder.h> +#include <gtkmm/button.h> +#include <gtkmm/entry.h> +#include <gtkmm/label.h> +#include <gtkmm/spinbutton.h> +#include <gtkmm/window.h> +#include <sigc++/functors/mem_fun.h> #include <cstdint> +#include <map> #include <string> +#include <utility> -namespace ingen { -namespace gui { +namespace ingen::gui { NewSubgraphWindow::NewSubgraphWindow(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& xml) @@ -49,10 +70,10 @@ NewSubgraphWindow::NewSubgraphWindow(BaseObjectType* cobject, } void -NewSubgraphWindow::present(SPtr<const client::GraphModel> graph, - Properties data) +NewSubgraphWindow::present(std::shared_ptr<const client::GraphModel> graph, + const Properties& data) { - set_graph(graph); + set_graph(std::move(graph)); _initial_data = data; Gtk::Window::present(); } @@ -62,9 +83,9 @@ NewSubgraphWindow::present(SPtr<const client::GraphModel> graph, * This function MUST be called before using the window in any way! */ void -NewSubgraphWindow::set_graph(SPtr<const client::GraphModel> graph) +NewSubgraphWindow::set_graph(std::shared_ptr<const client::GraphModel> graph) { - _graph = graph; + _graph = std::move(graph); } /** Called every time the user types into the name input box. @@ -73,11 +94,11 @@ NewSubgraphWindow::set_graph(SPtr<const client::GraphModel> graph) void NewSubgraphWindow::name_changed() { - std::string name = _name_entry->get_text(); - if (!Raul::Symbol::is_valid(name)) { + const std::string name = _name_entry->get_text(); + if (!raul::Symbol::is_valid(name)) { _message_label->set_text("Name contains invalid characters."); _ok_button->property_sensitive() = false; - } else if (_app->store()->find(_graph->path().child(Raul::Symbol(name))) + } else if (_app->store()->find(_graph->path().child(raul::Symbol(name))) != _app->store()->end()) { _message_label->set_text("An object already exists with that name."); _ok_button->property_sensitive() = false; @@ -91,14 +112,14 @@ void NewSubgraphWindow::ok_clicked() { const uint32_t poly = _poly_spinbutton->get_value_as_int(); - const Raul::Path path = _graph->path().child( - Raul::Symbol::symbolify(_name_entry->get_text())); + const raul::Path path = _graph->path().child( + raul::Symbol::symbolify(_name_entry->get_text())); // Create graph Properties props; props.emplace(_app->uris().rdf_type, Property(_app->uris().ingen_Graph)); - props.emplace(_app->uris().ingen_polyphony, _app->forge().make(int32_t(poly))); - props.emplace(_app->uris().ingen_enabled, _app->forge().make(bool(true))); + props.emplace(_app->uris().ingen_polyphony, _app->forge().make(static_cast<int32_t>(poly))); + props.emplace(_app->uris().ingen_enabled, _app->forge().make(true)); _app->interface()->put( path_to_uri(path), props, Resource::Graph::INTERNAL); @@ -117,5 +138,4 @@ NewSubgraphWindow::cancel_clicked() hide(); } -} // namespace gui -} // namespace ingen +} // namespace ingen::gui diff --git a/src/gui/NewSubgraphWindow.hpp b/src/gui/NewSubgraphWindow.hpp index 2d249cf3..b0fb24d2 100644 --- a/src/gui/NewSubgraphWindow.hpp +++ b/src/gui/NewSubgraphWindow.hpp @@ -19,18 +19,27 @@ #include "Window.hpp" -#include "ingen/Node.hpp" -#include "ingen/types.hpp" +#include <ingen/Properties.hpp> -#include <gtkmm/builder.h> -#include <gtkmm/button.h> -#include <gtkmm/entry.h> -#include <gtkmm/label.h> -#include <gtkmm/spinbutton.h> +#include <memory> + +namespace Glib { +template <class T> class RefPtr; +} // namespace Glib + +namespace Gtk { +class Builder; +class Button; +class Entry; +class Label; +class SpinButton; +} // namespace Gtk namespace ingen { -namespace client { class GraphModel; } +namespace client { +class GraphModel; +} // namespace client namespace gui { @@ -46,24 +55,24 @@ public: NewSubgraphWindow(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& xml); - void set_graph(SPtr<const client::GraphModel> graph); + void set_graph(std::shared_ptr<const client::GraphModel> graph); - void present(SPtr<const client::GraphModel> graph, - Properties data); + void present(std::shared_ptr<const client::GraphModel> graph, + const Properties& data); private: void name_changed(); void ok_clicked(); void cancel_clicked(); - Properties _initial_data; - SPtr<const client::GraphModel> _graph; + Properties _initial_data; + std::shared_ptr<const client::GraphModel> _graph; - Gtk::Entry* _name_entry; - Gtk::Label* _message_label; - Gtk::SpinButton* _poly_spinbutton; - Gtk::Button* _ok_button; - Gtk::Button* _cancel_button; + Gtk::Entry* _name_entry{nullptr}; + Gtk::Label* _message_label{nullptr}; + Gtk::SpinButton* _poly_spinbutton{nullptr}; + Gtk::Button* _ok_button{nullptr}; + Gtk::Button* _cancel_button{nullptr}; }; } // namespace gui diff --git a/src/gui/NodeMenu.cpp b/src/gui/NodeMenu.cpp index e2478592..2815194c 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 @@ -17,37 +17,58 @@ #include "NodeMenu.hpp" #include "App.hpp" -#include "WidgetFactory.hpp" -#include "WindowFactory.hpp" - -#include "ingen/Interface.hpp" -#include "ingen/Log.hpp" -#include "ingen/URIMap.hpp" -#include "ingen/client/BlockModel.hpp" -#include "ingen/client/PluginModel.hpp" -#include "ingen/client/PortModel.hpp" -#include "lv2/presets/presets.h" +#include "ObjectMenu.hpp" + +#include <ingen/Atom.hpp> +#include <ingen/Forge.hpp> +#include <ingen/Interface.hpp> +#include <ingen/Properties.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIs.hpp> +#include <ingen/client/BlockModel.hpp> +#include <ingen/client/ObjectModel.hpp> +#include <ingen/client/PluginModel.hpp> +#include <ingen/client/PortModel.hpp> +#include <raul/Symbol.hpp> #include <glib.h> +#include <glibmm/convert.h> +#include <glibmm/miscutils.h> +#include <glibmm/refptr.h> +#include <glibmm/ustring.h> +#include <gtkmm/box.h> +#include <gtkmm/builder.h> +#include <gtkmm/checkmenuitem.h> +#include <gtkmm/dialog.h> #include <gtkmm/entry.h> +#include <gtkmm/enums.h> +#include <gtkmm/filechooser.h> #include <gtkmm/filechooserdialog.h> #include <gtkmm/image.h> +#include <gtkmm/label.h> +#include <gtkmm/menu.h> +#include <gtkmm/menu_elems.h> +#include <gtkmm/menuitem.h> +#include <gtkmm/object.h> +#include <gtkmm/separatormenuitem.h> #include <gtkmm/stock.h> +#include <gtkmm/stockid.h> +#include <sigc++/adaptors/bind.h> +#include <sigc++/functors/mem_fun.h> +#include <algorithm> #include <cstdint> +#include <map> +#include <memory> #include <string> #include <utility> +#include <vector> -namespace ingen { - -using namespace client; - -namespace gui { +namespace ingen::gui { NodeMenu::NodeMenu(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& xml) : ObjectMenu(cobject, xml) - , _presets_menu(nullptr) { xml->get_widget("node_popup_gui_menuitem", _popup_gui_menuitem); xml->get_widget("node_embed_gui_menuitem", _embed_gui_menuitem); @@ -56,7 +77,7 @@ NodeMenu::NodeMenu(BaseObjectType* cobject, } void -NodeMenu::init(App& app, SPtr<const client::BlockModel> block) +NodeMenu::init(App& app, const std::shared_ptr<const client::BlockModel>& block) { ObjectMenu::init(app, block); @@ -71,7 +92,7 @@ NodeMenu::init(App& app, SPtr<const client::BlockModel> block) _randomize_menuitem->signal_activate().connect( sigc::mem_fun(this, &NodeMenu::on_menu_randomize)); - SPtr<PluginModel> plugin = block->plugin_model(); + auto plugin = block->plugin_model(); if (plugin) { // Get the plugin to receive related presets _preset_connection = plugin->signal_preset().connect( @@ -141,6 +162,12 @@ NodeMenu::init(App& app, SPtr<const client::BlockModel> block) _enable_signal = true; } +std::shared_ptr<const client::BlockModel> +NodeMenu::block() const +{ + return std::dynamic_pointer_cast<const client::BlockModel>(_object); +} + void NodeMenu::add_preset(const URI& uri, const std::string& label) { @@ -164,7 +191,7 @@ NodeMenu::on_menu_enabled() { _app->set_property(_object->uri(), _app->uris().ingen_enabled, - _app->forge().make(bool(_enabled_menuitem->get_active()))); + _app->forge().make(_enabled_menuitem->get_active())); } void @@ -172,12 +199,15 @@ NodeMenu::on_menu_randomize() { _app->interface()->bundle_begin(); - const SPtr<const BlockModel> bm = block(); + const auto bm = block(); for (const auto& p : bm->ports()) { if (p->is_input() && _app->can_control(p.get())) { - float min = 0.0f, max = 1.0f; + float min = 0.0f; + float max = 1.0f; bm->port_value_range(p, min, max, _app->sample_rate()); - const float val = g_random_double_range(0.0, 1.0) * (max - min) + min; + + const auto r = static_cast<float>(g_random_double_range(0.0, 1.0)); + const float val = (r * (max - min)) + min; _app->set_property(p->uri(), _app->uris().ingen_value, _app->forge().make(val)); @@ -215,15 +245,15 @@ NodeMenu::on_save_preset_activated() const std::string user_path = Glib::filename_from_uri(user_uri); const std::string dirname = Glib::path_get_dirname(user_path); const std::string basename = Glib::path_get_basename(user_path); - const std::string sym = Raul::Symbol::symbolify(basename); + const std::string sym = raul::Symbol::symbolify(basename); const std::string plugname = block()->plugin_model()->human_name(); - const std::string prefix = Raul::Symbol::symbolify(plugname); + const std::string prefix = raul::Symbol::symbolify(plugname); const std::string bundle = prefix + "_" + sym + ".preset.lv2/"; const std::string file = sym + ".ttl"; const std::string real_path = Glib::build_filename(dirname, bundle, file); const std::string real_uri = Glib::filename_to_uri(real_path); - Properties props{ + const Properties props{ { _app->uris().rdf_type, _app->uris().pset_Preset }, { _app->uris().rdfs_label, @@ -245,14 +275,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 gui -} // namespace ingen +} // namespace ingen::gui diff --git a/src/gui/NodeMenu.hpp b/src/gui/NodeMenu.hpp index 2a3268b4..0427672c 100644 --- a/src/gui/NodeMenu.hpp +++ b/src/gui/NodeMenu.hpp @@ -19,18 +19,35 @@ #include "ObjectMenu.hpp" -#include "ingen/client/BlockModel.hpp" -#include "ingen/types.hpp" +#include <ingen/URI.hpp> -#include <gtkmm/builder.h> -#include <gtkmm/menu.h> -#include <gtkmm/menushell.h> +#include <sigc++/connection.h> +#include <sigc++/signal.h> +#include <memory> #include <string> +namespace Glib { +template <class T> class RefPtr; +} // namespace Glib + +namespace Gtk { +class Builder; +class CheckMenuItem; +class Menu; +class MenuItem; +} // namespace Gtk + namespace ingen { + +namespace client { +class BlockModel; +} // namespace client + namespace gui { +class App; + /** Menu for a Node. * * \ingroup GUI @@ -41,7 +58,7 @@ public: NodeMenu(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& xml); - void init(App& app, SPtr<const client::BlockModel> block); + void init(App& app, const std::shared_ptr<const client::BlockModel>& block); bool has_control_inputs(); @@ -49,9 +66,7 @@ public: sigc::signal<void, bool> signal_embed_gui; protected: - SPtr<const client::BlockModel> block() const { - return dynamic_ptr_cast<const client::BlockModel>(_object); - } + std::shared_ptr<const client::BlockModel> block() const; void add_preset(const URI& uri, const std::string& label); @@ -62,11 +77,11 @@ protected: void on_save_preset_activated(); void on_preset_activated(const std::string& uri); - Gtk::MenuItem* _popup_gui_menuitem; - Gtk::CheckMenuItem* _embed_gui_menuitem; - Gtk::CheckMenuItem* _enabled_menuitem; - Gtk::MenuItem* _randomize_menuitem; - Gtk::Menu* _presets_menu; + Gtk::MenuItem* _popup_gui_menuitem{nullptr}; + Gtk::CheckMenuItem* _embed_gui_menuitem{nullptr}; + Gtk::CheckMenuItem* _enabled_menuitem{nullptr}; + Gtk::MenuItem* _randomize_menuitem{nullptr}; + Gtk::Menu* _presets_menu{nullptr}; sigc::connection _preset_connection; }; diff --git a/src/gui/NodeModule.cpp b/src/gui/NodeModule.cpp index 5984dbe1..deb8fe52 100644 --- a/src/gui/NodeModule.cpp +++ b/src/gui/NodeModule.cpp @@ -17,45 +17,69 @@ #include "NodeModule.hpp" #include "App.hpp" +#include "GraphBox.hpp" #include "GraphCanvas.hpp" #include "GraphWindow.hpp" #include "NodeMenu.hpp" #include "Port.hpp" -#include "RenameWindow.hpp" -#include "Style.hpp" #include "SubgraphModule.hpp" #include "WidgetFactory.hpp" #include "WindowFactory.hpp" #include "ingen_config.h" -#include "ingen/Atom.hpp" -#include "ingen/Configuration.hpp" -#include "ingen/Interface.hpp" -#include "ingen/Log.hpp" -#include "ingen/client/BlockModel.hpp" -#include "ingen/client/GraphModel.hpp" -#include "ingen/client/PluginModel.hpp" -#include "ingen/client/PluginUI.hpp" -#include "lv2/atom/util.h" - +#include <ganv/Module.hpp> +#include <ganv/Port.hpp> +#include <ingen/Atom.hpp> +#include <ingen/Configuration.hpp> +#include <ingen/Forge.hpp> +#include <ingen/Interface.hpp> +#include <ingen/Log.hpp> +#include <ingen/Properties.hpp> +#include <ingen/Resource.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIs.hpp> +#include <ingen/World.hpp> +#include <ingen/client/BlockModel.hpp> +#include <ingen/client/GraphModel.hpp> +#include <ingen/client/PluginModel.hpp> +#include <ingen/client/PluginUI.hpp> +#include <ingen/client/PortModel.hpp> +#include <lv2/atom/util.h> +#include <raul/Path.hpp> +#include <raul/Symbol.hpp> + +#include <glibmm/main.h> +#include <glibmm/ustring.h> +#include <gtkmm/container.h> #include <gtkmm/eventbox.h> +#include <gtkmm/widget.h> +#include <gtkmm/window.h> +#include <sigc++/adaptors/bind.h> +#include <sigc++/adaptors/retype_return.h> +#include <sigc++/functors/mem_fun.h> +#include <sigc++/functors/slot.h> +#include <sigc++/signal.h> #include <cassert> +#include <map> +#include <memory> #include <string> +#include <utility> +#include <vector> namespace ingen { -using namespace client; +using client::BlockModel; +using client::GraphModel; +using client::PluginModel; +using client::PortModel; namespace gui { -NodeModule::NodeModule(GraphCanvas& canvas, - SPtr<const BlockModel> block) - : Ganv::Module(canvas, block->path().symbol(), 0, 0, true) - , _block(block) - , _gui_widget(nullptr) - , _gui_window(nullptr) - , _initialised(false) +NodeModule::NodeModule(GraphCanvas& canvas, + const std::shared_ptr<const BlockModel>& block) + : Ganv::Module(canvas, block->path().symbol(), 0, 0, true) + , _block(block) { block->signal_new_port().connect( sigc::mem_fun(this, &NodeModule::new_port_view)); @@ -75,7 +99,7 @@ NodeModule::NodeModule(GraphCanvas& canvas, signal_selected().connect( sigc::mem_fun(this, &NodeModule::on_selected)); - const PluginModel* plugin = dynamic_cast<const PluginModel*>(block->plugin()); + const auto* plugin = dynamic_cast<const PluginModel*>(block->plugin()); if (plugin) { plugin->signal_changed().connect( sigc::mem_fun(this, &NodeModule::plugin_changed)); @@ -104,8 +128,8 @@ NodeModule::~NodeModule() bool NodeModule::idle_init() { - if (_block->ports().size() == 0) { - return true; // Need to embed GUI, but ports haven't shown up yet + if (_block->ports().empty()) { + return true; // Need to embed GUI, but ports haven't shown up yet } // Ports have arrived, embed GUI and deregister this callback @@ -133,11 +157,11 @@ NodeModule::show_menu(GdkEventButton* ev) } NodeModule* -NodeModule::create(GraphCanvas& canvas, - SPtr<const BlockModel> block, - bool human) +NodeModule::create(GraphCanvas& canvas, + const std::shared_ptr<const BlockModel>& block, + bool human) { - SPtr<const GraphModel> graph = dynamic_ptr_cast<const GraphModel>(block); + auto graph = std::dynamic_pointer_cast<const GraphModel>(block); NodeModule* ret = (graph) ? new SubgraphModule(canvas, graph) @@ -163,7 +187,7 @@ NodeModule::create(GraphCanvas& canvas, App& NodeModule::app() const { - return ((GraphCanvas*)canvas())->app(); + return static_cast<GraphCanvas*>(canvas())->app(); } void @@ -177,22 +201,22 @@ NodeModule::show_human_names(bool b) set_label(block()->symbol().c_str()); } - for (iterator i = begin(); i != end(); ++i) { - ingen::gui::Port* const port = dynamic_cast<ingen::gui::Port*>(*i); + for (auto* p : *this) { + auto* const port = dynamic_cast<ingen::gui::Port*>(p); Glib::ustring label(port->model()->symbol().c_str()); if (b) { const Atom& name_property = port->model()->get_property(uris.lv2_name); if (name_property.type() == uris.forge.String) { label = name_property.ptr<char>(); } else { - Glib::ustring hn = block()->plugin_model()->port_human_name( + const Glib::ustring hn = block()->plugin_model()->port_human_name( port->model()->index()); if (!hn.empty()) { label = hn; } } } - (*i)->set_label(label.c_str()); + port->set_label(label.c_str()); } } @@ -234,8 +258,8 @@ NodeModule::port_value_changed(uint32_t index, const Atom& value) void NodeModule::plugin_changed() { - for (iterator p = begin(); p != end(); ++p) { - dynamic_cast<ingen::gui::Port*>(*p)->update_metadata(); + for (auto* p : *this) { + dynamic_cast<ingen::gui::Port*>(p)->update_metadata(); } } @@ -268,7 +292,9 @@ NodeModule::embed_gui(bool embed) if (!_plugin_ui->instantiate()) { app().log().error("Failed to instantiate LV2 UI\n"); } else { - GtkWidget* c_widget = (GtkWidget*)_plugin_ui->get_widget(); + auto* c_widget = + static_cast<GtkWidget*>(_plugin_ui->get_widget()); + _gui_widget = Glib::wrap(c_widget); Gtk::Container* container = new Gtk::EventBox(); @@ -302,7 +328,7 @@ NodeModule::rename() } void -NodeModule::new_port_view(SPtr<const PortModel> port) +NodeModule::new_port_view(const std::shared_ptr<const PortModel>& port) { Port::create(app(), *this, port); @@ -316,10 +342,10 @@ NodeModule::new_port_view(SPtr<const PortModel> port) } Port* -NodeModule::port(SPtr<const PortModel> model) +NodeModule::port(const std::shared_ptr<const PortModel>& model) { - for (iterator p = begin(); p != end(); ++p) { - Port* const port = dynamic_cast<Port*>(*p); + for (auto* p : *this) { + auto* const port = dynamic_cast<Port*>(p); if (port->model() == model) { return port; } @@ -328,15 +354,16 @@ NodeModule::port(SPtr<const PortModel> model) } void -NodeModule::delete_port_view(SPtr<const PortModel> model) +NodeModule::delete_port_view(const std::shared_ptr<const PortModel>& model) { - Port* p = port(model); - if (p) { - delete p; - } else { + Port* const p = port(model); + + if (!p) { app().log().warn("Failed to find port %1% on module %2%\n", model->path(), _block->path()); } + + delete p; } bool @@ -348,7 +375,9 @@ NodeModule::popup_gui() return true; } - const PluginModel* const plugin = dynamic_cast<const PluginModel*>(_block->plugin()); + const auto* const plugin = + dynamic_cast<const PluginModel*>(_block->plugin()); + assert(plugin); _plugin_ui = plugin->ui(app().world(), _block); @@ -362,7 +391,8 @@ NodeModule::popup_gui() return false; } - GtkWidget* c_widget = (GtkWidget*)_plugin_ui->get_widget(); + auto* c_widget = static_cast<GtkWidget*>(_plugin_ui->get_widget()); + _gui_widget = Glib::wrap(c_widget); _gui_window = new Gtk::Window(); @@ -380,9 +410,9 @@ NodeModule::popup_gui() _gui_window->present(); return true; - } else { - app().log().warn("No LV2 GUI for %1%\n", _block->path()); } + + app().log().warn("No LV2 GUI for %1%\n", _block->path()); } return false; @@ -421,17 +451,21 @@ NodeModule::on_event(GdkEvent* ev) { if (ev->type == GDK_BUTTON_PRESS && ev->button.button == 3) { return show_menu(&ev->button); - } else if (ev->type == GDK_2BUTTON_PRESS) { + } + + if (ev->type == GDK_2BUTTON_PRESS) { return on_double_click(&ev->button); - } else if (ev->type == GDK_ENTER_NOTIFY) { + } + + if (ev->type == GDK_ENTER_NOTIFY) { GraphBox* const box = app().window_factory()->graph_box( - dynamic_ptr_cast<const GraphModel>(_block->parent())); + std::dynamic_pointer_cast<const GraphModel>(_block->parent())); if (box) { box->object_entered(_block.get()); } } else if (ev->type == GDK_LEAVE_NOTIFY) { GraphBox* const box = app().window_factory()->graph_box( - dynamic_ptr_cast<const GraphModel>(_block->parent())); + std::dynamic_pointer_cast<const GraphModel>(_block->parent())); if (box) { box->object_left(_block.get()); } @@ -462,9 +496,9 @@ NodeModule::property_changed(const URI& key, const Atom& value) const URIs& uris = app().uris(); if (value.type() == uris.forge.Float) { if (key == uris.ingen_canvasX) { - move_to(value.get<float>(), get_y()); + move_to(static_cast<double>(value.get<float>()), get_y()); } else if (key == uris.ingen_canvasY) { - move_to(get_x(), value.get<float>()); + move_to(get_x(), static_cast<double>(value.get<float>())); } } else if (value.type() == uris.forge.Bool) { if (key == uris.ingen_polyphonic) { @@ -499,11 +533,11 @@ NodeModule::on_selected(gboolean selected) } if (selected && win->documentation_is_visible()) { - GraphWindow* win = app().window_factory()->parent_graph_window(block()); std::string doc; - bool html = false; -#ifdef HAVE_WEBKIT - html = true; +#if USE_WEBKIT + const bool html = true; +#else + const bool html = false; #endif if (block()->plugin_model()) { doc = block()->plugin_model()->documentation(html); diff --git a/src/gui/NodeModule.hpp b/src/gui/NodeModule.hpp index ed5914de..64ad8f66 100644 --- a/src/gui/NodeModule.hpp +++ b/src/gui/NodeModule.hpp @@ -17,25 +17,37 @@ #ifndef INGEN_GUI_NODEMODULE_HPP #define INGEN_GUI_NODEMODULE_HPP -#include "ganv/Module.hpp" -#include "ingen/types.hpp" +#include <ganv/Module.hpp> +#include <ingen/URI.hpp> -#include "Port.hpp" +#include <gdk/gdk.h> +#include <glib.h> -namespace Raul { class Atom; } +#include <cstdint> +#include <memory> -namespace ingen { namespace client { +namespace Gtk { +class Widget; +class Window; +} // namespace Gtk + +namespace ingen { + +class Atom; + +namespace client { class BlockModel; class PluginUI; class PortModel; -} } +} // namespace client +} // namespace ingen -namespace ingen { -namespace gui { +namespace ingen::gui { +class App; class GraphCanvas; -class Port; class NodeMenu; +class Port; /** A module in a graphn. * @@ -46,26 +58,28 @@ class NodeMenu; class NodeModule : public Ganv::Module { public: - static NodeModule* create( - GraphCanvas& canvas, - SPtr<const client::BlockModel> block, - bool human); + static NodeModule* + create(GraphCanvas& canvas, + const std::shared_ptr<const client::BlockModel>& block, + bool human); - virtual ~NodeModule(); + ~NodeModule() override; App& app() const; - Port* port(SPtr<const client::PortModel> model); + Port* port(const std::shared_ptr<const client::PortModel>& model); - void delete_port_view(SPtr<const client::PortModel> model); + void + delete_port_view(const std::shared_ptr<const client::PortModel>& model); virtual void store_location(double ax, double ay); void show_human_names(bool b); - SPtr<const client::BlockModel> block() const { return _block; } + std::shared_ptr<const client::BlockModel> block() const { return _block; } protected: - NodeModule(GraphCanvas& canvas, SPtr<const client::BlockModel> block); + NodeModule(GraphCanvas& canvas, + const std::shared_ptr<const client::BlockModel>& block); virtual bool on_double_click(GdkEventButton* ev); @@ -81,7 +95,7 @@ protected: void rename(); void property_changed(const URI& key, const Atom& value); - void new_port_view(SPtr<const client::PortModel> port); + void new_port_view(const std::shared_ptr<const client::PortModel>& port); void port_activity(uint32_t index, const Atom& value); void port_value_changed(uint32_t index, const Atom& value); @@ -90,15 +104,14 @@ protected: bool show_menu(GdkEventButton* ev); - SPtr<const client::BlockModel> _block; - NodeMenu* _menu; - SPtr<client::PluginUI> _plugin_ui; - Gtk::Widget* _gui_widget; - Gtk::Window* _gui_window; ///< iff popped up - bool _initialised; + std::shared_ptr<const client::BlockModel> _block; + NodeMenu* _menu{nullptr}; + std::shared_ptr<client::PluginUI> _plugin_ui; + Gtk::Widget* _gui_widget{nullptr}; + Gtk::Window* _gui_window{nullptr}; ///< iff popped up + bool _initialised{false}; }; -} // namespace gui -} // namespace ingen +} // namespace ingen::gui #endif // INGEN_GUI_NODEMODULE_HPP diff --git a/src/gui/ObjectMenu.cpp b/src/gui/ObjectMenu.cpp index 7a523f4e..8c41ff10 100644 --- a/src/gui/ObjectMenu.cpp +++ b/src/gui/ObjectMenu.cpp @@ -17,31 +17,33 @@ #include "ObjectMenu.hpp" #include "App.hpp" -#include "WidgetFactory.hpp" #include "WindowFactory.hpp" -#include "ingen/Forge.hpp" -#include "ingen/Interface.hpp" -#include "ingen/client/ObjectModel.hpp" +#include <ingen/Atom.hpp> +#include <ingen/Forge.hpp> +#include <ingen/Interface.hpp> +#include <ingen/Properties.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIs.hpp> +#include <ingen/client/ObjectModel.hpp> + +#include <glibmm/refptr.h> +#include <gtkmm/builder.h> +#include <gtkmm/checkmenuitem.h> +#include <gtkmm/menuitem.h> +#include <gtkmm/separatormenuitem.h> +#include <sigc++/adaptors/bind.h> +#include <sigc++/functors/mem_fun.h> +#include <sigc++/signal.h> #include <cstdint> +#include <memory> -namespace ingen { - -using namespace client; - -namespace gui { +namespace ingen::gui { ObjectMenu::ObjectMenu(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& xml) : Gtk::Menu(cobject) - , _app(nullptr) - , _polyphonic_menuitem(nullptr) - , _disconnect_menuitem(nullptr) - , _rename_menuitem(nullptr) - , _destroy_menuitem(nullptr) - , _properties_menuitem(nullptr) - , _enable_signal(false) { xml->get_widget("object_learn_menuitem", _learn_menuitem); xml->get_widget("object_unlearn_menuitem", _unlearn_menuitem); @@ -54,7 +56,8 @@ ObjectMenu::ObjectMenu(BaseObjectType* cobject, } void -ObjectMenu::init(App& app, SPtr<const ObjectModel> object) +ObjectMenu::init(App& app, + const std::shared_ptr<const client::ObjectModel>& object) { _app = &app; _object = object; @@ -96,7 +99,7 @@ ObjectMenu::on_menu_learn() { _app->interface()->set_property(_object->uri(), _app->uris().midi_binding, - _app->uris().patch_wildcard.urid); + _app->uris().patch_wildcard.urid_atom()); } void @@ -115,7 +118,7 @@ ObjectMenu::on_menu_polyphonic() _app->set_property( _object->uri(), _app->uris().ingen_polyphonic, - _app->forge().make(bool(_polyphonic_menuitem->get_active()))); + _app->forge().make(_polyphonic_menuitem->get_active())); } } @@ -142,5 +145,4 @@ ObjectMenu::on_menu_properties() _app->window_factory()->present_properties(_object); } -} // namespace gui -} // namespace ingen +} // namespace ingen::gui diff --git a/src/gui/ObjectMenu.hpp b/src/gui/ObjectMenu.hpp index 22eef74b..5a4c83f4 100644 --- a/src/gui/ObjectMenu.hpp +++ b/src/gui/ObjectMenu.hpp @@ -17,21 +17,34 @@ #ifndef INGEN_GUI_OBJECTMENU_HPP #define INGEN_GUI_OBJECTMENU_HPP -#include "ingen/client/ObjectModel.hpp" -#include "ingen/types.hpp" +#include <ingen/URI.hpp> -#include <gtkmm/builder.h> -#include <gtkmm/checkmenuitem.h> #include <gtkmm/menu.h> -#include <gtkmm/menuitem.h> + +#include <memory> + +namespace Glib { +template <class T> class RefPtr; +} // namespace Glib + +namespace Gtk { +class Builder; +class CheckMenuItem; +class MenuItem; +class SeparatorMenuItem; +} // namespace Gtk namespace ingen { + +class Atom; + +namespace client { +class ObjectModel; +} // namespace client + namespace gui { class App; -class ObjectControlWindow; -class ObjectPropertiesWindow; -class GraphCanvas; /** Menu for a Object. * @@ -43,10 +56,15 @@ public: ObjectMenu(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& xml); - void init(App& app, SPtr<const client::ObjectModel> object); + void + init(App& app, const std::shared_ptr<const client::ObjectModel>& object); + + std::shared_ptr<const client::ObjectModel> object() const + { + return _object; + } - SPtr<const client::ObjectModel> object() const { return _object; } - App* app() const { return _app; } + App* app() const { return _app; } protected: void on_menu_learn(); @@ -58,18 +76,18 @@ protected: void property_changed(const URI& predicate, const Atom& value); - App* _app; - SPtr<const client::ObjectModel> _object; - Gtk::MenuItem* _learn_menuitem; - Gtk::MenuItem* _unlearn_menuitem; - Gtk::CheckMenuItem* _polyphonic_menuitem; - Gtk::MenuItem* _disconnect_menuitem; - Gtk::MenuItem* _rename_menuitem; - Gtk::MenuItem* _destroy_menuitem; - Gtk::MenuItem* _properties_menuitem; - Gtk::SeparatorMenuItem* _separator_menuitem; - - bool _enable_signal; + App* _app{nullptr}; + std::shared_ptr<const client::ObjectModel> _object; + Gtk::MenuItem* _learn_menuitem{nullptr}; + Gtk::MenuItem* _unlearn_menuitem{nullptr}; + Gtk::CheckMenuItem* _polyphonic_menuitem{nullptr}; + Gtk::MenuItem* _disconnect_menuitem{nullptr}; + Gtk::MenuItem* _rename_menuitem{nullptr}; + Gtk::MenuItem* _destroy_menuitem{nullptr}; + Gtk::MenuItem* _properties_menuitem{nullptr}; + Gtk::SeparatorMenuItem* _separator_menuitem{nullptr}; + + bool _enable_signal{false}; }; } // namespace gui diff --git a/src/gui/PluginMenu.cpp b/src/gui/PluginMenu.cpp index f30c2b4b..26bbed08 100644 --- a/src/gui/PluginMenu.cpp +++ b/src/gui/PluginMenu.cpp @@ -15,13 +15,24 @@ */ #include "PluginMenu.hpp" -#include "ingen/Log.hpp" -#include "ingen/client/PluginModel.hpp" +#include <ingen/Log.hpp> +#include <ingen/URIs.hpp> +#include <ingen/World.hpp> +#include <ingen/client/PluginModel.hpp> +#include <lilv/lilv.h> + +#include <glibmm/ustring.h> +#include <gtkmm/menu_elems.h> +#include <gtkmm/menuitem.h> +#include <gtkmm/object.h> +#include <sigc++/adaptors/bind.h> +#include <sigc++/functors/mem_fun.h> + +#include <memory> #include <utility> -namespace ingen { -namespace gui { +namespace ingen::gui { PluginMenu::PluginMenu(ingen::World& world) : _world(world) @@ -44,7 +55,7 @@ PluginMenu::clear() // Build skeleton LV2Children children; - LILV_FOREACH(plugin_classes, i, classes) { + LILV_FOREACH (plugin_classes, i, classes) { const LilvPluginClass* c = lilv_plugin_classes_get(classes, i); const LilvNode* p = lilv_plugin_class_get_parent_uri(c); if (!p) { @@ -64,10 +75,8 @@ PluginMenu::clear() } void -PluginMenu::add_plugin(SPtr<client::PluginModel> p) +PluginMenu::add_plugin(const std::shared_ptr<client::PluginModel>& p) { - using iterator = ClassMenus::iterator; - if (!p->lilv_plugin() || lilv_plugin_is_replaced(p->lilv_plugin())) { return; } @@ -76,7 +85,7 @@ PluginMenu::add_plugin(SPtr<client::PluginModel> p) const LilvNode* class_uri = lilv_plugin_class_get_uri(pc); const char* class_uri_str = lilv_node_as_string(class_uri); - std::pair<iterator, iterator> range = _class_menus.equal_range(class_uri_str); + const auto range = _class_menus.equal_range(class_uri_str); if (range.first == _class_menus.end() || range.first == range.second || range.first->second.menu == this) { // Add to uncategorized plugin menu @@ -100,16 +109,14 @@ PluginMenu::build_plugin_class_menu(Gtk::Menu* menu, const LilvNode* class_uri = lilv_plugin_class_get_uri(plugin_class); const char* class_uri_str = lilv_node_as_string(class_uri); - const std::pair<LV2Children::const_iterator, LV2Children::const_iterator> kids - = children.equal_range(class_uri_str); - + const auto kids = children.equal_range(class_uri_str); if (kids.first == children.end()) { return 0; } // Add submenus ancestors.insert(class_uri_str); - for (LV2Children::const_iterator i = kids.first; i != kids.second; ++i) { + for (auto i = kids.first; i != kids.second; ++i) { const LilvPluginClass* c = i->second; const char* sub_label_str = lilv_node_as_string(lilv_plugin_class_get_label(c)); const char* sub_uri_str = lilv_node_as_string(lilv_plugin_class_get_uri(c)); @@ -119,7 +126,7 @@ PluginMenu::build_plugin_class_menu(Gtk::Menu* menu, return 0; } - Gtk::Menu_Helpers::MenuElem menu_elem = Gtk::Menu_Helpers::MenuElem( + const Gtk::Menu_Helpers::MenuElem menu_elem = Gtk::Menu_Helpers::MenuElem( std::string("_") + sub_label_str); menu->items().push_back(menu_elem); Gtk::MenuItem* menu_item = &(menu->items().back()); @@ -127,7 +134,7 @@ PluginMenu::build_plugin_class_menu(Gtk::Menu* menu, Gtk::Menu* submenu = Gtk::manage(new Gtk::Menu()); menu_item->set_submenu(*submenu); - size_t num_child_items = build_plugin_class_menu( + const size_t num_child_items = build_plugin_class_menu( submenu, c, classes, children, ancestors); _class_menus.emplace(sub_uri_str, MenuRecord(menu_item, submenu)); @@ -143,17 +150,18 @@ PluginMenu::build_plugin_class_menu(Gtk::Menu* menu, } void -PluginMenu::add_plugin_to_menu(MenuRecord& menu, SPtr<client::PluginModel> p) +PluginMenu::add_plugin_to_menu(MenuRecord& menu, + const std::shared_ptr<client::PluginModel>& p) { const URIs& uris = _world.uris(); LilvWorld* lworld = _world.lilv_world(); LilvNode* ingen_Graph = lilv_new_uri(lworld, uris.ingen_Graph.c_str()); LilvNode* rdf_type = lilv_new_uri(lworld, uris.rdf_type.c_str()); - bool is_graph = lilv_world_ask(lworld, - lilv_plugin_get_uri(p->lilv_plugin()), - rdf_type, - ingen_Graph); + const bool is_graph = lilv_world_ask(lworld, + lilv_plugin_get_uri(p->lilv_plugin()), + rdf_type, + ingen_Graph); menu.menu->items().push_back( Gtk::Menu_Helpers::MenuElem( @@ -169,10 +177,9 @@ PluginMenu::add_plugin_to_menu(MenuRecord& menu, SPtr<client::PluginModel> p) } void -PluginMenu::load_plugin(WPtr<client::PluginModel> weak_plugin) +PluginMenu::load_plugin(const std::weak_ptr<client::PluginModel>& weak_plugin) { signal_load_plugin.emit(weak_plugin); } -} // namespace gui -} // namespace ingen +} // namespace ingen::gui diff --git a/src/gui/PluginMenu.hpp b/src/gui/PluginMenu.hpp index 6c7aa6b0..eb0a565a 100644 --- a/src/gui/PluginMenu.hpp +++ b/src/gui/PluginMenu.hpp @@ -17,20 +17,28 @@ #ifndef INGEN_GUI_PLUGINMENU_HPP #define INGEN_GUI_PLUGINMENU_HPP -#include "ingen/World.hpp" -#include "ingen/types.hpp" -#include "lilv/lilv.h" +#include <lilv/lilv.h> #include <gtkmm/menu.h> +#include <sigc++/signal.h> #include <cstddef> #include <map> +#include <memory> #include <set> #include <string> +namespace Gtk { +class MenuItem; +} // namespace Gtk + namespace ingen { -namespace client { class PluginModel; } +class World; + +namespace client { +class PluginModel; +} // namespace client namespace gui { @@ -42,16 +50,18 @@ namespace gui { class PluginMenu : public Gtk::Menu { public: - PluginMenu(ingen::World& world); + explicit PluginMenu(ingen::World& world); void clear(); - void add_plugin(SPtr<client::PluginModel> p); + void add_plugin(const std::shared_ptr<client::PluginModel>& p); - sigc::signal< void, WPtr<client::PluginModel> > signal_load_plugin; + sigc::signal<void, std::weak_ptr<client::PluginModel>> signal_load_plugin; private: struct MenuRecord { - MenuRecord(Gtk::MenuItem* i, Gtk::Menu* m) : item(i), menu(m) {} + MenuRecord(Gtk::MenuItem* i, Gtk::Menu* m) noexcept : item(i), menu(m) + {} + Gtk::MenuItem* item; Gtk::Menu* menu; }; @@ -66,9 +76,10 @@ private: const LV2Children& children, std::set<const char*>& ancestors); - void add_plugin_to_menu(MenuRecord& menu, SPtr<client::PluginModel> p); + void add_plugin_to_menu(MenuRecord& menu, + const std::shared_ptr<client::PluginModel>& p); - void load_plugin(WPtr<client::PluginModel> weak_plugin); + void load_plugin(const std::weak_ptr<client::PluginModel>& weak_plugin); ingen::World& _world; MenuRecord _classless_menu; diff --git a/src/gui/Port.cpp b/src/gui/Port.cpp index 14f87fc1..4d11e309 100644 --- a/src/gui/Port.cpp +++ b/src/gui/Port.cpp @@ -17,6 +17,7 @@ #include "Port.hpp" #include "App.hpp" +#include "GraphBox.hpp" #include "GraphWindow.hpp" #include "PortMenu.hpp" #include "RDFS.hpp" @@ -26,45 +27,76 @@ #include "ingen_config.h" #include "rgba.hpp" -#include "ganv/Module.hpp" -#include "ingen/Configuration.hpp" -#include "ingen/Interface.hpp" -#include "ingen/Log.hpp" -#include "ingen/URIMap.hpp" -#include "ingen/client/GraphModel.hpp" -#include "ingen/client/PortModel.hpp" +#include <ganv/Port.hpp> +#include <ingen/Atom.hpp> +#include <ingen/Configuration.hpp> +#include <ingen/Forge.hpp> +#include <ingen/Log.hpp> +#include <ingen/Properties.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIMap.hpp> +#include <ingen/URIs.hpp> +#include <ingen/World.hpp> +#include <ingen/client/BlockModel.hpp> +#include <ingen/client/GraphModel.hpp> +#include <ingen/client/ObjectModel.hpp> +#include <ingen/client/PluginModel.hpp> +#include <ingen/client/PortModel.hpp> +#include <lilv/lilv.h> +#include <raul/Path.hpp> +#include <raul/Symbol.hpp> +#include <sord/sordmm.hpp> + +#include <glibmm/ustring.h> +#include <gtkmm/menu.h> +#include <gtkmm/menu_elems.h> +#include <gtkmm/menuitem.h> +#include <gtkmm/object.h> +#include <sigc++/adaptors/bind.h> +#include <sigc++/functors/mem_fun.h> +#include <sigc++/signal.h> #include <cassert> +#include <cmath> +#include <cstdint> +#include <map> +#include <memory> #include <string> - -using namespace ingen::client; +#include <utility> namespace ingen { + +using client::BlockModel; +using client::GraphModel; +using client::PluginModel; +using client::PortModel; + namespace gui { Port* -Port::create(App& app, - Ganv::Module& module, - SPtr<const PortModel> pm, - bool flip) +Port::create(App& app, + Ganv::Module& module, + const std::shared_ptr<const PortModel>& pm, + bool flip) { return new Port(app, module, pm, port_label(app, pm), flip); } /** @param flip Make an input port appear as an output port, and vice versa. */ -Port::Port(App& app, - Ganv::Module& module, - SPtr<const PortModel> pm, - const std::string& name, - bool flip) - : Ganv::Port(module, name, - flip ? (!pm->is_input()) : pm->is_input(), - app.style()->get_port_color(pm.get())) - , _app(app) - , _port_model(pm) - , _entered(false) - , _flipped(flip) +Port::Port(App& app, + Ganv::Module& module, + const std::shared_ptr<const PortModel>& pm, + const std::string& name, + bool flip) + : Ganv::Port(module, + name, + flip ? (!pm->is_input()) : pm->is_input(), + app.style()->get_port_color(pm.get())) + , _app(app) + , _port_model(pm) + , _entered(false) + , _flipped(flip) { assert(pm); @@ -111,7 +143,7 @@ Port::~Port() } std::string -Port::port_label(App& app, SPtr<const PortModel> pm) +Port::port_label(App& app, const std::shared_ptr<const PortModel>& pm) { if (!pm) { return ""; @@ -124,8 +156,8 @@ Port::port_label(App& app, SPtr<const PortModel> pm) if (name.type() == app.forge().String) { label = name.ptr<char>(); } else { - const SPtr<const BlockModel> parent( - dynamic_ptr_cast<const BlockModel>(pm->parent())); + const auto parent = + std::dynamic_pointer_cast<const BlockModel>(pm->parent()); if (parent && parent->plugin_model()) { label = parent->plugin_model()->port_human_name(pm->index()); } @@ -148,9 +180,9 @@ Port::ensure_label() void Port::update_metadata() { - SPtr<const PortModel> pm = _port_model.lock(); + auto pm = _port_model.lock(); if (pm && _app.can_control(pm.get()) && pm->is_numeric()) { - SPtr<const BlockModel> parent = dynamic_ptr_cast<const BlockModel>(pm->parent()); + auto parent = std::dynamic_pointer_cast<const BlockModel>(pm->parent()); if (parent) { float min = 0.0f; float max = 1.0f; @@ -191,14 +223,14 @@ Port::on_value_changed(double value) const URIs& uris = _app.uris(); const Atom& current_value = model()->value(); if (current_value.type() != uris.forge.Float) { - return; // Non-float, unsupported + return; // Non-float, unsupported } - if (current_value.get<float>() == (float)value) { - return; // No change + if (current_value.get<float>() == static_cast<float>(value)) { + return; // No change } - const Atom atom = _app.forge().make(float(value)); + const Atom atom = _app.forge().make(static_cast<float>(value)); _app.set_property(model()->uri(), _app.world().uris().ingen_value, atom); @@ -230,17 +262,17 @@ Port::on_scale_point_activated(float f) Gtk::Menu* Port::build_enum_menu() { - SPtr<const BlockModel> block = dynamic_ptr_cast<BlockModel>(model()->parent()); - Gtk::Menu* menu = Gtk::manage(new Gtk::Menu()); + auto block = std::dynamic_pointer_cast<BlockModel>(model()->parent()); + Gtk::Menu* menu = Gtk::manage(new Gtk::Menu()); - PluginModel::ScalePoints points = block->plugin_model()->port_scale_points( + const PluginModel::ScalePoints points = block->plugin_model()->port_scale_points( model()->index()); - for (auto i = points.begin(); i != points.end(); ++i) { - menu->items().push_back(Gtk::Menu_Helpers::MenuElem(i->second)); + for (const auto& p : points) { + menu->items().push_back(Gtk::Menu_Helpers::MenuElem(p.second)); Gtk::MenuItem* menu_item = &(menu->items().back()); menu_item->signal_activate().connect( sigc::bind(sigc::mem_fun(this, &Port::on_scale_point_activated), - i->first)); + p.first)); } return menu; @@ -258,9 +290,9 @@ Port::on_uri_activated(const URI& uri) Gtk::Menu* Port::build_uri_menu() { - World& world = _app.world(); - SPtr<const BlockModel> block = dynamic_ptr_cast<BlockModel>(model()->parent()); - Gtk::Menu* menu = Gtk::manage(new Gtk::Menu()); + World& world = _app.world(); + auto block = std::dynamic_pointer_cast<BlockModel>(model()->parent()); + Gtk::Menu* menu = Gtk::manage(new Gtk::Menu()); // Get the port designation, which should be a rdf:Property const Atom& designation_atom = model()->get_property( @@ -278,13 +310,13 @@ Port::build_uri_menu() rdfs::URISet ranges; LilvNodes* range = lilv_world_find_nodes( world.lilv_world(), designation, rdfs_range, nullptr); - LILV_FOREACH(nodes, r, range) { + LILV_FOREACH (nodes, r, range) { ranges.insert(URI(lilv_node_as_string(lilv_nodes_get(range, r)))); } rdfs::classes(world, ranges, false); // Get all objects in range - rdfs::Objects values = rdfs::instances(world, ranges); + const rdfs::Objects values = rdfs::instances(world, ranges); // Add a menu item for each such class for (const auto& v : values) { @@ -325,7 +357,9 @@ Port::on_event(GdkEvent* ev) Gtk::Menu* menu = build_enum_menu(); menu->popup(ev->button.button, ev->button.time); return true; - } else if (model()->is_uri()) { + } + + if (model()->is_uri()) { Gtk::Menu* menu = build_uri_menu(); if (menu) { menu->popup(ev->button.button, ev->button.time); @@ -343,7 +377,7 @@ Port::on_event(GdkEvent* ev) return false; } -inline static uint32_t +static inline uint32_t peak_color(float peak) { static const uint32_t min = 0x4A8A0EC0; @@ -351,11 +385,11 @@ peak_color(float peak) static const uint32_t peak_min = 0xFF561FC0; static const uint32_t peak_max = 0xFF0A38C0; - if (peak < 1.0) { + if (peak < 1.0f) { return rgba_interpolate(min, max, peak); - } else { - return rgba_interpolate(peak_min, peak_max, fminf(peak, 2.0f) - 1.0f); } + + return rgba_interpolate(peak_min, peak_max, fminf(peak, 2.0f) - 1.0f); } void @@ -373,10 +407,10 @@ Port::activity(const Atom& value) GraphBox* Port::get_graph_box() const { - SPtr<const GraphModel> graph = dynamic_ptr_cast<const GraphModel>(model()->parent()); - GraphBox* box = _app.window_factory()->graph_box(graph); + auto graph = std::dynamic_pointer_cast<const GraphModel>(model()->parent()); + GraphBox* box = _app.window_factory()->graph_box(graph); if (!box) { - graph = dynamic_ptr_cast<const GraphModel>(model()->parent()->parent()); + graph = std::dynamic_pointer_cast<const GraphModel>(model()->parent()->parent()); box = _app.window_factory()->graph_box(graph); } return box; @@ -512,14 +546,17 @@ bool Port::on_selected(gboolean b) { if (b) { - SPtr<const PortModel> pm = _port_model.lock(); + auto pm = _port_model.lock(); if (pm) { - SPtr<const BlockModel> block = dynamic_ptr_cast<const BlockModel>(pm->parent()); + auto block = + std::dynamic_pointer_cast<const BlockModel>(pm->parent()); + GraphWindow* win = _app.window_factory()->parent_graph_window(block); if (win && win->documentation_is_visible() && block->plugin_model()) { - bool html = false; -#ifdef HAVE_WEBKIT - html = true; +#if USE_WEBKIT + const bool html = true; +#else + const bool html = false; #endif const std::string& doc = block->plugin_model()->port_documentation( pm->index(), html); diff --git a/src/gui/Port.hpp b/src/gui/Port.hpp index c95c93ef..bfd8e15d 100644 --- a/src/gui/Port.hpp +++ b/src/gui/Port.hpp @@ -17,24 +17,30 @@ #ifndef INGEN_GUI_PORT_HPP #define INGEN_GUI_PORT_HPP -#include "ganv/Port.hpp" -#include "ingen/types.hpp" +#include <ganv/Port.hpp> -#include <gtkmm/menu.h> +#include <gdk/gdk.h> +#include <glib.h> -#include <cassert> +#include <memory> #include <string> -namespace Raul { -class Atom; -} +namespace Ganv { +class Module; +} // namespace Ganv + +namespace Gtk { +class Menu; +} // namespace Gtk namespace ingen { class URI; class Atom; -namespace client { class PortModel; } +namespace client { +class PortModel; +} // namespace client namespace gui { @@ -48,15 +54,17 @@ class GraphBox; class Port : public Ganv::Port { public: - static Port* create( - App& app, - Ganv::Module& module, - SPtr<const client::PortModel> pm, - bool flip = false); + static Port* create(App& app, + Ganv::Module& module, + const std::shared_ptr<const client::PortModel>& pm, + bool flip = false); - ~Port(); + ~Port() override; - SPtr<const client::PortModel> model() const { return _port_model.lock(); } + std::shared_ptr<const client::PortModel> model() const + { + return _port_model.lock(); + } bool show_menu(GdkEventButton* ev); void update_metadata(); @@ -68,13 +76,14 @@ public: bool on_selected(gboolean b) override; private: - Port(App& app, - Ganv::Module& module, - SPtr<const client::PortModel> pm, - const std::string& name, - bool flip = false); + Port(App& app, + Ganv::Module& module, + const std::shared_ptr<const client::PortModel>& pm, + const std::string& name, + bool flip = false); - static std::string port_label(App& app, SPtr<const client::PortModel> pm); + static std::string + port_label(App& app, const std::shared_ptr<const client::PortModel>& pm); Gtk::Menu* build_enum_menu(); Gtk::Menu* build_uri_menu(); @@ -91,10 +100,10 @@ private: void port_properties_changed(); void set_type_tag(); - App& _app; - WPtr<const client::PortModel> _port_model; - bool _entered : 1; - bool _flipped : 1; + App& _app; + std::weak_ptr<const client::PortModel> _port_model; + bool _entered : 1; + bool _flipped : 1; }; } // namespace gui diff --git a/src/gui/PortMenu.cpp b/src/gui/PortMenu.cpp index ff3d2571..373425cf 100644 --- a/src/gui/PortMenu.cpp +++ b/src/gui/PortMenu.cpp @@ -17,25 +17,45 @@ #include "PortMenu.hpp" #include "App.hpp" -#include "WindowFactory.hpp" - -#include "ingen/Interface.hpp" -#include "ingen/client/GraphModel.hpp" -#include "ingen/client/PortModel.hpp" -#include "ingen/types.hpp" - +#include "ObjectMenu.hpp" + +#include <ingen/Atom.hpp> +#include <ingen/Forge.hpp> +#include <ingen/Interface.hpp> +#include <ingen/Properties.hpp> +#include <ingen/Resource.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIs.hpp> +#include <ingen/client/BlockModel.hpp> +#include <ingen/client/GraphModel.hpp> +#include <ingen/client/ObjectModel.hpp> +#include <ingen/client/PortModel.hpp> +#include <ingen/paths.hpp> +#include <raul/Path.hpp> +#include <raul/Symbol.hpp> + +#include <glibmm/refptr.h> +#include <gtkmm/builder.h> +#include <gtkmm/checkmenuitem.h> +#include <gtkmm/menu.h> +#include <gtkmm/menuitem.h> +#include <gtkmm/separatormenuitem.h> +#include <sigc++/functors/mem_fun.h> + +#include <memory> #include <string> namespace ingen { -using namespace client; +using client::BlockModel; +using client::GraphModel; +using client::PortModel; namespace gui { PortMenu::PortMenu(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& xml) : ObjectMenu(cobject, xml) - , _internal_graph_port(false) { xml->get_widget("object_menu", _port_menu); xml->get_widget("port_set_min_menuitem", _set_min_menuitem); @@ -45,7 +65,9 @@ PortMenu::PortMenu(BaseObjectType* cobject, } void -PortMenu::init(App& app, SPtr<const PortModel> port, bool internal_graph_port) +PortMenu::init(App& app, + const std::shared_ptr<const PortModel>& port, + bool internal_graph_port) { const URIs& uris = app.uris(); @@ -65,7 +87,7 @@ PortMenu::init(App& app, SPtr<const PortModel> port, bool internal_graph_port) sigc::mem_fun(this, &PortMenu::on_menu_expose)); const bool is_control(app.can_control(port.get()) && port->is_numeric()); - const bool is_on_graph(dynamic_ptr_cast<GraphModel>(port->parent())); + const bool is_on_graph(std::dynamic_pointer_cast<GraphModel>(port->parent())); const bool is_input(port->is_input()); if (!is_on_graph) { @@ -107,9 +129,9 @@ PortMenu::on_menu_disconnect() void PortMenu::on_menu_set_min() { - const URIs& uris = _app->uris(); - SPtr<const PortModel> model = dynamic_ptr_cast<const PortModel>(_object); - const Atom& value = model->get_property(uris.ingen_value); + const URIs& uris = _app->uris(); + auto model = std::dynamic_pointer_cast<const PortModel>(_object); + const Atom& value = model->get_property(uris.ingen_value); if (value.is_valid()) { _app->set_property(_object->uri(), uris.lv2_minimum, value); } @@ -118,9 +140,9 @@ PortMenu::on_menu_set_min() void PortMenu::on_menu_set_max() { - const URIs& uris = _app->uris(); - SPtr<const PortModel> model = dynamic_ptr_cast<const PortModel>(_object); - const Atom& value = model->get_property(uris.ingen_value); + const URIs& uris = _app->uris(); + auto model = std::dynamic_pointer_cast<const PortModel>(_object); + const Atom& value = model->get_property(uris.ingen_value); if (value.is_valid()) { _app->set_property(_object->uri(), uris.lv2_maximum, value); } @@ -129,8 +151,8 @@ PortMenu::on_menu_set_max() void PortMenu::on_menu_reset_range() { - const URIs& uris = _app->uris(); - SPtr<const PortModel> model = dynamic_ptr_cast<const PortModel>(_object); + const URIs& uris = _app->uris(); + auto model = std::dynamic_pointer_cast<const PortModel>(_object); // Remove lv2:minimum and lv2:maximum properties Properties remove; @@ -142,14 +164,14 @@ PortMenu::on_menu_reset_range() void PortMenu::on_menu_expose() { - const URIs& uris = _app->uris(); - SPtr<const PortModel> port = dynamic_ptr_cast<const PortModel>(_object); - SPtr<const BlockModel> block = dynamic_ptr_cast<const BlockModel>(port->parent()); + const URIs& uris = _app->uris(); + auto port = std::dynamic_pointer_cast<const PortModel>(_object); + auto block = std::dynamic_pointer_cast<const BlockModel>(port->parent()); const std::string label = block->label() + " " + block->port_label(port); - const Raul::Path path = Raul::Path(block->path() + Raul::Symbol("_" + port->symbol())); + const auto path = raul::Path{block->path() + raul::Symbol("_" + port->symbol())}; - ingen::Resource r(*_object.get()); + ingen::Resource r(*_object); r.remove_property(uris.lv2_index, uris.patch_wildcard); r.set_property(uris.lv2_symbol, _app->forge().alloc(path.symbol())); r.set_property(uris.lv2_name, _app->forge().alloc(label.c_str())); diff --git a/src/gui/PortMenu.hpp b/src/gui/PortMenu.hpp index 26298e76..cf7f9c62 100644 --- a/src/gui/PortMenu.hpp +++ b/src/gui/PortMenu.hpp @@ -19,16 +19,28 @@ #include "ObjectMenu.hpp" -#include "ingen/client/PortModel.hpp" -#include "ingen/types.hpp" +#include <memory> -#include <gtkmm/builder.h> -#include <gtkmm/menu.h> -#include <gtkmm/menushell.h> +namespace Glib { +template <class T> class RefPtr; +} // namespace Glib + +namespace Gtk { +class Builder; +class Menu; +class MenuItem; +} // namespace Gtk namespace ingen { + +namespace client { +class PortModel; +} // namespace client + namespace gui { +class App; + /** Menu for a Port. * * \ingroup GUI @@ -39,9 +51,9 @@ public: PortMenu(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& xml); - void init(App& app, - SPtr<const client::PortModel> port, - bool internal_graph_port = false); + void init(App& app, + const std::shared_ptr<const client::PortModel>& port, + bool internal_graph_port = false); private: void on_menu_disconnect() override; @@ -50,14 +62,14 @@ private: void on_menu_reset_range(); void on_menu_expose(); - Gtk::Menu* _port_menu; - Gtk::MenuItem* _set_min_menuitem; - Gtk::MenuItem* _set_max_menuitem; - Gtk::MenuItem* _reset_range_menuitem; - Gtk::MenuItem* _expose_menuitem; + Gtk::Menu* _port_menu{nullptr}; + Gtk::MenuItem* _set_min_menuitem{nullptr}; + Gtk::MenuItem* _set_max_menuitem{nullptr}; + Gtk::MenuItem* _reset_range_menuitem{nullptr}; + Gtk::MenuItem* _expose_menuitem{nullptr}; /// True iff this is a (flipped) port on a GraphPortModule in its graph - bool _internal_graph_port; + bool _internal_graph_port{false}; }; } // namespace gui diff --git a/src/gui/PropertiesWindow.cpp b/src/gui/PropertiesWindow.cpp index 9912f73a..0dde0ab2 100644 --- a/src/gui/PropertiesWindow.cpp +++ b/src/gui/PropertiesWindow.cpp @@ -14,31 +14,64 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "App.hpp" #include "PropertiesWindow.hpp" + +#include "App.hpp" #include "RDFS.hpp" #include "URIEntry.hpp" - -#include "ingen/Interface.hpp" -#include "ingen/Log.hpp" -#include "ingen/URIMap.hpp" -#include "ingen/World.hpp" -#include "ingen/client/BlockModel.hpp" -#include "ingen/client/PluginModel.hpp" - +#include "Window.hpp" + +#include <ingen/Atom.hpp> +#include <ingen/Forge.hpp> +#include <ingen/Interface.hpp> +#include <ingen/Log.hpp> +#include <ingen/Properties.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIMap.hpp> +#include <ingen/URIs.hpp> +#include <ingen/World.hpp> +#include <ingen/client/ObjectModel.hpp> +#include <lilv/lilv.h> +#include <lv2/urid/urid.h> +#include <raul/Path.hpp> +#include <sord/sordmm.hpp> + +#include <glibmm/containers.h> +#include <glibmm/propertyproxy.h> +#include <glibmm/ustring.h> +#include <gtk/gtk.h> +#include <gtkmm/alignment.h> +#include <gtkmm/bin.h> +#include <gtkmm/box.h> +#include <gtkmm/builder.h> +#include <gtkmm/button.h> +#include <gtkmm/checkbutton.h> +#include <gtkmm/combobox.h> +#include <gtkmm/entry.h> +#include <gtkmm/enums.h> #include <gtkmm/label.h> +#include <gtkmm/object.h> +#include <gtkmm/scrolledwindow.h> #include <gtkmm/spinbutton.h> +#include <gtkmm/table.h> +#include <gtkmm/treeiter.h> +#include <gtkmm/widget.h> +#include <gtkmm/window.h> +#include <sigc++/adaptors/bind.h> +#include <sigc++/functors/mem_fun.h> +#include <sigc++/signal.h> #include <algorithm> #include <cfloat> #include <climits> #include <cstdint> +#include <memory> #include <set> #include <utility> namespace ingen { -using namespace client; +using client::ObjectModel; namespace gui { @@ -47,7 +80,6 @@ using URISet = std::set<URI>; PropertiesWindow::PropertiesWindow(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& xml) : Window(cobject) - , _value_type(0) { xml->get_widget("properties_vbox", _vbox); xml->get_widget("properties_scrolledwindow", _scrolledwindow); @@ -96,7 +128,7 @@ PropertiesWindow::reset() } void -PropertiesWindow::present(SPtr<const ObjectModel> model) +PropertiesWindow::present(const std::shared_ptr<const ObjectModel>& model) { set_object(model); Gtk::Window::present(); @@ -116,10 +148,12 @@ PropertiesWindow::add_property(const URI& key, const Atom& value) if (name.empty()) { name = world.rdf_world()->prefixes().qualify(key); } - Gtk::Label* label = new Gtk::Label( - std::string("<a href=\"") + key.string() + "\">" + name + "</a>", - 1.0, - 0.5); + + auto* label = new Gtk::Label(std::string("<a href=\"") + key.string() + + "\">" + name + "</a>", + 1.0, + 0.5); + label->set_use_markup(true); _app->set_tooltip(label, prop); _table->attach(*Gtk::manage(label), 0, 1, n_rows, n_rows + 1, @@ -154,16 +188,24 @@ PropertiesWindow::datatype_supported(const rdfs::URISet& types, if (types.find(_app->uris().atom_Int) != types.end()) { *widget_type = _app->uris().atom_Int; return true; - } else if (types.find(_app->uris().atom_Float) != types.end()) { + } + + if (types.find(_app->uris().atom_Float) != types.end()) { *widget_type = _app->uris().atom_Float; return true; - } else if (types.find(_app->uris().atom_Bool) != types.end()) { + } + + if (types.find(_app->uris().atom_Bool) != types.end()) { *widget_type = _app->uris().atom_Bool; return true; - } else if (types.find(_app->uris().atom_String) != types.end()) { + } + + if (types.find(_app->uris().atom_String) != types.end()) { *widget_type = _app->uris().atom_String; return true; - } else if (types.find(_app->uris().atom_URID) != types.end()) { + } + + if (types.find(_app->uris().atom_URID) != types.end()) { *widget_type = _app->uris().atom_URID; return true; } @@ -200,7 +242,7 @@ PropertiesWindow::class_supported(const rdfs::URISet& types) * This function MUST be called before using this object in any way. */ void -PropertiesWindow::set_object(SPtr<const ObjectModel> model) +PropertiesWindow::set_object(const std::shared_ptr<const ObjectModel>& model) { reset(); _model = model; @@ -245,8 +287,9 @@ PropertiesWindow::set_object(SPtr<const ObjectModel> model) } for (const auto& e : entries) { - Gtk::ListStore::iterator ki = _key_store->append(); - Gtk::ListStore::Row row = *ki; + auto ki = _key_store->append(); + auto row = *ki; + row[_combo_columns.uri_col] = e.second.string(); row[_combo_columns.label_col] = e.first; } @@ -301,19 +344,23 @@ PropertiesWindow::create_value_widget(const URI& key, widget->signal_value_changed().connect( sigc::bind(sigc::mem_fun(this, &PropertiesWindow::on_change), key)); return widget; - } else if (type == _app->uris().atom_Float) { + } + + if (type == _app->uris().atom_Float) { Gtk::SpinButton* widget = manage(new Gtk::SpinButton(0.0, 4)); widget->property_numeric() = true; widget->set_snap_to_ticks(false); - widget->set_range(-FLT_MAX, FLT_MAX); + widget->set_range(-DBL_MAX, DBL_MAX); widget->set_increments(0.1, 1.0); if (value.is_valid()) { - widget->set_value(value.get<float>()); + widget->set_value(static_cast<double>(value.get<float>())); } widget->signal_value_changed().connect( sigc::bind(sigc::mem_fun(this, &PropertiesWindow::on_change), key)); return widget; - } else if (type == _app->uris().atom_Bool) { + } + + if (type == _app->uris().atom_Bool) { Gtk::CheckButton* widget = manage(new Gtk::CheckButton()); if (value.is_valid()) { widget->set_active(value.get<int32_t>()); @@ -321,7 +368,9 @@ PropertiesWindow::create_value_widget(const URI& key, widget->signal_toggled().connect( sigc::bind(sigc::mem_fun(this, &PropertiesWindow::on_change), key)); return widget; - } else if (type == _app->uris().atom_String) { + } + + if (type == _app->uris().atom_String) { Gtk::Entry* widget = manage(new Gtk::Entry()); if (value.is_valid()) { widget->set_text(value.ptr<char>()); @@ -329,14 +378,16 @@ PropertiesWindow::create_value_widget(const URI& key, widget->signal_changed().connect( sigc::bind(sigc::mem_fun(this, &PropertiesWindow::on_change), key)); return widget; - } else if (type == _app->uris().atom_URID) { + } + + if (type == _app->uris().atom_URID) { const char* str = (value.is_valid() ? world.uri_map().unmap_uri(value.get<int32_t>()) : ""); - LilvNode* pred = lilv_new_uri(lworld, key.c_str()); - URISet ranges = rdfs::range(world, pred, true); - URIEntry* widget = manage(new URIEntry(_app, ranges, str ? str : "")); + LilvNode* pred = lilv_new_uri(lworld, key.c_str()); + const URISet ranges = rdfs::range(world, pred, true); + URIEntry* widget = manage(new URIEntry(_app, ranges, str ? str : "")); widget->signal_changed().connect( sigc::bind(sigc::mem_fun(this, &PropertiesWindow::on_change), key)); lilv_node_free(pred); @@ -352,10 +403,10 @@ PropertiesWindow::create_value_widget(const URI& key, if (type == _app->uris().atom_URI || type == _app->uris().rdfs_Class || is_class) { - LilvNode* pred = lilv_new_uri(lworld, key.c_str()); - URISet ranges = rdfs::range(world, pred, true); - const char* str = value.is_valid() ? value.ptr<const char>() : ""; - URIEntry* widget = manage(new URIEntry(_app, ranges, str)); + LilvNode* pred = lilv_new_uri(lworld, key.c_str()); + const URISet ranges = rdfs::range(world, pred, true); + const char* str = value.is_valid() ? value.ptr<const char>() : ""; + URIEntry* widget = manage(new URIEntry(_app, ranges, str)); widget->signal_changed().connect( sigc::bind(sigc::mem_fun(this, &PropertiesWindow::on_change), key)); lilv_node_free(pred); @@ -434,38 +485,40 @@ PropertiesWindow::remove_property(const URI& key, const Atom& value) Atom PropertiesWindow::get_value(LV2_URID type, Gtk::Widget* value_widget) { - Forge& forge = _app->forge(); + const Forge& forge = _app->forge(); if (type == forge.Int) { - Gtk::SpinButton* spin = dynamic_cast<Gtk::SpinButton*>(value_widget); + auto* spin = dynamic_cast<Gtk::SpinButton*>(value_widget); if (spin) { return _app->forge().make(spin->get_value_as_int()); } } else if (type == forge.Float) { - Gtk::SpinButton* spin = dynamic_cast<Gtk::SpinButton*>(value_widget); + auto* spin = dynamic_cast<Gtk::SpinButton*>(value_widget); if (spin) { return _app->forge().make(static_cast<float>(spin->get_value())); } } else if (type == forge.Bool) { - Gtk::CheckButton* check = dynamic_cast<Gtk::CheckButton*>(value_widget); + auto* check = dynamic_cast<Gtk::CheckButton*>(value_widget); if (check) { return _app->forge().make(check->get_active()); } } else if (type == forge.URI || type == forge.URID) { - URIEntry* uri_entry = dynamic_cast<URIEntry*>(value_widget); - if (uri_entry && URI::is_valid(uri_entry->get_text())) { - return _app->forge().make_urid(URI(uri_entry->get_text())); - } else { + auto* uri_entry = dynamic_cast<URIEntry*>(value_widget); + if (uri_entry) { + if (URI::is_valid(uri_entry->get_text())) { + return _app->forge().make_urid(URI(uri_entry->get_text())); + } + _app->log().error("Invalid URI <%1%>\n", uri_entry->get_text()); } } else if (type == forge.String) { - Gtk::Entry* entry = dynamic_cast<Gtk::Entry*>(value_widget); + auto* entry = dynamic_cast<Gtk::Entry*>(value_widget); if (entry) { return _app->forge().alloc(entry->get_text()); } } - return Atom(); + return {}; } void @@ -490,12 +543,12 @@ PropertiesWindow::on_change(const URI& key) std::string PropertiesWindow::active_key() const { - const Gtk::ListStore::iterator iter = _key_combo->get_active(); + const auto iter = _key_combo->get_active(); if (!iter) { return ""; } - Glib::ustring prop_uri = (*iter)[_combo_columns.uri_col]; + const Glib::ustring prop_uri = (*iter)[_combo_columns.uri_col]; return prop_uri; } diff --git a/src/gui/PropertiesWindow.hpp b/src/gui/PropertiesWindow.hpp index 81e29ae1..e788d140 100644 --- a/src/gui/PropertiesWindow.hpp +++ b/src/gui/PropertiesWindow.hpp @@ -19,26 +19,43 @@ #include "Window.hpp" -#include "ingen/client/BlockModel.hpp" -#include "ingen/types.hpp" - -#include <gtkmm/alignment.h> -#include <gtkmm/box.h> -#include <gtkmm/builder.h> -#include <gtkmm/button.h> -#include <gtkmm/checkbutton.h> -#include <gtkmm/combobox.h> +#include <ingen/Atom.hpp> +#include <ingen/URI.hpp> +#include <lv2/urid/urid.h> + +#include <glibmm/refptr.h> #include <gtkmm/liststore.h> -#include <gtkmm/scrolledwindow.h> -#include <gtkmm/table.h> +#include <gtkmm/treemodel.h> +#include <gtkmm/treemodelcolumn.h> +#include <sigc++/connection.h> #include <map> +#include <memory> #include <set> #include <string> +namespace Glib { +class ustring; +} // namespace Glib + +namespace Gtk { +class Alignment; +class Bin; +class Builder; +class Button; +class CheckButton; +class ComboBox; +class ScrolledWindow; +class Table; +class VBox; +class Widget; +} // namespace Gtk + namespace ingen { -namespace client { class ObjectModel; } +namespace client { +class ObjectModel; +} // namespace client namespace gui { @@ -54,8 +71,8 @@ public: PropertiesWindow(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& xml); - void present(SPtr<const client::ObjectModel> model); - void set_object(SPtr<const client::ObjectModel> model); + void present(const std::shared_ptr<const client::ObjectModel>& model); + void set_object(const std::shared_ptr<const client::ObjectModel>& model); private: /** Record of a property (row in the table) */ @@ -108,21 +125,21 @@ private: using Records = std::map<URI, Record>; Records _records; - SPtr<const client::ObjectModel> _model; - ComboColumns _combo_columns; - Glib::RefPtr<Gtk::ListStore> _key_store; - sigc::connection _property_connection; - sigc::connection _property_removed_connection; - Gtk::VBox* _vbox; - Gtk::ScrolledWindow* _scrolledwindow; - Gtk::Table* _table; - Gtk::ComboBox* _key_combo; - LV2_URID _value_type; - Gtk::Bin* _value_bin; - Gtk::Button* _add_button; - Gtk::Button* _cancel_button; - Gtk::Button* _apply_button; - Gtk::Button* _ok_button; + std::shared_ptr<const client::ObjectModel> _model; + ComboColumns _combo_columns; + Glib::RefPtr<Gtk::ListStore> _key_store; + sigc::connection _property_connection; + sigc::connection _property_removed_connection; + Gtk::VBox* _vbox{nullptr}; + Gtk::ScrolledWindow* _scrolledwindow{nullptr}; + Gtk::Table* _table{nullptr}; + Gtk::ComboBox* _key_combo{nullptr}; + LV2_URID _value_type{0}; + Gtk::Bin* _value_bin{nullptr}; + Gtk::Button* _add_button{nullptr}; + Gtk::Button* _cancel_button{nullptr}; + Gtk::Button* _apply_button{nullptr}; + Gtk::Button* _ok_button{nullptr}; }; } // namespace gui diff --git a/src/gui/RDFS.cpp b/src/gui/RDFS.cpp index 1091c443..09af81af 100644 --- a/src/gui/RDFS.cpp +++ b/src/gui/RDFS.cpp @@ -14,20 +14,20 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "ingen/Forge.hpp" -#include "ingen/Log.hpp" -#include "ingen/Resource.hpp" -#include "ingen/World.hpp" -#include "ingen/client/ObjectModel.hpp" -#include "lilv/lilv.h" - #include "RDFS.hpp" +#include <ingen/Forge.hpp> +#include <ingen/Log.hpp> +#include <ingen/Properties.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIs.hpp> +#include <ingen/World.hpp> +#include <ingen/client/ObjectModel.hpp> +#include <lilv/lilv.h> + #include <utility> -namespace ingen { -namespace gui { -namespace rdfs { +namespace ingen::gui::rdfs { std::string label(World& world, const LilvNode* node) @@ -75,10 +75,10 @@ closure(World& world, const LilvNode* pred, URISet& types, bool super) world.lilv_world(), type, pred, nullptr) : lilv_world_find_nodes( world.lilv_world(), nullptr, pred, type); - LILV_FOREACH(nodes, m, matches) { + LILV_FOREACH (nodes, m, matches) { const LilvNode* klass_node = lilv_nodes_get(matches, m); if (lilv_node_is_uri(klass_node)) { - URI klass(lilv_node_as_uri(klass_node)); + const URI klass{lilv_node_as_uri(klass_node)}; if (!types.count(klass)) { ++added; klasses.insert(klass); @@ -115,22 +115,19 @@ datatypes(World& world, URISet& types, bool super) } URISet -types(World& world, SPtr<const client::ObjectModel> model) +types(World& world, const std::shared_ptr<const client::ObjectModel>& model) { - using PropIter = Properties::const_iterator; - using PropRange = std::pair<PropIter, PropIter>; - // Start with every rdf:type URISet types; types.insert(URI(LILV_NS_RDFS "Resource")); - PropRange range = model->properties().equal_range(world.uris().rdf_type); + const auto range = model->properties().equal_range(world.uris().rdf_type); for (auto t = range.first; t != range.second; ++t) { if (t->second.type() == world.forge().URI || t->second.type() == world.forge().URID) { const URI type(world.forge().str(t->second, false)); types.insert(type); if (world.uris().ingen_Graph == type) { - // Add lv2:Plugin as a type for graphs so plugin properties show up + // Add lv2:Plugin as a type so plugin properties show up types.insert(world.uris().lv2_Plugin); } } else { @@ -145,10 +142,11 @@ types(World& world, SPtr<const client::ObjectModel> model) } URISet -properties(World& world, SPtr<const client::ObjectModel> model) +properties(World& world, + const std::shared_ptr<const client::ObjectModel>& model) { - URISet properties; - URISet types = rdfs::types(world, model); + URISet properties; + const URISet types = rdfs::types(world, model); LilvNode* rdf_type = lilv_new_uri(world.lilv_world(), LILV_NS_RDF "type"); @@ -159,13 +157,13 @@ properties(World& world, SPtr<const client::ObjectModel> model) LilvNodes* props = lilv_world_find_nodes( world.lilv_world(), nullptr, rdf_type, rdf_Property); - LILV_FOREACH(nodes, p, props) { + LILV_FOREACH (nodes, p, props) { const LilvNode* prop = lilv_nodes_get(props, p); if (lilv_node_is_uri(prop)) { LilvNodes* domains = lilv_world_find_nodes( world.lilv_world(), prop, rdfs_domain, nullptr); unsigned n_matching_domains = 0; - LILV_FOREACH(nodes, d, domains) { + LILV_FOREACH (nodes, d, domains) { const LilvNode* domain_node = lilv_nodes_get(domains, d); if (!lilv_node_is_uri(domain_node)) { // TODO: Blank node domains (e.g. unions) @@ -206,7 +204,7 @@ instances(World& world, const URISet& types) LilvNode* type = lilv_new_uri(world.lilv_world(), t.c_str()); LilvNodes* objects = lilv_world_find_nodes( world.lilv_world(), nullptr, rdf_type, type); - LILV_FOREACH(nodes, o, objects) { + LILV_FOREACH (nodes, o, objects) { const LilvNode* object = lilv_nodes_get(objects, o); if (!lilv_node_is_uri(object)) { continue; @@ -231,8 +229,10 @@ range(World& world, const LilvNode* prop, bool recursive) world.lilv_world(), prop, rdfs_range, nullptr); URISet ranges; - LILV_FOREACH(nodes, n, nodes) { - ranges.insert(URI(lilv_node_as_string(lilv_nodes_get(nodes, n)))); + LILV_FOREACH (nodes, n, nodes) { + if (lilv_node_is_uri(lilv_nodes_get(nodes, n))) { + ranges.insert(URI(lilv_node_as_string(lilv_nodes_get(nodes, n)))); + } } if (recursive) { @@ -256,6 +256,4 @@ is_a(World& world, const LilvNode* inst, const LilvNode* klass) return is_instance; } -} // namespace rdfs -} // namespace gui -} // namespace ingen +} // namespace ingen::gui::rdfs diff --git a/src/gui/RDFS.hpp b/src/gui/RDFS.hpp index a8d161cb..e4c2b673 100644 --- a/src/gui/RDFS.hpp +++ b/src/gui/RDFS.hpp @@ -17,11 +17,11 @@ #ifndef INGEN_GUI_RDF_HPP #define INGEN_GUI_RDF_HPP -#include "ingen/URI.hpp" -#include "ingen/types.hpp" -#include "lilv/lilv.h" +#include <ingen/URI.hpp> +#include <lilv/lilv.h> #include <map> +#include <memory> #include <set> #include <string> @@ -29,11 +29,11 @@ namespace ingen { class World; -namespace client { class ObjectModel; } +namespace client { +class ObjectModel; +} // namespace client -namespace gui { - -namespace rdfs { +namespace gui::rdfs { /** Set of URIs. */ using URISet = std::set<URI>; @@ -61,10 +61,13 @@ void datatypes(World& world, URISet& types, bool super); Objects instances(World& world, const URISet& types); /** Get all the types which `model` is an instance of. */ -URISet types(World& world, SPtr<const client::ObjectModel> model); +URISet +types(World& world, const std::shared_ptr<const client::ObjectModel>& model); /** Get all the properties with domains appropriate for `model`. */ -URISet properties(World& world, SPtr<const client::ObjectModel> model); +URISet +properties(World& world, + const std::shared_ptr<const client::ObjectModel>& model); /** Return the range (value types) of `prop`. * @param recursive If true, include all subclasses. @@ -74,8 +77,7 @@ URISet range(World& world, const LilvNode* prop, bool recursive); /** Return true iff `inst` is-a `klass`. */ bool is_a(World& world, const LilvNode* inst, const LilvNode* klass); -} // namespace rdfs -} // namespace gui +} // namespace gui::rdfs } // namespace ingen #endif // INGEN_GUI_RDF_HPP diff --git a/src/gui/RenameWindow.cpp b/src/gui/RenameWindow.cpp index 8c5e9edb..569baea8 100644 --- a/src/gui/RenameWindow.cpp +++ b/src/gui/RenameWindow.cpp @@ -17,18 +17,34 @@ #include "RenameWindow.hpp" #include "App.hpp" - -#include "ingen/Forge.hpp" -#include "ingen/Interface.hpp" -#include "ingen/client/ClientStore.hpp" -#include "ingen/client/ObjectModel.hpp" -#include "lv2/core/lv2.h" - +#include "Window.hpp" + +#include <ingen/Atom.hpp> +#include <ingen/Forge.hpp> +#include <ingen/Interface.hpp> +#include <ingen/URIs.hpp> +#include <ingen/client/ClientStore.hpp> +#include <ingen/client/ObjectModel.hpp> +#include <ingen/paths.hpp> +#include <raul/Path.hpp> +#include <raul/Symbol.hpp> + +#include <glibmm/propertyproxy.h> +#include <glibmm/refptr.h> +#include <glibmm/ustring.h> +#include <gtkmm/builder.h> +#include <gtkmm/button.h> +#include <gtkmm/entry.h> +#include <gtkmm/label.h> +#include <gtkmm/window.h> +#include <sigc++/functors/mem_fun.h> + +#include <memory> #include <string> namespace ingen { -using namespace client; +using client::ObjectModel; namespace gui { @@ -58,7 +74,7 @@ RenameWindow::RenameWindow(BaseObjectType* cobject, * This function MUST be called before using this object in any way. */ void -RenameWindow::set_object(SPtr<const ObjectModel> object) +RenameWindow::set_object(const std::shared_ptr<const ObjectModel>& object) { _object = object; _symbol_entry->set_text(object->path().symbol()); @@ -68,7 +84,7 @@ RenameWindow::set_object(SPtr<const ObjectModel> object) } void -RenameWindow::present(SPtr<const ObjectModel> object) +RenameWindow::present(const std::shared_ptr<const ObjectModel>& object) { set_object(object); _symbol_entry->grab_focus(); @@ -79,12 +95,12 @@ void RenameWindow::values_changed() { const std::string& symbol = _symbol_entry->get_text(); - if (!Raul::Symbol::is_valid(symbol)) { + if (!raul::Symbol::is_valid(symbol)) { _message_label->set_text("Invalid symbol"); _ok_button->property_sensitive() = false; } else if (_object->symbol() != symbol && _app->store()->object( - _object->parent()->path().child(Raul::Symbol(symbol)))) { + _object->parent()->path().child(raul::Symbol(symbol)))) { _message_label->set_text("An object already exists with that path"); _ok_button->property_sensitive() = false; } else { @@ -112,7 +128,7 @@ RenameWindow::ok_clicked() const URIs& uris = _app->uris(); const std::string& symbol_str = _symbol_entry->get_text(); const std::string& label = _label_entry->get_text(); - Raul::Path path = _object->path(); + raul::Path path = _object->path(); const Atom& name_atom = _object->get_property(uris.lv2_name); if (!label.empty() && (name_atom.type() != uris.forge.String || @@ -122,8 +138,8 @@ RenameWindow::ok_clicked() _app->forge().alloc(label)); } - if (Raul::Symbol::is_valid(symbol_str)) { - const Raul::Symbol symbol(symbol_str); + if (raul::Symbol::is_valid(symbol_str)) { + const raul::Symbol symbol(symbol_str); if (symbol != _object->symbol()) { path = _object->path().parent().child(symbol); _app->interface()->move(_object->path(), path); diff --git a/src/gui/RenameWindow.hpp b/src/gui/RenameWindow.hpp index 3b50f04e..9c97d234 100644 --- a/src/gui/RenameWindow.hpp +++ b/src/gui/RenameWindow.hpp @@ -19,15 +19,25 @@ #include "Window.hpp" -#include "ingen/client/ObjectModel.hpp" -#include "ingen/types.hpp" +#include <memory> -#include <gtkmm/builder.h> -#include <gtkmm/button.h> -#include <gtkmm/entry.h> -#include <gtkmm/label.h> +namespace Glib { +template <class T> class RefPtr; +} // namespace Glib + +namespace Gtk { +class Builder; +class Button; +class Entry; +class Label; +} // namespace Gtk namespace ingen { + +namespace client { +class ObjectModel; +} // namespace client + namespace gui { /** Rename window. Handles renaming of any (Ingen) object. @@ -40,22 +50,22 @@ public: RenameWindow(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& xml); - void present(SPtr<const client::ObjectModel> object); + void present(const std::shared_ptr<const client::ObjectModel>& object); private: - void set_object(SPtr<const client::ObjectModel> object); + void set_object(const std::shared_ptr<const client::ObjectModel>& object); void values_changed(); void cancel_clicked(); void ok_clicked(); - SPtr<const client::ObjectModel> _object; + std::shared_ptr<const client::ObjectModel> _object; - Gtk::Entry* _symbol_entry; - Gtk::Entry* _label_entry; - Gtk::Label* _message_label; - Gtk::Button* _cancel_button; - Gtk::Button* _ok_button; + Gtk::Entry* _symbol_entry{nullptr}; + Gtk::Entry* _label_entry{nullptr}; + Gtk::Label* _message_label{nullptr}; + Gtk::Button* _cancel_button{nullptr}; + Gtk::Button* _ok_button{nullptr}; }; } // namespace gui diff --git a/src/gui/Style.cpp b/src/gui/Style.cpp index 81c9da2f..f1f1b12b 100644 --- a/src/gui/Style.cpp +++ b/src/gui/Style.cpp @@ -17,49 +17,31 @@ #include "Style.hpp" #include "App.hpp" -#include "Port.hpp" - -#include "ganv/Port.hpp" -#include "ingen/Log.hpp" -#include "ingen/Parser.hpp" -#include "ingen/client/PluginModel.hpp" -#include "ingen/client/PortModel.hpp" - -#include <cassert> -#include <cstdlib> -#include <fstream> -#include <map> -#include <string> -namespace ingen { -namespace gui { +#include <ingen/URIs.hpp> +#include <ingen/client/PortModel.hpp> + +#include <string> -using namespace ingen::client; +namespace ingen::gui { Style::Style(App& app) - // Colours from the Tango palette with modified V - : _app(app) + : _app(app) +{ #ifdef INGEN_USE_LIGHT_THEME - , _audio_port_color(0xC8E6ABFF) // Green - , _control_port_color(0xAAC0E6FF) // Blue - , _cv_port_color(0xACE6E0FF) // Teal (between audio and control) - , _event_port_color(0xE6ABABFF) // Red - , _string_port_color(0xD8ABE6FF) // Plum -#else - , _audio_port_color(0x4A8A0EFF) // Green - , _control_port_color(0x244678FF) // Blue - , _cv_port_color(0x248780FF) // Teal (between audio and control) - , _event_port_color(0x960909FF) // Red - , _string_port_color(0x5C3566FF) // Plum + _audio_port_color = 0xC8E6ABFF; + _control_port_color = 0xAAC0E6FF; + _cv_port_color = 0xACE6E0FF; + _event_port_color = 0xE6ABABFF; + _string_port_color = 0xD8ABE6FF; #endif -{ } /** Loads settings from the rc file. Passing no parameter will load from * the default location. */ void -Style::load_settings(std::string filename) +Style::load_settings(const std::string& filename) { /* ... */ } @@ -68,7 +50,7 @@ Style::load_settings(std::string filename) * default location. */ void -Style::save_settings(std::string filename) +Style::save_settings(const std::string& filename) { /* ... */ } @@ -86,22 +68,32 @@ uint32_t Style::get_port_color(const client::PortModel* p) { const URIs& uris = _app.uris(); + if (p->is_a(uris.lv2_AudioPort)) { return _audio_port_color; - } else if (p->is_a(uris.lv2_ControlPort)) { + } + + if (p->is_a(uris.lv2_ControlPort)) { return _control_port_color; - } else if (p->is_a(uris.lv2_CVPort)) { + } + + if (p->is_a(uris.lv2_CVPort)) { return _cv_port_color; - } else if (p->supports(uris.atom_String)) { + } + + if (p->supports(uris.atom_String)) { return _string_port_color; - } else if (_app.can_control(p)) { + } + + if (_app.can_control(p)) { return _control_port_color; - } else if (p->is_a(uris.atom_AtomPort)) { + } + + if (p->is_a(uris.atom_AtomPort)) { return _event_port_color; } return 0x555555FF; } -} // namespace gui -} // namespace ingen +} // namespace ingen::gui diff --git a/src/gui/Style.hpp b/src/gui/Style.hpp index bb403ffd..20d560a8 100644 --- a/src/gui/Style.hpp +++ b/src/gui/Style.hpp @@ -20,21 +20,23 @@ #include <cstdint> #include <string> -namespace ingen { namespace client { class PortModel; } } - namespace ingen { + +namespace client { +class PortModel; +} // namespace client + namespace gui { class App; -class Port; class Style { public: explicit Style(App& app); - void load_settings(std::string filename = ""); - void save_settings(std::string filename = ""); + void load_settings(const std::string& filename = ""); + void save_settings(const std::string& filename = ""); void apply_settings(); @@ -43,11 +45,12 @@ public: private: App& _app; - uint32_t _audio_port_color; - uint32_t _control_port_color; - uint32_t _cv_port_color; - uint32_t _event_port_color; - uint32_t _string_port_color; + // Colours from the Tango palette with modified V + uint32_t _audio_port_color{0x4A8A0EFF}; // Green + uint32_t _control_port_color{0x244678FF}; // Blue + uint32_t _cv_port_color{0x248780FF}; // Teal {between audio/control} + uint32_t _event_port_color{0x960909FF}; // Red + uint32_t _string_port_color{0x5C3566FF}; // Plum }; } // namespace gui diff --git a/src/gui/SubgraphModule.cpp b/src/gui/SubgraphModule.cpp index 52c37787..a1b14bb6 100644 --- a/src/gui/SubgraphModule.cpp +++ b/src/gui/SubgraphModule.cpp @@ -18,27 +18,31 @@ #include "App.hpp" #include "NodeModule.hpp" -#include "GraphCanvas.hpp" -#include "GraphWindow.hpp" -#include "Port.hpp" #include "WindowFactory.hpp" -#include "ingen/Interface.hpp" -#include "ingen/client/GraphModel.hpp" +#include <ingen/Atom.hpp> +#include <ingen/Forge.hpp> +#include <ingen/Interface.hpp> +#include <ingen/Resource.hpp> +#include <ingen/URIs.hpp> +#include <ingen/client/BlockModel.hpp> +#include <ingen/client/GraphModel.hpp> #include <cassert> +#include <memory> #include <utility> namespace ingen { -using namespace client; +using client::GraphModel; namespace gui { -SubgraphModule::SubgraphModule(GraphCanvas& canvas, - SPtr<const GraphModel> graph) - : NodeModule(canvas, graph) - , _graph(graph) +class GraphWindow; + +SubgraphModule::SubgraphModule(GraphCanvas& canvas, + const std::shared_ptr<const GraphModel>& graph) + : NodeModule(canvas, graph), _graph(graph) { assert(graph); } @@ -48,7 +52,7 @@ SubgraphModule::on_double_click(GdkEventButton* event) { assert(_graph); - SPtr<GraphModel> parent = dynamic_ptr_cast<GraphModel>(_graph->parent()); + auto parent = std::dynamic_pointer_cast<GraphModel>(_graph->parent()); GraphWindow* const preferred = ( (parent && (event->state & GDK_SHIFT_MASK)) ? nullptr @@ -84,7 +88,7 @@ SubgraphModule::browse_to_graph() { assert(_graph->parent()); - SPtr<GraphModel> parent = dynamic_ptr_cast<GraphModel>(_graph->parent()); + auto parent = std::dynamic_pointer_cast<GraphModel>(_graph->parent()); GraphWindow* const preferred = (parent) ? app().window_factory()->graph_window(parent) diff --git a/src/gui/SubgraphModule.hpp b/src/gui/SubgraphModule.hpp index 6f4e1c4c..11a24e52 100644 --- a/src/gui/SubgraphModule.hpp +++ b/src/gui/SubgraphModule.hpp @@ -17,18 +17,18 @@ #ifndef INGEN_GUI_SUBGRAPHMODULE_HPP #define INGEN_GUI_SUBGRAPHMODULE_HPP -#include "ingen/types.hpp" - #include "NodeModule.hpp" -#include "GraphPortModule.hpp" -namespace ingen { namespace client { -class GraphModel; -class GraphWindow; -class PortModel; -} } +#include <gdk/gdk.h> + +#include <memory> namespace ingen { + +namespace client { +class GraphModel; +} // namespace client + namespace gui { class GraphCanvas; @@ -40,10 +40,10 @@ class GraphCanvas; class SubgraphModule : public NodeModule { public: - SubgraphModule(GraphCanvas& canvas, - SPtr<const client::GraphModel> graph); + SubgraphModule(GraphCanvas& canvas, + const std::shared_ptr<const client::GraphModel>& graph); - virtual ~SubgraphModule() {} + ~SubgraphModule() override = default; bool on_double_click(GdkEventButton* event) override; @@ -52,10 +52,10 @@ public: void browse_to_graph(); void menu_remove(); - SPtr<const client::GraphModel> graph() const { return _graph; } + std::shared_ptr<const client::GraphModel> graph() const { return _graph; } protected: - SPtr<const client::GraphModel> _graph; + std::shared_ptr<const client::GraphModel> _graph; }; } // namespace gui diff --git a/src/gui/ThreadedLoader.cpp b/src/gui/ThreadedLoader.cpp index 45ac4f7f..abbedbaf 100644 --- a/src/gui/ThreadedLoader.cpp +++ b/src/gui/ThreadedLoader.cpp @@ -18,24 +18,40 @@ #include "App.hpp" -#include "ingen/Log.hpp" -#include "ingen/Module.hpp" -#include "ingen/World.hpp" -#include "ingen/client/GraphModel.hpp" +#include <ingen/FilePath.hpp> +#include <ingen/Log.hpp> +#include <ingen/Parser.hpp> +#include <ingen/Properties.hpp> +#include <ingen/Serialiser.hpp> +#include <ingen/URI.hpp> +#include <ingen/World.hpp> +#include <ingen/client/GraphModel.hpp> +#include <raul/Path.hpp> +#include <raul/Semaphore.hpp> +#include <raul/Symbol.hpp> + +#include <glibmm/ustring.h> +#include <sigc++/adaptors/bind.h> +#include <sigc++/adaptors/retype_return.h> +#include <sigc++/functors/mem_fun.h> #include <cassert> +#include <filesystem> +#include <memory> +#include <optional> #include <string> - -using boost::optional; +#include <string_view> +#include <utility> namespace ingen { + +class Interface; + namespace gui { -ThreadedLoader::ThreadedLoader(App& app, SPtr<Interface> engine) +ThreadedLoader::ThreadedLoader(App& app, std::shared_ptr<Interface> engine) : _app(app) - , _sem(0) , _engine(std::move(engine)) - , _exit_flag(false) , _thread(&ThreadedLoader::run, this) { if (!parser()) { @@ -52,7 +68,7 @@ ThreadedLoader::~ThreadedLoader() } } -SPtr<Parser> +std::shared_ptr<Parser> ThreadedLoader::parser() { return _app.world().parser(); @@ -62,7 +78,7 @@ void ThreadedLoader::run() { while (_sem.wait() && !_exit_flag) { - std::lock_guard<std::mutex> lock(_mutex); + const std::lock_guard<std::mutex> lock{_mutex}; while (!_events.empty()) { _events.front()(); _events.pop_front(); @@ -71,24 +87,24 @@ ThreadedLoader::run() } void -ThreadedLoader::load_graph(bool merge, - const FilePath& file_path, - optional<Raul::Path> engine_parent, - optional<Raul::Symbol> engine_symbol, - optional<Properties> engine_data) +ThreadedLoader::load_graph(bool merge, + const FilePath& file_path, + const std::optional<raul::Path>& engine_parent, + const std::optional<raul::Symbol>& engine_symbol, + const std::optional<Properties>& engine_data) { - std::lock_guard<std::mutex> lock(_mutex); + const std::lock_guard<std::mutex> lock{_mutex}; Glib::ustring engine_base = ""; if (engine_parent) { if (merge) { - engine_base = engine_parent.get(); + engine_base = *engine_parent; } else { - engine_base = engine_parent.get().base(); + engine_base = engine_parent->base(); } } - _events.push_back(sigc::hide_return( + _events.emplace_back(sigc::hide_return( sigc::bind(sigc::mem_fun(this, &ThreadedLoader::load_graph_event), file_path, engine_parent, @@ -99,12 +115,13 @@ ThreadedLoader::load_graph(bool merge, } void -ThreadedLoader::load_graph_event(const FilePath& file_path, - optional<Raul::Path> engine_parent, - optional<Raul::Symbol> engine_symbol, - optional<Properties> engine_data) +ThreadedLoader::load_graph_event( + const FilePath& file_path, + const std::optional<raul::Path>& engine_parent, + const std::optional<raul::Symbol>& engine_symbol, + const std::optional<Properties>& engine_data) { - std::lock_guard<std::mutex> lock(_app.world().rdf_mutex()); + const std::lock_guard<std::mutex> lock{_app.world().rdf_mutex()}; _app.world().parser()->parse_file(_app.world(), *_app.world().interface(), @@ -115,11 +132,13 @@ ThreadedLoader::load_graph_event(const FilePath& file_path, } void -ThreadedLoader::save_graph(SPtr<const client::GraphModel> model, const URI& uri) +ThreadedLoader::save_graph( + const std::shared_ptr<const client::GraphModel>& model, + const URI& uri) { - std::lock_guard<std::mutex> lock(_mutex); + const std::lock_guard<std::mutex> lock{_mutex}; - _events.push_back(sigc::hide_return( + _events.emplace_back(sigc::hide_return( sigc::bind(sigc::mem_fun(this, &ThreadedLoader::save_graph_event), model, uri))); @@ -128,12 +147,13 @@ ThreadedLoader::save_graph(SPtr<const client::GraphModel> model, const URI& uri) } void -ThreadedLoader::save_graph_event(SPtr<const client::GraphModel> model, - const URI& uri) +ThreadedLoader::save_graph_event( + const std::shared_ptr<const client::GraphModel>& model, + const URI& uri) { assert(uri.scheme() == "file"); if (_app.serialiser()) { - std::lock_guard<std::mutex> lock(_app.world().rdf_mutex()); + const std::lock_guard<std::mutex> lock{_app.world().rdf_mutex()}; if (uri.string().find(".ingen") != std::string::npos) { _app.serialiser()->write_bundle(model, uri); diff --git a/src/gui/ThreadedLoader.hpp b/src/gui/ThreadedLoader.hpp index 3ab8f4a2..27ba7c8c 100644 --- a/src/gui/ThreadedLoader.hpp +++ b/src/gui/ThreadedLoader.hpp @@ -17,25 +17,32 @@ #ifndef INGEN_GUI_THREADEDLOADER_HPP #define INGEN_GUI_THREADEDLOADER_HPP -#include "ingen/FilePath.hpp" -#include "ingen/Interface.hpp" -#include "ingen/Parser.hpp" -#include "ingen/Serialiser.hpp" -#include "raul/Semaphore.hpp" +#include <ingen/FilePath.hpp> +#include <raul/Semaphore.hpp> -#include <boost/optional/optional.hpp> -#include <sigc++/sigc++.h> +#include <sigc++/functors/slot.h> #include <list> +#include <memory> #include <mutex> +#include <optional> #include <thread> -#include <utility> + +namespace raul { +class Path; +class Symbol; +} // namespace raul namespace ingen { +class Interface; +class Parser; +class Properties; class URI; -namespace client { class GraphModel; } +namespace client { +class GraphModel; +} // namespace client namespace gui { @@ -43,7 +50,7 @@ class App; /** Thread for loading graph files. * - * This is a seperate thread so it can send all the loading message without + * This is a separate thread so it can send all the loading message without * blocking everything else, so the app can respond to the incoming events * caused as a result of the graph loading, while the graph loads. * @@ -56,41 +63,43 @@ class ThreadedLoader { public: ThreadedLoader(App& app, - SPtr<Interface> engine); + std::shared_ptr<Interface> engine); ~ThreadedLoader(); - void load_graph(bool merge, - const FilePath& file_path, - boost::optional<Raul::Path> engine_parent, - boost::optional<Raul::Symbol> engine_symbol, - boost::optional<Properties> engine_data); + void load_graph(bool merge, + const FilePath& file_path, + const std::optional<raul::Path>& engine_parent, + const std::optional<raul::Symbol>& engine_symbol, + const std::optional<Properties>& engine_data); - void save_graph(SPtr<const client::GraphModel> model, const URI& uri); + void save_graph(const std::shared_ptr<const client::GraphModel>& model, + const URI& uri); - SPtr<Parser> parser(); + std::shared_ptr<Parser> parser(); private: - void load_graph_event(const FilePath& file_path, - boost::optional<Raul::Path> engine_parent, - boost::optional<Raul::Symbol> engine_symbol, - boost::optional<Properties> engine_data); + void load_graph_event(const FilePath& file_path, + const std::optional<raul::Path>& engine_parent, + const std::optional<raul::Symbol>& engine_symbol, + const std::optional<Properties>& engine_data); - void save_graph_event(SPtr<const client::GraphModel> model, - const URI& filename); + void + 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(); - App& _app; - Raul::Semaphore _sem; - SPtr<Interface> _engine; - std::mutex _mutex; - std::list<Closure> _events; - bool _exit_flag; - std::thread _thread; + App& _app; + raul::Semaphore _sem{0}; + std::shared_ptr<Interface> _engine; + std::mutex _mutex; + std::list<Closure> _events; + bool _exit_flag{false}; + std::thread _thread; }; } // namespace gui diff --git a/src/gui/URIEntry.cpp b/src/gui/URIEntry.cpp index 9d5249e8..92320009 100644 --- a/src/gui/URIEntry.cpp +++ b/src/gui/URIEntry.cpp @@ -19,11 +19,23 @@ #include "App.hpp" #include "RDFS.hpp" +#include <ingen/URI.hpp> +#include <ingen/World.hpp> +#include <lilv/lilv.h> + +#include <gdk/gdk.h> +#include <gtkmm/button.h> +#include <gtkmm/menu.h> +#include <gtkmm/menu_elems.h> +#include <gtkmm/menuitem.h> +#include <gtkmm/object.h> +#include <sigc++/adaptors/bind.h> +#include <sigc++/functors/mem_fun.h> + #include <map> #include <utility> -namespace ingen { -namespace gui { +namespace ingen::gui { URIEntry::URIEntry(App* app, std::set<URI> types, const std::string& value) : Gtk::HBox(false, 4) @@ -46,7 +58,7 @@ URIEntry::build_value_menu() { World& world = _app->world(); LilvWorld* lworld = world.lilv_world(); - Gtk::Menu* menu = new Gtk::Menu(); + auto* menu = new Gtk::Menu(); LilvNode* owl_onDatatype = lilv_new_uri(lworld, LILV_NS_OWL "onDatatype"); LilvNode* rdf_type = lilv_new_uri(lworld, LILV_NS_RDF "type"); @@ -54,7 +66,7 @@ URIEntry::build_value_menu() LilvNode* rdfs_Datatype = lilv_new_uri(lworld, LILV_NS_RDFS "Datatype"); LilvNode* rdfs_subClassOf = lilv_new_uri(lworld, LILV_NS_RDFS "subClassOf"); - rdfs::Objects values = rdfs::instances(world, _types); + const rdfs::Objects values = rdfs::instances(world, _types); for (const auto& v : values) { const LilvNode* inst = lilv_new_uri(lworld, v.second.c_str()); @@ -110,7 +122,7 @@ URIEntry::build_subclass_menu(const LilvNode* klass) return nullptr; } - Gtk::Menu* menu = new Gtk::Menu(); + auto* menu = new Gtk::Menu(); // Add "header" item for choosing this class itself add_leaf_menu_item(menu, klass, rdfs::label(world, klass)); @@ -118,11 +130,11 @@ URIEntry::build_subclass_menu(const LilvNode* klass) // Put subclasses/types in a map keyed by label (to sort menu) std::map<std::string, const LilvNode*> entries; - LILV_FOREACH(nodes, s, subclasses) { + LILV_FOREACH (nodes, s, subclasses) { const LilvNode* node = lilv_nodes_get(subclasses, s); entries.emplace(rdfs::label(world, node), node); } - LILV_FOREACH(nodes, s, subtypes) { + LILV_FOREACH (nodes, s, subtypes) { const LilvNode* node = lilv_nodes_get(subtypes, s); entries.emplace(rdfs::label(world, node), node); } @@ -190,5 +202,4 @@ URIEntry::menu_button_event(GdkEvent* ev) return true; } -} // namespace gui -} // namespace ingen +} // namespace ingen::gui diff --git a/src/gui/URIEntry.hpp b/src/gui/URIEntry.hpp index 535f0805..45fa6894 100644 --- a/src/gui/URIEntry.hpp +++ b/src/gui/URIEntry.hpp @@ -17,23 +17,29 @@ #ifndef INGEN_GUI_URI_ENTRY_HPP #define INGEN_GUI_URI_ENTRY_HPP -#include "ingen/URI.hpp" -#include "lilv/lilv.h" +#include <ingen/URI.hpp> +#include <lilv/lilv.h> +#include <gdk/gdk.h> +#include <glibmm/signalproxy.h> +#include <glibmm/ustring.h> #include <gtkmm/box.h> -#include <gtkmm/button.h> #include <gtkmm/entry.h> -#include <gtkmm/menu.h> #include <set> #include <string> -namespace ingen { -namespace gui { +namespace Gtk { +class Button; +class Menu; +} // namespace Gtk + +namespace ingen::gui { class App; -class URIEntry : public Gtk::HBox { +class URIEntry : public Gtk::HBox +{ public: /** Create a widget for entering URIs. * @@ -66,7 +72,6 @@ private: Gtk::Entry* _entry; }; -} // namespace gui -} // namespace ingen +} // namespace ingen::gui #endif // INGEN_GUI_URI_ENTRY_HPP diff --git a/src/gui/WidgetFactory.cpp b/src/gui/WidgetFactory.cpp index 154bcd3f..33660d77 100644 --- a/src/gui/WidgetFactory.cpp +++ b/src/gui/WidgetFactory.cpp @@ -16,20 +16,18 @@ #include "WidgetFactory.hpp" -#include "ingen/Log.hpp" -#include "ingen/runtime_paths.hpp" +#include <ingen/runtime_paths.hpp> #include <cstdlib> #include <fstream> #include <stdexcept> #include <string> -namespace ingen { -namespace gui { +namespace ingen::gui { Glib::ustring WidgetFactory::ui_filename = ""; -inline static bool +static inline bool is_readable(const std::string& filename) { std::ifstream fs(filename.c_str()); @@ -72,10 +70,9 @@ WidgetFactory::create(const std::string& toplevel_widget) if (toplevel_widget.empty()) { return Gtk::Builder::create_from_file(ui_filename); - } else { - return Gtk::Builder::create_from_file(ui_filename, toplevel_widget.c_str()); } + + return Gtk::Builder::create_from_file(ui_filename, toplevel_widget.c_str()); } -} // namespace gui -} // namespace ingen +} // namespace ingen::gui diff --git a/src/gui/WidgetFactory.hpp b/src/gui/WidgetFactory.hpp index 0a9ea4c3..d10a5e1a 100644 --- a/src/gui/WidgetFactory.hpp +++ b/src/gui/WidgetFactory.hpp @@ -14,8 +14,8 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef INGEN_GUI_GLADEFACTORY_HPP -#define INGEN_GUI_GLADEFACTORY_HPP +#ifndef INGEN_GUI_WIDGETFACTORY_HPP +#define INGEN_GUI_WIDGETFACTORY_HPP #include <glibmm/refptr.h> #include <glibmm/ustring.h> @@ -23,30 +23,28 @@ #include <string> -namespace Gtk { class Builder; } - -namespace ingen { -namespace gui { +namespace ingen::gui { /** Loads widgets from an XML description. * Purely static. * * \ingroup GUI */ -class WidgetFactory { +class WidgetFactory +{ public: static Glib::RefPtr<Gtk::Builder> create(const std::string& toplevel_widget=""); template<typename T> static void get_widget(const Glib::ustring& name, T*& widget) { - Glib::RefPtr<Gtk::Builder> xml = create(name); + const Glib::RefPtr<Gtk::Builder> xml = create(name); xml->get_widget(name, widget); } template<typename T> static void get_widget_derived(const Glib::ustring& name, T*& widget) { - Glib::RefPtr<Gtk::Builder> xml = create(name); + const Glib::RefPtr<Gtk::Builder> xml = create(name); xml->get_widget_derived(name, widget); } @@ -55,7 +53,6 @@ private: static Glib::ustring ui_filename; }; -} // namespace gui -} // namespace ingen +} // namespace ingen::gui -#endif // INGEN_GUI_GLADEFACTORY_HPP +#endif // INGEN_GUI_WIDGETFACTORY_HPP diff --git a/src/gui/Window.hpp b/src/gui/Window.hpp index 5f49bc10..756ba8f0 100644 --- a/src/gui/Window.hpp +++ b/src/gui/Window.hpp @@ -17,13 +17,12 @@ #ifndef INGEN_GUI_WINDOW_HPP #define INGEN_GUI_WINDOW_HPP +#include <gdk/gdk.h> #include <gdk/gdkkeysyms.h> #include <gtkmm/dialog.h> #include <gtkmm/window.h> -namespace ingen { - -namespace gui { +namespace ingen::gui { class App; @@ -33,13 +32,16 @@ class App; class Window : public Gtk::Window { public: - Window() : Gtk::Window(), _app(nullptr) {} - explicit Window(BaseObjectType* cobject) : Gtk::Window(cobject), _app(nullptr) {} + Window() = default; + + explicit Window(BaseObjectType* cobject) + : Gtk::Window(cobject) + {} virtual void init_window(App& app) { _app = &app; } bool on_key_press_event(GdkEventKey* event) override { - if (event->keyval == GDK_w && event->state & GDK_CONTROL_MASK) { + if (event->keyval == GDK_KEY_w && event->state & GDK_CONTROL_MASK) { hide(); return true; } @@ -48,7 +50,7 @@ public: static bool key_press_handler(Gtk::Window* win, GdkEventKey* event); - App* _app; + App* _app = nullptr; }; /** Ingen GUI Dialog @@ -57,23 +59,25 @@ public: class Dialog : public Gtk::Dialog { public: - Dialog() : Gtk::Dialog(), _app(nullptr) {} - explicit Dialog(BaseObjectType* cobject) : Gtk::Dialog(cobject), _app(nullptr) {} + Dialog() = default; + + explicit Dialog(BaseObjectType* cobject) + : Gtk::Dialog(cobject) + {} virtual void init_dialog(App& app) { _app = &app; } bool on_key_press_event(GdkEventKey* event) override { - if (event->keyval == GDK_w && event->state & GDK_CONTROL_MASK) { + if (event->keyval == GDK_KEY_w && event->state & GDK_CONTROL_MASK) { hide(); return true; } return Gtk::Window::on_key_press_event(event); } - App* _app; + App* _app = nullptr; }; -} // namespace gui -} // namespace ingen +} // namespace ingen::gui #endif // INGEN_GUI_WINDOW_HPP diff --git a/src/gui/WindowFactory.cpp b/src/gui/WindowFactory.cpp index d85987f0..78acf4fb 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 @@ -14,38 +14,47 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ +#include "WindowFactory.hpp" + #include "App.hpp" +#include "GraphBox.hpp" +#include "GraphWindow.hpp" #include "LoadGraphWindow.hpp" #include "LoadPluginWindow.hpp" #include "NewSubgraphWindow.hpp" -#include "GraphView.hpp" -#include "GraphWindow.hpp" #include "PropertiesWindow.hpp" #include "RenameWindow.hpp" #include "WidgetFactory.hpp" -#include "WindowFactory.hpp" -#include "ingen/Log.hpp" -#include "ingen/client/GraphModel.hpp" +#include <ingen/Log.hpp> +#include <ingen/client/BlockModel.hpp> +#include <ingen/client/GraphModel.hpp> +#include <ingen/client/ObjectModel.hpp> +#include <raul/Path.hpp> + +#include <gdkmm/window.h> +#include <sigc++/adaptors/bind.h> +#include <sigc++/functors/mem_fun.h> +#include <algorithm> #include <cassert> +#include <memory> #include <stdexcept> #include <string> #include <utility> namespace ingen { -using namespace client; +class Properties; + +using client::BlockModel; +using client::GraphModel; +using client::ObjectModel; namespace gui { WindowFactory::WindowFactory(App& app) : _app(app) - , _main_box(nullptr) - , _load_plugin_win(nullptr) - , _load_graph_win(nullptr) - , _new_subgraph_win(nullptr) - , _properties_win(nullptr) { WidgetFactory::get_widget_derived("load_plugin_win", _load_plugin_win); WidgetFactory::get_widget_derived("load_graph_win", _load_graph_win); @@ -87,29 +96,24 @@ 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* -WindowFactory::graph_box(SPtr<const GraphModel> graph) +WindowFactory::graph_box(const std::shared_ptr<const GraphModel>& graph) { GraphWindow* window = graph_window(graph); if (window) { return window->box(); - } else { - return _main_box; } + + return _main_box; } GraphWindow* -WindowFactory::graph_window(SPtr<const GraphModel> graph) +WindowFactory::graph_window(const std::shared_ptr<const GraphModel>& graph) { if (!graph) { return nullptr; @@ -121,13 +125,14 @@ WindowFactory::graph_window(SPtr<const GraphModel> graph) } GraphWindow* -WindowFactory::parent_graph_window(SPtr<const BlockModel> block) +WindowFactory::parent_graph_window( + const std::shared_ptr<const BlockModel>& block) { if (!block) { return nullptr; } - return graph_window(dynamic_ptr_cast<GraphModel>(block->parent())); + return graph_window(std::dynamic_pointer_cast<GraphModel>(block->parent())); } /** Present a GraphWindow for a Graph. @@ -137,12 +142,10 @@ WindowFactory::parent_graph_window(SPtr<const BlockModel> block) * presented and `preferred` left unmodified. */ void -WindowFactory::present_graph(SPtr<const GraphModel> graph, - GraphWindow* preferred, - SPtr<GraphView> view) +WindowFactory::present_graph(const std::shared_ptr<const GraphModel>& graph, + GraphWindow* preferred, + const std::shared_ptr<GraphView>& view) { - assert(!view || view->graph() == graph); - auto w = _graph_windows.find(graph->path()); if (w != _graph_windows.end()) { @@ -163,11 +166,9 @@ WindowFactory::present_graph(SPtr<const GraphModel> graph, } GraphWindow* -WindowFactory::new_graph_window(SPtr<const GraphModel> graph, - SPtr<GraphView> view) +WindowFactory::new_graph_window(const std::shared_ptr<const GraphModel>& graph, + const std::shared_ptr<GraphView>& view) { - assert(!view || view->graph() == graph); - GraphWindow* win = nullptr; WidgetFactory::get_widget_derived("graph_win", win); if (!win) { @@ -205,8 +206,9 @@ WindowFactory::remove_graph_window(GraphWindow* win, GdkEventAny* ignored) } void -WindowFactory::present_load_plugin(SPtr<const GraphModel> graph, - Properties data) +WindowFactory::present_load_plugin( + const std::shared_ptr<const GraphModel>& graph, + const Properties& data) { _app.request_plugins_if_necessary(); @@ -219,9 +221,10 @@ WindowFactory::present_load_plugin(SPtr<const GraphModel> graph, _load_plugin_win->set_modal(false); _load_plugin_win->set_type_hint(Gdk::WINDOW_TYPE_HINT_DIALOG); if (w->second) { - int width, height; + int width = 0; + int height = 0; w->second->get_size(width, height); - _load_plugin_win->set_default_size(width - width / 8, height / 2); + _load_plugin_win->set_default_size(width - (width / 8), height / 2); } _load_plugin_win->set_title( std::string("Load Plugin - ") + graph->path() + " - Ingen"); @@ -229,8 +232,9 @@ WindowFactory::present_load_plugin(SPtr<const GraphModel> graph, } void -WindowFactory::present_load_graph(SPtr<const GraphModel> graph, - Properties data) +WindowFactory::present_load_graph( + const std::shared_ptr<const GraphModel>& graph, + const Properties& data) { auto w = _graph_windows.find(graph->path()); @@ -242,8 +246,9 @@ WindowFactory::present_load_graph(SPtr<const GraphModel> graph, } void -WindowFactory::present_load_subgraph(SPtr<const GraphModel> graph, - Properties data) +WindowFactory::present_load_subgraph( + const std::shared_ptr<const GraphModel>& graph, + const Properties& data) { auto w = _graph_windows.find(graph->path()); @@ -255,8 +260,9 @@ WindowFactory::present_load_subgraph(SPtr<const GraphModel> graph, } void -WindowFactory::present_new_subgraph(SPtr<const GraphModel> graph, - Properties data) +WindowFactory::present_new_subgraph( + const std::shared_ptr<const GraphModel>& graph, + const Properties& data) { auto w = _graph_windows.find(graph->path()); @@ -268,7 +274,7 @@ WindowFactory::present_new_subgraph(SPtr<const GraphModel> graph, } void -WindowFactory::present_rename(SPtr<const ObjectModel> object) +WindowFactory::present_rename(const std::shared_ptr<const ObjectModel>& object) { auto w = _graph_windows.find(object->path()); if (w == _graph_windows.end()) { @@ -283,7 +289,8 @@ WindowFactory::present_rename(SPtr<const ObjectModel> object) } void -WindowFactory::present_properties(SPtr<const ObjectModel> object) +WindowFactory::present_properties( + const std::shared_ptr<const ObjectModel>& object) { auto w = _graph_windows.find(object->path()); if (w == _graph_windows.end()) { diff --git a/src/gui/WindowFactory.hpp b/src/gui/WindowFactory.hpp index fad5b308..e643505a 100644 --- a/src/gui/WindowFactory.hpp +++ b/src/gui/WindowFactory.hpp @@ -17,11 +17,14 @@ #ifndef INGEN_GUI_WINDOWFACTORY_HPP #define INGEN_GUI_WINDOWFACTORY_HPP -#include "ingen/Node.hpp" -#include "ingen/types.hpp" +#include <ingen/Properties.hpp> +#include <raul/Path.hpp> + +#include <gdk/gdk.h> #include <cstddef> #include <map> +#include <memory> namespace ingen { @@ -29,7 +32,7 @@ namespace client { class BlockModel; class ObjectModel; class GraphModel; -} +} // namespace client namespace gui { @@ -49,28 +52,46 @@ class RenameWindow; * as well as an enumeration of all windows (the goal being to reduce that * number as much as possible). */ -class WindowFactory { +class WindowFactory +{ public: explicit WindowFactory(App& app); ~WindowFactory(); size_t num_open_graph_windows(); - GraphBox* graph_box(SPtr<const client::GraphModel> graph); - GraphWindow* graph_window(SPtr<const client::GraphModel> graph); - GraphWindow* parent_graph_window(SPtr<const client::BlockModel> block); + GraphBox* graph_box(const std::shared_ptr<const client::GraphModel>& graph); + + GraphWindow* + graph_window(const std::shared_ptr<const client::GraphModel>& graph); + + GraphWindow* + parent_graph_window(const std::shared_ptr<const client::BlockModel>& block); + + void present_graph(const std::shared_ptr<const client::GraphModel>& graph, + GraphWindow* preferred = nullptr, + const std::shared_ptr<GraphView>& view = nullptr); + + void + present_load_plugin(const std::shared_ptr<const client::GraphModel>& graph, + const Properties& data = Properties()); + + void + present_load_graph(const std::shared_ptr<const client::GraphModel>& graph, + const Properties& data = Properties()); + + void present_load_subgraph( + const std::shared_ptr<const client::GraphModel>& graph, + const Properties& data = Properties()); + + void + present_new_subgraph(const std::shared_ptr<const client::GraphModel>& graph, + const Properties& data = Properties()); - void present_graph( - SPtr<const client::GraphModel> graph, - GraphWindow* preferred = nullptr, - SPtr<GraphView> view = SPtr<GraphView>()); + void + present_rename(const std::shared_ptr<const client::ObjectModel>& object); - void present_load_plugin(SPtr<const client::GraphModel> graph, Properties data=Properties()); - void present_load_graph(SPtr<const client::GraphModel> graph, Properties data=Properties()); - void present_load_subgraph(SPtr<const client::GraphModel> graph, Properties data=Properties()); - void present_new_subgraph(SPtr<const client::GraphModel> graph, Properties data=Properties()); - void present_rename(SPtr<const client::ObjectModel> object); - void present_properties(SPtr<const client::ObjectModel> object); + void present_properties(const std::shared_ptr<const client::ObjectModel>& object); bool remove_graph_window(GraphWindow* win, GdkEventAny* ignored = nullptr); @@ -79,19 +100,20 @@ public: void clear(); private: - using GraphWindowMap = std::map<Raul::Path, GraphWindow*>; + using GraphWindowMap = std::map<raul::Path, GraphWindow*>; - GraphWindow* new_graph_window(SPtr<const client::GraphModel> graph, - SPtr<GraphView> view); + GraphWindow* + new_graph_window(const std::shared_ptr<const client::GraphModel>& graph, + const std::shared_ptr<GraphView>& view); App& _app; - GraphBox* _main_box; + GraphBox* _main_box{nullptr}; GraphWindowMap _graph_windows; - LoadPluginWindow* _load_plugin_win; - LoadGraphWindow* _load_graph_win; - NewSubgraphWindow* _new_subgraph_win; - PropertiesWindow* _properties_win; - RenameWindow* _rename_win; + LoadPluginWindow* _load_plugin_win{nullptr}; + LoadGraphWindow* _load_graph_win{nullptr}; + NewSubgraphWindow* _new_subgraph_win{nullptr}; + PropertiesWindow* _properties_win{nullptr}; + RenameWindow* _rename_win{nullptr}; }; } // namespace gui diff --git a/src/gui/ingen_gui.cpp b/src/gui/ingen_gui.cpp index 4504d3fe..7fba2d50 100644 --- a/src/gui/ingen_gui.cpp +++ b/src/gui/ingen_gui.cpp @@ -14,25 +14,33 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "ingen/Configuration.hpp" -#include "ingen/Module.hpp" -#include "ingen/QueuedInterface.hpp" -#include "ingen/client/SigClientInterface.hpp" - #include "App.hpp" -namespace ingen { -namespace gui { +#include <ingen/Atom.hpp> +#include <ingen/Configuration.hpp> +#include <ingen/Interface.hpp> +#include <ingen/Module.hpp> +#include <ingen/QueuedInterface.hpp> +#include <ingen/URI.hpp> +#include <ingen/World.hpp> +#include <ingen/client/SigClientInterface.hpp> + +#include <glibmm/thread.h> + +#include <memory> +#include <string> + +namespace ingen::gui { struct GUIModule : public Module { using SigClientInterface = client::SigClientInterface; void load(World& world) override { - URI uri(world.conf().option("connect").ptr<char>()); + const URI uri{world.conf().option("connect").ptr<char>()}; if (!world.interface()) { world.set_interface( world.new_interface(URI(uri), make_client(world))); - } else if (!dynamic_ptr_cast<SigClientInterface>( + } else if (!std::dynamic_pointer_cast<SigClientInterface>( world.interface()->respondee())) { world.interface()->set_respondee(make_client(world)); } @@ -44,20 +52,22 @@ struct GUIModule : public Module { app->run(); } - SPtr<Interface> make_client(World& world) { - SPtr<SigClientInterface> sci(new SigClientInterface()); - return world.engine() ? sci : SPtr<Interface>(new QueuedInterface(sci)); + std::shared_ptr<Interface> make_client(World& world) + { + auto sci = std::make_shared<SigClientInterface>(); + return world.engine() + ? sci + : std::shared_ptr<Interface>(new QueuedInterface(sci)); } - SPtr<gui::App> app; + std::shared_ptr<gui::App> app; }; -} // namespace gui -} // namespace ingen +} // namespace ingen::gui extern "C" { -ingen::Module* +INGEN_MODULE_EXPORT ingen::Module* ingen_module_load() { Glib::thread_init(); diff --git a/src/gui/ingen_gui.ui b/src/gui/ingen_gui.ui.in index 9e751064..9e751064 100644 --- a/src/gui/ingen_gui.ui +++ b/src/gui/ingen_gui.ui.in diff --git a/src/gui/ingen_gui_lv2.cpp b/src/gui/ingen_gui_lv2.cpp index 4817e9ae..67290c76 100644 --- a/src/gui/ingen_gui_lv2.cpp +++ b/src/gui/ingen_gui_lv2.cpp @@ -17,41 +17,40 @@ #include "App.hpp" #include "GraphBox.hpp" -#include "ingen/AtomReader.hpp" -#include "ingen/AtomSink.hpp" -#include "ingen/AtomWriter.hpp" -#include "ingen/Forge.hpp" -#include "ingen/Interface.hpp" -#include "ingen/Properties.hpp" -#include "ingen/URI.hpp" -#include "ingen/URIs.hpp" -#include "ingen/World.hpp" -#include "ingen/client/ClientStore.hpp" -#include "ingen/client/GraphModel.hpp" -#include "ingen/client/SigClientInterface.hpp" -#include "ingen/ingen.h" -#include "ingen/paths.hpp" -#include "ingen/runtime_paths.hpp" -#include "ingen/types.hpp" -#include "lv2/atom/atom.h" -#include "lv2/atom/util.h" -#include "lv2/core/lv2.h" -#include "lv2/core/lv2.h" -#include "lv2/log/log.h" -#include "lv2/ui/ui.h" -#include "lv2/urid/urid.h" -#include "lv2/urid/urid.h" -#include "raul/Path.hpp" +#include <ingen/AtomReader.hpp> +#include <ingen/AtomSink.hpp> +#include <ingen/AtomWriter.hpp> +#include <ingen/Forge.hpp> +#include <ingen/Interface.hpp> +#include <ingen/Properties.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIs.hpp> +#include <ingen/World.hpp> +#include <ingen/client/ClientStore.hpp> +#include <ingen/client/GraphModel.hpp> +#include <ingen/client/SigClientInterface.hpp> +#include <ingen/ingen.h> +#include <ingen/paths.hpp> +#include <ingen/runtime_paths.hpp> +#include <lv2/atom/atom.h> +#include <lv2/atom/util.h> +#include <lv2/core/lv2.h> +#include <lv2/log/log.h> +#include <lv2/ui/ui.h> +#include <lv2/urid/urid.h> +#include <raul/Path.hpp> #include <cstdint> #include <cstring> +#include <memory> #define INGEN_LV2_UI_URI INGEN_NS "GraphUIGtk2" namespace ingen { /** A sink that writes atoms to a port via the UI extension. */ -struct IngenLV2AtomSink : public AtomSink { +class IngenLV2AtomSink : public AtomSink { +public: IngenLV2AtomSink(URIs& uris, LV2UI_Write_Function ui_write, LV2UI_Controller ui_controller) @@ -69,30 +68,23 @@ struct IngenLV2AtomSink : public AtomSink { return true; } +private: URIs& _uris; LV2UI_Write_Function _ui_write; LV2UI_Controller _ui_controller; }; struct IngenLV2UI { - IngenLV2UI() - : argc(0) - , argv(nullptr) - , forge(nullptr) - , world(nullptr) - , sink(nullptr) - {} - - int argc; - char** argv; - Forge* forge; - World* world; - IngenLV2AtomSink* sink; - SPtr<gui::App> app; - SPtr<gui::GraphBox> view; - SPtr<Interface> engine; - SPtr<AtomReader> reader; - SPtr<client::SigClientInterface> client; + int argc{0}; + char** argv{nullptr}; + Forge* forge{nullptr}; + World* world{nullptr}; + IngenLV2AtomSink* sink{nullptr}; + std::shared_ptr<gui::App> app; + std::shared_ptr<gui::GraphBox> view; + std::shared_ptr<Interface> engine; + std::shared_ptr<AtomReader> reader; + std::shared_ptr<client::SigClientInterface> client; }; } // namespace ingen @@ -106,24 +98,20 @@ instantiate(const LV2UI_Descriptor* descriptor, LV2UI_Widget* widget, const LV2_Feature* const* features) { -#if __cplusplus >= 201103L - using ingen::SPtr; -#endif - ingen::set_bundle_path(bundle_path); - ingen::IngenLV2UI* ui = new ingen::IngenLV2UI(); + auto* ui = new ingen::IngenLV2UI(); LV2_URID_Map* map = nullptr; LV2_URID_Unmap* unmap = nullptr; LV2_Log_Log* log = nullptr; for (int i = 0; features[i]; ++i) { if (!strcmp(features[i]->URI, LV2_URID__map)) { - map = (LV2_URID_Map*)features[i]->data; + map = static_cast<LV2_URID_Map*>(features[i]->data); } else if (!strcmp(features[i]->URI, LV2_URID__unmap)) { - unmap = (LV2_URID_Unmap*)features[i]->data; + unmap = static_cast<LV2_URID_Unmap*>(features[i]->data); } else if (!strcmp(features[i]->URI, LV2_LOG__log)) { - log = (LV2_Log_Log*)features[i]->data; + log = static_cast<LV2_Log_Log*>(features[i]->data); } } @@ -141,24 +129,22 @@ instantiate(const LV2UI_Descriptor* descriptor, ui->world->uris(), write_function, controller); // Set up an engine interface that writes LV2 atoms - ui->engine = SPtr<ingen::Interface>( + ui->engine = std::shared_ptr<ingen::Interface>( new ingen::AtomWriter( ui->world->uri_map(), ui->world->uris(), *ui->sink)); ui->world->set_interface(ui->engine); // Create App and client - ui->app = ingen::gui::App::create(*ui->world); - ui->client = SPtr<ingen::client::SigClientInterface>( - new ingen::client::SigClientInterface()); + ui->app = ingen::gui::App::create(*ui->world); + ui->client = std::make_shared<ingen::client::SigClientInterface>(); ui->app->set_is_plugin(true); ui->app->attach(ui->client); - ui->reader = SPtr<ingen::AtomReader>( - new ingen::AtomReader(ui->world->uri_map(), - ui->world->uris(), - ui->world->log(), - *ui->client.get())); + ui->reader = std::make_shared<ingen::AtomReader>(ui->world->uri_map(), + ui->world->uris(), + ui->world->log(), + *ui->client); // Create empty root graph model ingen::Properties props; @@ -167,9 +153,9 @@ instantiate(const LV2UI_Descriptor* descriptor, ui->app->store()->put(ingen::main_uri(), props); // Create a GraphBox for the root and set as the UI widget - SPtr<const ingen::client::GraphModel> root = - ingen::dynamic_ptr_cast<const ingen::client::GraphModel>( - ui->app->store()->object(Raul::Path("/"))); + auto root = std::dynamic_pointer_cast<const ingen::client::GraphModel>( + ui->app->store()->object(raul::Path("/"))); + ui->view = ingen::gui::GraphBox::create(*ui->app, root); ui->view->unparent(); *widget = ui->view->gobj(); @@ -183,7 +169,7 @@ instantiate(const LV2UI_Descriptor* descriptor, static void cleanup(LV2UI_Handle handle) { - ingen::IngenLV2UI* ui = (ingen::IngenLV2UI*)handle; + auto* ui = static_cast<ingen::IngenLV2UI*>(handle); delete ui; } @@ -194,8 +180,8 @@ port_event(LV2UI_Handle handle, uint32_t format, const void* buffer) { - ingen::IngenLV2UI* ui = (ingen::IngenLV2UI*)handle; - const LV2_Atom* atom = (const LV2_Atom*)buffer; + auto* ui = static_cast<ingen::IngenLV2UI*>(handle); + const auto* atom = static_cast<const LV2_Atom*>(buffer); ui->reader->write(atom); } diff --git a/src/gui/meson.build b/src/gui/meson.build new file mode 100644 index 00000000..810c7829 --- /dev/null +++ b/src/gui/meson.build @@ -0,0 +1,179 @@ +# Copyright 2022 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: 0BSD OR GPL-3.0-or-later + +################ +# Dependencies # +################ + +gui_defines = platform_defines + +glibmm_dep = dependency( + 'glibmm-2.4', + include_type: 'system', + required: get_option('gui'), + version: '>= 2.14.0', +) + +gthread_dep = dependency( + 'gthread-2.0', + include_type: 'system', + required: get_option('gui'), + version: '>= 2.14.0', +) + +gtkmm_dep = dependency( + 'gtkmm-2.4', + include_type: 'system', + required: get_option('gui'), + version: '>= 2.14.0', +) + +ganv_dep = dependency( + 'ganv-1', + include_type: 'system', + required: get_option('gui'), + version: '>= 1.5.2', +) + +webkit_dep = dependency( + 'webkit-1.0', + include_type: 'system', + required: false, + version: '>= 1.4.0', +) + +build_gui = ( + glibmm_dep.found() + and gthread_dep.found() + and gtkmm_dep.found() + and ganv_dep.found() +) + +if webkit_dep.found() + gui_defines += ['-DHAVE_WEBKIT=1'] +else + gui_defines += ['-DHAVE_WEBKIT=0'] +endif + +########## +# Module # +########## + +if build_gui + gui_sources = files( + 'App.cpp', + 'Arc.cpp', + 'BreadCrumbs.cpp', + 'ConnectWindow.cpp', + 'GraphBox.cpp', + 'GraphCanvas.cpp', + 'GraphPortModule.cpp', + 'GraphTreeWindow.cpp', + 'GraphView.cpp', + 'GraphWindow.cpp', + 'LoadGraphWindow.cpp', + 'LoadPluginWindow.cpp', + 'MessagesWindow.cpp', + 'NewSubgraphWindow.cpp', + 'NodeMenu.cpp', + 'NodeModule.cpp', + 'ObjectMenu.cpp', + 'PluginMenu.cpp', + 'Port.cpp', + 'PortMenu.cpp', + 'PropertiesWindow.cpp', + 'RDFS.cpp', + 'RenameWindow.cpp', + 'Style.cpp', + 'SubgraphModule.cpp', + 'ThreadedLoader.cpp', + 'URIEntry.cpp', + 'WidgetFactory.cpp', + 'WindowFactory.cpp', + 'ingen_gui.cpp', + ) + + gui_dependencies = [ + boost_dep, + ganv_dep, + glibmm_dep, + gthread_dep, + gtkmm_dep, + ingen_client_dep, + ingen_dep, + lilv_dep, + raul_dep, + sigcpp_dep, + suil_dep, + thread_dep, + webkit_dep, + ] + + gui_suppressions = [] + if cpp.get_id() == 'clang' + gui_suppressions += [ + '-Wno-reserved-identifier', # Ganv + ] + endif + + gui_suppressions = cpp.get_supported_arguments(gui_suppressions) + gui_suppressions += cpp_suppressions + + gui_args = gui_suppressions + gui_defines + ['-DINGEN_GUI_INTERNAL'] + + libingen_gui = shared_library( + 'ingen_gui', + gui_sources, + cpp_args: gui_args, + dependencies: gui_dependencies, + gnu_symbol_visibility: 'hidden', + implicit_include_directories: false, + include_directories: ingen_include_dirs, + install: true, + install_dir: ingen_module_dir, + ) + + ingen_gui_dep = declare_dependency( + dependencies: gui_dependencies, + link_with: libingen_gui, + ) + + ########## + # LV2 UI # + ########## + + ingen_gui_lv2 = shared_library( + 'ingen_gui_lv2', + files('ingen_gui_lv2.cpp'), + cpp_args: gui_args, + dependencies: [ingen_gui_dep], + gnu_symbol_visibility: 'hidden', + implicit_include_directories: false, + include_directories: ingen_include_dirs, + install: true, + install_dir: lv2dir / 'ingen.lv2', + ) + + ############### + # Shared Data # + ############### + + config = configuration_data() + config.set('INGEN_VERSION', meson.project_version()) + + configure_file( + configuration: config, + input: files('ingen_gui.ui.in'), + install: true, + install_dir: ingen_data_dir, + output: 'ingen_gui.ui', + ) + + configure_file( + copy: true, + input: files('ingen_style.rc'), + install: true, + install_dir: ingen_data_dir, + output: '@PLAINNAME@', + ) +endif diff --git a/src/gui/rgba.hpp b/src/gui/rgba.hpp index f31e958c..e01a069d 100644 --- a/src/gui/rgba.hpp +++ b/src/gui/rgba.hpp @@ -18,31 +18,31 @@ #define INGEN_GUI_RGBA_HPP #include <cmath> +#include <cstdint> -namespace ingen { -namespace gui { +namespace ingen::gui { -static inline uint32_t +inline uint32_t rgba_to_uint(uint8_t r, uint8_t g, uint8_t b, uint8_t a) { - return ((((uint32_t)(r)) << 24) | - (((uint32_t)(g)) << 16) | - (((uint32_t)(b)) << 8) | - (((uint32_t)(a)))); + return ((static_cast<uint32_t>(r) << 24) | + (static_cast<uint32_t>(g) << 16) | + (static_cast<uint32_t>(b) << 8) | + (static_cast<uint32_t>(a))); } -static inline uint8_t +inline uint8_t mono_interpolate(uint8_t v1, uint8_t v2, float f) { - return ((int)rint((v2) * (f) + (v1) * (1 - (f)))); + return static_cast<uint8_t>(rintf((v2 * f) + (v1 * (1.0f - f)))); } -#define RGBA_R(x) (((uint32_t)(x)) >> 24) -#define RGBA_G(x) ((((uint32_t)(x)) >> 16) & 0xFF) -#define RGBA_B(x) ((((uint32_t)(x)) >> 8) & 0xFF) -#define RGBA_A(x) (((uint32_t)(x)) & 0xFF) +#define RGBA_R(x) (static_cast<uint32_t>(x) >> 24) +#define RGBA_G(x) ((static_cast<uint32_t>(x) >> 16) & 0xFF) +#define RGBA_B(x) ((static_cast<uint32_t>(x) >> 8) & 0xFF) +#define RGBA_A(x) (static_cast<uint32_t>(x) & 0xFF) -static inline uint32_t +inline uint32_t rgba_interpolate(uint32_t c1, uint32_t c2, float f) { return rgba_to_uint( @@ -52,7 +52,6 @@ rgba_interpolate(uint32_t c1, uint32_t c2, float f) mono_interpolate(RGBA_A(c1), RGBA_A(c2), f)); } -} // namespace gui -} // namespace ingen +} // namespace ingen::gui #endif // INGEN_GUI_RGBA_HPP diff --git a/src/gui/wscript b/src/gui/wscript deleted file mode 100644 index b33bd31e..00000000 --- a/src/gui/wscript +++ /dev/null @@ -1,127 +0,0 @@ -#!/usr/bin/env python - -import waflib.Utils as Utils -import waflib.Options as Options - - -def options(ctx): - opt = ctx.configuration_options() - opt.add_option('--light-theme', action='store_true', dest='light_theme', - help='use light coloured theme') - - -def configure(conf): - conf.check_pkg('glibmm-2.4 >= 2.14.0', - uselib_store='GLIBMM', - system=True, - mandatory=False) - conf.check_pkg('gthread-2.0 >= 2.14.0', - uselib_store='GTHREAD', - system=True, - mandatory=False) - conf.check_pkg('gtkmm-2.4 >= 2.14.0', - uselib_store='GTKMM', - system=True, - mandatory=False) - conf.check_pkg('ganv-1 >= 1.5.4', - uselib_store='GANV', - mandatory=False) - if not Options.options.no_webkit: - conf.check_pkg('webkit-1.0 >= 1.4.0', - uselib_store='WEBKIT', - system=True, - mandatory=False) - - if conf.env.HAVE_GANV and conf.env.HAVE_GTKMM: - conf.env.INGEN_BUILD_GUI = 1 - - if Options.options.light_theme: - conf.define('INGEN_USE_LIGHT_THEME', 1) - - -def build(bld): - obj = bld(features = 'cxx cxxshlib', - cflags = ['-fvisibility=hidden'], - export_includes = ['../..'], - includes = ['../..'], - name = 'libingen_gui', - target = 'ingen_gui', - install_path = '${LIBDIR}', - use = 'libingen libingen_client', - uselib = ''' - GANV - GLADEMM - GLIBMM - GNOMECANVAS - GTKMM - LILV - LV2 - RAUL - SIGCPP - SERD - SORD - SRATOM - SOUP - SUIL - WEBKIT - ''') - - obj.source = ''' - App.cpp - Arc.cpp - BreadCrumbs.cpp - ConnectWindow.cpp - GraphBox.cpp - GraphCanvas.cpp - GraphPortModule.cpp - GraphTreeWindow.cpp - GraphView.cpp - GraphWindow.cpp - LoadGraphWindow.cpp - LoadPluginWindow.cpp - MessagesWindow.cpp - NewSubgraphWindow.cpp - NodeMenu.cpp - NodeModule.cpp - ObjectMenu.cpp - PluginMenu.cpp - Port.cpp - PortMenu.cpp - PropertiesWindow.cpp - RDFS.cpp - RenameWindow.cpp - Style.cpp - SubgraphModule.cpp - ThreadedLoader.cpp - URIEntry.cpp - WidgetFactory.cpp - WindowFactory.cpp - ingen_gui.cpp - ''' - - # XML UI definition - bld(features = 'subst', - source = 'ingen_gui.ui', - target = '../../ingen_gui.ui', - install_path = '${DATADIR}/ingen', - chmod = Utils.O755, - INGEN_VERSION = bld.env.INGEN_VERSION) - - # Gtk style - bld(features = 'subst', - is_copy = True, - source = 'ingen_style.rc', - target = '../../ingen_style.rc', - install_path = '${DATADIR}/ingen', - chmod = Utils.O755) - - # LV2 UI - obj = bld(features = 'cxx cxxshlib', - cflags = ['-fvisibility=hidden'], - source = 'ingen_gui_lv2.cpp', - includes = ['.', '../..'], - name = 'ingen_gui_lv2', - target = 'ingen_gui_lv2', - install_path = '${LV2DIR}/ingen.lv2/', - use = 'libingen libingen_gui', - uselib = 'LV2 SERD SORD SRATOM LILV RAUL GLIBMM GTKMM') diff --git a/src/include/ingen_config.h b/src/include/ingen_config.h new file mode 100644 index 00000000..6d5f36e0 --- /dev/null +++ b/src/include/ingen_config.h @@ -0,0 +1,216 @@ +// Copyright 2021-2022 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC + +/* + Configuration header that defines reasonable defaults at compile time. + + This allows compile-time configuration from the command line, while still + allowing the source to be built "as-is" without any configuration. The idea + is to support an advanced build system with configuration checks, while still + allowing the code to be simply "thrown at a compiler" with features + determined from the compiler or system headers. Everything can be + overridden, so it should never be necessary to edit this file to build + successfully. + + To ensure that all configure checks are performed, the build system can + define INGEN_NO_DEFAULT_CONFIG to disable defaults. In this case, it must + define all HAVE_FEATURE symbols below to 1 or 0 to enable or disable + features. Any missing definitions will generate a compiler warning. + + To ensure that this header is always included properly, all code that uses + configuration variables includes this header and checks their value with #if + (not #ifdef). Variables like USE_FEATURE are internal and should never be + defined on the command line. +*/ + +#ifndef INGEN_CONFIG_H +#define INGEN_CONFIG_H + +// Define version unconditionally so a warning will catch a mismatch +#define INGEN_VERSION "0.5.1" + +#if !defined(INGEN_NO_DEFAULT_CONFIG) + +// We need unistd.h to check _POSIX_VERSION +# ifndef INGEN_NO_POSIX +# ifdef __has_include +# if __has_include(<unistd.h>) +# include <unistd.h> +# endif +# elif defined(__unix__) +# include <unistd.h> +# endif +# endif + +// POSIX.1-2001: fileno() +# ifndef HAVE_FILENO +# if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L +# define HAVE_FILENO 1 +# else +# define HAVE_FILENO 0 +# endif +# endif + +// POSIX.1-2001: isatty() +# ifndef HAVE_ISATTY +# if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L +# define HAVE_ISATTY 1 +# else +# define HAVE_ISATTY 0 +# endif +# endif + +// POSIX.1-2001: posix_memalign() +# ifndef HAVE_POSIX_MEMALIGN +# if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L +# define HAVE_POSIX_MEMALIGN 1 +# else +# define HAVE_POSIX_MEMALIGN 0 +# endif +# endif + +// BSD and GNU: vasprintf() +# ifndef HAVE_VASPRINTF +# if defined(_BSD_SOURCE) || defined(_GNU_SOURCE) +# define HAVE_VASPRINTF 1 +# else +# define HAVE_VASPRINTF 0 +# endif +# endif + +// JACK +# ifndef HAVE_JACK +# ifdef __has_include +# if __has_include("jack/jack.h") +# define HAVE_JACK 1 +# else +# define HAVE_JACK 0 +# endif +# else +# define HAVE_JACK 0 +# endif +# endif + +// JACK metadata API +# ifndef HAVE_JACK_METADATA +# ifdef __has_include +# if __has_include("jack/metadata.h") +# define HAVE_JACK_METADATA 1 +# else +# define HAVE_JACK_METADATA 0 +# endif +# else +# define HAVE_JACK_METADATA 0 +# endif +# endif + +// JACK jack_port_rename() function +# ifndef HAVE_JACK_PORT_RENAME +# define HAVE_JACK_PORT_RENAME HAVE_JACK +# endif + +// BSD sockets +# ifndef HAVE_SOCKET +# ifdef __has_include +# if __has_include("sys/socket.h") +# define HAVE_SOCKET 1 +# else +# define HAVE_SOCKET 0 +# endif +# else +# define HAVE_SOCKET 0 +# endif +# endif + +// Webkit +# ifndef HAVE_WEBKIT +# ifdef __has_include +# if __has_include(<webkit/webkit.h>) +# define HAVE_WEBKIT 1 +# else +# define HAVE_WEBKIT 0 +# endif +# else +# define HAVE_WEBKIT 0 +# endif +# endif + +// Installation directories +# ifndef INGEN_DATA_DIR +# define INGEN_DATA_DIR "/usr/local/share/ingen" +# endif +# ifndef INGEN_MODULE_DIR +# define INGEN_MODULE_DIR "/usr/local/lib/ingen" +# endif +# ifndef INGEN_BUNDLE_DIR +# define INGEN_BUNDLE_DIR "/usr/local/lib/lv2/ingen.lv2" +# endif + +#endif // !defined(INGEN_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_FILENO) +# define USE_FILENO HAVE_FILENO +#else +# define USE_FILENO 0 +#endif + +#if defined(HAVE_ISATTY) +# define USE_ISATTY HAVE_ISATTY +#else +# define USE_ISATTY 0 +#endif + +#if defined(HAVE_POSIX_MEMALIGN) +# define USE_POSIX_MEMALIGN HAVE_POSIX_MEMALIGN +#else +# define USE_POSIX_MEMALIGN 0 +#endif + +#if defined(HAVE_SOCKET) +# define USE_SOCKET HAVE_SOCKET +#else +# define USE_SOCKET 0 +#endif + +#if defined(HAVE_VASPRINTF) +# define USE_VASPRINTF HAVE_VASPRINTF +#else +# define USE_VASPRINTF 0 +#endif + +#if defined(HAVE_WEBKIT) +# define USE_WEBKIT HAVE_WEBKIT +#else +# define USE_WEBKIT 0 +#endif + +#if defined(HAVE_JACK_METADATA) +# define USE_JACK_METADATA HAVE_JACK_METADATA +#else +# define USE_JACK_METADATA 0 +#endif + +#if defined(HAVE_JACK_PORT_TYPE_GET_BUFFER_SIZE) +# define USE_JACK_PORT_TYPE_GET_BUFFER_SIZE \ + HAVE_JACK_PORT_TYPE_GET_BUFFER_SIZE +#else +# define USE_JACK_PORT_TYPE_GET_BUFFER_SIZE 0 +#endif + +#if defined(HAVE_JACK_PORT_RENAME) +# define USE_JACK_PORT_RENAME HAVE_JACK_PORT_RENAME +#else +# define USE_JACK_PORT_RENAME 0 +#endif + +#define INGEN_BUNDLED 0 + +#endif // INGEN_CONFIG_H diff --git a/src/ingen/.clang-tidy b/src/ingen/.clang-tidy new file mode 100644 index 00000000..e7bf0b6a --- /dev/null +++ b/src/ingen/.clang-tidy @@ -0,0 +1,3 @@ +Checks: > + -bugprone-exception-escape, +InheritParentConfig: true diff --git a/src/ingen/ingen.cpp b/src/ingen/ingen.cpp index 15544c10..7f1a587e 100644 --- a/src/ingen/ingen.cpp +++ b/src/ingen/ingen.cpp @@ -14,35 +14,40 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "ingen/Configuration.hpp" -#include "ingen/EngineBase.hpp" -#include "ingen/Interface.hpp" -#include "ingen/Log.hpp" -#include "ingen/Parser.hpp" -#include "ingen/World.hpp" -#include "ingen/paths.hpp" -#include "ingen/runtime_paths.hpp" -#include "ingen/types.hpp" -#include "ingen_config.h" -#include "raul/Path.hpp" -#include "raul/Symbol.hpp" - -#ifdef HAVE_SOCKET +#include <ingen/Atom.hpp> +#include <ingen/Configuration.hpp> +#include <ingen/EngineBase.hpp> +#include <ingen/Interface.hpp> +#include <ingen/Message.hpp> +#include <ingen/Parser.hpp> +#include <ingen/URI.hpp> +#include <ingen/World.hpp> +#include <ingen/fmt.hpp> +#include <ingen/paths.hpp> +#include <ingen/runtime_paths.hpp> +#include <ingen_config.h> +#include <raul/Path.hpp> +#include <raul/Symbol.hpp> +#include <serd/serd.h> + +#if USE_SOCKET #include "ingen/client/SocketClient.hpp" #endif #include <chrono> +#include <csignal> #include <cstdint> #include <cstdlib> +#include <exception> #include <iostream> #include <memory> #include <mutex> -#include <signal.h> +#include <optional> #include <string> #include <thread> -using namespace std; -using namespace ingen; +namespace ingen { +namespace { class DummyInterface : public Interface { @@ -50,64 +55,65 @@ class DummyInterface : public Interface void message(const Message& msg) override {} }; -unique_ptr<World> world; +std::unique_ptr<World> world; -static void +void ingen_interrupt(int signal) { if (signal == SIGTERM) { - cerr << "ingen: Terminated" << endl; + std::cerr << "ingen: Terminated\n"; exit(EXIT_FAILURE); } else { - cout << "ingen: Interrupted" << endl; + std::cout << "ingen: Interrupted\n"; if (world && world->engine()) { world->engine()->quit(); } } } -static void +void ingen_try(bool cond, const char* msg) { if (!cond) { - cerr << "ingen: error: " << msg << endl; + std::cerr << "ingen: error: " << msg << "\n"; exit(EXIT_FAILURE); } } -static int +int print_version() { - cout << "ingen " << INGEN_VERSION - << " <http://drobilla.net/software/ingen>\n" - << "Copyright 2007-2017 David Robillard <http://drobilla.net>.\n" - << "License: <https://www.gnu.org/licenses/agpl-3.0>\n" - << "This is free software; you are free to change and redistribute it.\n" - << "There is NO WARRANTY, to the extent permitted by law." << endl; + std::cout << "ingen " << INGEN_VERSION + << " <http://drobilla.net/software/ingen>\n" + << "Copyright 2007-2020 David Robillard <http://drobilla.net>.\n" + << "License: <https://www.gnu.org/licenses/agpl-3.0>\n" + << "This is free software; you are free to change and redistribute it.\n" + << "There is NO WARRANTY, to the extent permitted by law.\n"; return EXIT_SUCCESS; } int -main(int argc, char** argv) +run(int argc, char** argv) { - ingen::set_bundle_path_from_code((void*)&print_version); - // Create world try { - world = unique_ptr<ingen::World>( - new ingen::World(nullptr, nullptr, nullptr)); + world = std::make_unique<ingen::World>(nullptr, nullptr, nullptr); world->load_configuration(argc, argv); if (argc <= 1) { - world->conf().print_usage("ingen", cout); + world->conf().print_usage("ingen", std::cout); return EXIT_FAILURE; - } else if (world->conf().option("help").get<int32_t>()) { - world->conf().print_usage("ingen", cout); + } + + if (world->conf().option("help").get<int32_t>()) { + world->conf().print_usage("ingen", std::cout); return EXIT_SUCCESS; - } else if (world->conf().option("version").get<int32_t>()) { + } + + if (world->conf().option("version").get<int32_t>()) { return print_version(); } } catch (std::exception& e) { - cout << "ingen: error: " << e.what() << endl; + std::cout << "ingen: error: " << e.what() << "\n"; return EXIT_FAILURE; } @@ -119,17 +125,17 @@ main(int argc, char** argv) // Run engine if (conf.option("engine").get<int32_t>()) { if (world->conf().option("threads").get<int32_t>() < 1) { - cerr << "ingen: error: threads must be > 0" << endl; + std::cerr << "ingen: error: threads must be > 0\n"; return EXIT_FAILURE; } ingen_try(world->load_module("server"), "Failed to load server module"); - ingen_try(bool(world->engine()), "Unable to create engine"); + ingen_try(!!world->engine(), "Unable to create engine"); world->engine()->listen(); } -#ifdef HAVE_SOCKET +#if USE_SOCKET client::SocketClient::register_factories(*world); #endif @@ -140,8 +146,8 @@ main(int argc, char** argv) } // If we don't have a local engine interface (from the GUI), use network - SPtr<Interface> engine_interface(world->interface()); - SPtr<Interface> dummy_client(new DummyInterface()); + auto engine_interface = world->interface(); + auto dummy_client = std::make_shared<DummyInterface>(); if (!engine_interface) { const char* const uri = conf.option("connect").ptr<char>(); ingen_try(URI::is_valid(uri), @@ -149,7 +155,7 @@ main(int argc, char** argv) engine_interface = world->new_interface(URI(uri), dummy_client); if (!engine_interface && !conf.option("gui").get<int32_t>()) { - cerr << fmt("ingen: error: Failed to connect to `%1%'\n", uri); + std::cerr << fmt("ingen: error: Failed to connect to `%1%'\n", uri); return EXIT_FAILURE; } @@ -159,56 +165,58 @@ main(int argc, char** argv) // Activate the engine, if we have one if (world->engine()) { if (!world->load_module("jack") && !world->load_module("portaudio")) { - cerr << "ingen: error: Failed to load driver module" << endl; + std::cerr << "ingen: error: Failed to load driver module\n"; return EXIT_FAILURE; } if (!world->engine()->supports_dynamic_ports() && !conf.option("load").is_valid()) { - cerr << "ingen: error: Initial graph required for driver" << endl; + std::cerr << "ingen: error: Initial graph required for driver\n"; return EXIT_FAILURE; } } // Load a graph if (conf.option("load").is_valid()) { - boost::optional<Raul::Path> parent; - boost::optional<Raul::Symbol> symbol; + std::optional<raul::Path> parent; + std::optional<raul::Symbol> symbol; const Atom& path_option = conf.option("path"); if (path_option.is_valid()) { - if (Raul::Path::is_valid(path_option.ptr<char>())) { - const Raul::Path p(path_option.ptr<char>()); + if (raul::Path::is_valid(path_option.ptr<char>())) { + const raul::Path p(path_option.ptr<char>()); if (!p.is_root()) { parent = p.parent(); - symbol = Raul::Symbol(p.symbol()); + symbol = raul::Symbol(p.symbol()); } } else { - cerr << "Invalid path given: '" << path_option.ptr<char>() << endl; + std::cerr << "Invalid path given: '" << path_option.ptr<char>() + << "\n"; } } - ingen_try(bool(world->parser()), "Failed to create parser"); + ingen_try(!!world->parser(), "Failed to create parser"); - const string graph = conf.option("load").ptr<char>(); + const std::string graph = conf.option("load").ptr<char>(); engine_interface->get(URI("ingen:/plugins")); engine_interface->get(main_uri()); - std::lock_guard<std::mutex> lock(world->rdf_mutex()); + const std::lock_guard<std::mutex> lock{world->rdf_mutex()}; world->parser()->parse_file( *world, *engine_interface, graph, parent, symbol); } else if (conf.option("server-load").is_valid()) { const char* path = conf.option("server-load").ptr<char>(); - if (serd_uri_string_has_scheme((const uint8_t*)path)) { - std::cout << "Loading " << path << " (server side)" << std::endl; + if (serd_uri_string_has_scheme(reinterpret_cast<const uint8_t*>(path))) { + std::cout << "Loading " << path << " (server side)" << "\n"; engine_interface->copy(URI(path), main_uri()); } else { SerdNode uri = serd_node_new_file_uri( - (const uint8_t*)path, nullptr, nullptr, true); - std::cout << "Loading " << (const char*)uri.buf - << " (server side)" << std::endl; - engine_interface->copy(URI((const char*)uri.buf), main_uri()); + reinterpret_cast<const uint8_t*>(path), nullptr, nullptr, true); + std::cout << "Loading " << reinterpret_cast<const char*>(uri.buf) + << " (server side)\n"; + engine_interface->copy(URI(reinterpret_cast<const char*>(uri.buf)), + main_uri()); serd_node_free(&uri); } } @@ -216,14 +224,15 @@ main(int argc, char** argv) // Save the currently loaded graph if (conf.option("save").is_valid()) { const char* path = conf.option("save").ptr<char>(); - if (serd_uri_string_has_scheme((const uint8_t*)path)) { - std::cout << "Saving to " << path << std::endl; + if (serd_uri_string_has_scheme(reinterpret_cast<const uint8_t*>(path))) { + std::cout << "Saving to " << path << "\n"; engine_interface->copy(main_uri(), URI(path)); } else { SerdNode uri = serd_node_new_file_uri( - (const uint8_t*)path, nullptr, nullptr, true); - std::cout << "Saving to " << (const char*)uri.buf << std::endl; - engine_interface->copy(main_uri(), URI((const char*)uri.buf)); + reinterpret_cast<const uint8_t*>(path), nullptr, nullptr, true); + std::cout << "Saving to " << reinterpret_cast<const char*>(uri.buf) + << "\n"; + engine_interface->copy(main_uri(), URI(reinterpret_cast<const char*>(uri.buf))); serd_node_free(&uri); } } @@ -243,12 +252,12 @@ main(int argc, char** argv) } else if (world->engine()) { // Run engine main loop until interrupt while (world->engine()->main_iteration()) { - this_thread::sleep_for(chrono::milliseconds(125)); + std::this_thread::sleep_for(std::chrono::milliseconds(125)); } } // Sleep for a half second to allow event queues to drain - this_thread::sleep_for(chrono::milliseconds(500)); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); // Shut down if (world->engine()) { @@ -264,3 +273,15 @@ main(int argc, char** argv) return 0; } + +} // namespace +} // namespace ingen + +int +main(int argc, char** argv) +{ + ingen::set_bundle_path_from_code( + reinterpret_cast<void (*)()>(&ingen::run)); + + return ingen::run(argc, argv); +} diff --git a/src/meson.build b/src/meson.build new file mode 100644 index 00000000..bbd4bb5f --- /dev/null +++ b/src/meson.build @@ -0,0 +1,69 @@ +# Copyright 2022 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: 0BSD OR GPL-3.0-or-later + +sources = files( + 'AtomForge.cpp', + 'AtomReader.cpp', + 'AtomWriter.cpp', + 'ClashAvoider.cpp', + 'ColorContext.cpp', + 'Configuration.cpp', + 'Forge.cpp', + 'LV2Features.cpp', + 'Library.cpp', + 'Log.cpp', + 'Parser.cpp', + 'Resource.cpp', + 'Serialiser.cpp', + 'Store.cpp', + 'StreamWriter.cpp', + 'TurtleWriter.cpp', + 'URI.cpp', + 'URIMap.cpp', + 'URIs.cpp', + 'World.cpp', + 'runtime_paths.cpp', +) + +if have_socket + sources += files('SocketReader.cpp', 'SocketWriter.cpp') +endif + +ingen_deps = [ + boost_dep, + lv2_dep, + raul_dep, + serd_dep, + thread_dep, + + sord_dep, + + lilv_dep, + sratom_dep, +] + +ingen_include_dirs = include_directories('../include', 'include') + +libingen = shared_library( + versioned_name, + sources, + cpp_args: cpp_suppressions + platform_defines, + darwin_versions: [major_version + '.0.0', meson.project_version()], + dependencies: ingen_deps, + gnu_symbol_visibility: 'hidden', + implicit_include_directories: false, + include_directories: ingen_include_dirs, + install: true, + soversion: soversion, + version: meson.project_version(), +) + +ingen_dep = declare_dependency( + dependencies: ingen_deps, + include_directories: include_directories('../include'), + link_with: libingen, +) + +subdir('server') +subdir('client') +subdir('gui') diff --git a/src/runtime_paths.cpp b/src/runtime_paths.cpp index db3ccd3f..17167e9a 100644 --- a/src/runtime_paths.cpp +++ b/src/runtime_paths.cpp @@ -14,15 +14,15 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "ingen/runtime_paths.hpp" +#include <ingen/runtime_paths.hpp> + +#include <ingen/FilePath.hpp> -#include "ingen/FilePath.hpp" -#include "ingen/filesystem.hpp" #include "ingen_config.h" -#include <algorithm> #include <cstdlib> #include <dlfcn.h> +#include <filesystem> #include <sstream> #include <string> @@ -45,7 +45,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; @@ -65,12 +66,12 @@ parse_search_path(const char* search_path, std::vector<FilePath> defaults) * Passing a function defined in a module etc. will not work! */ void -set_bundle_path_from_code(void* function) +set_bundle_path_from_code(void (*function)()) { Dl_info dli; - dladdr(function, &dli); + dladdr(reinterpret_cast<void*>(function), &dli); -#ifdef BUNDLE +#if INGEN_BUNDLED char bin_loc[PATH_MAX]; realpath(dli.dli_fname, bin_loc); #else @@ -92,7 +93,7 @@ find_in_search_path(const std::string& name, { for (const auto& dir : search_path) { FilePath path = dir / name; - if (filesystem::exists(path)) { + if (std::filesystem::exists(path)) { return path; } } @@ -117,7 +118,7 @@ data_file_path(const std::string& name) std::vector<FilePath> ingen_module_dirs() { -#ifdef BUNDLE +#if INGEN_BUNDLED const FilePath default_dir = FilePath(bundle_path) / INGEN_MODULE_DIR; #else const FilePath default_dir = INGEN_MODULE_DIR; @@ -138,22 +139,28 @@ FilePath user_config_dir() { if (const char* xdg_config_home = getenv("XDG_CONFIG_HOME")) { - return FilePath(xdg_config_home); - } else if (const char* home = getenv("HOME")) { + return {xdg_config_home}; + } + + if (const char* home = getenv("HOME")) { return FilePath(home) / ".config"; } - return FilePath(); + + return {}; } FilePath user_data_dir() { if (const char* xdg_data_home = getenv("XDG_DATA_HOME")) { - return FilePath(xdg_data_home); - } else if (const char* home = getenv("HOME")) { + return {xdg_data_home}; + } + + if (const char* home = getenv("HOME")) { return FilePath(home) / ".local/share"; } - return FilePath(); + + return {}; } std::vector<FilePath> @@ -186,7 +193,7 @@ data_dirs() std::vector<FilePath> paths = system_data_dirs(); const FilePath user_dir = user_data_dir(); -#ifdef BUNDLE +#if INGEN_BUNDLED paths.insert(paths.begin(), bundle_path / INGEN_DATA_DIR); #endif diff --git a/src/server/.clang-tidy b/src/server/.clang-tidy new file mode 100644 index 00000000..a580cc7e --- /dev/null +++ b/src/server/.clang-tidy @@ -0,0 +1,21 @@ +Checks: > + -*-avoid-c-arrays, + -*-narrowing-conversions, + -*-non-private-member-variables-in-classes, + -*-vararg, + -bugprone-branch-clone, + -bugprone-parent-virtual-call, + -bugprone-reserved-identifier, + -bugprone-suspicious-string-compare, + -cert-dcl37-c, + -cert-dcl51-cpp, + -cppcoreguidelines-pro-bounds-constant-array-index, + -cppcoreguidelines-pro-type-static-cast-downcast, + -google-readability-todo, + -google-runtime-int, + -google-runtime-references, + -hicpp-multiway-paths-covered, + -llvm-header-guard, + -misc-redundant-expression, + -portability-simd-intrinsics, +InheritParentConfig: true diff --git a/src/server/ArcImpl.cpp b/src/server/ArcImpl.cpp index d9a2b783..2c5b4ee1 100644 --- a/src/server/ArcImpl.cpp +++ b/src/server/ArcImpl.cpp @@ -22,15 +22,14 @@ #include "PortImpl.hpp" #include "PortType.hpp" -#include "ingen/URIs.hpp" -#include "raul/Path.hpp" +#include <ingen/URIs.hpp> +#include <raul/Path.hpp> #include <algorithm> #include <cassert> #include <string> -namespace ingen { -namespace server { +namespace ingen::server { /** Constructor for an arc from a block's output port. * @@ -55,13 +54,13 @@ ArcImpl::~ArcImpl() } } -const Raul::Path& +const raul::Path& ArcImpl::tail_path() const { return _tail->path(); } -const Raul::Path& +const raul::Path& ArcImpl::head_path() const { return _head->path(); @@ -85,33 +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 server -} // namespace ingen +} // namespace ingen::server diff --git a/src/server/ArcImpl.hpp b/src/server/ArcImpl.hpp index 1f42d3a5..5be51187 100644 --- a/src/server/ArcImpl.hpp +++ b/src/server/ArcImpl.hpp @@ -19,16 +19,14 @@ #include "BufferRef.hpp" -#include "ingen/Arc.hpp" -#include "raul/Noncopyable.hpp" -#include "raul/Path.hpp" +#include <ingen/Arc.hpp> +#include <raul/Noncopyable.hpp> #include <boost/intrusive/slist_hook.hpp> #include <cstdint> -namespace ingen { -namespace server { +namespace ingen::server { class InputPort; class PortImpl; @@ -47,19 +45,19 @@ class RunContext; * \ingroup engine */ class ArcImpl - : private Raul::Noncopyable + : private raul::Noncopyable , public Arc , public boost::intrusive::slist_base_hook<> { public: ArcImpl(PortImpl* tail, PortImpl* head); - ~ArcImpl(); + ~ArcImpl() override; - inline PortImpl* tail() const { return _tail; } - inline PortImpl* head() const { return _head; } + PortImpl* tail() const { return _tail; } + PortImpl* head() const { return _head; } - const Raul::Path& tail_path() const override; - const Raul::Path& head_path() const override; + const raul::Path& tail_path() const override; + const raul::Path& head_path() const override; /** Get the buffer for a particular voice. * An Arc is smart - it knows the destination port requesting the @@ -78,7 +76,6 @@ protected: PortImpl* const _head; }; -} // namespace server -} // namespace ingen +} // namespace ingen::server #endif // INGEN_ENGINE_ARC_IMPL_HPP diff --git a/src/server/BlockFactory.cpp b/src/server/BlockFactory.cpp index 9e1693df..a70de0b6 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 @@ -22,30 +22,30 @@ #include "PortType.hpp" #include "ThreadManager.hpp" -#include "ingen/LV2Features.hpp" -#include "ingen/Log.hpp" -#include "ingen/URIs.hpp" -#include "ingen/World.hpp" -#include "internals/BlockDelay.hpp" -#include "internals/Controller.hpp" -#include "internals/Note.hpp" -#include "internals/Time.hpp" -#include "internals/Trigger.hpp" -#include "lilv/lilv.h" +#include <ingen/LV2Features.hpp> +#include <ingen/Log.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIs.hpp> +#include <ingen/World.hpp> +#include <internals/BlockDelay.hpp> +#include <internals/Controller.hpp> +#include <internals/Note.hpp> +#include <internals/Time.hpp> +#include <internals/Trigger.hpp> +#include <lilv/lilv.h> #include <algorithm> #include <cstdint> +#include <iterator> +#include <memory> +#include <string> #include <utility> #include <vector> -namespace ingen { -namespace server { - -using namespace internals; +namespace ingen::server { BlockFactory::BlockFactory(ingen::World& world) : _world(world) - , _has_loaded(false) { load_internal_plugins(); } @@ -61,12 +61,12 @@ BlockFactory::plugins() return _plugins; } -std::set<SPtr<PluginImpl>> +std::set<std::shared_ptr<PluginImpl>> BlockFactory::refresh() { // Record current plugins, and those that are currently zombies - const Plugins old_plugins(_plugins); - std::set<SPtr<PluginImpl>> zombies; + const Plugins old_plugins(_plugins); + std::set<std::shared_ptr<PluginImpl>> zombies; for (const auto& p : _plugins) { if (p.second->is_zombie()) { zombies.insert(p.second); @@ -77,7 +77,7 @@ BlockFactory::refresh() load_lv2_plugins(); // Add any new plugins to response - std::set<SPtr<PluginImpl>> new_plugins; + std::set<std::shared_ptr<PluginImpl>> new_plugins; for (const auto& p : _plugins) { auto o = old_plugins.find(p.first); if (o == old_plugins.end()) { @@ -86,11 +86,10 @@ BlockFactory::refresh() } // Add any resurrected plugins to response - for (const auto& z : zombies) { - if (!z->is_zombie()) { - new_plugins.insert(z); - } - } + std::copy_if(zombies.begin(), + zombies.end(), + std::inserter(new_plugins, new_plugins.end()), + [](const auto& z) { return !z->is_zombie(); }); return new_plugins; } @@ -99,7 +98,7 @@ PluginImpl* BlockFactory::plugin(const URI& uri) { load_plugin(uri); - const Plugins::const_iterator i = _plugins.find(uri); + const auto i = _plugins.find(uri); return ((i != _plugins.end()) ? i->second.get() : nullptr); } @@ -107,20 +106,23 @@ void BlockFactory::load_internal_plugins() { ingen::URIs& uris = _world.uris(); - InternalPlugin* block_delay_plug = BlockDelayNode::internal_plugin(uris); - _plugins.emplace(block_delay_plug->uri(), block_delay_plug); - InternalPlugin* controller_plug = ControllerNode::internal_plugin(uris); - _plugins.emplace(controller_plug->uri(), controller_plug); + InternalPlugin* block_delay = + internals::BlockDelayNode::internal_plugin(uris); + _plugins.emplace(block_delay->uri(), block_delay); - InternalPlugin* note_plug = NoteNode::internal_plugin(uris); - _plugins.emplace(note_plug->uri(), note_plug); + InternalPlugin* controller = + internals::ControllerNode::internal_plugin(uris); + _plugins.emplace(controller->uri(), controller); - InternalPlugin* time_plug = TimeNode::internal_plugin(uris); - _plugins.emplace(time_plug->uri(), time_plug); + InternalPlugin* note = internals::NoteNode::internal_plugin(uris); + _plugins.emplace(note->uri(), note); - InternalPlugin* trigger_plug = TriggerNode::internal_plugin(uris); - _plugins.emplace(trigger_plug->uri(), trigger_plug); + InternalPlugin* time = internals::TimeNode::internal_plugin(uris); + _plugins.emplace(time->uri(), time); + + InternalPlugin* trigger = internals::TriggerNode::internal_plugin(uris); + _plugins.emplace(trigger->uri(), trigger); } void @@ -146,24 +148,25 @@ void BlockFactory::load_lv2_plugins() { // Build an array of port type nodes for checking compatibility - using Types = std::vector<SPtr<LilvNode>>; + 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((PortType::ID)t).uri()); - types.push_back( - SPtr<LilvNode>(lilv_new_uri(_world.lilv_world(), uri.c_str()), - lilv_node_free)); + 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)); } const LilvPlugins* plugins = lilv_world_get_all_plugins(_world.lilv_world()); - LILV_FOREACH(plugins, i, plugins) { + LILV_FOREACH (plugins, i, plugins) { const LilvPlugin* lv2_plug = lilv_plugins_get(plugins, i); const URI uri(lilv_node_as_uri(lilv_plugin_get_uri(lv2_plug))); // Ignore plugins that require features Ingen doesn't support LilvNodes* features = lilv_plugin_get_required_features(lv2_plug); bool supported = true; - LILV_FOREACH(nodes, f, features) { + LILV_FOREACH (nodes, f, features) { const char* feature = lilv_node_as_uri(lilv_nodes_get(features, f)); if (!_world.lv2_features().is_supported(feature)) { supported = false; @@ -187,13 +190,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, @@ -221,5 +224,4 @@ BlockFactory::load_lv2_plugins() _world.log().info("Loaded %1% plugins\n", _plugins.size()); } -} // namespace server -} // namespace ingen +} // namespace ingen::server diff --git a/src/server/BlockFactory.hpp b/src/server/BlockFactory.hpp index 234a20fa..68699d8a 100644 --- a/src/server/BlockFactory.hpp +++ b/src/server/BlockFactory.hpp @@ -17,11 +17,11 @@ #ifndef INGEN_ENGINE_BLOCKFACTORY_HPP #define INGEN_ENGINE_BLOCKFACTORY_HPP -#include "ingen/URI.hpp" -#include "ingen/types.hpp" -#include "raul/Noncopyable.hpp" +#include <ingen/URI.hpp> +#include <raul/Noncopyable.hpp> #include <map> +#include <memory> #include <set> namespace ingen { @@ -36,7 +36,7 @@ class PluginImpl; * * \ingroup engine */ -class BlockFactory : public Raul::Noncopyable +class BlockFactory : public raul::Noncopyable { public: explicit BlockFactory(ingen::World& world); @@ -47,11 +47,11 @@ public: * * @return The set of newly loaded plugins. */ - std::set<SPtr<PluginImpl>> refresh(); + std::set<std::shared_ptr<PluginImpl>> refresh(); void load_plugin(const URI& uri); - using Plugins = std::map<URI, SPtr<PluginImpl>>; + using Plugins = std::map<URI, std::shared_ptr<PluginImpl>>; const Plugins& plugins(); PluginImpl* plugin(const URI& uri); @@ -62,7 +62,7 @@ private: Plugins _plugins; ingen::World& _world; - bool _has_loaded; + bool _has_loaded{false}; }; } // namespace server diff --git a/src/server/BlockImpl.cpp b/src/server/BlockImpl.cpp index ba0bdc77..b4f407c3 100644 --- a/src/server/BlockImpl.cpp +++ b/src/server/BlockImpl.cpp @@ -20,33 +20,31 @@ #include "GraphImpl.hpp" #include "PluginImpl.hpp" #include "PortImpl.hpp" +#include "PortType.hpp" #include "RunContext.hpp" #include "ThreadManager.hpp" -#include "raul/Array.hpp" -#include "raul/Maid.hpp" -#include "raul/Symbol.hpp" +#include <lv2/urid/urid.h> +#include <raul/Array.hpp> +#include <raul/Symbol.hpp> +#include <algorithm> #include <cassert> #include <cstdint> #include <initializer_list> #include <string> -namespace ingen { -namespace server { +namespace ingen::server { BlockImpl::BlockImpl(PluginImpl* plugin, - const Raul::Symbol& symbol, + const raul::Symbol& symbol, bool polyphonic, GraphImpl* parent, SampleRate) : NodeImpl(plugin->uris(), parent, symbol) , _plugin(plugin) , _polyphony((polyphonic && parent) ? parent->internal_poly() : 1) - , _mark(Mark::UNVISITED) , _polyphonic(polyphonic) - , _activated(false) - , _enabled(true) { assert(_plugin); assert(_polyphony > 0); @@ -57,7 +55,7 @@ BlockImpl::~BlockImpl() assert(!_activated); if (is_linked()) { - ((GraphImpl*)_parent)->remove_block(*this); + reinterpret_cast<GraphImpl*>(_parent)->remove_block(*this); } } @@ -120,7 +118,7 @@ BlockImpl::prepare_poly(BufferFactory& bufs, uint32_t poly) } bool -BlockImpl::apply_poly(RunContext& context, uint32_t poly) +BlockImpl::apply_poly(RunContext& ctx, uint32_t poly) { if (!_polyphonic) { poly = 1; @@ -130,7 +128,7 @@ BlockImpl::apply_poly(RunContext& context, uint32_t poly) if (_ports) { for (uint32_t i = 0; i < num_ports(); ++i) { - _ports->at(i)->apply_poly(context, poly); + _ports->at(i)->apply_poly(ctx, poly); } } @@ -138,7 +136,7 @@ BlockImpl::apply_poly(RunContext& context, uint32_t poly) } void -BlockImpl::set_buffer_size(RunContext& context, +BlockImpl::set_buffer_size(RunContext& ctx, BufferFactory& bufs, LV2_URID type, uint32_t size) @@ -147,7 +145,7 @@ BlockImpl::set_buffer_size(RunContext& context, for (uint32_t i = 0; i < _ports->size(); ++i) { PortImpl* const p = _ports->at(i); if (p->buffer_type() == type) { - p->set_buffer_size(context, bufs, size); + p->set_buffer_size(ctx, bufs, size); } } } @@ -180,18 +178,18 @@ BlockImpl::port_by_symbol(const char* symbol) } void -BlockImpl::pre_process(RunContext& context) +BlockImpl::pre_process(RunContext& ctx) { // Mix down input ports for (uint32_t i = 0; i < num_ports(); ++i) { PortImpl* const port = _ports->at(i); - port->pre_process(context); + port->pre_process(ctx); port->connect_buffers(); } } void -BlockImpl::bypass(RunContext& context) +BlockImpl::bypass(RunContext& ctx) { if (!_ports) { return; @@ -200,20 +198,22 @@ BlockImpl::bypass(RunContext& context) // Prepare port buffers for reading, converting/mixing if necessary for (uint32_t i = 0; i < _ports->size(); ++i) { _ports->at(i)->connect_buffers(); - _ports->at(i)->pre_run(context); + _ports->at(i)->pre_run(ctx); } // Dumb bypass - for (PortType t : { PortType::AUDIO, PortType::CV, PortType::ATOM }) { + 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 - } else if (in) { + break; // Finished writing all outputs + } + + if (in) { // Copy corresponding input to output for (uint32_t v = 0; v < _polyphony; ++v) { - out->buffer(v)->copy(context, in->buffer(v).get()); + out->buffer(v)->copy(ctx, in->buffer(v).get()); } } else { // Output but no corresponding input, clear @@ -223,32 +223,30 @@ BlockImpl::bypass(RunContext& context) } } } - post_process(context); + post_process(ctx); } void -BlockImpl::process(RunContext& context) +BlockImpl::process(RunContext& ctx) { - pre_process(context); + pre_process(ctx); if (!_enabled) { - bypass(context); - post_process(context); + bypass(ctx); + post_process(ctx); return; } - RunContext subcontext(context); - for (SampleCount offset = 0; offset < context.nframes();) { + RunContext subcontext(ctx); + for (SampleCount offset = 0; offset < ctx.nframes();) { // Find earliest offset of a value change - SampleCount chunk_end = context.nframes(); + 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, context.nframes()); - if (o < chunk_end) { - chunk_end = o; - } + offset, ctx.nframes()); + chunk_end = std::min(o, chunk_end); } } @@ -266,7 +264,7 @@ BlockImpl::process(RunContext& context) // 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) { @@ -279,15 +277,15 @@ BlockImpl::process(RunContext& context) subcontext.slice(offset, chunk_end - offset); } - post_process(context); + post_process(ctx); } void -BlockImpl::post_process(RunContext& context) +BlockImpl::post_process(RunContext& ctx) { // Write output ports for (uint32_t i = 0; _ports && i < _ports->size(); ++i) { - _ports->at(i)->post_process(context); + _ports->at(i)->post_process(ctx); } } @@ -298,5 +296,4 @@ BlockImpl::set_port_buffer(uint32_t, uint32_t, const BufferRef&, SampleCount) << " buffer " << buf << " offset " << offset << std::endl;*/ } -} // namespace server -} // namespace ingen +} // namespace ingen::server diff --git a/src/server/BlockImpl.hpp b/src/server/BlockImpl.hpp index 15a4e075..69564ff4 100644 --- a/src/server/BlockImpl.hpp +++ b/src/server/BlockImpl.hpp @@ -19,28 +19,32 @@ #include "BufferRef.hpp" #include "NodeImpl.hpp" -#include "PortType.hpp" +#include "State.hpp" #include "types.hpp" -#include "ingen/Node.hpp" -#include "ingen/Properties.hpp" -#include "ingen/Resource.hpp" -#include "ingen/URI.hpp" -#include "lilv/lilv.h" -#include "lv2/urid/urid.h" -#include "raul/Array.hpp" +#include <ingen/Properties.hpp> +#include <ingen/Resource.hpp> +#include <ingen/URI.hpp> +#include <lilv/lilv.h> +#include <lv2/urid/urid.h> +#include <raul/Array.hpp> +#include <raul/Maid.hpp> #include <boost/intrusive/slist_hook.hpp> -#include <boost/optional/optional.hpp> #include <cstdint> +#include <memory> +#include <optional> #include <set> -namespace Raul { +namespace raul { class Symbol; -} +} // namespace raul namespace ingen { + +enum class PortType; + namespace server { class BufferFactory; @@ -59,18 +63,18 @@ class Worker; * \ingroup engine */ class BlockImpl : public NodeImpl - , public boost::intrusive::slist_base_hook<> // In GraphImpl + , public boost::intrusive::slist_base_hook<> // In GraphImpl { public: - using Ports = Raul::Array<PortImpl*>; + using Ports = raul::Array<PortImpl*>; BlockImpl(PluginImpl* plugin, - const Raul::Symbol& symbol, + const raul::Symbol& symbol, bool polyphonic, GraphImpl* parent, SampleRate rate); - virtual ~BlockImpl(); + ~BlockImpl() override; GraphType graph_type() const override { return GraphType::BLOCK; } @@ -91,7 +95,7 @@ public: /** Duplicate this Node. */ virtual BlockImpl* duplicate(Engine& engine, - const Raul::Symbol& symbol, + const raul::Symbol& symbol, GraphImpl* parent) { return nullptr; } /** Return true iff this block is activated */ @@ -104,33 +108,37 @@ public: void set_enabled(bool e) { _enabled = e; } /** Load a preset from the world for this block. */ - virtual LilvState* load_preset(const URI& uri) { return nullptr; } + virtual StatePtr load_preset(const URI& uri) { return {}; } /** Restore `state`. */ - virtual void apply_state(const UPtr<Worker>& worker, const LilvState* state) {} + virtual void + apply_state(const std::unique_ptr<Worker>& worker, const LilvState* state) + {} /** Save current state as preset. */ - virtual boost::optional<Resource> - save_preset(const URI& bundle, - const Properties& props) { return boost::optional<Resource>(); } + virtual std::optional<Resource> + save_preset(const URI& bundle, const Properties& props) + { + return std::nullopt; + } /** Learn the next incoming MIDI event (for internals) */ virtual void learn() {} - /** Do whatever needs doing in the process thread before process() is called */ - virtual void pre_process(RunContext& context); + /** 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()). */ - virtual void process(RunContext& context); + virtual void process(RunContext& ctx); /** Bypass block for an entire process cycle (called from process()). */ - virtual void bypass(RunContext& context); + virtual void bypass(RunContext& ctx); /** Run block for a portion of process cycle (called from process()). */ - virtual void run(RunContext& context) = 0; + virtual void run(RunContext& ctx) = 0; /** Do whatever needs doing in the process thread after process() is called */ - virtual void post_process(RunContext& context); + virtual void post_process(RunContext& ctx); /** Set the buffer of a port to a given buffer (e.g. connect plugin to buffer) */ virtual void set_port_buffer(uint32_t voice, @@ -145,10 +153,12 @@ public: virtual PortImpl* port_by_symbol(const char* symbol); /** Blocks that are connected to this Block's inputs. */ - std::set<BlockImpl*>& providers() { return _providers; } + std::set<BlockImpl*>& providers() { return _providers; } + const std::set<BlockImpl*>& providers() const { return _providers; } /** Blocks that are connected to this Block's outputs. */ - std::set<BlockImpl*>& dependants() { return _dependants; } + std::set<BlockImpl*>& dependants() { return _dependants; } + const std::set<BlockImpl*>& dependants() const { return _dependants; } /** Flag block as polyphonic. * @@ -159,7 +169,7 @@ public: virtual void set_polyphonic(bool p) { _polyphonic = p; } bool prepare_poly(BufferFactory& bufs, uint32_t poly) override; - bool apply_poly(RunContext& context, uint32_t poly) override; + bool apply_poly(RunContext& ctx, uint32_t poly) override; /** Information about the Plugin this Block is an instance of. * Not the best name - not all blocks come from plugins (ie Graph) @@ -173,13 +183,16 @@ public: virtual void plugin(PluginImpl* pi) { _plugin = pi; } - virtual void set_buffer_size(RunContext& context, + virtual void set_buffer_size(RunContext& ctx, BufferFactory& bufs, LV2_URID type, uint32_t size); /** The Graph this Block belongs to. */ - GraphImpl* parent_graph() const override { return (GraphImpl*)_parent; } + GraphImpl* parent_graph() const override + { + return reinterpret_cast<GraphImpl*>(_parent); + } uint32_t num_ports() const override { return _ports ? _ports->size() : 0; } @@ -193,15 +206,15 @@ public: protected: PortImpl* nth_port_by_type(uint32_t n, bool input, PortType type); - PluginImpl* _plugin; - MPtr<Ports> _ports; ///< Access in audio thread only - uint32_t _polyphony; - std::set<BlockImpl*> _providers; ///< Blocks connected to this one's input ports - std::set<BlockImpl*> _dependants; ///< Blocks this one's output ports are connected to - Mark _mark; ///< Mark for graph compilation algorithm - bool _polyphonic; - bool _activated; - bool _enabled; + PluginImpl* _plugin; + raul::managed_ptr<Ports> _ports; ///< Access in audio thread only + uint32_t _polyphony; + std::set<BlockImpl*> _providers; ///< Blocks connected to this one's input ports + std::set<BlockImpl*> _dependants; ///< Blocks this one's output ports are connected to + Mark _mark{Mark::UNVISITED}; ///< Mark for graph walks + bool _polyphonic; + bool _activated{false}; + bool _enabled{true}; }; } // namespace server diff --git a/src/server/Broadcaster.cpp b/src/server/Broadcaster.cpp index 914b891b..76b21fc6 100644 --- a/src/server/Broadcaster.cpp +++ b/src/server/Broadcaster.cpp @@ -19,22 +19,17 @@ #include "BlockFactory.hpp" #include "PluginImpl.hpp" -#include "ingen/Interface.hpp" +#include <ingen/Interface.hpp> #include <cstddef> +#include <memory> #include <utility> -namespace ingen { -namespace server { - -Broadcaster::Broadcaster() - : _must_broadcast(false) - , _bundle_depth(0) -{} +namespace ingen::server { Broadcaster::~Broadcaster() { - std::lock_guard<std::mutex> lock(_clients_mutex); + const std::lock_guard<std::mutex> lock{_clients_mutex}; _clients.clear(); _broadcastees.clear(); } @@ -42,9 +37,9 @@ Broadcaster::~Broadcaster() /** Register a client to receive messages over the notification band. */ void -Broadcaster::register_client(const SPtr<Interface>& client) +Broadcaster::register_client(const std::shared_ptr<Interface>& client) { - std::lock_guard<std::mutex> lock(_clients_mutex); + const std::lock_guard<std::mutex> lock{_clients_mutex}; _clients.insert(client); } @@ -53,16 +48,17 @@ Broadcaster::register_client(const SPtr<Interface>& client) * @return true if client was found and removed. */ bool -Broadcaster::unregister_client(const SPtr<Interface>& client) +Broadcaster::unregister_client(const std::shared_ptr<Interface>& client) { - std::lock_guard<std::mutex> lock(_clients_mutex); + const std::lock_guard<std::mutex> lock{_clients_mutex}; const size_t erased = _clients.erase(client); _broadcastees.erase(client); return (erased > 0); } void -Broadcaster::set_broadcast(const SPtr<Interface>& client, bool broadcast) +Broadcaster::set_broadcast(const std::shared_ptr<Interface>& client, + bool broadcast) { if (broadcast) { _broadcastees.insert(client); @@ -75,7 +71,7 @@ Broadcaster::set_broadcast(const SPtr<Interface>& client, bool broadcast) void Broadcaster::send_plugins(const BlockFactory::Plugins& plugins) { - std::lock_guard<std::mutex> lock(_clients_mutex); + const std::lock_guard<std::mutex> lock{_clients_mutex}; for (const auto& c : _clients) { send_plugins_to(c.get(), plugins); } @@ -95,5 +91,4 @@ Broadcaster::send_plugins_to(Interface* client, client->bundle_end(); } -} // namespace server -} // namespace ingen +} // namespace ingen::server diff --git a/src/server/Broadcaster.hpp b/src/server/Broadcaster.hpp index d8857356..4cdf65ca 100644 --- a/src/server/Broadcaster.hpp +++ b/src/server/Broadcaster.hpp @@ -19,18 +19,17 @@ #include "BlockFactory.hpp" -#include "ingen/Interface.hpp" -#include "ingen/Message.hpp" -#include "ingen/URI.hpp" -#include "ingen/types.hpp" -#include "raul/Noncopyable.hpp" +#include <ingen/Interface.hpp> +#include <ingen/Message.hpp> +#include <ingen/URI.hpp> +#include <raul/Noncopyable.hpp> #include <atomic> +#include <memory> #include <mutex> #include <set> -namespace ingen { -namespace server { +namespace ingen::server { /** Broadcaster for all clients. * @@ -42,20 +41,21 @@ namespace server { class Broadcaster : public Interface { public: - Broadcaster(); - ~Broadcaster(); + Broadcaster() = default; + ~Broadcaster() override; - void register_client(const SPtr<Interface>& client); - bool unregister_client(const SPtr<Interface>& client); + void register_client(const std::shared_ptr<Interface>& client); + bool unregister_client(const std::shared_ptr<Interface>& client); - void set_broadcast(const SPtr<Interface>& client, bool broadcast); + void + set_broadcast(const std::shared_ptr<Interface>& client, bool broadcast); /** Ignore a client when broadcasting. * * This is used to prevent feeding back updates to the client that * initiated a property set in the first place. */ - void set_ignore_client(const SPtr<Interface>& client) + void set_ignore_client(const std::shared_ptr<Interface>& client) { _ignore_client = client; } @@ -75,7 +75,8 @@ public: * This makes doing the right thing in recursive functions that send * updates simple (e.g. Event::post_process()). */ - class Transfer : public Raul::Noncopyable { + class Transfer : public raul::Noncopyable + { public: explicit Transfer(Broadcaster& b) : broadcaster(b) { if (++broadcaster._bundle_depth == 1) { @@ -96,7 +97,7 @@ public: send_plugins_to(Interface*, const BlockFactory::Plugins& plugins); void message(const Message& msg) override { - std::lock_guard<std::mutex> lock(_clients_mutex); + const std::lock_guard<std::mutex> lock{_clients_mutex}; for (const auto& c : _clients) { if (c != _ignore_client) { c->message(msg); @@ -109,17 +110,16 @@ public: private: friend class Transfer; - using Clients = std::set<SPtr<Interface>>; + using Clients = std::set<std::shared_ptr<Interface>>; - std::mutex _clients_mutex; - Clients _clients; - std::set< SPtr<Interface> > _broadcastees; - std::atomic<bool> _must_broadcast; - unsigned _bundle_depth; - SPtr<Interface> _ignore_client; + std::mutex _clients_mutex; + Clients _clients; + std::set<std::shared_ptr<Interface>> _broadcastees; + std::atomic<bool> _must_broadcast{false}; + unsigned _bundle_depth{0}; + std::shared_ptr<Interface> _ignore_client; }; -} // namespace server -} // namespace ingen +} // namespace ingen::server #endif // INGEN_ENGINE_BROADCASTER_HPP diff --git a/src/server/Buffer.cpp b/src/server/Buffer.cpp index fffc86b0..0c4c0951 100644 --- a/src/server/Buffer.cpp +++ b/src/server/Buffer.cpp @@ -14,24 +14,23 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#define __STDC_LIMIT_MACROS 1 - #include "Buffer.hpp" #include "BufferFactory.hpp" #include "Engine.hpp" +#include "PortType.hpp" #include "RunContext.hpp" - -#include "ingen/Atom.hpp" -#include "ingen/Log.hpp" -#include "ingen/URIs.hpp" #include "ingen_config.h" -#include "lv2/atom/atom.h" -#include "lv2/atom/util.h" + +#include <ingen/Atom.hpp> +#include <ingen/Log.hpp> +#include <ingen/URIs.hpp> +#include <lv2/atom/atom.h> +#include <lv2/atom/util.h> +#include <lv2/urid/urid.h> #include <algorithm> #include <cstdint> -#include <cstdio> #include <cstdlib> #include <cstring> #include <new> @@ -40,8 +39,7 @@ # include <xmmintrin.h> #endif -namespace ingen { -namespace server { +namespace ingen::server { Buffer::Buffer(BufferFactory& bufs, LV2_URID type, @@ -50,13 +48,10 @@ Buffer::Buffer(BufferFactory& bufs, bool external, void*) : _factory(bufs) - , _next(nullptr) , _buf(external ? nullptr : aligned_alloc(capacity)) - , _latest_event(0) , _type(type) , _value_type(value_type) , _capacity(capacity) - , _refs(0) , _external(external) { if (!external && !_buf) { @@ -102,12 +97,12 @@ Buffer::recycle() } void -Buffer::set_type(GetFn get, LV2_URID type, LV2_URID value_type) +Buffer::set_type(GetFn get_func, LV2_URID type, LV2_URID value_type) { _type = type; _value_type = value_type; if (type == _factory.uris().atom_Sequence && value_type) { - _value_buffer = (_factory.*get)(value_type, 0, 0); + _value_buffer = (_factory.*get_func)(value_type, 0, 0); } } @@ -129,30 +124,32 @@ Buffer::clear() } void -Buffer::render_sequence(const RunContext& context, const Buffer* src, bool add) +Buffer::render_sequence(const RunContext& ctx, const Buffer* src, bool add) { const LV2_URID atom_Float = _factory.uris().atom_Float; const auto* seq = src->get<const LV2_Atom_Sequence>(); - const auto* init = (const LV2_Atom_Float*)src->value(); + const auto* init = reinterpret_cast<const LV2_Atom_Float*>(src->value()); float value = init ? init->body : 0.0f; - SampleCount offset = context.offset(); + SampleCount offset = ctx.offset(); - LV2_ATOM_SEQUENCE_FOREACH(seq, ev) { + LV2_ATOM_SEQUENCE_FOREACH (seq, ev) { if (ev->time.frames >= offset && ev->body.type == atom_Float) { write_block(value, offset, ev->time.frames, add); - value = ((const LV2_Atom_Float*)&ev->body)->body; + value = reinterpret_cast<const LV2_Atom_Float*>(&ev->body)->body; offset = ev->time.frames; } } - write_block(value, offset, context.offset() + context.nframes(), add); + write_block(value, offset, ctx.offset() + ctx.nframes(), add); } void -Buffer::copy(const RunContext& context, const Buffer* src) +Buffer::copy(const RunContext& ctx, const Buffer* src) { if (!_buf) { return; - } else if (_type == src->type()) { + } + + if (_type == src->type()) { const uint32_t src_size = src->size(); if (src_size <= _capacity) { memcpy(_buf, src->_buf, src_size); @@ -162,10 +159,10 @@ Buffer::copy(const RunContext& context, const Buffer* src) } else if (src->is_audio() && is_control()) { samples()[0] = src->samples()[0]; } else if (src->is_control() && is_audio()) { - set_block(src->samples()[0], 0, context.nframes()); + set_block(src->samples()[0], 0, ctx.nframes()); } else if (src->is_sequence() && is_audio() && src->value_type() == _factory.uris().atom_Float) { - render_sequence(context, src, false); + render_sequence(ctx, src, false); } else { clear(); } @@ -175,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 { @@ -186,22 +188,24 @@ 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 (Sample*)_buf + offset; + return static_cast<Sample*>(_buf) + offset; } break; - case PortType::ID::ATOM: + case PortType::ATOM: if (_type != _factory.uris().atom_Sound) { return _buf; } - default: break; + break; + default: + break; } return nullptr; } @@ -209,8 +213,7 @@ Buffer::port_data(PortType port_type, SampleCount offset) const void* Buffer::port_data(PortType port_type, SampleCount offset) const { - return const_cast<void*>( - const_cast<Buffer*>(this)->port_data(port_type, offset)); + return const_cast<Buffer*>(this)->port_data(port_type, offset); } #ifdef __SSE__ @@ -218,18 +221,18 @@ Buffer::port_data(PortType port_type, SampleCount offset) const static inline __m128 mm_abs_ps(__m128 x) { - const __m128 sign_mask = _mm_set1_ps(-0.0f); // -0.0f = 1 << 31 + const __m128 sign_mask = _mm_set1_ps(-0.0f); // -0.0f = 1 << 31 return _mm_andnot_ps(sign_mask, x); } #endif float -Buffer::peak(const RunContext& context) const +Buffer::peak(const RunContext& ctx) const { #ifdef __SSE__ - const auto* const vbuf = (const __m128*)samples(); + const auto* const vbuf = reinterpret_cast<const __m128*>(samples()); __m128 vpeak = mm_abs_ps(vbuf[0]); - const SampleCount nblocks = context.nframes() / 4; + const SampleCount nblocks = ctx.nframes() / 4; // First, find the vector absolute max of the buffer for (SampleCount i = 1; i < nblocks; ++i) { @@ -252,14 +255,14 @@ Buffer::peak(const RunContext& context) const vpeak = _mm_max_ps(vpeak, tmp); // peak = vpeak[0] - float peak; + float peak = 0.0f; _mm_store_ss(&peak, vpeak); return peak; #else const Sample* const buf = samples(); float peak = 0.0f; - for (SampleCount i = 0; i < context.nframes(); ++i) { + for (SampleCount i = 0; i < ctx.nframes(); ++i) { peak = fmaxf(peak, fabsf(buf[i])); } return peak; @@ -272,7 +275,7 @@ Buffer::prepare_write(RunContext&) if (_type == _factory.uris().atom_Sequence) { auto* atom = get<LV2_Atom>(); - atom->type = (LV2_URID)_factory.uris().atom_Sequence; + atom->type = static_cast<LV2_URID>(_factory.uris().atom_Sequence); atom->size = sizeof(LV2_Atom_Sequence_Body); _latest_event = 0; } @@ -284,7 +287,7 @@ Buffer::prepare_output_write(RunContext&) if (_type == _factory.uris().atom_Sequence) { auto* atom = get<LV2_Atom>(); - atom->type = (LV2_URID)_factory.uris().atom_Chunk; + atom->type = static_cast<LV2_URID>(_factory.uris().atom_Chunk); atom->size = _capacity - sizeof(LV2_Atom); _latest_event = 0; } @@ -300,16 +303,16 @@ Buffer::append_event(int64_t frames, auto* atom = get<LV2_Atom>(); if (atom->type == _factory.uris().atom_Chunk) { - clear(); // Chunk initialized with prepare_output_write(), clear + clear(); // Chunk initialized with prepare_output_write(), clear } if (sizeof(LV2_Atom) + atom->size + lv2_atom_pad_size(size) > _capacity) { return false; } - auto* seq = (LV2_Atom_Sequence*)atom; - auto* ev = (LV2_Atom_Event*)( - (uint8_t*)seq + lv2_atom_total_size(&seq->atom)); + auto* seq = reinterpret_cast<LV2_Atom_Sequence*>(atom); + auto* ev = reinterpret_cast<LV2_Atom_Event*>( + reinterpret_cast<uint8_t*>(seq) + lv2_atom_total_size(&seq->atom)); ev->time.frames = frames; ev->body.size = size; @@ -326,23 +329,28 @@ Buffer::append_event(int64_t frames, bool Buffer::append_event(int64_t frames, const LV2_Atom* body) { - return append_event(frames, body->size, body->type, (const uint8_t*)(body + 1)); + return append_event(frames, + body->size, + body->type, + reinterpret_cast<const uint8_t*>(body + 1)); } bool Buffer::append_event_buffer(const Buffer* buf) { - auto* seq = (LV2_Atom_Sequence*)get<LV2_Atom>(); - auto* bseq = (LV2_Atom_Sequence*)buf->get<LV2_Atom>(); + auto* seq = reinterpret_cast<LV2_Atom_Sequence*>(get<LV2_Atom>()); + const auto* bseq = + reinterpret_cast<const LV2_Atom_Sequence*>(buf->get<LV2_Atom>()); + if (seq->atom.type == _factory.uris().atom_Chunk) { - clear(); // Chunk initialized with prepare_output_write(), clear + clear(); // Chunk initialized with prepare_output_write(), clear } const uint32_t total_size = lv2_atom_total_size(&seq->atom); - uint8_t* const end = (uint8_t*)seq + total_size; + uint8_t* const end = reinterpret_cast<uint8_t*>(seq) + total_size; const uint32_t n_bytes = bseq->atom.size - sizeof(bseq->body); if (sizeof(LV2_Atom) + total_size + n_bytes >= _capacity) { - return false; // Not enough space + return false; // Not enough space } memcpy(end, bseq + 1, n_bytes); @@ -358,7 +366,7 @@ Buffer::next_value_offset(SampleCount offset, SampleCount end) const { if (_type == _factory.uris().atom_Sequence && _value_type) { const auto* seq = get<const LV2_Atom_Sequence>(); - LV2_ATOM_SEQUENCE_FOREACH(seq, ev) { + LV2_ATOM_SEQUENCE_FOREACH (seq, ev) { if (ev->time.frames > offset && ev->time.frames < end && ev->body.type == _value_type) { @@ -411,10 +419,12 @@ Buffer::update_value_buffer(SampleCount offset) auto* seq = get<LV2_Atom_Sequence>(); LV2_Atom_Event* latest = nullptr; - LV2_ATOM_SEQUENCE_FOREACH(seq, ev) { + LV2_ATOM_SEQUENCE_FOREACH (seq, ev) { if (ev->time.frames > offset) { break; - } else if (ev->body.type == _value_type) { + } + + if (ev->body.type == _value_type) { latest = ev; } } @@ -426,27 +436,11 @@ Buffer::update_value_buffer(SampleCount offset) } } -#ifndef NDEBUG -void -Buffer::dump_cv(const RunContext& context) const -{ - float value = samples()[0]; - fprintf(stderr, "{ 0000: %.02f\n", value); - for (uint32_t i = 0; i < context.nframes(); ++i) { - if (samples()[i] != value) { - value = samples()[i]; - fprintf(stderr, " %4d: %.02f\n", i, value); - } - } - fprintf(stderr, "}\n"); -} -#endif - void* Buffer::aligned_alloc(size_t size) { -#ifdef HAVE_POSIX_MEMALIGN - void* buf; - if (!posix_memalign((void**)&buf, 16, size)) { +#if USE_POSIX_MEMALIGN + void* buf = nullptr; + if (!posix_memalign(&buf, 16, size)) { memset(buf, 0, size); return buf; } @@ -468,5 +462,4 @@ intrusive_ptr_release(Buffer* b) b->deref(); } -} // namespace server -} // namespace ingen +} // namespace ingen::server diff --git a/src/server/Buffer.hpp b/src/server/Buffer.hpp index c67f9fd7..2c32076b 100644 --- a/src/server/Buffer.hpp +++ b/src/server/Buffer.hpp @@ -19,14 +19,12 @@ #include "BufferFactory.hpp" #include "BufferRef.hpp" -#include "PortType.hpp" +#include "server.h" #include "types.hpp" -#include "ingen/URIs.hpp" -#include "ingen/ingen.h" -#include "ingen/types.hpp" -#include "lv2/atom/atom.h" -#include "lv2/urid/urid.h" +#include <ingen/URIs.hpp> +#include <lv2/atom/atom.h> +#include <lv2/urid/urid.h> #include <atomic> #include <cassert> @@ -35,13 +33,15 @@ namespace ingen { +enum class PortType; + class Atom; namespace server { class RunContext; -class INGEN_API Buffer +class INGEN_SERVER_API Buffer { public: Buffer(BufferFactory& bufs, @@ -56,74 +56,83 @@ public: void clear(); void resize(uint32_t capacity); - void copy(const RunContext& context, const Buffer* src); - void prepare_write(RunContext& context); + void copy(const RunContext& ctx, const Buffer* src); + void prepare_write(RunContext& ctx); void* port_data(PortType port_type, SampleCount offset); const void* port_data(PortType port_type, SampleCount offset) const; - inline LV2_URID type() const { return _type; } - inline LV2_URID value_type() const { return _value_type; } - inline uint32_t capacity() const { return _capacity; } - inline uint32_t size() const { + LV2_URID type() const { return _type; } + LV2_URID value_type() const { return _value_type; } + uint32_t capacity() const { return _capacity; } + uint32_t size() const { return is_audio() ? _capacity : sizeof(LV2_Atom) + get<LV2_Atom>()->size; } - typedef BufferRef (BufferFactory::*GetFn)(LV2_URID, LV2_URID, uint32_t); + using GetFn = BufferRef (BufferFactory::*)(LV2_URID, LV2_URID, uint32_t); /** Set the buffer type and optional value type for this buffer. * - * @param get Called to get auxiliary buffers if necessary. + * @param get_func Called to get auxiliary buffers if necessary. * @param type Type of buffer. * @param value_type Type of values in buffer if applicable (for sequences). */ - void set_type(GetFn get, LV2_URID type, LV2_URID value_type); + void set_type(GetFn get_func, LV2_URID type, LV2_URID value_type); - inline bool is_audio() const { + bool is_audio() const { return _type == _factory.uris().atom_Sound; } - inline bool is_control() const { + bool is_control() const { return _type == _factory.uris().atom_Float; } - inline bool is_sequence() const { + bool is_sequence() const { return _type == _factory.uris().atom_Sequence; } /// Audio or float buffers only - inline const Sample* samples() const { + const Sample* samples() const { if (is_control()) { - return (const Sample*)LV2_ATOM_BODY_CONST(get<LV2_Atom_Float>()); - } else if (is_audio()) { - return (const Sample*)_buf; + return static_cast<const Sample*>( + LV2_ATOM_BODY_CONST(get<LV2_Atom_Float>())); + } + + if (is_audio()) { + return static_cast<const Sample*>(_buf); } + return nullptr; } /// Audio buffers only - inline Sample* samples() { + Sample* samples() { if (is_control()) { - return (Sample*)LV2_ATOM_BODY(get<LV2_Atom_Float>()); - } else if (is_audio()) { - return (Sample*)_buf; + return static_cast<Sample*>(LV2_ATOM_BODY(get<LV2_Atom_Float>())); } + + if (is_audio()) { + return static_cast<Sample*>(_buf); + } + return nullptr; } /// Numeric buffers only - inline Sample value_at(SampleCount offset) const { + Sample value_at(SampleCount offset) const { if (is_audio() || is_control()) { return samples()[offset]; - } else if (_value_buffer) { - return ((LV2_Atom_Float*)value())->body; } + + if (_value_buffer) { + return reinterpret_cast<const LV2_Atom_Float*>(value())->body; + } + return 0.0f; } - inline void set_block(const Sample val, - const SampleCount start, - const SampleCount end) + void + set_block(const Sample val, const SampleCount start, const SampleCount end) { if (is_sequence()) { append_event(start, sizeof(val), _factory.uris().atom_Float, @@ -142,9 +151,8 @@ public: } } - inline void add_block(const Sample val, - const SampleCount start, - const SampleCount end) + void + add_block(const Sample val, const SampleCount start, const SampleCount end) { assert(is_audio() || is_control()); assert(end <= _capacity / sizeof(Sample)); @@ -155,10 +163,10 @@ public: } } - inline void write_block(const Sample val, - const SampleCount start, - const SampleCount end, - const bool add) + void write_block(const Sample val, + const SampleCount start, + const SampleCount end, + const bool add) { if (add) { add_block(val, start, end); @@ -168,10 +176,10 @@ public: } /// Audio buffers only - float peak(const RunContext& context) const; + float peak(const RunContext& ctx) const; /// Sequence buffers only - void prepare_output_write(RunContext& context); + void prepare_output_write(RunContext& ctx); /// Sequence buffers only bool append_event(int64_t frames, @@ -201,11 +209,7 @@ public: void update_value_buffer(SampleCount offset); /// Set/add to audio buffer from the Sequence of Float in `src` - void render_sequence(const RunContext& context, const Buffer* src, bool add); - -#ifndef NDEBUG - void dump_cv(const RunContext& context) const; -#endif + void render_sequence(const RunContext& ctx, const Buffer* src, bool add); void set_capacity(uint32_t capacity) { _capacity = capacity; } @@ -216,9 +220,9 @@ public: template<typename T> const T* get() const { return reinterpret_cast<const T*>(_buf); } template<typename T> T* get() { return reinterpret_cast<T*>(_buf); } - inline void ref() { ++_refs; } + void ref() { ++_refs; } - inline void deref() { + void deref() { if ((--_refs) == 0) { recycle(); } @@ -230,15 +234,18 @@ private: void recycle(); - BufferFactory& _factory; - Buffer* _next; ///< Intrusive linked list for BufferFactory + BufferFactory& _factory; + + // NOLINTNEXTLINE(clang-analyzer-webkit.NoUncountedMemberChecker) + Buffer* _next{nullptr}; ///< Intrusive linked list for BufferFactory + void* _buf; ///< Actual buffer memory BufferRef _value_buffer; ///< Value buffer for numeric sequences - int64_t _latest_event; + int64_t _latest_event{0}; LV2_URID _type; LV2_URID _value_type; uint32_t _capacity; - std::atomic<unsigned> _refs; ///< Intrusive reference count + std::atomic<unsigned> _refs{0}; ///< Intrusive reference count bool _external; ///< Buffer is externally allocated }; diff --git a/src/server/BufferFactory.cpp b/src/server/BufferFactory.cpp index 23b44884..b8f6ee35 100644 --- a/src/server/BufferFactory.cpp +++ b/src/server/BufferFactory.cpp @@ -19,16 +19,16 @@ #include "Buffer.hpp" #include "Engine.hpp" -#include "ingen/Log.hpp" -#include "ingen/URIs.hpp" -#include "ingen/World.hpp" -#include "lv2/atom/atom.h" -#include "lv2/urid/urid.h" +#include <ingen/Log.hpp> +#include <ingen/URIs.hpp> +#include <ingen/World.hpp> +#include <lv2/atom/atom.h> +#include <lv2/urid/urid.h> #include <algorithm> +#include <memory> -namespace ingen { -namespace server { +namespace ingen::server { BufferFactory::BufferFactory(Engine& engine, URIs& uris) : _free_audio(nullptr) @@ -37,18 +37,20 @@ BufferFactory::BufferFactory(Engine& engine, URIs& uris) , _free_object(nullptr) , _engine(engine) , _uris(uris) - , _seq_size(0) , _silent_buffer(nullptr) -{ -} +{} BufferFactory::~BufferFactory() { _silent_buffer.reset(); - free_list(_free_audio.load()); - free_list(_free_control.load()); - free_list(_free_sequence.load()); - free_list(_free_object.load()); + + // Run twice to delete value buffer references which are dropped + for (unsigned i = 0; i < 2; ++i) { + free_list(_free_audio.exchange(nullptr)); + free_list(_free_control.exchange(nullptr)); + free_list(_free_sequence.exchange(nullptr)); + free_list(_free_object.exchange(nullptr)); + } } Forge& @@ -57,7 +59,7 @@ BufferFactory::forge() return _engine.world().forge(); } -Raul::Maid& +raul::Maid& BufferFactory::maid() { return *_engine.maid(); @@ -96,19 +98,25 @@ BufferFactory::default_size(LV2_URID type) const { if (type == _uris.atom_Float) { return sizeof(LV2_Atom_Float); - } else if (type == _uris.atom_Sound) { + } + + if (type == _uris.atom_Sound) { return audio_buffer_size(_engine.block_length()); - } else if (type == _uris.atom_URID) { + } + + if (type == _uris.atom_URID) { return sizeof(LV2_Atom_URID); - } else if (type == _uris.atom_Sequence) { - if (_seq_size == 0) { + } + + if (type == _uris.atom_Sequence) { + if (_seq_size == 0U) { return _engine.sequence_size(); - } else { - return _seq_size; } - } else { - return 0; + + return _seq_size; } + + return 0; } Buffer* @@ -116,7 +124,7 @@ BufferFactory::try_get_buffer(LV2_URID type) { std::atomic<Buffer*>& head_ptr = free_list(type); Buffer* head = nullptr; - Buffer* next; + Buffer* next = nullptr; do { head = head_ptr.load(); if (!head) { @@ -141,7 +149,7 @@ BufferFactory::get_buffer(LV2_URID type, try_head->_next = nullptr; try_head->set_type(&BufferFactory::get_buffer, type, value_type); try_head->clear(); - return BufferRef(try_head); + return {try_head}; } BufferRef @@ -150,12 +158,12 @@ BufferFactory::claim_buffer(LV2_URID type, LV2_URID value_type, uint32_t) Buffer* try_head = try_get_buffer(type); if (!try_head) { _engine.world().log().rt_error("Failed to obtain buffer"); - return BufferRef(); + return {}; } try_head->_next = nullptr; try_head->set_type(&BufferFactory::claim_buffer, type, value_type); - return BufferRef(try_head); + return {try_head}; } BufferRef @@ -170,24 +178,24 @@ BufferFactory::create(LV2_URID type, LV2_URID value_type, uint32_t capacity) if (capacity == 0) { capacity = default_size(type); } else if (type == _uris.atom_Float) { - capacity = std::max(capacity, (uint32_t)sizeof(LV2_Atom_Float)); + capacity = + std::max(capacity, static_cast<uint32_t>(sizeof(LV2_Atom_Float))); } else if (type == _uris.atom_Sound) { capacity = std::max(capacity, default_size(_uris.atom_Sound)); } - return BufferRef(new Buffer(*this, type, value_type, capacity)); + return {new Buffer(*this, type, value_type, capacity)}; } void BufferFactory::recycle(Buffer* buf) { std::atomic<Buffer*>& head_ptr = free_list(buf->type()); - Buffer* try_head; + Buffer* try_head = nullptr; do { try_head = head_ptr.load(); buf->_next = try_head; } while (!head_ptr.compare_exchange_weak(try_head, buf)); } -} // namespace server -} // namespace ingen +} // namespace ingen::server diff --git a/src/server/BufferFactory.hpp b/src/server/BufferFactory.hpp index 03a85d1c..dbadaede 100644 --- a/src/server/BufferFactory.hpp +++ b/src/server/BufferFactory.hpp @@ -17,18 +17,20 @@ #ifndef INGEN_ENGINE_BUFFERFACTORY_HPP #define INGEN_ENGINE_BUFFERFACTORY_HPP -#include "ingen/URIs.hpp" -#include "ingen/ingen.h" -#include "lv2/urid/urid.h" - #include "BufferRef.hpp" +#include "server.h" #include "types.hpp" +#include <ingen/URIs.hpp> +#include <lv2/urid/urid.h> + #include <atomic> -#include <mutex> #include <cstdint> +#include <mutex> -namespace Raul { class Maid; } +namespace raul { +class Maid; +} // namespace raul namespace ingen { @@ -39,7 +41,8 @@ namespace server { class Buffer; class Engine; -class INGEN_API BufferFactory { +class INGEN_SERVER_API BufferFactory +{ public: BufferFactory(Engine& engine, URIs& uris); ~BufferFactory(); @@ -71,7 +74,7 @@ public: void set_seq_size(uint32_t seq_size) { _seq_size = seq_size; } Forge& forge(); - Raul::Maid& maid(); + raul::Maid& maid(); URIs& uris() { return _uris; } Engine& engine() { return _engine; } @@ -82,29 +85,33 @@ private: Buffer* try_get_buffer(LV2_URID type); - inline std::atomic<Buffer*>& free_list(LV2_URID type) { + std::atomic<Buffer*>& free_list(LV2_URID type) { if (type == _uris.atom_Float) { return _free_control; - } else if (type == _uris.atom_Sound) { + } + + if (type == _uris.atom_Sound) { return _free_audio; - } else if (type == _uris.atom_Sequence) { + } + + if (type == _uris.atom_Sequence) { return _free_sequence; - } else { - return _free_object; } + + return _free_object; } static void free_list(Buffer* head); - std::atomic<Buffer*> _free_audio; - std::atomic<Buffer*> _free_control; - std::atomic<Buffer*> _free_sequence; - std::atomic<Buffer*> _free_object; + std::atomic<Buffer*> _free_audio{nullptr}; + std::atomic<Buffer*> _free_control{nullptr}; + std::atomic<Buffer*> _free_sequence{nullptr}; + std::atomic<Buffer*> _free_object{nullptr}; std::mutex _mutex; Engine& _engine; URIs& _uris; - uint32_t _seq_size; + uint32_t _seq_size{0U}; BufferRef _silent_buffer; }; diff --git a/src/server/BufferRef.hpp b/src/server/BufferRef.hpp index 64eab668..cc5b840f 100644 --- a/src/server/BufferRef.hpp +++ b/src/server/BufferRef.hpp @@ -17,22 +17,20 @@ #ifndef INGEN_ENGINE_BUFFER_REF_HPP #define INGEN_ENGINE_BUFFER_REF_HPP -#include "ingen/ingen.h" +#include "server.h" -#include <boost/intrusive_ptr.hpp> +#include <boost/smart_ptr/intrusive_ptr.hpp> // IWYU pragma: export -namespace ingen { -namespace server { +namespace ingen::server { class Buffer; using BufferRef = boost::intrusive_ptr<Buffer>; // Defined in Buffer.cpp -INGEN_API void intrusive_ptr_add_ref(Buffer* b); -INGEN_API void intrusive_ptr_release(Buffer* b); +INGEN_SERVER_API void intrusive_ptr_add_ref(Buffer* b); +INGEN_SERVER_API void intrusive_ptr_release(Buffer* b); -} // namespace server -} // namespace ingen +} // namespace ingen::server #endif // INGEN_ENGINE_BUFFER_REF_HPP diff --git a/src/server/ClientUpdate.cpp b/src/server/ClientUpdate.cpp index 26f45ef1..008e9843 100644 --- a/src/server/ClientUpdate.cpp +++ b/src/server/ClientUpdate.cpp @@ -23,21 +23,25 @@ #include "PortImpl.hpp" #include "PortType.hpp" -#include "ingen/Arc.hpp" -#include "ingen/Atom.hpp" -#include "ingen/Forge.hpp" -#include "ingen/Interface.hpp" -#include "ingen/Node.hpp" -#include "ingen/URIs.hpp" -#include "ingen/types.hpp" +#include <ingen/Arc.hpp> +#include <ingen/Forge.hpp> +#include <ingen/Interface.hpp> +#include <ingen/Properties.hpp> +#include <ingen/Resource.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIs.hpp> +#include <raul/Path.hpp> + +#include <boost/intrusive/slist.hpp> #include <algorithm> #include <cstddef> #include <cstdint> +#include <map> +#include <memory> #include <utility> -namespace ingen { -namespace server { +namespace ingen::server { void ClientUpdate::put(const URI& uri, @@ -69,7 +73,7 @@ ClientUpdate::put_block(const BlockImpl* block) const URIs& uris = plugin->uris(); if (uris.ingen_Graph == plugin->type()) { - put_graph((const GraphImpl*)block); + put_graph(static_cast<const GraphImpl*>(block)); } else { put(block->uri(), block->properties()); for (size_t j = 0; j < block->num_ports(); ++j) { @@ -101,8 +105,8 @@ ClientUpdate::put_graph(const GraphImpl* graph) // Enqueue arcs for (const auto& a : graph->arcs()) { - const SPtr<const Arc> arc = a.second; - const Connect connect = { arc->tail_path(), arc->head_path() }; + const auto arc = a.second; + const Connect connect = {arc->tail_path(), arc->head_path()}; connects.push_back(connect); } } @@ -124,7 +128,7 @@ ClientUpdate::put_preset(const URIs& uris, const std::string& label) { const Properties props{ - { uris.rdf_type, uris.pset_Preset.urid }, + { uris.rdf_type, uris.pset_Preset.urid_atom() }, { uris.rdfs_label, uris.forge.alloc(label) }, { uris.lv2_appliesTo, uris.forge.make_urid(plugin) }}; put(preset, props); @@ -164,5 +168,4 @@ ClientUpdate::send(Interface& dest) } } -} // namespace server -} // namespace ingen +} // namespace ingen::server diff --git a/src/server/ClientUpdate.hpp b/src/server/ClientUpdate.hpp index 57848e62..1d16e6d6 100644 --- a/src/server/ClientUpdate.hpp +++ b/src/server/ClientUpdate.hpp @@ -17,10 +17,10 @@ #ifndef INGEN_ENGINE_CLIENTUPDATE_HPP #define INGEN_ENGINE_CLIENTUPDATE_HPP -#include "ingen/Properties.hpp" -#include "ingen/Resource.hpp" -#include "ingen/URI.hpp" -#include "raul/Path.hpp" +#include <ingen/Properties.hpp> +#include <ingen/Resource.hpp> +#include <ingen/URI.hpp> +#include <raul/Path.hpp> #include <string> #include <vector> @@ -67,8 +67,8 @@ struct ClientUpdate { }; struct Connect { - Raul::Path tail; - Raul::Path head; + raul::Path tail; + raul::Path head; }; std::vector<URI> dels; diff --git a/src/server/CompiledGraph.cpp b/src/server/CompiledGraph.cpp index 9efed05f..89fc8843 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 @@ -21,56 +21,64 @@ #include "GraphImpl.hpp" #include "ThreadManager.hpp" -#include "ingen/ColorContext.hpp" -#include "ingen/Configuration.hpp" -#include "ingen/Log.hpp" -#include "ingen/World.hpp" +#include <ingen/Atom.hpp> +#include <ingen/ColorContext.hpp> +#include <ingen/Configuration.hpp> +#include <ingen/Log.hpp> +#include <ingen/World.hpp> +#include <raul/Path.hpp> + +#include <boost/intrusive/slist.hpp> #include <algorithm> #include <cassert> #include <cstdint> #include <cstdio> +#include <exception> +#include <functional> #include <limits> +#include <memory> #include <utility> -namespace ingen { -namespace server { +namespace ingen::server { /** Graph contains ambiguous feedback with no delay nodes. */ -class FeedbackException : public std::exception { +class FeedbackException : public std::exception +{ public: - explicit FeedbackException(const BlockImpl* node, - const BlockImpl* root = nullptr) - : node(node), root(root) + explicit FeedbackException(const BlockImpl* n) + : node(n) {} - const BlockImpl* node; - const BlockImpl* root; + FeedbackException(const BlockImpl* n, const BlockImpl* r) + : node(n), root(r) + {} + + const BlockImpl* node = nullptr; + const BlockImpl* root = nullptr; }; static bool -has_provider_with_many_dependants(BlockImpl* n) +has_provider_with_many_dependants(const BlockImpl* n) { - for (BlockImpl* 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) - : _master(std::unique_ptr<Task>(new Task(Task::Mode::SEQUENTIAL))) + : _master{std::make_unique<Task>(Task::Mode::SEQUENTIAL)} { compile_graph(graph); } -MPtr<CompiledGraph> -CompiledGraph::compile(Raul::Maid& maid, GraphImpl& graph) +std::unique_ptr<CompiledGraph> +CompiledGraph::compile(GraphImpl& graph) { try { - return maid.make_managed<CompiledGraph>(&graph); + return std::unique_ptr<CompiledGraph>(new CompiledGraph(&graph)); } catch (const FeedbackException& e) { Log& log = graph.engine().log(); if (e.node && e.root) { @@ -79,31 +87,29 @@ CompiledGraph::compile(Raul::Maid& maid, GraphImpl& graph) } else { log.error("Feedback compiling %1%\n", e.node->path()); } - return MPtr<CompiledGraph>(); + return nullptr; } } static size_t -num_unvisited_dependants(BlockImpl* block) +num_unvisited_dependants(const BlockImpl* block) { - size_t count = 0; - for (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 -parallel_depth(BlockImpl* block) +parallel_depth(const BlockImpl* block) { if (has_provider_with_many_dependants(block)) { return 2; } size_t min_provider_depth = std::numeric_limits<size_t>::max(); - for (auto p : block->providers()) { + for (const auto* p : block->providers()) { min_provider_depth = std::min(min_provider_depth, parallel_depth(p)); } @@ -133,12 +139,12 @@ CompiledGraph::compile_graph(GraphImpl* graph) // Calculate maximum sequential depth to consume this phase size_t depth = std::numeric_limits<size_t>::max(); - for (auto i : blocks) { + for (const auto* i : blocks) { depth = std::min(depth, parallel_depth(i)); } Task par(Task::Mode::PARALLEL); - for (auto b : blocks) { + for (auto* b : blocks) { assert(num_unvisited_dependants(b) == 0); Task seq(Task::Mode::SEQUENTIAL); compile_block(b, seq, depth, predecessors); @@ -151,7 +157,7 @@ CompiledGraph::compile_graph(GraphImpl* graph) _master = Task::simplify(std::move(_master)); if (graph->engine().world().conf().option("trace").get<int32_t>()) { - ColorContext ctx(stderr, ColorContext::Color::YELLOW); + const ColorContext ctx{stderr, ColorContext::Color::YELLOW}; dump(graph->path()); } } @@ -164,7 +170,7 @@ check_feedback(const BlockImpl* root, BlockImpl* provider) throw FeedbackException(root); } - for (auto p : provider->providers()) { + for (auto* p : provider->providers()) { const BlockImpl::Mark mark = p->get_mark(); switch (mark) { case BlockImpl::Mark::UNVISITED: @@ -227,12 +233,12 @@ CompiledGraph::compile_block(BlockImpl* n, if (n->providers().size() < 2) { // Single provider, prepend it to this sequential task - for (auto p : n->providers()) { + for (auto* p : n->providers()) { compile_provider(n, p, task, max_depth - 1, k); } } else if (has_provider_with_many_dependants(n)) { // Stop recursion and enqueue providers for the next round - for (auto p : n->providers()) { + for (auto* p : n->providers()) { if (num_unvisited_dependants(p) == 0) { k.insert(p); } @@ -241,7 +247,7 @@ CompiledGraph::compile_block(BlockImpl* n, // Multiple providers with only this node as dependant, // make a new parallel task to execute them Task par(Task::Mode::PARALLEL); - for (auto p : n->providers()) { + for (auto* p : n->providers()) { compile_provider(n, p, par, max_depth - 1, k); } task.push_front(std::move(par)); @@ -258,9 +264,9 @@ CompiledGraph::compile_block(BlockImpl* n, } void -CompiledGraph::run(RunContext& context) +CompiledGraph::run(RunContext& ctx) { - _master->run(context); + _master->run(ctx); } void @@ -276,5 +282,4 @@ CompiledGraph::dump(const std::string& name) const sink(")\n"); } -} // namespace server -} // namespace ingen +} // namespace ingen::server diff --git a/src/server/CompiledGraph.hpp b/src/server/CompiledGraph.hpp index 959fb18e..1949563d 100644 --- a/src/server/CompiledGraph.hpp +++ b/src/server/CompiledGraph.hpp @@ -19,16 +19,14 @@ #include "Task.hpp" -#include "ingen/types.hpp" -#include "raul/Maid.hpp" -#include "raul/Noncopyable.hpp" +#include <raul/Noncopyable.hpp> #include <cstddef> +#include <memory> #include <set> #include <string> -namespace ingen { -namespace server { +namespace ingen::server { class BlockImpl; class GraphImpl; @@ -40,18 +38,15 @@ class RunContext; * execute the nodes in order and have nodes always executed before any of * their dependencies. */ -class CompiledGraph : public Raul::Maid::Disposable - , public Raul::Noncopyable +class CompiledGraph : public raul::Noncopyable { public: - static MPtr<CompiledGraph> compile(Raul::Maid& maid, GraphImpl& graph); + static std::unique_ptr<CompiledGraph> compile(GraphImpl& graph); - void run(RunContext& context); + void run(RunContext& ctx); private: - friend class Raul::Maid; ///< Allow make_managed to construct - - CompiledGraph(GraphImpl* graph); + explicit CompiledGraph(GraphImpl* graph); using BlockSet = std::set<BlockImpl*>; @@ -73,12 +68,12 @@ private: std::unique_ptr<Task> _master; }; -inline MPtr<CompiledGraph> compile(Raul::Maid& maid, GraphImpl& graph) +inline std::unique_ptr<CompiledGraph> +compile(GraphImpl& graph) { - return CompiledGraph::compile(maid, graph); + return CompiledGraph::compile(graph); } -} // namespace server -} // namespace ingen +} // namespace ingen::server #endif // INGEN_ENGINE_COMPILEDGRAPH_HPP diff --git a/src/server/ControlBindings.cpp b/src/server/ControlBindings.cpp index 3e123a16..489d5384 100644 --- a/src/server/ControlBindings.cpp +++ b/src/server/ControlBindings.cpp @@ -23,25 +23,27 @@ #include "RunContext.hpp" #include "ThreadManager.hpp" -#include "ingen/Atom.hpp" -#include "ingen/Forge.hpp" -#include "ingen/Log.hpp" -#include "ingen/URIMap.hpp" -#include "ingen/URIs.hpp" -#include "ingen/World.hpp" -#include "lv2/atom/atom.h" -#include "lv2/atom/forge.h" -#include "lv2/atom/util.h" -#include "lv2/midi/midi.h" -#include "lv2/urid/urid.h" -#include "raul/Path.hpp" - +#include <ingen/Atom.hpp> +#include <ingen/Forge.hpp> +#include <ingen/Log.hpp> +#include <ingen/URIMap.hpp> +#include <ingen/URIs.hpp> +#include <ingen/World.hpp> +#include <lv2/atom/atom.h> +#include <lv2/atom/forge.h> +#include <lv2/atom/util.h> +#include <lv2/midi/midi.h> +#include <lv2/urid/urid.h> +#include <raul/Path.hpp> + +#include <boost/intrusive/bstree.hpp> + +#include <algorithm> #include <cmath> #include <cstring> #include <string> -namespace ingen { -namespace server { +namespace ingen::server { ControlBindings::ControlBindings(Engine& engine) : _engine(engine) @@ -53,8 +55,7 @@ ControlBindings::ControlBindings(Engine& engine) 4096)) // FIXME: capacity? , _forge() { - lv2_atom_forge_init( - &_forge, &engine.world().uri_map().urid_map_feature()->urid_map); + lv2_atom_forge_init(&_forge, &engine.world().uri_map().urid_map()); } ControlBindings::~ControlBindings() @@ -72,6 +73,12 @@ ControlBindings::port_binding(PortImpl* port) const return binding_key(binding); } +static int16_t +get_atom_num(const LV2_Atom* const atom) +{ + return static_cast<int16_t>(reinterpret_cast<const LV2_Atom_Int*>(atom)->body); +} + ControlBindings::Key ControlBindings::binding_key(const Atom& binding) const { @@ -79,15 +86,37 @@ ControlBindings::binding_key(const Atom& binding) const Key key; LV2_Atom* num = nullptr; if (binding.type() == uris.atom_Object) { - const auto* obj = (const LV2_Atom_Object_Body*)binding.get_body(); + const auto* obj = static_cast<const LV2_Atom_Object_Body*>(binding.get_body()); if (obj->otype == uris.midi_Bender) { - key = Key(Type::MIDI_BENDER); + lv2_atom_object_body_get(binding.size(), + obj, + uris.midi_channel.urid(), + &num, + nullptr); + if (!num) { + _engine.log().rt_error("Bender binding missing channel\n"); + } else if (num->type != uris.atom_Int) { + _engine.log().rt_error("Bender channel not an integer\n"); + } else { + key = Key(Type::MIDI_BENDER, get_atom_num(num)); + } } else if (obj->otype == uris.midi_ChannelPressure) { - key = Key(Type::MIDI_CHANNEL_PRESSURE); + lv2_atom_object_body_get(binding.size(), + obj, + uris.midi_channel.urid(), + &num, + nullptr); + if (!num) { + _engine.log().rt_error("Pressure binding missing channel\n"); + } else if (num->type != uris.atom_Int) { + _engine.log().rt_error("Pressure channel not an integer\n"); + } else { + key = Key(Type::MIDI_CHANNEL_PRESSURE, get_atom_num(num)); + } } else if (obj->otype == uris.midi_Controller) { lv2_atom_object_body_get(binding.size(), obj, - (LV2_URID)uris.midi_controllerNumber, + uris.midi_controllerNumber.urid(), &num, nullptr); if (!num) { @@ -95,12 +124,12 @@ ControlBindings::binding_key(const Atom& binding) const } else if (num->type != uris.atom_Int) { _engine.log().rt_error("Controller number not an integer\n"); } else { - key = Key(Type::MIDI_CC, ((LV2_Atom_Int*)num)->body); + key = Key(Type::MIDI_CC, get_atom_num(num)); } } else if (obj->otype == uris.midi_NoteOn) { lv2_atom_object_body_get(binding.size(), obj, - (LV2_URID)uris.midi_noteNumber, + uris.midi_noteNumber.urid(), &num, nullptr); if (!num) { @@ -108,7 +137,7 @@ ControlBindings::binding_key(const Atom& binding) const } else if (num->type != uris.atom_Int) { _engine.log().rt_error("Note number not an integer\n"); } else { - key = Key(Type::MIDI_NOTE, ((LV2_Atom_Int*)num)->body); + key = Key(Type::MIDI_NOTE, get_atom_num(num)); } } } else if (binding.type()) { @@ -118,21 +147,28 @@ ControlBindings::binding_key(const Atom& binding) const } ControlBindings::Key -ControlBindings::midi_event_key(uint16_t, const uint8_t* buf, uint16_t& value) +ControlBindings::midi_event_key(const uint8_t* buf, uint16_t& value) { switch (lv2_midi_message_type(buf)) { case LV2_MIDI_MSG_CONTROLLER: - value = static_cast<int8_t>(buf[2]); - return {Type::MIDI_CC, static_cast<int8_t>(buf[1])}; + value = buf[2]; + return {Type::MIDI_CC, + static_cast<int16_t>(((buf[0] & 0x0FU) << 8U) | buf[1])}; case LV2_MIDI_MSG_BENDER: - value = (static_cast<int8_t>(buf[2]) << 7) + static_cast<int8_t>(buf[1]); - return {Type::MIDI_BENDER}; + value = static_cast<uint16_t>((buf[2] << 7U) + buf[1]); + return {Type::MIDI_BENDER, static_cast<int16_t>((buf[0] & 0x0FU))}; case LV2_MIDI_MSG_CHANNEL_PRESSURE: - value = static_cast<int8_t>(buf[1]); - return {Type::MIDI_CHANNEL_PRESSURE}; + value = buf[1]; + return {Type::MIDI_CHANNEL_PRESSURE, + static_cast<int16_t>((buf[0] & 0x0FU))}; case LV2_MIDI_MSG_NOTE_ON: - value = 1.0f; - return {Type::MIDI_NOTE, static_cast<int8_t>(buf[1])}; + value = 1; + return {Type::MIDI_NOTE, + static_cast<int16_t>(((buf[0] & 0x0FU) << 8U) | buf[1])}; + case LV2_MIDI_MSG_NOTE_OFF: + value = 0; + return {Type::MIDI_NOTE, + static_cast<int16_t>(((buf[0] & 0x0FU) << 8U) | buf[1])}; default: return {}; } @@ -150,9 +186,9 @@ ControlBindings::set_port_binding(RunContext&, binding->port = port; _bindings->insert(*binding); return true; - } else { - return false; } + + return false; } void @@ -163,15 +199,16 @@ ControlBindings::port_value_changed(RunContext& ctx, { const ingen::URIs& uris = ctx.engine().world().uris(); if (!!key) { - int16_t value = port_value_to_control( - ctx, port, key.type, value_atom); + const int16_t value = + port_value_to_control(ctx, port, key.type, value_atom); + uint16_t size = 0; uint8_t buf[4]; switch (key.type) { case Type::MIDI_CC: size = 3; buf[0] = LV2_MIDI_MSG_CONTROLLER; - buf[1] = key.num; + buf[1] = static_cast<uint8_t>(key.num); buf[2] = static_cast<int8_t>(value); break; case Type::MIDI_CHANNEL_PRESSURE: @@ -192,14 +229,17 @@ ControlBindings::port_value_changed(RunContext& ctx, } else if (value == 0) { buf[0] = LV2_MIDI_MSG_NOTE_OFF; } - buf[1] = key.num; + buf[1] = static_cast<uint8_t>(key.num); buf[2] = 0x64; // MIDI spec default break; default: break; } if (size > 0) { - _feedback->append_event(ctx.nframes() - 1, size, (LV2_URID)uris.midi_MidiEvent, buf); + _feedback->append_event(ctx.nframes() - 1, + size, + static_cast<LV2_URID>(uris.midi_MidiEvent), + buf); } } } @@ -210,25 +250,25 @@ 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; } } static void -get_range(RunContext& context, const PortImpl* port, float* min, float* max) +get_range(RunContext& ctx, const PortImpl* port, float* min, float* max) { *min = port->minimum().get<float>(); *max = port->maximum().get<float>(); if (port->is_sample_rate()) { - *min *= context.engine().sample_rate(); - *max *= context.engine().sample_rate(); + *min *= ctx.engine().sample_rate(); + *max *= ctx.engine().sample_rate(); } } float -ControlBindings::control_to_port_value(RunContext& context, +ControlBindings::control_to_port_value(RunContext& ctx, const PortImpl* port, Type type, int16_t value) @@ -237,10 +277,10 @@ ControlBindings::control_to_port_value(RunContext& context, switch (type) { case Type::MIDI_CC: case Type::MIDI_CHANNEL_PRESSURE: - normal = (float)value / 127.0f; + normal = static_cast<float>(value) / 127.0f; break; case Type::MIDI_BENDER: - normal = (float)value / 16383.0f; + normal = static_cast<float>(value) / 16383.0f; break; case Type::MIDI_NOTE: normal = (value == 0) ? 0.0f : 1.0f; @@ -250,18 +290,18 @@ ControlBindings::control_to_port_value(RunContext& context, } if (port->is_logarithmic()) { - normal = (expf(normal) - 1.0f) / ((float)M_E - 1.0f); + normal = (expf(normal) - 1.0f) / (static_cast<float>(M_E) - 1.0f); } float min = 0.0f; float max = 1.0f; - get_range(context, port, &min, &max); + get_range(ctx, port, &min, &max); - return normal * (max - min) + min; + return (normal * (max - min)) + min; } int16_t -ControlBindings::port_value_to_control(RunContext& context, +ControlBindings::port_value_to_control(RunContext& ctx, PortImpl* port, Type type, const Atom& value_atom) @@ -272,29 +312,23 @@ ControlBindings::port_value_to_control(RunContext& context, float min = 0.0f; float max = 1.0f; - get_range(context, port, &min, &max); + get_range(ctx, port, &min, &max); const float value = value_atom.get<float>(); float normal = (value - min) / (max - min); - if (normal < 0.0f) { - normal = 0.0f; - } - - if (normal > 1.0f) { - normal = 1.0f; - } + normal = std::max(0.0f, std::min(1.0f, normal)); if (port->is_logarithmic()) { - normal = logf(normal * ((float)M_E - 1.0f) + 1.0f); + normal = logf((normal * (static_cast<float>(M_E) - 1.0f)) + 1.0f); } switch (type) { case Type::MIDI_CC: case Type::MIDI_CHANNEL_PRESSURE: - return lrintf(normal * 127.0f); + return static_cast<int16_t>(lrintf(normal * 127.0f)); case Type::MIDI_BENDER: - return lrintf(normal * 16383.0f); + return static_cast<int16_t>(lrintf(normal * 16383.0f)); case Type::MIDI_NOTE: return (value > 0.0f) ? 1 : 0; default: @@ -317,9 +351,13 @@ forge_binding(const URIs& uris, break; case ControlBindings::Type::MIDI_BENDER: lv2_atom_forge_object(forge, &frame, 0, uris.midi_Bender); + lv2_atom_forge_key(forge, uris.midi_channel); + lv2_atom_forge_int(forge, value); break; case ControlBindings::Type::MIDI_CHANNEL_PRESSURE: lv2_atom_forge_object(forge, &frame, 0, uris.midi_ChannelPressure); + lv2_atom_forge_key(forge, uris.midi_channel); + lv2_atom_forge_int(forge, value); break; case ControlBindings::Type::MIDI_NOTE: lv2_atom_forge_object(forge, &frame, 0, uris.midi_NoteOn); @@ -334,29 +372,29 @@ forge_binding(const URIs& uris, } void -ControlBindings::set_port_value(RunContext& context, +ControlBindings::set_port_value(RunContext& ctx, PortImpl* port, Type type, - int16_t value) + int16_t value) const { float min = 0.0f; float max = 1.0f; - get_range(context, port, &min, &max); + get_range(ctx, port, &min, &max); - const float val = control_to_port_value(context, port, type, value); + const float val = control_to_port_value(ctx, port, type, value); // TODO: Set port value property so it is saved - port->set_control_value(context, context.start(), val); + port->set_control_value(ctx, ctx.start(), val); - URIs& uris = context.engine().world().uris(); - context.notify(uris.ingen_value, context.start(), port, - sizeof(float), _forge.Float, &val); + const URIs& uris = ctx.engine().world().uris(); + ctx.notify(uris.ingen_value, ctx.start(), port, + sizeof(float), _forge.Float, &val); } bool -ControlBindings::finish_learn(RunContext& context, Key key) +ControlBindings::finish_learn(RunContext& ctx, Key key) { - const ingen::URIs& uris = context.engine().world().uris(); + const ingen::URIs& uris = ctx.engine().world().uris(); Binding* binding = _learn_binding.exchange(nullptr); if (!binding || (key.type == Type::MIDI_NOTE && !binding->port->is_toggled())) { return false; @@ -367,19 +405,19 @@ ControlBindings::finish_learn(RunContext& context, Key key) LV2_Atom buf[16]; memset(buf, 0, sizeof(buf)); - lv2_atom_forge_set_buffer(&_forge, (uint8_t*)buf, sizeof(buf)); + lv2_atom_forge_set_buffer(&_forge, reinterpret_cast<uint8_t*>(buf), sizeof(buf)); forge_binding(uris, &_forge, key.type, key.num); const LV2_Atom* atom = buf; - context.notify(uris.midi_binding, - context.start(), - binding->port, - atom->size, atom->type, LV2_ATOM_BODY_CONST(atom)); + ctx.notify(uris.midi_binding, + ctx.start(), + binding->port, + atom->size, atom->type, LV2_ATOM_BODY_CONST(atom)); return true; } void -ControlBindings::get_all(const Raul::Path& path, std::vector<Binding*>& bindings) +ControlBindings::get_all(const raul::Path& path, std::vector<Binding*>& bindings) { ThreadManager::assert_thread(THREAD_PRE_PROCESS); @@ -406,22 +444,22 @@ ControlBindings::pre_process(RunContext& ctx, Buffer* buffer) _feedback->clear(); if ((!_learn_binding && _bindings->empty()) || !buffer->get<LV2_Atom>()) { - return; // Don't bother reading input + return; // Don't bother reading input } auto* seq = buffer->get<LV2_Atom_Sequence>(); - LV2_ATOM_SEQUENCE_FOREACH(seq, ev) { + LV2_ATOM_SEQUENCE_FOREACH (seq, ev) { if (ev->body.type == uris.midi_MidiEvent) { - const auto* buf = (const uint8_t*)LV2_ATOM_BODY(&ev->body); - const Key key = midi_event_key(ev->body.size, buf, value); + const auto* buf = static_cast<const uint8_t*>(LV2_ATOM_BODY(&ev->body)); + const Key key = midi_event_key(buf, value); if (_learn_binding && !!key) { - finish_learn(ctx, key); // Learn new binding + finish_learn(ctx, key); // Learn new binding } // Set all controls bound to this key const Binding k = {key, nullptr}; - for (Bindings::const_iterator i = _bindings->lower_bound(k); + for (auto i = _bindings->lower_bound(k); i != _bindings->end() && i->key == key; ++i) { set_port_value(ctx, i->port, key.type, value); @@ -438,5 +476,4 @@ ControlBindings::post_process(RunContext&, Buffer* buffer) } } -} // namespace server -} // namespace ingen +} // namespace ingen::server diff --git a/src/server/ControlBindings.hpp b/src/server/ControlBindings.hpp index bb113666..0e6dbf63 100644 --- a/src/server/ControlBindings.hpp +++ b/src/server/ControlBindings.hpp @@ -19,9 +19,8 @@ #include "BufferRef.hpp" -#include "ingen/types.hpp" -#include "lv2/atom/forge.h" -#include "raul/Maid.hpp" +#include <lv2/atom/forge.h> +#include <raul/Maid.hpp> #include <boost/intrusive/options.hpp> #include <boost/intrusive/set.hpp> @@ -29,10 +28,12 @@ #include <atomic> #include <cstdint> -#include <utility> +#include <memory> #include <vector> -namespace Raul { class Path; } +namespace raul { +class Path; +} // namespace raul namespace ingen { @@ -45,7 +46,8 @@ class Engine; class RunContext; class PortImpl; -class ControlBindings { +class ControlBindings +{ public: enum class Type : uint16_t { NULL_CONTROL, @@ -58,25 +60,31 @@ public: }; struct Key { - Key(Type t=Type::NULL_CONTROL, int16_t n=0) : type(t), num(n) {} - inline bool operator<(const Key& other) const { + 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) || (type == other.type && num < other.num)); } - inline bool operator==(const Key& other) const { + + bool operator==(const Key& other) const { return type == other.type && num == other.num; } - inline bool operator!() const { return type == Type::NULL_CONTROL; } + + bool operator!() const { return type == Type::NULL_CONTROL; } + Type type; int16_t num; }; /** 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(std::move(k)), port(p) {} + public raul::Maid::Disposable { + Binding(Key k, PortImpl* p) noexcept : key{k}, port{p} {} + Binding() noexcept : Binding{Key{}, nullptr} {} - inline bool operator<(const Binding& rhs) const { return key < rhs.key; } + bool operator<(const Binding& rhs) const { return key < rhs.key; } Key key; PortImpl* port; @@ -112,7 +120,7 @@ public: void post_process(RunContext& ctx, Buffer* buffer); /** Get all bindings for `path` or children of `path`. */ - void get_all(const Raul::Path& path, std::vector<Binding*>& bindings); + void get_all(const raul::Path& path, std::vector<Binding*>& bindings); /** Remove a set of bindings from an earlier call to get_all(). */ void remove(RunContext& ctx, const std::vector<Binding*>& bindings); @@ -123,30 +131,30 @@ private: boost::intrusive::compare<BindingLess>>; static Key - midi_event_key(uint16_t size, const uint8_t* buf, uint16_t& value); + midi_event_key(const uint8_t* buf, uint16_t& value); - void set_port_value(RunContext& context, + void set_port_value(RunContext& ctx, PortImpl* port, Type type, - int16_t value); + int16_t value) const; - bool finish_learn(RunContext& context, Key key); + bool finish_learn(RunContext& ctx, Key key); - static float control_to_port_value(RunContext& context, - const PortImpl* port, - Type type, - int16_t value); + static float control_to_port_value(RunContext& ctx, + const PortImpl* port, + Type type, + int16_t value); - static int16_t port_value_to_control(RunContext& context, + static int16_t port_value_to_control(RunContext& ctx, PortImpl* port, Type type, const Atom& value_atom); - Engine& _engine; - std::atomic<Binding*> _learn_binding; - SPtr<Bindings> _bindings; - BufferRef _feedback; - LV2_Atom_Forge _forge; + Engine& _engine; + std::atomic<Binding*> _learn_binding; + std::shared_ptr<Bindings> _bindings; + BufferRef _feedback; + LV2_Atom_Forge _forge; }; } // namespace server diff --git a/src/server/DirectDriver.hpp b/src/server/DirectDriver.hpp index bb949a14..bc52fc3a 100644 --- a/src/server/DirectDriver.hpp +++ b/src/server/DirectDriver.hpp @@ -18,29 +18,50 @@ #define INGEN_ENGINE_DIRECT_DRIVER_HPP #include "Driver.hpp" +#include "DuplexPort.hpp" #include "Engine.hpp" +#include "EnginePort.hpp" +#include "RunContext.hpp" +#include "types.hpp" + +#include <raul/Path.hpp> #include <boost/intrusive/slist.hpp> +#include <cstddef> +#include <cstdint> +#include <string> + +namespace boost::intrusive { +template <bool Enabled> struct cache_last; +} // namespace boost::intrusive + namespace ingen { + +class Atom; +class URI; + namespace server { +class Buffer; + /** Driver for running Ingen directly as a library. * \ingroup engine */ -class DirectDriver : public Driver { +class DirectDriver : public Driver +{ public: DirectDriver(Engine& engine, double sample_rate, SampleCount block_length, - size_t seq_size) + uint32_t seq_size) : _engine(engine) , _sample_rate(sample_rate) , _block_length(block_length) , _seq_size(seq_size) {} - virtual ~DirectDriver() { + ~DirectDriver() override { _ports.clear_and_dispose([](EnginePort* p) { delete p; }); } @@ -50,7 +71,7 @@ public: return new EnginePort(graph_port); } - EnginePort* get_port(const Raul::Path& path) override { + EnginePort* get_port(const raul::Path& path) override { for (auto& p : _ports) { if (p.graph_port()->path() == path) { return &p; @@ -60,18 +81,18 @@ public: return nullptr; } - void add_port(RunContext& context, EnginePort* port) override { + void add_port(RunContext&, EnginePort* port) override { _ports.push_back(*port); } - void remove_port(RunContext& context, EnginePort* port) override { + void remove_port(RunContext&, EnginePort* port) override { _ports.erase(_ports.iterator_to(*port)); } - void rename_port(const Raul::Path& old_path, - const Raul::Path& new_path) override {} + void rename_port(const raul::Path& old_path, + const raul::Path& new_path) override {} - void port_property(const Raul::Path& path, + void port_property(const raul::Path& path, const URI& uri, const Atom& value) override {} @@ -80,7 +101,7 @@ public: SampleCount block_length() const override { return _block_length; } - size_t seq_size() const override { return _seq_size; } + uint32_t seq_size() const override { return _seq_size; } SampleCount sample_rate() const override { return _sample_rate; } @@ -88,7 +109,7 @@ public: return _engine.run_context().start(); } - void append_time_events(RunContext& context, Buffer& buffer) override {} + void append_time_events(RunContext&, Buffer&) override {} int real_time_priority() override { return 60; } @@ -100,7 +121,7 @@ private: Ports _ports; SampleCount _sample_rate; SampleCount _block_length; - size_t _seq_size; + uint32_t _seq_size; }; } // namespace server diff --git a/src/server/Driver.hpp b/src/server/Driver.hpp index 4da04a55..112fb8ba 100644 --- a/src/server/Driver.hpp +++ b/src/server/Driver.hpp @@ -17,18 +17,27 @@ #ifndef INGEN_ENGINE_DRIVER_HPP #define INGEN_ENGINE_DRIVER_HPP -#include "DuplexPort.hpp" -#include "EnginePort.hpp" +#include "types.hpp" -#include "raul/Noncopyable.hpp" +#include <ingen/URI.hpp> +#include <raul/Noncopyable.hpp> -namespace Raul { class Path; } +#include <cstddef> + +namespace raul { +class Path; +} // namespace raul namespace ingen { + +class Atom; + namespace server { +class Buffer; class DuplexPort; class EnginePort; +class RunContext; /** Engine driver base class. * @@ -37,7 +46,8 @@ class EnginePort; * * \ingroup engine */ -class Driver : public Raul::Noncopyable { +class Driver : public raul::Noncopyable +{ public: virtual ~Driver() = default; @@ -53,10 +63,10 @@ public: virtual EnginePort* create_port(DuplexPort* graph_port) = 0; /** Find a system port by path. */ - virtual EnginePort* get_port(const Raul::Path& path) = 0; + virtual EnginePort* get_port(const raul::Path& path) = 0; /** Add a system visible port (e.g. a port on the root graph). */ - virtual void add_port(RunContext& context, EnginePort* port) = 0; + virtual void add_port(RunContext& ctx, EnginePort* port) = 0; /** Remove a system visible port. * @@ -64,7 +74,7 @@ public: * destroy the port. To actually remove the system port, unregister_port() * must be called later in another thread. */ - virtual void remove_port(RunContext& context, EnginePort* port) = 0; + virtual void remove_port(RunContext& ctx, EnginePort* port) = 0; /** Return true iff driver supports dynamic adding/removing of ports. */ virtual bool dynamic_ports() const { return false; } @@ -76,11 +86,11 @@ public: virtual void unregister_port(EnginePort& port) = 0; /** Rename a system visible port. */ - virtual void rename_port(const Raul::Path& old_path, - const Raul::Path& new_path) = 0; + virtual void rename_port(const raul::Path& old_path, + const raul::Path& new_path) = 0; /** Apply a system visible port property. */ - virtual void port_property(const Raul::Path& path, + virtual void port_property(const raul::Path& path, const URI& uri, const Atom& value) = 0; @@ -88,7 +98,7 @@ public: virtual SampleCount block_length() const = 0; /** Return the event buffer size in bytes */ - virtual size_t seq_size() const = 0; + virtual uint32_t seq_size() const = 0; /** Return the sample rate in Hz */ virtual SampleRate sample_rate() const = 0; @@ -97,8 +107,7 @@ public: virtual SampleCount frame_time() const = 0; /** Append time events for this cycle to `buffer`. */ - virtual void append_time_events(RunContext& context, - Buffer& buffer) = 0; + virtual void append_time_events(RunContext& ctx, Buffer& buffer) = 0; /** Return the real-time priority of the audio thread, or -1. */ virtual int real_time_priority() = 0; diff --git a/src/server/DuplexPort.cpp b/src/server/DuplexPort.cpp index 8297e3cc..1e07afd2 100644 --- a/src/server/DuplexPort.cpp +++ b/src/server/DuplexPort.cpp @@ -23,25 +23,28 @@ #include "Engine.hpp" #include "GraphImpl.hpp" #include "NodeImpl.hpp" - -#include "ingen/Atom.hpp" -#include "ingen/Forge.hpp" -#include "ingen/Node.hpp" -#include "ingen/Properties.hpp" -#include "ingen/URIs.hpp" -#include "ingen/types.hpp" -#include "raul/Array.hpp" +#include "PortType.hpp" + +#include <ingen/Atom.hpp> +#include <ingen/Forge.hpp> +#include <ingen/Node.hpp> +#include <ingen/Properties.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIs.hpp> +#include <lv2/urid/urid.h> +#include <raul/Array.hpp> +#include <raul/Maid.hpp> #include <algorithm> #include <map> +#include <memory> #include <utility> -namespace ingen { -namespace server { +namespace ingen::server { DuplexPort::DuplexPort(BufferFactory& bufs, GraphImpl* parent, - const Raul::Symbol& symbol, + const raul::Symbol& symbol, uint32_t index, bool polyphonic, PortType type, @@ -69,8 +72,11 @@ DuplexPort::DuplexPort(BufferFactory& bufs, _is_output = is_output; if (is_output) { if (parent->graph_type() != Node::GraphType::GRAPH) { - remove_property(bufs.uris().rdf_type, bufs.uris().lv2_InputPort.urid); - add_property(bufs.uris().rdf_type, bufs.uris().lv2_OutputPort.urid); + remove_property(bufs.uris().rdf_type, + bufs.uris().lv2_InputPort.urid_atom()); + + add_property(bufs.uris().rdf_type, + bufs.uris().lv2_OutputPort.urid_atom()); } } @@ -87,11 +93,11 @@ DuplexPort::~DuplexPort() DuplexPort* DuplexPort::duplicate(Engine& engine, - const Raul::Symbol& symbol, + const raul::Symbol& symbol, GraphImpl* parent) { BufferFactory& bufs = *engine.buffer_factory(); - const Atom polyphonic = get_property(bufs.uris().ingen_polyphonic); + const Atom& polyphonic = get_property(bufs.uris().ingen_polyphonic); auto* dup = new DuplexPort( bufs, parent, symbol, _index, @@ -141,17 +147,20 @@ DuplexPort::on_property(const URI& uri, const Atom& value) } bool -DuplexPort::get_buffers(BufferFactory& bufs, - PortImpl::GetFn get, - const MPtr<Voices>& voices, - uint32_t poly, - size_t num_in_arcs) const +DuplexPort::get_buffers(BufferFactory& bufs, + PortImpl::GetFn get, + const raul::managed_ptr<Voices>& voices, + uint32_t poly, + size_t num_in_arcs) const { if (!_is_driver_port && is_output()) { return InputPort::get_buffers(bufs, get, voices, poly, num_in_arcs); - } else if (!_is_driver_port && is_input()) { + } + + if (!_is_driver_port && is_input()) { return PortImpl::get_buffers(bufs, get, voices, poly, num_in_arcs); } + return false; } @@ -160,9 +169,12 @@ DuplexPort::setup_buffers(RunContext& ctx, BufferFactory& bufs, uint32_t poly) { if (!_is_driver_port && is_output()) { return InputPort::setup_buffers(ctx, bufs, poly); - } else if (!_is_driver_port && is_input()) { + } + + if (!_is_driver_port && is_input()) { return PortImpl::setup_buffers(ctx, bufs, poly); } + return false; } @@ -198,46 +210,46 @@ DuplexPort::prepare_poly(BufferFactory& bufs, uint32_t poly) } bool -DuplexPort::apply_poly(RunContext& context, uint32_t poly) +DuplexPort::apply_poly(RunContext& ctx, uint32_t poly) { if (!parent()->parent() || poly != parent()->parent_graph()->internal_poly()) { return false; } - return PortImpl::apply_poly(context, poly); + return PortImpl::apply_poly(ctx, poly); } void -DuplexPort::pre_process(RunContext& context) +DuplexPort::pre_process(RunContext& ctx) { if (_is_output) { /* This is a graph output, which is an input from the internal perspective. Prepare buffers for write so plugins can deliver to them */ for (uint32_t v = 0; v < _poly; ++v) { - _voices->at(v).buffer->prepare_write(context); + _voices->at(v).buffer->prepare_write(ctx); } } else { /* This is a a graph input, which is an output from the internal perspective. Do whatever a normal block's input port does to prepare input for reading. */ - InputPort::pre_process(context); - InputPort::pre_run(context); + InputPort::pre_process(ctx); + InputPort::pre_run(ctx); } } void -DuplexPort::post_process(RunContext& context) +DuplexPort::post_process(RunContext& ctx) { if (_is_output) { /* This is a graph output, which is an input from the internal perspective. Mix down input delivered by plugins so output (external perspective) is ready. */ - InputPort::pre_process(context); - InputPort::pre_run(context); + InputPort::pre_process(ctx); + InputPort::pre_run(ctx); } - monitor(context); + monitor(ctx); } SampleCount @@ -246,5 +258,4 @@ DuplexPort::next_value_offset(SampleCount offset, SampleCount end) const return PortImpl::next_value_offset(offset, end); } -} // namespace server -} // namespace ingen +} // namespace ingen::server diff --git a/src/server/DuplexPort.hpp b/src/server/DuplexPort.hpp index 6b3d0ae6..fb3eb74e 100644 --- a/src/server/DuplexPort.hpp +++ b/src/server/DuplexPort.hpp @@ -19,30 +19,32 @@ #include "InputPort.hpp" #include "PortImpl.hpp" -#include "PortType.hpp" +#include "server.h" #include "types.hpp" -#include "ingen/URI.hpp" -#include "lv2/urid/urid.h" +#include <lv2/urid/urid.h> +#include <raul/Maid.hpp> #include <boost/intrusive/slist_hook.hpp> #include <cstddef> #include <cstdint> -namespace Raul { class Symbol; } +namespace raul { +class Symbol; +} // namespace raul namespace ingen { +enum class PortType; + class Atom; -class Properties; namespace server { class BufferFactory; class Engine; class GraphImpl; -class RunContext; /** A duplex Port (both an input and output port on a Graph) * @@ -53,14 +55,14 @@ class RunContext; * * \ingroup engine */ -class INGEN_API DuplexPort final +class INGEN_SERVER_API DuplexPort final : public InputPort , public boost::intrusive::slist_base_hook<> // In GraphImpl { public: DuplexPort(BufferFactory& bufs, GraphImpl* parent, - const Raul::Symbol& symbol, + const raul::Symbol& symbol, uint32_t index, bool polyphonic, PortType type, @@ -69,10 +71,10 @@ public: const Atom& value, bool is_output); - virtual ~DuplexPort(); + ~DuplexPort() override; DuplexPort* duplicate(Engine& engine, - const Raul::Symbol& symbol, + const raul::Symbol& symbol, GraphImpl* parent); void inherit_neighbour(const PortImpl* port, @@ -81,17 +83,17 @@ public: void on_property(const URI& uri, const Atom& value) override; - uint32_t max_tail_poly(RunContext& context) const override; + uint32_t max_tail_poly(RunContext& ctx) const override; bool prepare_poly(BufferFactory& bufs, uint32_t poly) override; - bool apply_poly(RunContext& context, uint32_t poly) override; + bool apply_poly(RunContext& ctx, uint32_t poly) override; - bool get_buffers(BufferFactory& bufs, - PortImpl::GetFn get, - const MPtr<Voices>& voices, - uint32_t poly, - size_t num_in_arcs) const override; + bool get_buffers(BufferFactory& bufs, + PortImpl::GetFn get, + const raul::managed_ptr<Voices>& voices, + uint32_t poly, + size_t num_in_arcs) const override; void set_is_driver_port(BufferFactory& bufs) override; @@ -105,8 +107,8 @@ public: bool setup_buffers(RunContext& ctx, BufferFactory& bufs, uint32_t poly) override; - void pre_process(RunContext& context) override; - void post_process(RunContext& context) override; + void pre_process(RunContext& ctx) override; + void post_process(RunContext& ctx) override; SampleCount next_value_offset(SampleCount offset, SampleCount end) const override; diff --git a/src/server/Engine.cpp b/src/server/Engine.cpp index 8256981b..4d753bbc 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 @@ -26,52 +26,66 @@ #include "EventWriter.hpp" #include "GraphImpl.hpp" #include "LV2Options.hpp" +#include "NodeImpl.hpp" +#include "PortImpl.hpp" #include "PostProcessor.hpp" #include "PreProcessor.hpp" #include "RunContext.hpp" +#include "Task.hpp" #include "ThreadManager.hpp" #include "UndoStack.hpp" #include "Worker.hpp" #include "events/CreateGraph.hpp" #include "ingen_config.h" -#ifdef HAVE_SOCKET +#if USE_SOCKET #include "SocketListener.hpp" #endif -#include "ingen/AtomReader.hpp" -#include "ingen/Configuration.hpp" -#include "ingen/Forge.hpp" -#include "ingen/Log.hpp" -#include "ingen/Store.hpp" -#include "ingen/StreamWriter.hpp" -#include "ingen/Tee.hpp" -#include "ingen/URIs.hpp" -#include "ingen/World.hpp" -#include "ingen/types.hpp" -#include "lv2/buf-size/buf-size.h" -#include "lv2/state/state.h" -#include "raul/Maid.hpp" +#include <ingen/Atom.hpp> +#include <ingen/AtomReader.hpp> +#include <ingen/Clock.hpp> +#include <ingen/ColorContext.hpp> +#include <ingen/Configuration.hpp> +#include <ingen/Forge.hpp> +#include <ingen/Interface.hpp> +#include <ingen/LV2Features.hpp> +#include <ingen/Log.hpp> +#include <ingen/Properties.hpp> +#include <ingen/Resource.hpp> +#include <ingen/Store.hpp> +#include <ingen/StreamWriter.hpp> +#include <ingen/Tee.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIs.hpp> +#include <ingen/World.hpp> +#include <lv2/buf-size/buf-size.h> +#include <lv2/state/state.h> +#include <raul/Maid.hpp> +#include <raul/Path.hpp> +#include <raul/RingBuffer.hpp> #include <algorithm> #include <cmath> #include <cstdint> #include <cstdio> #include <limits> +#include <map> +#include <memory> +#include <string> #include <thread> #include <utility> -namespace ingen { -namespace server { +namespace ingen::server { -INGEN_THREAD_LOCAL unsigned ThreadManager::flags(0); -bool ThreadManager::single_threaded(true); +thread_local unsigned ThreadManager::flags(0); +bool ThreadManager::single_threaded(true); Engine::Engine(ingen::World& world) : _world(world) , _options(new LV2Options(world.uris())) , _buffer_factory(new BufferFactory(*this, world.uris())) - , _maid(new Raul::Maid) + , _maid(new raul::Maid) , _worker(new Worker(world.log(), event_queue_size())) , _sync_worker(new Worker(world.log(), event_queue_size(), true)) , _broadcaster(new Broadcaster()) @@ -85,41 +99,38 @@ Engine::Engine(ingen::World& world) , _interface(_event_writer) , _atom_interface( new AtomReader(world.uri_map(), world.uris(), world.log(), *_interface)) - , _root_graph(nullptr) - , _cycle_start_time(0) , _rand_engine(reinterpret_cast<uintptr_t>(this)) - , _uniform_dist(0.0f, 1.0f) - , _quit_flag(false) - , _reset_load_flag(false) , _atomic_bundles(world.conf().option("atomic-bundles").get<int32_t>()) - , _activated(false) { if (!world.store()) { world.set_store(std::make_shared<ingen::Store>()); } for (int i = 0; i < world.conf().option("threads").get<int32_t>(); ++i) { + const bool is_threaded = (i > 0); _notifications.emplace_back( - make_unique<Raul::RingBuffer>(uint32_t(24 * event_queue_size()))); + std::make_unique<raul::RingBuffer>(24U * event_queue_size())); _run_contexts.emplace_back( - make_unique<RunContext>( - *this, _notifications.back().get(), unsigned(i), i > 0)); + std::make_unique<RunContext>(*this, + _notifications.back().get(), + static_cast<unsigned>(i), + is_threaded)); } _world.lv2_features().add_feature(_worker->schedule_feature()); _world.lv2_features().add_feature(_options); _world.lv2_features().add_feature( - SPtr<LV2Features::Feature>( - new LV2Features::EmptyFeature(LV2_BUF_SIZE__powerOf2BlockLength))); + std::make_shared<LV2Features::EmptyFeature>( + LV2_BUF_SIZE__powerOf2BlockLength)); _world.lv2_features().add_feature( - SPtr<LV2Features::Feature>( - new LV2Features::EmptyFeature(LV2_BUF_SIZE__fixedBlockLength))); + std::make_shared<LV2Features::EmptyFeature>( + LV2_BUF_SIZE__fixedBlockLength)); _world.lv2_features().add_feature( - SPtr<LV2Features::Feature>( - new LV2Features::EmptyFeature(LV2_BUF_SIZE__boundedBlockLength))); + std::make_shared<LV2Features::EmptyFeature>( + LV2_BUF_SIZE__boundedBlockLength)); _world.lv2_features().add_feature( - SPtr<LV2Features::Feature>( - new LV2Features::EmptyFeature(LV2_STATE__loadDefaultState))); + std::make_shared<LV2Features::EmptyFeature>( + LV2_STATE__loadDefaultState)); if (world.conf().option("dump").get<int32_t>()) { _interface = std::make_shared<Tee>( @@ -154,28 +165,28 @@ Engine::~Engine() // Delete run contexts _quit_flag = true; _tasks_available.notify_all(); - for (const auto& ctx : _run_contexts) { - ctx->join(); + for (const auto& thread_ctx : _run_contexts) { + thread_ctx->join(); } - const SPtr<Store> store = this->store(); + const auto store = this->store(); if (store) { - for (auto& s : *store.get()) { - if (!dynamic_ptr_cast<NodeImpl>(s.second)->parent()) { + for (auto& s : *store) { + if (!std::dynamic_pointer_cast<NodeImpl>(s.second)->parent()) { s.second.reset(); } } store->clear(); } - _world.set_store(SPtr<ingen::Store>()); + _world.set_store(nullptr); } void Engine::listen() { -#ifdef HAVE_SOCKET - _listener = UPtr<SocketListener>(new SocketListener(*this)); +#if USE_SOCKET + _listener = std::make_unique<SocketListener>(*this); #endif } @@ -231,12 +242,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 @@ -272,7 +282,7 @@ Engine::steal_task(unsigned start_thread) return nullptr; } -SPtr<Store> +std::shared_ptr<Store> Engine::store() const { return _world.store(); @@ -290,16 +300,17 @@ Engine::block_length() const return _driver->block_length(); } -size_t +uint32_t Engine::sequence_size() const { return _driver->seq_size(); } -size_t +uint32_t Engine::event_queue_size() const { - return _world.conf().option("queue-size").get<int32_t>(); + return static_cast<uint32_t>( + std::max(0, _world.conf().option("queue-size").get<int32_t>())); } void @@ -336,7 +347,7 @@ Engine::main_iteration() } void -Engine::set_driver(const SPtr<Driver>& driver) +Engine::set_driver(const std::shared_ptr<Driver>& driver) { _driver = driver; for (const auto& ctx : _run_contexts) { @@ -373,9 +384,10 @@ Engine::reset_load() } void -Engine::init(double sample_rate, uint32_t block_length, size_t seq_size) +Engine::init(double sample_rate, uint32_t block_length, uint32_t seq_size) { - set_driver(SPtr<Driver>(new DirectDriver(*this, sample_rate, block_length, seq_size))); + set_driver(std::make_shared<DirectDriver>( + *this, sample_rate, block_length, seq_size)); } bool @@ -405,7 +417,7 @@ Engine::activate() enqueue_event( new events::CreateGraph( - *this, SPtr<Interface>(), -1, 0, Raul::Path("/"), properties)); + *this, nullptr, -1, 0, raul::Path("/"), properties)); flush_events(std::chrono::milliseconds(10)); if (!_root_graph) { @@ -510,18 +522,17 @@ Engine::log() const } void -Engine::register_client(const SPtr<Interface>& client) +Engine::register_client(const std::shared_ptr<Interface>& client) { log().info("Registering client <%1%>\n", client->uri().c_str()); _broadcaster->register_client(client); } bool -Engine::unregister_client(const SPtr<Interface>& client) +Engine::unregister_client(const std::shared_ptr<Interface>& client) { log().info("Unregistering client <%1%>\n", client->uri().c_str()); return _broadcaster->unregister_client(client); } -} // namespace server -} // namespace ingen +} // namespace ingen::server diff --git a/src/server/Engine.hpp b/src/server/Engine.hpp index 45379ad1..8fa1d169 100644 --- a/src/server/Engine.hpp +++ b/src/server/Engine.hpp @@ -19,26 +19,26 @@ #include "Event.hpp" #include "Load.hpp" +#include "server.h" #include "types.hpp" -#include "ingen/Clock.hpp" -#include "ingen/EngineBase.hpp" -#include "ingen/Properties.hpp" -#include "ingen/ingen.h" -#include "ingen/types.hpp" +#include <ingen/Clock.hpp> +#include <ingen/EngineBase.hpp> +#include <ingen/Properties.hpp> #include <chrono> #include <condition_variable> #include <cstddef> #include <cstdint> +#include <memory> #include <mutex> #include <random> #include <vector> -namespace Raul { +namespace raul { class Maid; class RingBuffer; -} +} // namespace raul namespace ingen { @@ -75,17 +75,17 @@ class Worker; @ingroup engine */ -class INGEN_API Engine final : public EngineBase +class INGEN_SERVER_API Engine final : public EngineBase { public: explicit Engine(ingen::World& world); - virtual ~Engine(); + ~Engine() override; Engine(const Engine&) = delete; Engine& operator=(const Engine&) = delete; // EngineBase methods - void init(double sample_rate, uint32_t block_length, size_t seq_size) override; + void init(double sample_rate, uint32_t block_length, uint32_t seq_size) override; bool supports_dynamic_ports() const override; bool activate() override; void deactivate() override; @@ -93,15 +93,15 @@ public: unsigned run(uint32_t sample_count) override; void quit() override; bool main_iteration() override; - void register_client(const SPtr<Interface>& client) override; - bool unregister_client(const SPtr<Interface>& client) override; + void register_client(const std::shared_ptr<Interface>& client) override; + bool unregister_client(const std::shared_ptr<Interface>& client) override; void listen() override; /** Return a random [0..1] float with uniform distribution */ float frand() { return _uniform_dist(_rand_engine); } - void set_driver(const SPtr<Driver>& driver); + void set_driver(const std::shared_ptr<Driver>& driver); /** Return the frame time to execute an event that arrived now. * @@ -114,7 +114,7 @@ public: * * This value is comparable to the value returned by current_time(). */ - inline uint64_t cycle_start_time(const RunContext& context) const { + uint64_t cycle_start_time(const RunContext&) const { return _cycle_start_time; } @@ -136,20 +136,20 @@ public: ingen::World& world() const { return _world; } Log& log() const; - const SPtr<Interface>& interface() const { return _interface; } - const SPtr<EventWriter>& event_writer() const { return _event_writer; } - const UPtr<AtomReader>& atom_interface() const { return _atom_interface; } - const UPtr<BlockFactory>& block_factory() const { return _block_factory; } - const UPtr<Broadcaster>& broadcaster() const { return _broadcaster; } - const UPtr<BufferFactory>& buffer_factory() const { return _buffer_factory; } - const UPtr<ControlBindings>& control_bindings() const { return _control_bindings; } - const SPtr<Driver>& driver() const { return _driver; } - const UPtr<PostProcessor>& post_processor() const { return _post_processor; } - const UPtr<Raul::Maid>& maid() const { return _maid; } - const UPtr<UndoStack>& undo_stack() const { return _undo_stack; } - const UPtr<UndoStack>& redo_stack() const { return _redo_stack; } - const UPtr<Worker>& worker() const { return _worker; } - const UPtr<Worker>& sync_worker() const { return _sync_worker; } + const std::shared_ptr<Interface>& interface() const { return _interface; } + const std::shared_ptr<EventWriter>& event_writer() const { return _event_writer; } + const std::unique_ptr<AtomReader>& atom_interface() const { return _atom_interface; } + const std::unique_ptr<BlockFactory>& block_factory() const { return _block_factory; } + const std::unique_ptr<Broadcaster>& broadcaster() const { return _broadcaster; } + const std::unique_ptr<BufferFactory>& buffer_factory() const { return _buffer_factory; } + const std::unique_ptr<ControlBindings>& control_bindings() const { return _control_bindings; } + const std::shared_ptr<Driver>& driver() const { return _driver; } + const std::unique_ptr<PostProcessor>& post_processor() const { return _post_processor; } + const std::unique_ptr<raul::Maid>& maid() const { return _maid; } + const std::unique_ptr<UndoStack>& undo_stack() const { return _undo_stack; } + const std::unique_ptr<UndoStack>& redo_stack() const { return _redo_stack; } + const std::unique_ptr<Worker>& worker() const { return _worker; } + const std::unique_ptr<Worker>& sync_worker() const { return _sync_worker; } GraphImpl* root_graph() const { return _root_graph; } void set_root_graph(GraphImpl* graph); @@ -166,12 +166,12 @@ public: void signal_tasks_available(); Task* steal_task(unsigned start_thread); - SPtr<Store> store() const; + std::shared_ptr<Store> store() const; SampleRate sample_rate() const; SampleCount block_length() const; - size_t sequence_size() const; - size_t event_queue_size() const; + uint32_t sequence_size() const; + uint32_t event_queue_size() const; size_t n_threads() const { return _run_contexts.size(); } bool atomic_bundles() const { return _atomic_bundles; } @@ -182,41 +182,41 @@ public: private: ingen::World& _world; - SPtr<LV2Options> _options; - UPtr<BufferFactory> _buffer_factory; - UPtr<Raul::Maid> _maid; - SPtr<Driver> _driver; - UPtr<Worker> _worker; - UPtr<Worker> _sync_worker; - UPtr<Broadcaster> _broadcaster; - UPtr<ControlBindings> _control_bindings; - UPtr<BlockFactory> _block_factory; - UPtr<UndoStack> _undo_stack; - UPtr<UndoStack> _redo_stack; - UPtr<PostProcessor> _post_processor; - UPtr<PreProcessor> _pre_processor; - UPtr<SocketListener> _listener; - SPtr<EventWriter> _event_writer; - SPtr<Interface> _interface; - UPtr<AtomReader> _atom_interface; - GraphImpl* _root_graph; - - std::vector<UPtr<Raul::RingBuffer>> _notifications; - std::vector<UPtr<RunContext>> _run_contexts; - uint64_t _cycle_start_time; - Load _run_load; - Clock _clock; + std::shared_ptr<LV2Options> _options; + std::unique_ptr<BufferFactory> _buffer_factory; + std::unique_ptr<raul::Maid> _maid; + std::shared_ptr<Driver> _driver; + std::unique_ptr<Worker> _worker; + std::unique_ptr<Worker> _sync_worker; + std::unique_ptr<Broadcaster> _broadcaster; + std::unique_ptr<ControlBindings> _control_bindings; + std::unique_ptr<BlockFactory> _block_factory; + std::unique_ptr<UndoStack> _undo_stack; + std::unique_ptr<UndoStack> _redo_stack; + std::unique_ptr<PostProcessor> _post_processor; + std::unique_ptr<PreProcessor> _pre_processor; + std::unique_ptr<SocketListener> _listener; + std::shared_ptr<EventWriter> _event_writer; + std::shared_ptr<Interface> _interface; + std::unique_ptr<AtomReader> _atom_interface; + GraphImpl* _root_graph{nullptr}; + + std::vector<std::unique_ptr<raul::RingBuffer>> _notifications; + std::vector<std::unique_ptr<RunContext>> _run_contexts; + uint64_t _cycle_start_time{0}; + Load _run_load; + Clock _clock; std::mt19937 _rand_engine; - std::uniform_real_distribution<float> _uniform_dist; + std::uniform_real_distribution<float> _uniform_dist{0.0f, 1.0f}; std::condition_variable _tasks_available; std::mutex _tasks_mutex; - bool _quit_flag; - bool _reset_load_flag; + bool _quit_flag{false}; + bool _reset_load_flag{false}; bool _atomic_bundles; - bool _activated; + bool _activated{false}; }; } // namespace server diff --git a/src/server/EnginePort.hpp b/src/server/EnginePort.hpp index 33e0e29c..d7e73f63 100644 --- a/src/server/EnginePort.hpp +++ b/src/server/EnginePort.hpp @@ -19,28 +19,26 @@ #include "DuplexPort.hpp" -#include "raul/Deletable.hpp" -#include "raul/Noncopyable.hpp" +#include <raul/Deletable.hpp> +#include <raul/Noncopyable.hpp> -#include <boost/intrusive/slist.hpp> +#include <boost/intrusive/slist_hook.hpp> -namespace ingen { -namespace server { +#include <cstdint> + +namespace ingen::server { /** A "system" port (e.g. a Jack port, an external port on Ingen). * * @ingroup engine */ -class EnginePort : public Raul::Noncopyable - , public Raul::Deletable +class EnginePort : public raul::Noncopyable + , public raul::Deletable , public boost::intrusive::slist_base_hook<> { public: explicit EnginePort(DuplexPort* port) : _graph_port(port) - , _buffer(nullptr) - , _handle(nullptr) - , _driver_index(0) {} void set_buffer(void* buf) { _buffer = buf; } @@ -55,12 +53,11 @@ public: protected: DuplexPort* _graph_port; - void* _buffer; - void* _handle; - uint32_t _driver_index; + void* _buffer{nullptr}; + void* _handle{nullptr}; + uint32_t _driver_index{0}; }; -} // namespace server -} // namespace ingen +} // namespace ingen::server #endif // INGEN_ENGINE_ENGINE_PORT_HPP diff --git a/src/server/Event.hpp b/src/server/Event.hpp index b2477ce8..3c9c5c26 100644 --- a/src/server/Event.hpp +++ b/src/server/Event.hpp @@ -19,18 +19,24 @@ #include "types.hpp" -#include "ingen/Interface.hpp" -#include "ingen/Node.hpp" -#include "ingen/Status.hpp" -#include "ingen/types.hpp" -#include "raul/Deletable.hpp" -#include "raul/Noncopyable.hpp" -#include "raul/Path.hpp" +#include <ingen/Interface.hpp> +#include <ingen/Status.hpp> +#include <ingen/URI.hpp> +#include <ingen/paths.hpp> +#include <raul/Deletable.hpp> +#include <raul/Noncopyable.hpp> #include <atomic> +#include <cstdint> +#include <memory> +#include <string> +#include <utility> -namespace ingen { -namespace server { +namespace raul { +class Path; +} // namespace raul + +namespace ingen::server { class Engine; class RunContext; @@ -48,7 +54,7 @@ class PreProcessContext; * * \ingroup engine */ -class Event : public Raul::Deletable, public Raul::Noncopyable +class Event : public raul::Deletable, public raul::Noncopyable { public: /** Event mode to distinguish normal events from undo events. */ @@ -56,20 +62,20 @@ public: /** Execution mode for events that block and unblock preprocessing. */ enum class Execution { - NORMAL, ///< Normal pipelined execution - ATOMIC, ///< Block pre-processing until this event is executed - BLOCK, ///< Begin atomic block of events - UNBLOCK ///< Finish atomic executed block of events + NORMAL, ///< Normal pipelined execution + ATOMIC, ///< Block pre-processing until this event is executed + BLOCK, ///< Begin atomic block of events + UNBLOCK ///< Finish atomic executed block of events }; /** Claim position in undo stack before pre-processing (non-realtime). */ - virtual void mark(PreProcessContext&) {}; + virtual void mark(PreProcessContext&) {} /** Pre-process event before execution (non-realtime). */ virtual bool pre_process(PreProcessContext& ctx) = 0; /** Execute this event in the audio thread (realtime). */ - virtual void execute(RunContext& context) = 0; + virtual void execute(RunContext& ctx) = 0; /** Post-process event after execution (non-realtime). */ virtual void post_process() = 0; @@ -78,13 +84,13 @@ public: virtual void undo(Interface& target) {} /** Return true iff this event has been pre-processed. */ - inline bool is_prepared() const { return _status != Status::NOT_PREPARED; } + bool is_prepared() const { return _status != Status::NOT_PREPARED; } /** Return the time stamp of this event. */ - inline SampleCount time() const { return _time; } + SampleCount time() const { return _time; } /** Set the time stamp of this event. */ - inline void set_time(SampleCount time) { _time = time; } + void set_time(SampleCount time) { _time = time; } /** Get the next event to be processed after this one. */ Event* next() const { return _next.load(); } @@ -104,20 +110,20 @@ public: /** Set the undo mode of this event. */ void set_mode(Mode mode) { _mode = mode; } - inline Engine& engine() { return _engine; } + Engine& engine() { return _engine; } protected: - Event(Engine& engine, - const SPtr<Interface>& client, - int32_t id, - FrameTime time) - : _engine(engine) - , _next(nullptr) - , _request_client(std::move(client)) - , _request_id(id) - , _time(time) - , _status(Status::NOT_PREPARED) - , _mode(Mode::NORMAL) + Event(Engine& engine, + std::shared_ptr<Interface> client, + int32_t id, + FrameTime time) noexcept + : _engine(engine) + , _next(nullptr) + , _request_client(std::move(client)) + , _request_id(id) + , _time(time) + , _status(Status::NOT_PREPARED) + , _mode(Mode::NORMAL) {} /** Constructor for internal events only */ @@ -130,39 +136,38 @@ protected: , _mode(Mode::NORMAL) {} - inline bool pre_process_done(Status st) { + bool pre_process_done(Status st) { _status = st; return st == Status::SUCCESS; } - inline bool pre_process_done(Status st, const URI& subject) { + bool pre_process_done(Status st, const URI& subject) { _err_subject = subject; return pre_process_done(st); } - inline bool pre_process_done(Status st, const Raul::Path& subject) { + bool pre_process_done(Status st, const raul::Path& subject) { return pre_process_done(st, path_to_uri(subject)); } /** Respond to the originating client. */ - inline Status respond() { + Status respond() { if (_request_client && _request_id) { _request_client->response(_request_id, _status, _err_subject); } return _status; } - Engine& _engine; - std::atomic<Event*> _next; - SPtr<Interface> _request_client; - int32_t _request_id; - FrameTime _time; - Status _status; - std::string _err_subject; - Mode _mode; + Engine& _engine; + std::atomic<Event*> _next; + std::shared_ptr<Interface> _request_client; + int32_t _request_id; + FrameTime _time; + Status _status; + std::string _err_subject; + Mode _mode; }; -} // namespace server -} // namespace ingen +} // namespace ingen::server #endif // INGEN_ENGINE_EVENT_HPP diff --git a/src/server/EventWriter.cpp b/src/server/EventWriter.cpp index c7db23ee..fff9226a 100644 --- a/src/server/EventWriter.cpp +++ b/src/server/EventWriter.cpp @@ -17,18 +17,26 @@ #include "EventWriter.hpp" #include "Engine.hpp" -#include "events.hpp" -#include <boost/variant/apply_visitor.hpp> +#include <events/Connect.hpp> +#include <events/Copy.hpp> +#include <events/Delete.hpp> +#include <events/Delta.hpp> +#include <events/Disconnect.hpp> +#include <events/DisconnectAll.hpp> +#include <events/Get.hpp> +#include <events/Mark.hpp> +#include <events/Move.hpp> +#include <events/Undo.hpp> +#include <ingen/Message.hpp> -namespace ingen { -namespace server { +#include <variant> + +namespace ingen::server { EventWriter::EventWriter(Engine& engine) : _engine(engine) - , _event_mode(Event::Mode::NORMAL) -{ -} +{} SampleCount EventWriter::now() const @@ -39,7 +47,7 @@ EventWriter::now() const void EventWriter::message(const Message& msg) { - boost::apply_visitor(*this, msg); + std::visit(*this, msg); } void @@ -142,5 +150,4 @@ EventWriter::operator()(const Get& msg) _event_mode); } -} // namespace server -} // namespace ingen +} // namespace ingen::server diff --git a/src/server/EventWriter.hpp b/src/server/EventWriter.hpp index 85aa6f70..55ee1158 100644 --- a/src/server/EventWriter.hpp +++ b/src/server/EventWriter.hpp @@ -20,13 +20,13 @@ #include "Event.hpp" #include "types.hpp" -#include "ingen/Interface.hpp" -#include "ingen/Message.hpp" -#include "ingen/URI.hpp" -#include "ingen/types.hpp" +#include <ingen/Interface.hpp> +#include <ingen/Message.hpp> +#include <ingen/URI.hpp> -namespace ingen { -namespace server { +#include <memory> + +namespace ingen::server { class Engine; @@ -39,11 +39,12 @@ public: URI uri() const override { return URI("ingen:/clients/event_writer"); } - SPtr<Interface> respondee() const override { + std::shared_ptr<Interface> respondee() const override { return _respondee; } - void set_respondee(SPtr<Interface> respondee) override { + void set_respondee(const std::shared_ptr<Interface>& respondee) override + { _respondee = respondee; } @@ -60,25 +61,24 @@ public: void operator()(const Delta&); void operator()(const Disconnect&); void operator()(const DisconnectAll&); - void operator()(const Error&) {} + void operator()(const Error&) noexcept {} void operator()(const Get&); void operator()(const Move&); void operator()(const Put&); void operator()(const Redo&); - void operator()(const Response&) {} + void operator()(const Response&) noexcept {} void operator()(const SetProperty&); void operator()(const Undo&); protected: - Engine& _engine; - SPtr<Interface> _respondee; - Event::Mode _event_mode; + Engine& _engine; + std::shared_ptr<Interface> _respondee; + Event::Mode _event_mode{Event::Mode::NORMAL}; private: SampleCount now() const; }; -} // namespace server -} // namespace ingen +} // namespace ingen::server #endif // INGEN_ENGINE_EVENTWRITER_HPP diff --git a/src/server/FrameTimer.hpp b/src/server/FrameTimer.hpp index 57acbaa5..0078f99c 100644 --- a/src/server/FrameTimer.hpp +++ b/src/server/FrameTimer.hpp @@ -17,12 +17,10 @@ #ifndef INGEN_ENGINE_FRAMETIMER_HPP #define INGEN_ENGINE_FRAMETIMER_HPP -#include <chrono> #include <cmath> #include <cstdint> -namespace ingen { -namespace server { +namespace ingen::server { /** Delay-locked loop for monotonic sample time. * @@ -37,13 +35,14 @@ public: static constexpr double us_per_s = 1000000.0; FrameTimer(uint32_t period_size, uint32_t sample_rate) - : tper(((double)period_size / (double)sample_rate) * us_per_s) - , omega(2 * PI * bandwidth / us_per_s * tper) - , b(sqrt(2) * omega) - , c(omega * omega) - , nper(period_size) - { - } + : tper((static_cast<double>(period_size) / + static_cast<double>(sample_rate)) * + us_per_s) + , omega(2 * PI * bandwidth / us_per_s * tper) + , b(sqrt(2) * omega) + , c(omega * omega) + , nper(period_size) + {} /** Update the timer for current real time `usec` and frame `frame`. */ void update(uint64_t usec, uint64_t frame) { @@ -53,7 +52,7 @@ public: } // Calculate loop error - const double e = ((double)usec - t1); + const double e = (static_cast<double>(usec) - t1); // Update loop t0 = t1; @@ -71,7 +70,7 @@ public: return 0; } - const double delta = (double)usec - t0; + const double delta = static_cast<double>(usec) - t0; const double period = t1 - t0; return n0 + std::round(delta / period * nper); } @@ -95,16 +94,15 @@ private: const double b; const double c; - uint64_t nper; - double e2; - double t0; - double t1; - uint64_t n0; - uint64_t n1; - bool initialized; + uint64_t nper = 0U; + double e2 = 0.0; + double t0 = 0.0; + double t1 = 0.0; + uint64_t n0 = 0U; + uint64_t n1 = 0U; + bool initialized = false; }; -} // namespace server -} // namespace ingen +} // namespace ingen::server #endif // INGEN_ENGINE_FRAMETIMER_HPP diff --git a/src/server/GraphImpl.cpp b/src/server/GraphImpl.cpp index 00d4cfd6..9e44a4d4 100644 --- a/src/server/GraphImpl.cpp +++ b/src/server/GraphImpl.cpp @@ -23,37 +23,44 @@ #include "DuplexPort.hpp" #include "Engine.hpp" #include "GraphPlugin.hpp" +#include "InputPort.hpp" +#include "PluginImpl.hpp" #include "PortImpl.hpp" #include "ThreadManager.hpp" -#include "ingen/Forge.hpp" -#include "ingen/URIs.hpp" -#include "ingen/World.hpp" -#include "raul/Maid.hpp" +#include <ingen/Forge.hpp> +#include <ingen/Properties.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIs.hpp> +#include <ingen/World.hpp> +#include <lv2/urid/urid.h> +#include <raul/Array.hpp> +#include <raul/Maid.hpp> +#include <raul/Symbol.hpp> #include <cassert> #include <cstddef> #include <map> +#include <memory> +#include <string> #include <unordered_map> -namespace ingen { -namespace server { +namespace ingen::server { GraphImpl::GraphImpl(Engine& engine, - const Raul::Symbol& symbol, + const raul::Symbol& symbol, uint32_t poly, GraphImpl* parent, SampleRate srate, uint32_t internal_poly) : BlockImpl(new GraphPlugin(engine.world().uris(), engine.world().uris().ingen_Graph, - Raul::Symbol("graph"), + raul::Symbol("graph"), "Ingen Graph"), symbol, poly, parent, srate) , _engine(engine) , _poly_pre(internal_poly) , _poly_process(internal_poly) - , _process(false) { assert(internal_poly >= 1); assert(internal_poly <= 128); @@ -70,7 +77,7 @@ GraphImpl::~GraphImpl() BlockImpl* GraphImpl::duplicate(Engine& engine, - const Raul::Symbol& symbol, + const raul::Symbol& symbol, GraphImpl* parent) { BufferFactory& bufs = *engine.buffer_factory(); @@ -115,8 +122,8 @@ GraphImpl::duplicate(Engine& engine, } // Add duplicates of all arcs - for (const auto& a : _arcs) { - SPtr<ArcImpl> arc = dynamic_ptr_cast<ArcImpl>(a.second); + for (const auto& a : _graph_arcs) { + auto arc = std::dynamic_pointer_cast<ArcImpl>(a.second); if (arc) { auto t = port_map.find(arc->tail()); auto h = port_map.find(arc->head()); @@ -156,11 +163,11 @@ GraphImpl::deactivate() } void -GraphImpl::disable(RunContext& context) +GraphImpl::disable(RunContext& ctx) { _process = false; for (auto& o : _outputs) { - o.clear_buffers(context); + o.clear_buffers(ctx); } } @@ -180,22 +187,22 @@ GraphImpl::prepare_internal_poly(BufferFactory& bufs, uint32_t poly) } bool -GraphImpl::apply_internal_poly(RunContext& context, +GraphImpl::apply_internal_poly(RunContext& ctx, BufferFactory& bufs, - Raul::Maid&, + raul::Maid&, uint32_t poly) { // TODO: Subgraph dynamic polyphony (i.e. changing port polyphony) for (auto& b : _blocks) { - b.apply_poly(context, poly); + b.apply_poly(ctx, poly); } for (auto& b : _blocks) { for (uint32_t j = 0; j < b.num_ports(); ++j) { PortImpl* const port = b.port_impl(j); if (port->is_input() && dynamic_cast<InputPort*>(port)->direct_connect()) { - port->setup_buffers(context, bufs, port->poly()); + port->setup_buffers(ctx, bufs, port->poly()); } port->connect_buffers(); } @@ -203,7 +210,7 @@ GraphImpl::apply_internal_poly(RunContext& context, const bool polyphonic = parent_graph() && (poly == parent_graph()->internal_poly_process()); for (auto& o : _outputs) { - o.setup_buffers(context, bufs, polyphonic ? poly : 1); + o.setup_buffers(ctx, bufs, polyphonic ? poly : 1); } _poly_process = poly; @@ -211,52 +218,52 @@ GraphImpl::apply_internal_poly(RunContext& context, } void -GraphImpl::pre_process(RunContext& context) +GraphImpl::pre_process(RunContext& ctx) { // Mix down input ports and connect buffers for (uint32_t i = 0; i < num_ports(); ++i) { PortImpl* const port = _ports->at(i); if (!port->is_driver_port()) { - port->pre_process(context); - port->pre_run(context); + port->pre_process(ctx); + port->pre_run(ctx); port->connect_buffers(); } } } void -GraphImpl::process(RunContext& context) +GraphImpl::process(RunContext& ctx) { if (!_process) { return; } - pre_process(context); - run(context); - post_process(context); + pre_process(ctx); + run(ctx); + post_process(ctx); } void -GraphImpl::run(RunContext& context) +GraphImpl::run(RunContext& ctx) { if (_compiled_graph) { - _compiled_graph->run(context); + _compiled_graph->run(ctx); } } void -GraphImpl::set_buffer_size(RunContext& context, +GraphImpl::set_buffer_size(RunContext& ctx, BufferFactory& bufs, LV2_URID type, uint32_t size) { - BlockImpl::set_buffer_size(context, bufs, type, size); + BlockImpl::set_buffer_size(ctx, bufs, type, size); if (_compiled_graph) { // FIXME // for (size_t i = 0; i < _compiled_graph->size(); ++i) { // const CompiledBlock& block = (*_compiled_graph)[i]; - // block.block()->set_buffer_size(context, bufs, type, size); + // block.block()->set_buffer_size(ctx, bufs, type, size); // } } } @@ -275,41 +282,43 @@ GraphImpl::remove_block(BlockImpl& block) } void -GraphImpl::add_arc(const SPtr<ArcImpl>& a) +GraphImpl::add_arc(const std::shared_ptr<ArcImpl>& a) { ThreadManager::assert_thread(THREAD_PRE_PROCESS); - _arcs.emplace(std::make_pair(a->tail(), a->head()), a); + _graph_arcs.emplace(std::make_pair(a->tail(), a->head()), a); } -SPtr<ArcImpl> +std::shared_ptr<ArcImpl> GraphImpl::remove_arc(const PortImpl* tail, const PortImpl* dst_port) { ThreadManager::assert_thread(THREAD_PRE_PROCESS); - auto i = _arcs.find(std::make_pair(tail, dst_port)); - if (i != _arcs.end()) { - SPtr<ArcImpl> arc = dynamic_ptr_cast<ArcImpl>(i->second); - _arcs.erase(i); + auto i = _graph_arcs.find(std::make_pair(tail, dst_port)); + if (i != _graph_arcs.end()) { + auto arc = std::dynamic_pointer_cast<ArcImpl>(i->second); + _graph_arcs.erase(i); return arc; - } else { - return SPtr<ArcImpl>(); } + + return nullptr; } bool GraphImpl::has_arc(const PortImpl* tail, const PortImpl* dst_port) const { ThreadManager::assert_thread(THREAD_PRE_PROCESS); - auto i = _arcs.find(std::make_pair(tail, dst_port)); - return (i != _arcs.end()); + auto i = _graph_arcs.find(std::make_pair(tail, dst_port)); + return (i != _graph_arcs.end()); } -void -GraphImpl::set_compiled_graph(MPtr<CompiledGraph>&& cg) +std::unique_ptr<CompiledGraph> +GraphImpl::swap_compiled_graph(std::unique_ptr<CompiledGraph> cg) { if (_compiled_graph && _compiled_graph != cg) { _engine.reset_load(); } - _compiled_graph = std::move(cg); + + _compiled_graph.swap(cg); + return cg; } uint32_t @@ -323,7 +332,7 @@ bool GraphImpl::has_port_with_index(uint32_t index) const { BufferFactory& bufs = *_engine.buffer_factory(); - const auto index_atom = bufs.forge().make(int32_t(index)); + const auto index_atom = bufs.forge().make(static_cast<int32_t>(index)); for (const auto& p : _inputs) { if (p.has_property(bufs.uris().lv2_index, index_atom)) { @@ -357,13 +366,13 @@ GraphImpl::clear_ports() _outputs.clear(); } -MPtr<BlockImpl::Ports> -GraphImpl::build_ports_array(Raul::Maid& maid) +raul::managed_ptr<BlockImpl::Ports> +GraphImpl::build_ports_array(raul::Maid& maid) { ThreadManager::assert_thread(THREAD_PRE_PROCESS); - const size_t n = _inputs.size() + _outputs.size(); - MPtr<Ports> result = maid.make_managed<Ports>(n); + const size_t n = _inputs.size() + _outputs.size(); + raul::managed_ptr<Ports> result = maid.make_managed<Ports>(n); std::map<size_t, DuplexPort*> ports; for (auto& p : _inputs) { @@ -383,5 +392,4 @@ GraphImpl::build_ports_array(Raul::Maid& maid) return result; } -} // namespace server -} // namespace ingen +} // namespace ingen::server diff --git a/src/server/GraphImpl.hpp b/src/server/GraphImpl.hpp index 3e3c6159..6c852106 100644 --- a/src/server/GraphImpl.hpp +++ b/src/server/GraphImpl.hpp @@ -1,6 +1,6 @@ /* This file is part of Ingen. - Copyright 2007-2015 David Robillard <http://drobilla.net/> + Copyright 2007-2023 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 @@ -20,22 +20,31 @@ #include "BlockImpl.hpp" #include "DuplexPort.hpp" #include "ThreadManager.hpp" +#include "server.h" +#include "types.hpp" -#include "ingen/types.hpp" +#include <lv2/urid/urid.h> +#include <raul/Maid.hpp> + +#include <boost/intrusive/options.hpp> +#include <boost/intrusive/slist.hpp> #include <cassert> #include <cstdint> #include <memory> #include <utility> -namespace raul { class Maid; } +namespace raul { +class Symbol; +} // namespace raul -namespace ingen { -namespace server { +namespace ingen::server { class ArcImpl; +class BufferFactory; class CompiledGraph; class Engine; +class PortImpl; class RunContext; /** A group of blocks in a graph, possibly polyphonic. @@ -46,32 +55,32 @@ class RunContext; * * \ingroup engine */ -class GraphImpl final : public BlockImpl +class INGEN_SERVER_API GraphImpl final : public BlockImpl { public: GraphImpl(Engine& engine, - const Raul::Symbol& symbol, + const raul::Symbol& symbol, uint32_t poly, GraphImpl* parent, SampleRate srate, uint32_t internal_poly); - virtual ~GraphImpl(); + ~GraphImpl() override; GraphType graph_type() const override { return GraphType::GRAPH; } BlockImpl* duplicate(Engine& engine, - const Raul::Symbol& symbol, + const raul::Symbol& symbol, GraphImpl* parent) override; void activate(BufferFactory& bufs) override; void deactivate() override; - void pre_process(RunContext& context) override; - void process(RunContext& context) override; - void run(RunContext& context) override; + void pre_process(RunContext& ctx) override; + void process(RunContext& ctx) override; + void run(RunContext& ctx) override; - void set_buffer_size(RunContext& context, + void set_buffer_size(RunContext& ctx, BufferFactory& bufs, LV2_URID type, uint32_t size) override; @@ -87,14 +96,19 @@ public: * * Audio thread. * - * \param context Process context + * \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& context, + bool apply_internal_poly(RunContext& ctx, BufferFactory& bufs, - Raul::Maid& maid, + raul::Maid& maid, uint32_t poly); // Graph specific stuff not inherited from Block @@ -156,28 +170,30 @@ public: /** Add an arc to this graph. * Pre-processing thread only. */ - void add_arc(const SPtr<ArcImpl>& a); + void add_arc(const std::shared_ptr<ArcImpl>& a); /** Remove an arc from this graph. * Pre-processing thread only. */ - SPtr<ArcImpl> remove_arc(const PortImpl* tail, const PortImpl* dst_port); + std::shared_ptr<ArcImpl> + remove_arc(const PortImpl* tail, const PortImpl* dst_port); bool has_arc(const PortImpl* tail, const PortImpl* dst_port) const; /** Set a new compiled graph to run, and return the old one. */ - void set_compiled_graph(MPtr<CompiledGraph>&& cg); + [[nodiscard]] std::unique_ptr<CompiledGraph> + swap_compiled_graph(std::unique_ptr<CompiledGraph> cg); - const MPtr<Ports>& external_ports() { return _ports; } + const raul::managed_ptr<Ports>& external_ports() { return _ports; } - void set_external_ports(MPtr<Ports>&& pa) { _ports = std::move(pa); } + void set_external_ports(raul::managed_ptr<Ports>&& pa) { _ports = std::move(pa); } - MPtr<Ports> build_ports_array(Raul::Maid& maid); + raul::managed_ptr<Ports> build_ports_array(raul::Maid& maid); /** Whether to run this graph's DSP bits in the audio thread */ bool enabled() const { return _process; } void enable() { _process = true; } - void disable(RunContext& context); + void disable(RunContext& ctx); uint32_t internal_poly() const { return _poly_pre; } uint32_t internal_poly_process() const { return _poly_process; } @@ -185,17 +201,18 @@ public: Engine& engine() { return _engine; } private: - Engine& _engine; - uint32_t _poly_pre; ///< Pre-process thread only - uint32_t _poly_process; ///< Process thread only - MPtr<CompiledGraph> _compiled_graph; ///< Process thread only - PortList _inputs; ///< Pre-process thread only - PortList _outputs; ///< Pre-process thread only - Blocks _blocks; ///< Pre-process thread only - bool _process; ///< True iff graph is enabled + using CompiledGraphPtr = std::unique_ptr<CompiledGraph>; + + Engine& _engine; + uint32_t _poly_pre; ///< Pre-process thread only + uint32_t _poly_process; ///< Process thread only + CompiledGraphPtr _compiled_graph; ///< Process thread only + PortList _inputs; ///< Pre-process thread only + PortList _outputs; ///< Pre-process thread only + Blocks _blocks; ///< Pre-process thread only + bool _process{false}; ///< True iff graph is enabled }; -} // namespace server -} // namespace ingen +} // namespace ingen::server #endif // INGEN_ENGINE_GRAPHIMPL_HPP diff --git a/src/server/GraphPlugin.hpp b/src/server/GraphPlugin.hpp index 9e221689..302141e7 100644 --- a/src/server/GraphPlugin.hpp +++ b/src/server/GraphPlugin.hpp @@ -19,12 +19,19 @@ #include "PluginImpl.hpp" +#include <ingen/URI.hpp> +#include <ingen/URIs.hpp> +#include <lilv/lilv.h> +#include <raul/Symbol.hpp> + #include <string> -namespace ingen { -namespace server { +namespace ingen::server { class BlockImpl; +class BufferFactory; +class Engine; +class GraphImpl; /** Implementation of a Graph plugin. * @@ -35,13 +42,13 @@ class GraphPlugin : public PluginImpl public: GraphPlugin(URIs& uris, const URI& uri, - const Raul::Symbol& symbol, + const raul::Symbol& symbol, const std::string& name) - : PluginImpl(uris, uris.ingen_Graph.urid, uri) + : PluginImpl(uris, uris.ingen_Graph.urid_atom(), uri) {} BlockImpl* instantiate(BufferFactory& bufs, - const Raul::Symbol& symbol, + const raul::Symbol& symbol, bool polyphonic, GraphImpl* parent, Engine& engine, @@ -50,15 +57,14 @@ public: return nullptr; } - Raul::Symbol symbol() const override { return Raul::Symbol("graph"); } - std::string name() const { return "Ingen Graph"; } + raul::Symbol symbol() const override { return raul::Symbol("graph"); } + static std::string name() { return "Ingen Graph"; } private: const std::string _symbol; const std::string _name; }; -} // namespace server -} // namespace ingen +} // namespace ingen::server #endif // INGEN_ENGINE_GRAPHPLUGIN_HPP diff --git a/src/server/InputPort.cpp b/src/server/InputPort.cpp index 9d02fd99..01622209 100644 --- a/src/server/InputPort.cpp +++ b/src/server/InputPort.cpp @@ -23,23 +23,27 @@ #include "BufferRef.hpp" #include "GraphImpl.hpp" #include "NodeImpl.hpp" +#include "PortType.hpp" #include "RunContext.hpp" #include "mix.hpp" -#include "ingen/Atom.hpp" -#include "ingen/Node.hpp" -#include "ingen/URIs.hpp" -#include "raul/Array.hpp" +#include <ingen/Atom.hpp> +#include <ingen/Node.hpp> +#include <ingen/URIs.hpp> +#include <lv2/urid/urid.h> +#include <raul/Array.hpp> +#include <raul/Maid.hpp> +#include <algorithm> #include <cassert> #include <cstdlib> +#include <memory> -namespace ingen { -namespace server { +namespace ingen::server { InputPort::InputPort(BufferFactory& bufs, BlockImpl* parent, - const Raul::Symbol& symbol, + const raul::Symbol& symbol, uint32_t index, uint32_t poly, PortType type, @@ -47,19 +51,18 @@ InputPort::InputPort(BufferFactory& bufs, const Atom& value, size_t buffer_size) : PortImpl(bufs, parent, symbol, index, poly, type, buffer_type, value, buffer_size, false) - , _num_arcs(0) { const ingen::URIs& uris = bufs.uris(); if (parent->graph_type() != Node::GraphType::GRAPH) { - add_property(uris.rdf_type, uris.lv2_InputPort.urid); + add_property(uris.rdf_type, uris.lv2_InputPort.urid_atom()); } } bool -InputPort::apply_poly(RunContext& context, const uint32_t poly) +InputPort::apply_poly(RunContext& ctx, const uint32_t poly) { - const bool ret = PortImpl::apply_poly(context, poly); + const bool ret = PortImpl::apply_poly(ctx, poly); (void)ret; assert(_voices->size() >= (ret ? poly : 1)); @@ -68,11 +71,11 @@ InputPort::apply_poly(RunContext& context, const uint32_t poly) } bool -InputPort::get_buffers(BufferFactory& bufs, - PortImpl::GetFn get, - const MPtr<Voices>& voices, - uint32_t poly, - size_t num_in_arcs) const +InputPort::get_buffers(BufferFactory& bufs, + PortImpl::GetFn get, + const raul::managed_ptr<Voices>& voices, + uint32_t poly, + size_t num_in_arcs) const { if (is_a(PortType::ATOM) && !_value.is_valid()) { poly = 1; @@ -100,9 +103,9 @@ InputPort::get_buffers(BufferFactory& bufs, } bool -InputPort::pre_get_buffers(BufferFactory& bufs, - MPtr<Voices>& voices, - uint32_t poly) const +InputPort::pre_get_buffers(BufferFactory& bufs, + raul::managed_ptr<Voices>& voices, + uint32_t poly) const { return get_buffers(bufs, &BufferFactory::get_buffer, voices, poly, _num_arcs); } @@ -144,38 +147,38 @@ InputPort::max_tail_poly(RunContext&) const } void -InputPort::pre_process(RunContext& context) +InputPort::pre_process(RunContext& ctx) { if (_arcs.empty()) { // No incoming arcs, just handle user-set value for (uint32_t v = 0; v < _poly; ++v) { // Update set state - update_set_state(context, v); + update_set_state(ctx, v); // Prepare for write in case a set event executes this cycle if (!_parent->is_main()) { - buffer(v)->prepare_write(context); + buffer(v)->prepare_write(ctx); } } } else if (direct_connect()) { // Directly connected, use source's buffer directly for (uint32_t v = 0; v < _poly; ++v) { - _voices->at(v).buffer = _arcs.front().buffer(context, v); + _voices->at(v).buffer = _arcs.front().buffer(ctx, v); } } else { // Mix down to local buffers in pre_run() for (uint32_t v = 0; v < _poly; ++v) { - buffer(v)->prepare_write(context); + buffer(v)->prepare_write(ctx); } } } void -InputPort::pre_run(RunContext& context) +InputPort::pre_run(RunContext& ctx) { if ((_user_buffer || !_arcs.empty()) && !direct_connect()) { - const uint32_t src_poly = max_tail_poly(context); - const uint32_t max_n_srcs = _arcs.size() * src_poly + 1; + const uint32_t src_poly = max_tail_poly(ctx); + const uint32_t max_n_srcs = (_arcs.size() * src_poly) + 1; for (uint32_t v = 0; v < _poly; ++v) { if (!buffer(v)->get<void>()) { @@ -196,24 +199,24 @@ InputPort::pre_run(RunContext& context) // P -> 1 or 1 -> 1: all tail voices => each head voice for (uint32_t w = 0; w < arc.tail()->poly(); ++w) { assert(n_srcs < max_n_srcs); - srcs[n_srcs++] = arc.buffer(context, w).get(); + srcs[n_srcs++] = arc.buffer(ctx, w).get(); assert(srcs[n_srcs - 1]); } } else { // P -> P or 1 -> P: tail voice => corresponding head voice assert(n_srcs < max_n_srcs); - srcs[n_srcs++] = arc.buffer(context, v).get(); + srcs[n_srcs++] = arc.buffer(ctx, v).get(); assert(srcs[n_srcs - 1]); } } // Then mix them into our buffer for this voice - mix(context, buffer(v).get(), srcs, n_srcs); - update_values(context.offset(), v); + mix(ctx, buffer(v).get(), srcs, n_srcs); + update_values(ctx.offset(), v); } } else if (is_a(PortType::CONTROL)) { for (uint32_t v = 0; v < _poly; ++v) { - update_values(context.offset(), v); + update_values(ctx.offset(), v); } } } @@ -229,19 +232,17 @@ InputPort::next_value_offset(SampleCount offset, SampleCount end) const for (const auto& arc : _arcs) { const SampleCount o = arc.tail()->next_value_offset(offset, end); - if (o < earliest) { - earliest = o; - } + earliest = std::min(o, earliest); } return earliest; } void -InputPort::post_process(RunContext& context) +InputPort::post_process(RunContext& ctx) { if (!_arcs.empty() || _force_monitor_update) { - monitor(context, _force_monitor_update); + monitor(ctx, _force_monitor_update); _force_monitor_update = false; } @@ -259,5 +260,4 @@ InputPort::direct_connect() const && buffer(0)->type() != _bufs.uris().atom_Sequence; } -} // namespace server -} // namespace ingen +} // namespace ingen::server diff --git a/src/server/InputPort.hpp b/src/server/InputPort.hpp index 35ddb2b9..f3c6e553 100644 --- a/src/server/InputPort.hpp +++ b/src/server/InputPort.hpp @@ -19,11 +19,10 @@ #include "ArcImpl.hpp" #include "PortImpl.hpp" -#include "PortType.hpp" #include "types.hpp" -#include "ingen/types.hpp" -#include "lv2/urid/urid.h" +#include <lv2/urid/urid.h> +#include <raul/Maid.hpp> #include <boost/intrusive/options.hpp> #include <boost/intrusive/slist.hpp> @@ -31,10 +30,14 @@ #include <cstdint> #include <cstdlib> -namespace Raul { class Symbol; } +namespace raul { +class Symbol; +} // namespace raul namespace ingen { +enum class PortType; + class Atom; namespace server { @@ -59,7 +62,7 @@ class InputPort : public PortImpl public: InputPort(BufferFactory& bufs, BlockImpl* parent, - const Raul::Symbol& symbol, + const raul::Symbol& symbol, uint32_t index, uint32_t poly, PortType type, @@ -72,9 +75,9 @@ public: boost::intrusive::constant_time_size<true>>; /** Return the maximum polyphony of an output connected to this input. */ - virtual uint32_t max_tail_poly(RunContext& context) const; + virtual uint32_t max_tail_poly(RunContext& ctx) const; - bool apply_poly(RunContext& context, uint32_t poly) override; + bool apply_poly(RunContext& ctx, uint32_t poly) override; /** Add an arc. Realtime safe. * @@ -83,7 +86,7 @@ public: * * setup_buffers() must be called later for the change to take effect. */ - void add_arc(RunContext& context, ArcImpl& c); + void add_arc(RunContext& ctx, ArcImpl& c); /** Remove an arc. Realtime safe. * @@ -93,25 +96,25 @@ public: /** Like `get_buffers`, but for the pre-process thread. * - * This uses the "current" number of arcs fromthe perspective of the + * This uses the "current" number of arcs from the perspective of the * pre-process thread to allocate buffers for application of a * connection/disconnection/etc in the next process cycle. */ - bool pre_get_buffers(BufferFactory& bufs, - MPtr<Voices>& voices, - uint32_t poly) const; + bool pre_get_buffers(BufferFactory& bufs, + raul::managed_ptr<Voices>& voices, + uint32_t poly) const; bool setup_buffers(RunContext& ctx, BufferFactory& bufs, uint32_t poly) override; /** Set up buffer pointers. */ - void pre_process(RunContext& context) override; + void pre_process(RunContext& ctx) override; /** Prepare buffer for access, mixing if necessary. */ - void pre_run(RunContext& context) override; + void pre_run(RunContext& ctx) override; /** Prepare buffer for next process cycle. */ - void post_process(RunContext& context) override; + void post_process(RunContext& ctx) override; SampleCount next_value_offset(SampleCount offset, SampleCount end) const override; @@ -123,14 +126,14 @@ public: bool direct_connect() const; protected: - bool get_buffers(BufferFactory& bufs, - PortImpl::GetFn get, - const MPtr<Voices>& voices, - uint32_t poly, - size_t num_in_arcs) const override; - - size_t _num_arcs; ///< Pre-process thread - Arcs _arcs; ///< Audio thread + bool get_buffers(BufferFactory& bufs, + PortImpl::GetFn get, + const raul::managed_ptr<Voices>& voices, + uint32_t poly, + size_t num_in_arcs) const override; + + size_t _num_arcs{0}; ///< Pre-process thread + Arcs _arcs; ///< Audio thread }; } // namespace server diff --git a/src/server/InternalBlock.cpp b/src/server/InternalBlock.cpp index 3cea7698..2eb0d411 100644 --- a/src/server/InternalBlock.cpp +++ b/src/server/InternalBlock.cpp @@ -23,15 +23,18 @@ #include "PluginImpl.hpp" #include "PortImpl.hpp" -#include "ingen/URIs.hpp" -#include "raul/Array.hpp" +#include <ingen/URIs.hpp> +#include <raul/Array.hpp> + +#include <boost/smart_ptr/intrusive_ptr.hpp> #include <cstddef> #include <cstdint> +#include <memory> -namespace Raul { +namespace raul { class Symbol; -} // namespace Raul +} // namespace raul namespace ingen { @@ -40,10 +43,9 @@ class Atom; namespace server { class GraphImpl; -class RunContext; InternalBlock::InternalBlock(PluginImpl* plugin, - const Raul::Symbol& symbol, + const raul::Symbol& symbol, bool poly, GraphImpl* parent, SampleRate rate) @@ -52,7 +54,7 @@ InternalBlock::InternalBlock(PluginImpl* plugin, BlockImpl* InternalBlock::duplicate(Engine& engine, - const Raul::Symbol& symbol, + const raul::Symbol& symbol, GraphImpl* parent) { BufferFactory& bufs = *engine.buffer_factory(); @@ -70,12 +72,12 @@ InternalBlock::duplicate(Engine& engine, } void -InternalBlock::pre_process(RunContext& context) +InternalBlock::pre_process(RunContext& ctx) { for (uint32_t i = 0; i < num_ports(); ++i) { PortImpl* const port = _ports->at(i); if (port->is_input()) { - port->pre_process(context); + port->pre_process(ctx); } else if (port->buffer_type() == _plugin->uris().atom_Sequence) { /* Output sequences are initialized in LV2 format, an atom:Chunk with size set to the capacity of the buffer. Internal nodes diff --git a/src/server/InternalBlock.hpp b/src/server/InternalBlock.hpp index e7f0ca95..9eca9716 100644 --- a/src/server/InternalBlock.hpp +++ b/src/server/InternalBlock.hpp @@ -18,14 +18,16 @@ #define INGEN_ENGINE_INTERNALBLOCK_HPP #include "BlockImpl.hpp" +#include "types.hpp" -namespace ingen { -namespace server { +namespace raul { +class Symbol; +} // namespace raul + +namespace ingen::server { -class Engine; class GraphImpl; class PluginImpl; -class RunContext; /** An internal Block implemented inside Ingen. * @@ -35,19 +37,18 @@ class InternalBlock : public BlockImpl { public: InternalBlock(PluginImpl* plugin, - const Raul::Symbol& symbol, + const raul::Symbol& symbol, bool poly, GraphImpl* parent, SampleRate rate); BlockImpl* duplicate(Engine& engine, - const Raul::Symbol& symbol, + const raul::Symbol& symbol, GraphImpl* parent) override; - void pre_process(RunContext& context) override; + void pre_process(RunContext& ctx) override; }; -} // namespace server -} // namespace ingen +} // namespace ingen::server #endif // INGEN_ENGINE_BLOCKIMPL_HPP diff --git a/src/server/InternalPlugin.cpp b/src/server/InternalPlugin.cpp index 8d43a321..7670c931 100644 --- a/src/server/InternalPlugin.cpp +++ b/src/server/InternalPlugin.cpp @@ -22,26 +22,27 @@ #include "internals/Note.hpp" #include "internals/Time.hpp" #include "internals/Trigger.hpp" +#include "types.hpp" -#include "ingen/URIs.hpp" +#include <ingen/URI.hpp> +#include <ingen/URIs.hpp> +#include <lilv/lilv.h> +#include <raul/Symbol.hpp> -namespace ingen { -namespace server { +#include <utility> -using namespace internals; +namespace ingen::server { -InternalPlugin::InternalPlugin(URIs& uris, - const URI& uri, - const Raul::Symbol& symbol) - : PluginImpl(uris, uris.ingen_Internal.urid, uri) - , _symbol(symbol) +InternalPlugin::InternalPlugin(URIs& uris, const URI& uri, raul::Symbol symbol) + : PluginImpl(uris, uris.ingen_Internal.urid_atom(), uri) + , _symbol(std::move(symbol)) { set_property(uris.rdf_type, uris.ingen_Internal); } BlockImpl* InternalPlugin::instantiate(BufferFactory& bufs, - const Raul::Symbol& symbol, + const raul::Symbol& symbol, bool polyphonic, GraphImpl* parent, Engine& engine, @@ -50,19 +51,31 @@ InternalPlugin::instantiate(BufferFactory& bufs, const SampleCount srate = engine.sample_rate(); if (uri() == NS_INTERNALS "BlockDelay") { - return new BlockDelayNode(this, bufs, symbol, polyphonic, parent, srate); - } else if (uri() == NS_INTERNALS "Controller") { - return new ControllerNode(this, bufs, symbol, polyphonic, parent, srate); - } else if (uri() == NS_INTERNALS "Note") { - return new NoteNode(this, bufs, symbol, polyphonic, parent, srate); - } else if (uri() == NS_INTERNALS "Time") { - return new TimeNode(this, bufs, symbol, polyphonic, parent, srate); - } else if (uri() == NS_INTERNALS "Trigger") { - return new TriggerNode(this, bufs, symbol, polyphonic, parent, srate); - } else { - return nullptr; + return new internals::BlockDelayNode( + this, bufs, symbol, polyphonic, parent, srate); } + + if (uri() == NS_INTERNALS "Controller") { + return new internals::ControllerNode( + this, bufs, symbol, polyphonic, parent, srate); + } + + if (uri() == NS_INTERNALS "Note") { + return new internals::NoteNode( + this, bufs, symbol, polyphonic, parent, srate); + } + + if (uri() == NS_INTERNALS "Time") { + return new internals::TimeNode( + this, bufs, symbol, polyphonic, parent, srate); + } + + if (uri() == NS_INTERNALS "Trigger") { + return new internals::TriggerNode( + this, bufs, symbol, polyphonic, parent, srate); + } + + return nullptr; } -} // namespace server -} // namespace ingen +} // namespace ingen::server diff --git a/src/server/InternalPlugin.hpp b/src/server/InternalPlugin.hpp index d96ea86a..4d715491 100644 --- a/src/server/InternalPlugin.hpp +++ b/src/server/InternalPlugin.hpp @@ -17,12 +17,12 @@ #ifndef INGEN_ENGINE_INTERNALPLUGIN_HPP #define INGEN_ENGINE_INTERNALPLUGIN_HPP -#include "ingen/URI.hpp" -#include "lilv/lilv.h" -#include "raul/Symbol.hpp" - #include "PluginImpl.hpp" +#include <ingen/URI.hpp> +#include <lilv/lilv.h> +#include <raul/Symbol.hpp> + #define NS_INTERNALS "http://drobilla.net/ns/ingen-internals#" namespace ingen { @@ -31,31 +31,24 @@ class URIs; namespace server { -class BlockImpl; -class BufferFactory; -class Engine; -class GraphImpl; - /** Implementation of an Internal plugin. */ class InternalPlugin : public PluginImpl { public: - InternalPlugin(URIs& uris, - const URI& uri, - const Raul::Symbol& symbol); + InternalPlugin(URIs& uris, const URI& uri, raul::Symbol symbol); BlockImpl* instantiate(BufferFactory& bufs, - const Raul::Symbol& symbol, + const raul::Symbol& symbol, bool polyphonic, GraphImpl* parent, Engine& engine, const LilvState* state) override; - Raul::Symbol symbol() const override { return _symbol; } + raul::Symbol symbol() const override { return _symbol; } private: - const Raul::Symbol _symbol; + const raul::Symbol _symbol; }; } // namespace server diff --git a/src/server/JackDriver.cpp b/src/server/JackDriver.cpp index 6d15f3a8..e508c850 100644 --- a/src/server/JackDriver.cpp +++ b/src/server/JackDriver.cpp @@ -17,62 +17,58 @@ #include "JackDriver.hpp" #include "Buffer.hpp" +#include "BufferFactory.hpp" +#include "BufferRef.hpp" #include "DuplexPort.hpp" #include "Engine.hpp" +#include "FrameTimer.hpp" #include "GraphImpl.hpp" -#include "PortImpl.hpp" +#include "PortType.hpp" +#include "RunContext.hpp" #include "ThreadManager.hpp" #include "ingen_config.h" #include "util.hpp" -#include "ingen/Configuration.hpp" -#include "ingen/LV2Features.hpp" -#include "ingen/Log.hpp" -#include "ingen/URI.hpp" -#include "ingen/URIMap.hpp" -#include "ingen/World.hpp" -#include "ingen/fmt.hpp" -#include "lv2/atom/util.h" - +#include <ingen/Atom.hpp> +#include <ingen/Configuration.hpp> +#include <ingen/Log.hpp> +#include <ingen/Properties.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIMap.hpp> +#include <ingen/URIs.hpp> +#include <ingen/World.hpp> +#include <lv2/atom/atom.h> +#include <lv2/atom/forge.h> +#include <lv2/atom/util.h> +#include <raul/Path.hpp> +#include <raul/Semaphore.hpp> + +#include <jack/jack.h> #include <jack/midiport.h> -#ifdef INGEN_JACK_SESSION -#include <jack/session.h> -#include "ingen/Serialiser.hpp" -#endif -#ifdef HAVE_JACK_METADATA -#include <jack/metadata.h> +#include <jack/transport.h> + +#if USE_JACK_METADATA #include "jackey.h" +#include <jack/metadata.h> #endif #include <cassert> #include <chrono> -#include <cstdlib> -#include <cstring> -#include <mutex> +#include <cstdint> +#include <map> #include <string> #include <utility> using jack_sample_t = jack_default_audio_sample_t; -namespace ingen { -namespace server { +namespace ingen::server { JackDriver::JackDriver(Engine& engine) - : _engine(engine) - , _sem(0) - , _flag(false) - , _client(nullptr) - , _block_length(0) - , _seq_size(0) - , _sample_rate(0) - , _is_activated(false) - , _old_bpm(120.0f) - , _old_frame(0) - , _old_rolling(false) + : _engine(engine) + , _forge() + , _midi_event_type(_engine.world().uris().midi_MidiEvent) { - _midi_event_type = _engine.world().uris().midi_MidiEvent; - lv2_atom_forge_init( - &_forge, &engine.world().uri_map().urid_map_feature()->urid_map); + lv2_atom_forge_init(&_forge, &engine.world().uri_map().urid_map()); } JackDriver::~JackDriver() @@ -88,17 +84,6 @@ JackDriver::attach(const std::string& server_name, { assert(!_client); if (!jack_client) { -#ifdef INGEN_JACK_SESSION - const std::string uuid = _engine.world().jack_uuid(); - if (!uuid.empty()) { - _client = jack_client_open(client_name.c_str(), - JackSessionID, nullptr, - uuid.c_str()); - _engine.log().info("Connected to Jack as `%1%' (UUID `%2%')\n", - client_name.c_str(), uuid); - } -#endif - // Try supplied server name if (!_client && !server_name.empty()) { if ((_client = jack_client_open(client_name.c_str(), @@ -108,7 +93,7 @@ JackDriver::attach(const std::string& server_name, } } - // Either server name not specified, or supplied server name does not exist + // Server name not specified, or that server doesn't exist // Connect to default server if (!_client) { if ((_client = jack_client_open(client_name.c_str(), JackNullOption, nullptr))) { @@ -122,12 +107,13 @@ JackDriver::attach(const std::string& server_name, return false; } } else { - _client = (jack_client_t*)jack_client; + _client = static_cast<jack_client_t*>(jack_client); } _sample_rate = jack_get_sample_rate(_client); _block_length = jack_get_buffer_size(_client); - _seq_size = jack_port_type_get_buffer_size(_client, JACK_DEFAULT_MIDI_TYPE); + _seq_size = static_cast<uint32_t>( + jack_port_type_get_buffer_size(_client, JACK_DEFAULT_MIDI_TYPE)); _fallback_buffer = AudioBufPtr( static_cast<float*>( @@ -137,14 +123,13 @@ JackDriver::attach(const std::string& server_name, jack_set_thread_init_callback(_client, thread_init_cb, this); jack_set_buffer_size_callback(_client, block_length_cb, this); -#ifdef INGEN_JACK_SESSION - jack_set_session_callback(_client, session_cb, this); -#endif for (auto& p : _ports) { register_port(p); } + _timer = std::make_unique<FrameTimer>(_block_length, _sample_rate); + return true; } @@ -174,10 +159,10 @@ JackDriver::activate() if (jack_activate(_client)) { _engine.log().error("Could not activate Jack client, aborting\n"); return false; - } else { - _engine.log().info("Activated Jack client `%1%'\n", - world.conf().option("jack-name").ptr<char>()); } + + _engine.log().info("Activated Jack client `%1%'\n", + world.conf().option("jack-name").ptr<char>()); return true; } @@ -204,7 +189,7 @@ JackDriver::deactivate() } EnginePort* -JackDriver::get_port(const Raul::Path& path) +JackDriver::get_port(const raul::Path& path) { for (auto& p : _ports) { if (p.graph_port()->path() == path) { @@ -216,14 +201,14 @@ JackDriver::get_port(const Raul::Path& path) } void -JackDriver::add_port(RunContext& context, EnginePort* port) +JackDriver::add_port(RunContext& ctx, EnginePort* port) { _ports.push_back(*port); DuplexPort* graph_port = port->graph_port(); if (graph_port->is_a(PortType::AUDIO) || graph_port->is_a(PortType::CV)) { - const SampleCount nframes = context.nframes(); - jack_port_t* jport = (jack_port_t*)port->handle(); + const SampleCount nframes = ctx.nframes(); + auto* jport = static_cast<jack_port_t*>(port->handle()); void* jbuf = jack_port_get_buffer(jport, nframes); /* Jack fails to return a buffer if this is too soon after registering @@ -235,7 +220,7 @@ JackDriver::add_port(RunContext& context, EnginePort* port) } void -JackDriver::remove_port(RunContext& context, EnginePort* port) +JackDriver::remove_port(RunContext&, EnginePort* port) { _ports.erase(_ports.iterator_to(*port)); } @@ -267,7 +252,7 @@ JackDriver::register_port(EnginePort& port) void JackDriver::unregister_port(EnginePort& port) { - if (jack_port_unregister(_client, (jack_port_t*)port.handle())) { + if (jack_port_unregister(_client, static_cast<jack_port_t*>(port.handle()))) { _engine.log().error("Failed to unregister Jack port\n"); } @@ -275,30 +260,33 @@ JackDriver::unregister_port(EnginePort& port) } void -JackDriver::rename_port(const Raul::Path& old_path, - const Raul::Path& new_path) +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) { -#ifdef HAVE_JACK_PORT_RENAME - jack_port_rename( - _client, (jack_port_t*)eport->handle(), new_path.substr(1).c_str()); +#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 } } void -JackDriver::port_property(const Raul::Path& path, +JackDriver::port_property(const raul::Path& path, const URI& uri, const Atom& value) { -#ifdef HAVE_JACK_METADATA +#if USE_JACK_METADATA EnginePort* eport = get_port(path); if (eport) { - const jack_port_t* const jport = (const jack_port_t*)eport->handle(); + const auto* const jport = + static_cast<const jack_port_t*>(eport->handle()); + port_property_internal(jport, uri, value); } #endif @@ -309,7 +297,7 @@ JackDriver::port_property_internal(const jack_port_t* jport, const URI& uri, const Atom& value) { -#ifdef HAVE_JACK_METADATA +#if USE_JACK_METADATA if (uri == _engine.world().uris().lv2_name) { jack_set_property(_client, jack_port_uuid(jport), JACK_METADATA_PRETTY_NAME, value.ptr<char>(), "text/plain"); @@ -348,11 +336,11 @@ JackDriver::create_port(DuplexPort* graph_port) } void -JackDriver::pre_process_port(RunContext& context, EnginePort* port) +JackDriver::pre_process_port(RunContext& ctx, EnginePort* port) { - const URIs& uris = context.engine().world().uris(); - const SampleCount nframes = context.nframes(); - jack_port_t* jack_port = (jack_port_t*)port->handle(); + const URIs& uris = ctx.engine().world().uris(); + const SampleCount nframes = ctx.nframes(); + auto* jack_port = static_cast<jack_port_t*>(port->handle()); DuplexPort* graph_port = port->graph_port(); Buffer* graph_buf = graph_port->buffer(0).get(); void* jack_buf = jack_port_get_buffer(jack_port, nframes); @@ -360,12 +348,12 @@ JackDriver::pre_process_port(RunContext& context, EnginePort* port) if (graph_port->is_a(PortType::AUDIO) || graph_port->is_a(PortType::CV)) { graph_port->set_driver_buffer(jack_buf, nframes * sizeof(float)); if (graph_port->is_input()) { - graph_port->monitor(context); + graph_port->monitor(ctx); } else { graph_port->buffer(0)->clear(); // TODO: Avoid when possible } } else if (graph_port->buffer_type() == uris.atom_Sequence) { - graph_buf->prepare_write(context); + graph_buf->prepare_write(ctx); if (graph_port->is_input()) { // Copy events from Jack port buffer into graph port buffer const jack_nframes_t event_count = jack_midi_get_event_count(jack_buf); @@ -378,16 +366,16 @@ JackDriver::pre_process_port(RunContext& context, EnginePort* port) } } } - graph_port->monitor(context); + graph_port->monitor(ctx); } } void -JackDriver::post_process_port(RunContext& context, EnginePort* port) +JackDriver::post_process_port(RunContext& ctx, EnginePort* port) const { - const URIs& uris = context.engine().world().uris(); - const SampleCount nframes = context.nframes(); - jack_port_t* jack_port = (jack_port_t*)port->handle(); + const URIs& uris = ctx.engine().world().uris(); + const SampleCount nframes = ctx.nframes(); + auto* jack_port = static_cast<jack_port_t*>(port->handle()); DuplexPort* graph_port = port->graph_port(); void* jack_buf = port->buffer(); @@ -400,13 +388,15 @@ JackDriver::post_process_port(RunContext& context, EnginePort* port) if (graph_port->buffer_type() == uris.atom_Sequence) { // Copy LV2 MIDI events to Jack MIDI buffer - Buffer* const graph_buf = graph_port->buffer(0).get(); - LV2_Atom_Sequence* seq = graph_buf->get<LV2_Atom_Sequence>(); + Buffer* const graph_buf = graph_port->buffer(0).get(); + auto* seq = graph_buf->get<LV2_Atom_Sequence>(); jack_midi_clear_buffer(jack_buf); - LV2_ATOM_SEQUENCE_FOREACH(seq, ev) { - const uint8_t* buf = (const uint8_t*)LV2_ATOM_BODY(&ev->body); - if (ev->body.type == _midi_event_type) { + LV2_ATOM_SEQUENCE_FOREACH (seq, ev) { + const auto* buf = + static_cast<const uint8_t*>(LV2_ATOM_BODY(&ev->body)); + + if (ev->body.type == this->_midi_event_type) { jack_midi_event_write( jack_buf, ev->time.frames, buf, ev->body.size); } @@ -421,10 +411,9 @@ JackDriver::post_process_port(RunContext& context, EnginePort* port) } void -JackDriver::append_time_events(RunContext& context, - Buffer& buffer) +JackDriver::append_time_events(RunContext& ctx, Buffer& buffer) { - const URIs& uris = context.engine().world().uris(); + const URIs& uris = ctx.engine().world().uris(); const jack_position_t* pos = &_position; const bool rolling = (_transport_state == JackTransportRolling); @@ -443,7 +432,10 @@ JackDriver::append_time_events(RunContext& context, // Build an LV2 position object to append to the buffer LV2_Atom pos_buf[16]; LV2_Atom_Forge_Frame frame; - lv2_atom_forge_set_buffer(&_forge, (uint8_t*)pos_buf, sizeof(pos_buf)); + lv2_atom_forge_set_buffer(&_forge, + reinterpret_cast<uint8_t*>(pos_buf), + sizeof(pos_buf)); + lv2_atom_forge_object(&_forge, &frame, 0, uris.time_Position); lv2_atom_forge_key(&_forge, uris.time_frame); lv2_atom_forge_long(&_forge, pos->frame); @@ -464,9 +456,17 @@ JackDriver::append_time_events(RunContext& context, } // Append position to buffer at offset 0 (start of this cycle) - LV2_Atom* lpos = (LV2_Atom*)pos_buf; - buffer.append_event( - 0, lpos->size, lpos->type, (const uint8_t*)LV2_ATOM_BODY_CONST(lpos)); + auto* lpos = static_cast<LV2_Atom*>(pos_buf); + buffer.append_event(0, + lpos->size, + lpos->type, + static_cast<const uint8_t*>(LV2_ATOM_BODY_CONST(lpos))); +} + +SampleCount +JackDriver::frame_time() const +{ + return _timer->frame_time(_engine.current_time()) + _engine.block_length(); } /**** Jack Callbacks ****/ @@ -491,6 +491,7 @@ JackDriver::_process_cb(jack_nframes_t nframes) _transport_state = jack_transport_query(_client, &_position); + _timer->update(_engine.current_time(), start_of_current_cycle - _engine.block_length()); _engine.locate(start_of_current_cycle, nframes); // Read input @@ -515,7 +516,7 @@ JackDriver::_process_cb(jack_nframes_t nframes) } void -JackDriver::_thread_init_cb() +JackDriver::thread_init_cb(void*) { ThreadManager::set_flag(THREAD_PROCESS); ThreadManager::set_flag(THREAD_IS_REAL_TIME); @@ -532,56 +533,22 @@ 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 = jack_port_type_get_buffer_size(_client, JACK_DEFAULT_MIDI_TYPE); + _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; } -#ifdef INGEN_JACK_SESSION -void -JackDriver::_session_cb(jack_session_event_t* event) -{ - _engine.log().info("Jack session save to %1%\n", event->session_dir); - - const std::string cmd = fmt("ingen -eg -n %1% -u %2% -l ${SESSION_DIR}", - jack_get_client_name(_client), - event->client_uuid); - - SPtr<Serialiser> serialiser = _engine.world().serialiser(); - if (serialiser) { - std::lock_guard<std::mutex> lock(_engine.world().rdf_mutex()); - - SPtr<Node> root(_engine.root_graph(), NullDeleter<Node>); - serialiser->write_bundle(root, - URI(std::string("file://") + event->session_dir)); - } - - event->command_line = (char*)malloc(cmd.size() + 1); - memcpy(event->command_line, cmd.c_str(), cmd.size() + 1); - jack_session_reply(_client, event); - - switch (event->type) { - case JackSessionSave: - break; - case JackSessionSaveAndQuit: - _engine.log().warn("Jack session quit\n"); - _engine.quit(); - break; - case JackSessionSaveTemplate: - break; - } - - jack_session_event_free(event); -} -#endif - -} // namespace server -} // namespace ingen +} // namespace ingen::server diff --git a/src/server/JackDriver.hpp b/src/server/JackDriver.hpp index 00b1836a..4c8e779e 100644 --- a/src/server/JackDriver.hpp +++ b/src/server/JackDriver.hpp @@ -19,34 +19,35 @@ #include "Driver.hpp" #include "EnginePort.hpp" -#include "ingen_config.h" +#include "types.hpp" -#include "ingen/types.hpp" -#include "lv2/atom/forge.h" -#include "raul/Semaphore.hpp" +#include <ingen/URI.hpp> +#include <ingen/memory.hpp> +#include <lv2/atom/forge.h> +#include <raul/Semaphore.hpp> + +#include <boost/intrusive/options.hpp> +#include <boost/intrusive/slist.hpp> +#include <jack/transport.h> // IWYU pragma: keep +#include <jack/types.h> -#include <jack/jack.h> #include <jack/thread.h> -#include <jack/transport.h> -#ifdef INGEN_JACK_SESSION -#include <jack/session.h> -#endif #include <atomic> -#include <cstddef> #include <cstdint> +#include <exception> +#include <memory> #include <string> -namespace Raul { class Path; } - namespace ingen { + +class Atom; + namespace server { -class DuplexPort; class Engine; -class GraphImpl; -class JackDriver; -class PortImpl; +class FrameTimer; +class RunContext; /** The Jack Driver. * @@ -60,7 +61,7 @@ class JackDriver : public Driver { public: explicit JackDriver(Engine& engine); - ~JackDriver(); + ~JackDriver() override; bool attach(const std::string& server_name, const std::string& client_name, @@ -72,21 +73,21 @@ public: bool dynamic_ports() const override { return true; } EnginePort* create_port(DuplexPort* graph_port) override; - EnginePort* get_port(const Raul::Path& path) override; + EnginePort* get_port(const raul::Path& path) override; - void rename_port(const Raul::Path& old_path, const Raul::Path& new_path) override; - void port_property(const Raul::Path& path, const URI& uri, const Atom& value) override; - void add_port(RunContext& context, EnginePort* port) override; - void remove_port(RunContext& context, EnginePort* port) override; + void rename_port(const raul::Path& old_path, const raul::Path& new_path) override; + void port_property(const raul::Path& path, const URI& uri, const Atom& value) override; + void add_port(RunContext& ctx, EnginePort* port) override; + void remove_port(RunContext& ctx, EnginePort* port) override; void register_port(EnginePort& port) override; void unregister_port(EnginePort& port) override; /** Transport state for this frame. * Intended to only be called from the audio thread. */ - inline const jack_position_t* position() { return &_position; } - inline jack_transport_state_t transport_state() { return _transport_state; } + const jack_position_t* position() { return &_position; } + jack_transport_state_t transport_state() { return _transport_state; } - void append_time_events(RunContext& context, Buffer& buffer) override; + void append_time_events(RunContext& ctx, Buffer& buffer) override; int real_time_priority() override { return jack_client_real_time_priority(_client); @@ -94,76 +95,71 @@ public: jack_client_t* jack_client() const { return _client; } SampleCount block_length() const override { return _block_length; } - size_t seq_size() const override { return _seq_size; } + uint32_t seq_size() const override { return _seq_size; } SampleCount sample_rate() const override { return _sample_rate; } - SampleCount frame_time() const override { - return _client ? jack_frame_time(_client) : 0; - } + SampleCount frame_time() const override; - class PortRegistrationFailedException : public std::exception {}; + class PortRegistrationFailedException : public std::exception + {}; private: friend class JackPort; + static void thread_init_cb(void* jack_driver); + // Static JACK callbacks which call the non-static callbacks (methods) - inline static void thread_init_cb(void* const jack_driver) { - return ((JackDriver*)jack_driver)->_thread_init_cb(); - } - inline static void shutdown_cb(void* const jack_driver) { - return ((JackDriver*)jack_driver)->_shutdown_cb(); - } - inline static int process_cb(jack_nframes_t nframes, void* const jack_driver) { - return ((JackDriver*)jack_driver)->_process_cb(nframes); + + static void shutdown_cb(void* const jack_driver) { + static_cast<JackDriver*>(jack_driver)->_shutdown_cb(); } - inline static int block_length_cb(jack_nframes_t nframes, void* const jack_driver) { - return ((JackDriver*)jack_driver)->_block_length_cb(nframes); + + static int process_cb(jack_nframes_t nframes, void* const jack_driver) { + return static_cast<JackDriver*>(jack_driver)->_process_cb(nframes); } -#ifdef INGEN_JACK_SESSION - inline static void session_cb(jack_session_event_t* event, void* jack_driver) { - ((JackDriver*)jack_driver)->_session_cb(event); + + static int block_length_cb(jack_nframes_t nframes, void* const jack_driver) { + return static_cast<JackDriver*>(jack_driver)->_block_length_cb(nframes); } -#endif - void pre_process_port(RunContext& context, EnginePort* port); - void post_process_port(RunContext& context, EnginePort* port); + // Internal methods for processing + + void pre_process_port(RunContext& ctx, EnginePort* port); + void post_process_port(RunContext& ctx, EnginePort* port) const; void port_property_internal(const jack_port_t* jport, const URI& uri, const Atom& value); // Non static callbacks (methods) - void _thread_init_cb(); void _shutdown_cb(); int _process_cb(jack_nframes_t nframes); int _block_length_cb(jack_nframes_t nframes); -#ifdef INGEN_JACK_SESSION - void _session_cb(jack_session_event_t* event); -#endif protected: using Ports = boost::intrusive::slist<EnginePort, boost::intrusive::cache_last<true>>; - using AudioBufPtr = UPtr<float, FreeDeleter<float>>; - - Engine& _engine; - Ports _ports; - AudioBufPtr _fallback_buffer; - LV2_Atom_Forge _forge; - Raul::Semaphore _sem; - std::atomic<bool> _flag; - jack_client_t* _client; - jack_nframes_t _block_length; - size_t _seq_size; - jack_nframes_t _sample_rate; - uint32_t _midi_event_type; - bool _is_activated; - jack_position_t _position; - jack_transport_state_t _transport_state; - float _old_bpm; - jack_nframes_t _old_frame; - bool _old_rolling; + using AudioBufPtr = std::unique_ptr<float, FreeDeleter<float>>; + + Engine& _engine; + Ports _ports; + AudioBufPtr _fallback_buffer; + LV2_Atom_Forge _forge; + raul::Semaphore _sem{0}; + std::unique_ptr<FrameTimer> _timer; + std::atomic<bool> _flag{false}; + jack_client_t* _client{nullptr}; + jack_nframes_t _block_length{0}; + uint32_t _seq_size{0}; + jack_nframes_t _sample_rate{0}; + uint32_t _midi_event_type; + bool _is_activated{false}; + jack_position_t _position{}; + jack_transport_state_t _transport_state{}; + double _old_bpm{120.0}; + jack_nframes_t _old_frame{0}; + bool _old_rolling{false}; }; } // namespace server diff --git a/src/server/LV2Block.cpp b/src/server/LV2Block.cpp index 124390ff..ad7b28ae 100644 --- a/src/server/LV2Block.cpp +++ b/src/server/LV2Block.cpp @@ -14,38 +14,53 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ +#include "LV2Block.hpp" + #include "Buffer.hpp" +#include "BufferFactory.hpp" #include "Engine.hpp" #include "GraphImpl.hpp" #include "InputPort.hpp" -#include "LV2Block.hpp" #include "LV2Plugin.hpp" #include "OutputPort.hpp" #include "PortImpl.hpp" +#include "PortType.hpp" #include "RunContext.hpp" #include "Worker.hpp" -#include "ingen/FilePath.hpp" -#include "ingen/Forge.hpp" -#include "ingen/Log.hpp" -#include "ingen/URI.hpp" -#include "ingen/URIMap.hpp" -#include "ingen/URIs.hpp" -#include "ingen/World.hpp" -#include "lv2/options/options.h" -#include "lv2/state/state.h" -#include "raul/Array.hpp" -#include "raul/Maid.hpp" +#include <ingen/Atom.hpp> +#include <ingen/FilePath.hpp> +#include <ingen/Forge.hpp> +#include <ingen/LV2Features.hpp> +#include <ingen/Log.hpp> +#include <ingen/Properties.hpp> +#include <ingen/Resource.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIMap.hpp> +#include <ingen/URIs.hpp> +#include <ingen/World.hpp> +#include <lilv/lilv.h> +#include <lv2/core/lv2.h> +#include <lv2/options/options.h> +#include <lv2/state/state.h> +#include <lv2/urid/urid.h> +#include <lv2/worker/worker.h> +#include <raul/Array.hpp> +#include <raul/Maid.hpp> +#include <raul/Path.hpp> +#include <raul/Symbol.hpp> #include <algorithm> #include <cassert> #include <cmath> #include <cstdint> +#include <map> +#include <memory> +#include <optional> #include <string> #include <utility> -namespace ingen { -namespace server { +namespace ingen::server { /** Partially construct a LV2Block. * @@ -53,13 +68,12 @@ namespace server { * (It _will_ crash!) */ LV2Block::LV2Block(LV2Plugin* plugin, - const Raul::Symbol& symbol, + const raul::Symbol& symbol, bool polyphonic, GraphImpl* parent, SampleRate srate) : BlockImpl(plugin, symbol, polyphonic, parent, srate) , _lv2_plugin(plugin) - , _worker_iface(nullptr) { assert(_lv2_plugin); } @@ -75,7 +89,7 @@ LV2Block::~LV2Block() drop_instances(_prepared_instances); } -SPtr<LV2Block::Instance> +std::shared_ptr<LV2Block::Instance> LV2Block::make_instance(URIs& uris, SampleRate rate, uint32_t voice, @@ -89,17 +103,17 @@ LV2Block::make_instance(URIs& uris, if (!inst) { engine.log().error("Failed to instantiate <%1%>\n", _lv2_plugin->uri().c_str()); - return SPtr<Instance>(); + return nullptr; } const LV2_Options_Interface* options_iface = nullptr; if (lilv_plugin_has_extension_data(lplug, uris.opt_interface)) { - options_iface = (const LV2_Options_Interface*) - lilv_instance_get_extension_data(inst, LV2_OPTIONS__interface); + options_iface = static_cast<const LV2_Options_Interface*>( + lilv_instance_get_extension_data(inst, LV2_OPTIONS__interface)); } 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(); @@ -137,7 +151,7 @@ LV2Block::make_instance(URIs& uris, options_iface->get(inst->lv2_handle, options); if (options[0].value) { - LV2_URID type = *(const LV2_URID*)options[0].value; + LV2_URID type = *static_cast<const LV2_URID*>(options[0].value); if (type == _uris.lv2_ControlPort) { port->set_type(PortType::CONTROL, 0); } else if (type == _uris.lv2_CVPort) { @@ -147,7 +161,7 @@ LV2Block::make_instance(URIs& uris, "%1% auto-morphed to unknown type %2%\n", port->path().c_str(), type); - return SPtr<Instance>(); + return nullptr; } } else { parent_graph()->engine().log().error( @@ -177,9 +191,9 @@ LV2Block::prepare_poly(BufferFactory& bufs, uint32_t poly) const SampleRate rate = bufs.engine().sample_rate(); assert(!_prepared_instances); _prepared_instances = bufs.maid().make_managed<Instances>( - poly, *_instances, SPtr<Instance>()); + poly, *_instances, nullptr); for (uint32_t i = _polyphony; i < _prepared_instances->size(); ++i) { - SPtr<Instance> inst = make_instance(bufs.uris(), rate, i, true); + auto inst = make_instance(bufs.uris(), rate, i, true); if (!inst) { _prepared_instances.reset(); return false; @@ -196,7 +210,7 @@ LV2Block::prepare_poly(BufferFactory& bufs, uint32_t poly) } bool -LV2Block::apply_poly(RunContext& context, uint32_t poly) +LV2Block::apply_poly(RunContext& ctx, uint32_t poly) { if (!_polyphonic) { poly = 1; @@ -207,12 +221,12 @@ LV2Block::apply_poly(RunContext& context, uint32_t poly) } assert(poly <= _instances->size()); - return BlockImpl::apply_poly(context, poly); + return BlockImpl::apply_poly(ctx, poly); } /** Instantiate self from LV2 plugin descriptor. * - * Implemented as a seperate function (rather than in the constructor) to + * Implemented as a separate function (rather than in the constructor) to * allow graceful error-catching of broken plugins. * * Returns whether or not plugin was successfully instantiated. If return @@ -246,7 +260,7 @@ LV2Block::instantiate(BufferFactory& bufs, const LilvState* state) /* LV2 port symbols are guaranteed to be unique, valid C identifiers, and Lilv guarantees that lilv_port_get_symbol() is valid. */ - const Raul::Symbol port_sym( + const raul::Symbol port_sym( lilv_node_as_string(lilv_port_get_symbol(plug, id))); // Get port type @@ -260,7 +274,7 @@ LV2Block::instantiate(BufferFactory& bufs, const LilvState* state) is_morph = true; LilvNodes* types = lilv_port_get_value( plug, id, uris.morph_supportsType); - LILV_FOREACH(nodes, i, types) { + LILV_FOREACH (nodes, i, types) { const LilvNode* type = lilv_nodes_get(types, i); if (lilv_node_equals(type, uris.lv2_CVPort)) { port_type = PortType::CV; @@ -291,7 +305,7 @@ LV2Block::instantiate(BufferFactory& bufs, const LilvState* state) if (!buffer_type) { LilvNodes* types = lilv_port_get_value( plug, id, uris.atom_bufferType); - LILV_FOREACH(nodes, i, types) { + LILV_FOREACH (nodes, i, types) { const LilvNode* type = lilv_nodes_get(types, i); if (lilv_node_is_uri(type)) { buffer_type = world.uri_map().map_uri( @@ -316,7 +330,7 @@ LV2Block::instantiate(BufferFactory& bufs, const LilvState* state) if (port_type == PortType::ATOM) { // Get default value, and its length LilvNodes* defaults = lilv_port_get_value(plug, id, uris.lv2_default); - LILV_FOREACH(nodes, i, defaults) { + LILV_FOREACH (nodes, i, defaults) { const LilvNode* d = lilv_nodes_get(defaults, i); if (lilv_node_is_string(d)) { const char* str_val = lilv_node_as_string(d); @@ -336,10 +350,10 @@ LV2Block::instantiate(BufferFactory& bufs, const LilvState* state) // Get minimum size, if set in data LilvNodes* sizes = lilv_port_get_value(plug, id, uris.rsz_minimumSize); - LILV_FOREACH(nodes, i, sizes) { + LILV_FOREACH (nodes, i, sizes) { const LilvNode* d = lilv_nodes_get(sizes, i); if (lilv_node_is_int(d)) { - uint32_t size_val = lilv_node_as_int(d); + const uint32_t size_val = lilv_node_as_int(d); port_buffer_size = std::max(port_buffer_size, size_val); } } @@ -404,11 +418,11 @@ LV2Block::instantiate(BufferFactory& bufs, const LilvState* state) nullptr }; for (int p = 0; preds[p]; ++p) { LilvNodes* values = lilv_port_get_value(plug, id, preds[p]); - LILV_FOREACH(nodes, v, values) { - const LilvNode* val = lilv_nodes_get(values, v); - if (lilv_node_is_uri(val)) { + LILV_FOREACH (nodes, v, values) { + const LilvNode* value = lilv_nodes_get(values, v); + if (lilv_node_is_uri(value)) { port->add_property(URI(lilv_node_as_uri(preds[p])), - forge.make_urid(URI(lilv_node_as_uri(val)))); + forge.make_urid(URI(lilv_node_as_uri(value)))); } } lilv_nodes_free(values); @@ -435,7 +449,7 @@ LV2Block::instantiate(BufferFactory& bufs, const LilvState* state) // Actually create plugin instances and port buffers. const SampleRate rate = bufs.engine().sample_rate(); _instances = bufs.maid().make_managed<Instances>( - _polyphony, SPtr<Instance>()); + _polyphony, nullptr); for (uint32_t i = 0; i < _polyphony; ++i) { _instances->at(i) = make_instance(bufs.uris(), rate, i, false); if (!_instances->at(i)) { @@ -444,9 +458,10 @@ LV2Block::instantiate(BufferFactory& bufs, const LilvState* state) } // Load initial state if no state is explicitly given - LilvState* default_state = nullptr; + StatePtr default_state{}; if (!state) { - state = default_state = load_preset(_lv2_plugin->uri()); + default_state = load_preset(_lv2_plugin->uri()); + state = default_state.get(); } // Apply state @@ -454,15 +469,11 @@ LV2Block::instantiate(BufferFactory& bufs, const LilvState* state) apply_state(nullptr, state); } - if (default_state) { - lilv_state_free(default_state); - } - // FIXME: Polyphony + worker? if (lilv_plugin_has_feature(plug, uris.work_schedule)) { - _worker_iface = (const LV2_Worker_Interface*) + _worker_iface = static_cast<const LV2_Worker_Interface*>( lilv_instance_get_extension_data(instance(0), - LV2_WORKER__interface); + LV2_WORKER__interface)); } return ret; @@ -474,48 +485,62 @@ LV2Block::save_state(const FilePath& dir) const World& world = _lv2_plugin->world(); LilvWorld* lworld = world.lilv_world(); - LilvState* state = lilv_state_new_from_instance( - _lv2_plugin->lilv_plugin(), const_cast<LV2Block*>(this)->instance(0), - &world.uri_map().urid_map_feature()->urid_map, - nullptr, dir.c_str(), dir.c_str(), dir.c_str(), nullptr, nullptr, - LV2_STATE_IS_POD|LV2_STATE_IS_PORTABLE, nullptr); + const StatePtr state{ + lilv_state_new_from_instance(_lv2_plugin->lilv_plugin(), + const_cast<LV2Block*>(this)->instance(0), + &world.uri_map().urid_map(), + nullptr, + dir.c_str(), + dir.c_str(), + dir.c_str(), + nullptr, + nullptr, + LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE, + nullptr)}; if (!state) { return false; - } else if (lilv_state_get_num_properties(state) == 0) { - lilv_state_free(state); + } + + if (lilv_state_get_num_properties(state.get()) == 0) { return false; } lilv_state_save(lworld, - &world.uri_map().urid_map_feature()->urid_map, - &world.uri_map().urid_unmap_feature()->urid_unmap, - state, + &world.uri_map().urid_map(), + &world.uri_map().urid_unmap(), + state.get(), nullptr, dir.c_str(), "state.ttl"); - lilv_state_free(state); - return true; } BlockImpl* LV2Block::duplicate(Engine& engine, - const Raul::Symbol& symbol, + const raul::Symbol& symbol, GraphImpl* parent) { const SampleRate rate = engine.sample_rate(); // Get current state - LilvState* state = lilv_state_new_from_instance( - _lv2_plugin->lilv_plugin(), instance(0), - &engine.world().uri_map().urid_map_feature()->urid_map, - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, LV2_STATE_IS_NATIVE, nullptr); + const StatePtr state{ + lilv_state_new_from_instance(_lv2_plugin->lilv_plugin(), + instance(0), + &engine.world().uri_map().urid_map(), + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + LV2_STATE_IS_NATIVE, + nullptr)}; // Duplicate and instantiate block auto* dup = new LV2Block(_lv2_plugin, symbol, _polyphonic, parent, rate); - if (!dup->instantiate(*engine.buffer_factory(), state)) { + if (!dup->instantiate(*engine.buffer_factory(), state.get())) { delete dup; return nullptr; } @@ -558,7 +583,7 @@ LV2Block::work_respond(LV2_Worker_Respond_Handle handle, uint32_t size, const void* data) { - auto* block = (LV2Block*)handle; + auto* block = static_cast<LV2Block*>(handle); auto* r = new LV2Block::Response(size, data); block->_responses.push_back(*r); return LV2_WORKER_SUCCESS; @@ -568,10 +593,10 @@ LV2_Worker_Status LV2Block::work(uint32_t size, const void* data) { if (_worker_iface) { - std::lock_guard<std::mutex> lock(_work_mutex); + const std::lock_guard<std::mutex> lock{_work_mutex}; - LV2_Handle inst = lilv_instance_get_handle(instance(0)); - LV2_Worker_Status st = _worker_iface->work(inst, work_respond, this, size, data); + LV2_Handle inst = lilv_instance_get_handle(instance(0)); + const LV2_Worker_Status st = _worker_iface->work(inst, work_respond, this, size, data); if (st) { parent_graph()->engine().log().error( "Error calling %1% work method\n", _path); @@ -582,15 +607,15 @@ LV2Block::work(uint32_t size, const void* data) } void -LV2Block::run(RunContext& context) +LV2Block::run(RunContext& ctx) { for (uint32_t i = 0; i < _polyphony; ++i) { - lilv_instance_run(instance(i), context.nframes()); + lilv_instance_run(instance(i), ctx.nframes()); } } void -LV2Block::post_process(RunContext& context) +LV2Block::post_process(RunContext& ctx) { /* Handle any worker responses. Note that this may write to output ports, so must be done first to prevent clobbering worker responses and @@ -601,7 +626,7 @@ LV2Block::post_process(RunContext& context) Response& r = _responses.front(); _worker_iface->work_response(inst, r.size, r.data); _responses.pop_front(); - context.engine().maid()->dispose(&r); + ctx.engine().maid()->dispose(&r); } if (_worker_iface->end_run) { @@ -610,10 +635,10 @@ LV2Block::post_process(RunContext& context) } /* Run cycle truly finished, finalise output ports. */ - BlockImpl::post_process(context); + BlockImpl::post_process(ctx); } -LilvState* +StatePtr LV2Block::load_preset(const URI& uri) { World& world = _lv2_plugin->world(); @@ -624,35 +649,33 @@ LV2Block::load_preset(const URI& uri) lilv_world_load_resource(lworld, preset); // Load preset from world - LV2_URID_Map* map = &world.uri_map().urid_map_feature()->urid_map; - LilvState* state = lilv_state_new_from_world(lworld, map, preset); + LV2_URID_Map* map = &world.uri_map().urid_map(); + StatePtr state{lilv_state_new_from_world(lworld, map, preset)}; lilv_node_free(preset); return state; } -LilvState* +StatePtr LV2Block::load_state(World& world, const FilePath& path) { LilvWorld* lworld = world.lilv_world(); const URI uri = URI(path); LilvNode* subject = lilv_new_uri(lworld, uri.c_str()); - LilvState* state = lilv_state_new_from_file( - lworld, - &world.uri_map().urid_map_feature()->urid_map, - subject, - path.c_str()); + StatePtr state{lilv_state_new_from_file( + lworld, &world.uri_map().urid_map(), subject, path.c_str())}; lilv_node_free(subject); return state; } void -LV2Block::apply_state(const UPtr<Worker>& worker, const LilvState* state) +LV2Block::apply_state(const std::unique_ptr<Worker>& worker, + const LilvState* state) { - World& world = parent_graph()->engine().world(); - SPtr<LV2_Feature> sched; + World& world = parent_graph()->engine().world(); + std::shared_ptr<LV2_Feature> sched; if (worker) { sched = worker->schedule_feature()->feature(world, this); } @@ -673,8 +696,8 @@ get_port_value(const char* port_symbol, uint32_t* size, uint32_t* type) { - auto* const block = (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(); @@ -685,40 +708,46 @@ get_port_value(const char* port_symbol, return nullptr; } -boost::optional<Resource> +std::optional<Resource> LV2Block::save_preset(const URI& uri, const Properties& props) { World& world = parent_graph()->engine().world(); LilvWorld* lworld = world.lilv_world(); - LV2_URID_Map* lmap = &world.uri_map().urid_map_feature()->urid_map; - LV2_URID_Unmap* lunmap = &world.uri_map().urid_unmap_feature()->urid_unmap; + LV2_URID_Map* lmap = &world.uri_map().urid_map(); + LV2_URID_Unmap* lunmap = &world.uri_map().urid_unmap(); const FilePath path = FilePath(uri.path()); const FilePath dirname = path.parent_path(); const FilePath basename = path.stem(); - LilvState* state = lilv_state_new_from_instance( - _lv2_plugin->lilv_plugin(), instance(0), lmap, - nullptr, nullptr, nullptr, path.c_str(), - get_port_value, this, LV2_STATE_IS_NATIVE, nullptr); + const StatePtr state{lilv_state_new_from_instance(_lv2_plugin->lilv_plugin(), + instance(0), + lmap, + nullptr, + nullptr, + nullptr, + path.c_str(), + get_port_value, + this, + LV2_STATE_IS_NATIVE, + nullptr)}; if (state) { - const Properties::const_iterator l = props.find(_uris.rdfs_label); + const auto l = props.find(_uris.rdfs_label); if (l != props.end() && l->second.type() == _uris.atom_String) { - lilv_state_set_label(state, l->second.ptr<char>()); + lilv_state_set_label(state.get(), l->second.ptr<char>()); } - lilv_state_save(lworld, lmap, lunmap, state, nullptr, + lilv_state_save(lworld, lmap, lunmap, state.get(), nullptr, dirname.c_str(), basename.c_str()); - const URI uri(lilv_node_as_uri(lilv_state_get_uri(state))); - const std::string label(lilv_state_get_label(state) - ? lilv_state_get_label(state) - : basename); - lilv_state_free(state); + const URI state_uri(lilv_node_as_uri(lilv_state_get_uri(state.get()))); + const std::string label(lilv_state_get_label(state.get()) + ? lilv_state_get_label(state.get()) + : basename); - Resource preset(_uris, uri); + Resource preset(_uris, state_uri); preset.set_property(_uris.rdf_type, _uris.pset_Preset); preset.set_property(_uris.rdfs_label, world.forge().alloc(label)); preset.set_property(_uris.lv2_appliesTo, @@ -729,10 +758,10 @@ LV2Block::save_preset(const URI& uri, lilv_world_load_bundle(lworld, lbundle); lilv_node_free(lbundle); - return preset; + return {preset}; } - return boost::optional<Resource>(); + return {}; } void @@ -748,5 +777,4 @@ LV2Block::set_port_buffer(uint32_t voice, buf ? buf->port_data(_ports->at(port_num)->type(), offset) : nullptr); } -} // namespace server -} // namespace ingen +} // namespace ingen::server diff --git a/src/server/LV2Block.hpp b/src/server/LV2Block.hpp index 9b454b07..78b5ffac 100644 --- a/src/server/LV2Block.hpp +++ b/src/server/LV2Block.hpp @@ -17,30 +17,42 @@ #ifndef INGEN_ENGINE_LV2BLOCK_HPP #define INGEN_ENGINE_LV2BLOCK_HPP -#include "BufferRef.hpp" #include "BlockImpl.hpp" +#include "BufferRef.hpp" +#include "State.hpp" #include "types.hpp" -#include "ingen/LV2Features.hpp" -#include "lilv/lilv.h" -#include "lv2/worker/worker.h" -#include "raul/Array.hpp" -#include "raul/Maid.hpp" -#include "raul/Noncopyable.hpp" +#include <ingen/LV2Features.hpp> +#include <lilv/lilv.h> +#include <lv2/worker/worker.h> +#include <raul/Array.hpp> +#include <raul/Maid.hpp> +#include <raul/Noncopyable.hpp> +#include <boost/intrusive/options.hpp> #include <boost/intrusive/slist.hpp> +#include <boost/intrusive/slist_hook.hpp> #include <cstdint> #include <cstdlib> #include <cstring> +#include <filesystem> +#include <memory> #include <mutex> +namespace raul { +class Symbol; +} // namespace raul + namespace ingen { -class FilePath; +class URIs; +class World; namespace server { +class BufferFactory; +class GraphImpl; class LV2Plugin; /** An instance of a LV2 plugin. @@ -51,68 +63,67 @@ class LV2Block final : public BlockImpl { public: LV2Block(LV2Plugin* plugin, - const Raul::Symbol& symbol, + const raul::Symbol& symbol, bool polyphonic, GraphImpl* parent, SampleRate srate); - ~LV2Block(); + ~LV2Block() override; bool instantiate(BufferFactory& bufs, const LilvState* state); LilvInstance* instance() override { return instance(0); } - bool save_state(const FilePath& dir) const override; + bool save_state(const std::filesystem::path& dir) const override; BlockImpl* duplicate(Engine& engine, - const Raul::Symbol& symbol, + const raul::Symbol& symbol, GraphImpl* parent) override; bool prepare_poly(BufferFactory& bufs, uint32_t poly) override; - bool apply_poly(RunContext& context, uint32_t poly) override; + bool apply_poly(RunContext& ctx, uint32_t poly) override; void activate(BufferFactory& bufs) override; void deactivate() override; LV2_Worker_Status work(uint32_t size, const void* data); - void run(RunContext& context) override; - void post_process(RunContext& context) override; + void run(RunContext& ctx) override; + void post_process(RunContext& ctx) override; - LilvState* load_preset(const URI& uri) override; + StatePtr load_preset(const URI& uri) override; - void apply_state(const UPtr<Worker>& worker, const LilvState* state) override; + void apply_state(const std::unique_ptr<Worker>& worker, + const LilvState* state) override; - boost::optional<Resource> save_preset(const URI& uri, - const Properties& props) override; + std::optional<Resource> save_preset(const URI& uri, + const Properties& props) override; void set_port_buffer(uint32_t voice, uint32_t port_num, const BufferRef& buf, SampleCount offset) override; - static LilvState* load_state(World& world, const FilePath& path); + static StatePtr load_state(World& world, const std::filesystem::path& path); protected: - struct Instance : public Raul::Noncopyable { - explicit Instance(LilvInstance* i) : instance(i) {} + struct Instance : public raul::Noncopyable { + explicit Instance(LilvInstance* i) noexcept : instance(i) {} ~Instance() { lilv_instance_free(instance); } LilvInstance* const instance; }; - SPtr<Instance> make_instance(URIs& uris, - SampleRate rate, - uint32_t voice, - bool preparing); + std::shared_ptr<Instance> + make_instance(URIs& uris, SampleRate rate, uint32_t voice, bool preparing); - inline LilvInstance* instance(uint32_t voice) { - return (LilvInstance*)(*_instances)[voice]->instance; + LilvInstance* instance(uint32_t voice) { + return static_cast<LilvInstance*>((*_instances)[voice]->instance); } - using Instances = Raul::Array<SPtr<Instance>>; + using Instances = raul::Array<std::shared_ptr<Instance>>; - void drop_instances(const MPtr<Instances>& instances) { + static void drop_instances(const raul::managed_ptr<Instances>& instances) { if (instances) { for (size_t i = 0; i < instances->size(); ++i) { (*instances)[i].reset(); @@ -120,18 +131,17 @@ protected: } } - struct Response : public Raul::Maid::Disposable - , public Raul::Noncopyable - , public boost::intrusive::slist_base_hook<> - { - inline Response(uint32_t s, const void* d) + struct Response : public raul::Maid::Disposable + , public raul::Noncopyable + , public boost::intrusive::slist_base_hook<> { + Response(uint32_t s, const void* d) : size(s) , data(malloc(s)) { memcpy(data, d, s); } - ~Response() { + ~Response() override { free(data); } @@ -147,13 +157,13 @@ protected: static LV2_Worker_Status work_respond( LV2_Worker_Respond_Handle handle, uint32_t size, const void* data); - LV2Plugin* _lv2_plugin; - MPtr<Instances> _instances; - MPtr<Instances> _prepared_instances; - const LV2_Worker_Interface* _worker_iface; - std::mutex _work_mutex; - Responses _responses; - SPtr<LV2Features::FeatureArray> _features; + LV2Plugin* _lv2_plugin; + raul::managed_ptr<Instances> _instances; + raul::managed_ptr<Instances> _prepared_instances; + const LV2_Worker_Interface* _worker_iface{nullptr}; + std::mutex _work_mutex; + Responses _responses; + std::shared_ptr<LV2Features::FeatureArray> _features; }; } // namespace server diff --git a/src/server/LV2Options.hpp b/src/server/LV2Options.hpp index fbe46eee..b1b57429 100644 --- a/src/server/LV2Options.hpp +++ b/src/server/LV2Options.hpp @@ -17,14 +17,25 @@ #ifndef INGEN_ENGINE_LV2OPTIONS_HPP #define INGEN_ENGINE_LV2OPTIONS_HPP -#include "ingen/LV2Features.hpp" -#include "ingen/URIs.hpp" -#include "lv2/options/options.h" +#include <ingen/LV2Features.hpp> +#include <ingen/URIs.hpp> +#include <lv2/core/lv2.h> +#include <lv2/options/options.h> + +#include <cstdint> +#include <cstdlib> +#include <cstring> +#include <memory> namespace ingen { + +class Node; +class World; + namespace server { -class LV2Options : public ingen::LV2Features::Feature { +class LV2Options : public ingen::LV2Features::Feature +{ public: explicit LV2Options(const URIs& uris) : _uris(uris) @@ -38,7 +49,7 @@ public: const char* uri() const override { return LV2_OPTIONS__options; } - SPtr<LV2_Feature> feature(World& w, Node* n) override { + std::shared_ptr<LV2_Feature> feature(World& w, Node* n) override { const LV2_Options_Option options[] = { { LV2_OPTIONS_INSTANCE, 0, _uris.bufsz_minBlockLength, sizeof(int32_t), _uris.atom_Int, &_block_length }, @@ -51,18 +62,18 @@ public: { LV2_OPTIONS_INSTANCE, 0, 0, 0, 0, nullptr } }; - LV2_Feature* f = (LV2_Feature*)malloc(sizeof(LV2_Feature)); + auto* f = static_cast<LV2_Feature*>(malloc(sizeof(LV2_Feature))); f->URI = LV2_OPTIONS__options; f->data = malloc(sizeof(options)); memcpy(f->data, options, sizeof(options)); - return SPtr<LV2_Feature>(f, &free_feature); + return {f, &free_feature}; } private: const URIs& _uris; - int32_t _sample_rate; - int32_t _block_length; - int32_t _seq_size; + int32_t _sample_rate = 0; + int32_t _block_length = 0; + int32_t _seq_size = 0; }; } // namespace server diff --git a/src/server/LV2Plugin.cpp b/src/server/LV2Plugin.cpp index 01357d8d..87072ab0 100644 --- a/src/server/LV2Plugin.cpp +++ b/src/server/LV2Plugin.cpp @@ -19,20 +19,22 @@ #include "Engine.hpp" #include "LV2Block.hpp" -#include "ingen/Forge.hpp" -#include "ingen/Log.hpp" -#include "ingen/URIs.hpp" -#include "ingen/World.hpp" +#include <ingen/Forge.hpp> +#include <ingen/Log.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIs.hpp> +#include <ingen/World.hpp> +#include <lilv/lilv.h> +#include <raul/Symbol.hpp> #include <cstdlib> #include <string> -namespace ingen { -namespace server { +namespace ingen::server { LV2Plugin::LV2Plugin(World& world, const LilvPlugin* lplugin) : PluginImpl(world.uris(), - world.uris().lv2_Plugin.urid, + world.uris().lv2_Plugin.urid_atom(), URI(lilv_node_as_uri(lilv_plugin_get_uri(lplugin)))) , _world(world) , _lilv_plugin(lplugin) @@ -65,31 +67,31 @@ LV2Plugin::update_properties() lilv_node_free(micro); } -Raul::Symbol +raul::Symbol LV2Plugin::symbol() const { std::string working = uri(); if (working.back() == '/') { - working = working.substr(0, working.length() - 1); + working.resize(working.length() - 1); } - while (working.length() > 0) { - size_t last_slash = working.find_last_of('/'); + while (!working.empty()) { + const size_t last_slash = working.find_last_of('/'); const std::string symbol = working.substr(last_slash+1); if ( (symbol[0] >= 'a' && symbol[0] <= 'z') || (symbol[0] >= 'A' && symbol[0] <= 'Z') ) { - return Raul::Symbol::symbolify(symbol); - } else { - working = working.substr(0, last_slash); + return raul::Symbol::symbolify(symbol); } + + working.resize(last_slash); } - return Raul::Symbol("lv2_symbol"); + return raul::Symbol("lv2_symbol"); } BlockImpl* LV2Plugin::instantiate(BufferFactory& bufs, - const Raul::Symbol& symbol, + const raul::Symbol& symbol, bool polyphonic, GraphImpl* parent, Engine& engine, @@ -101,9 +103,9 @@ LV2Plugin::instantiate(BufferFactory& bufs, if (!b->instantiate(bufs, state)) { delete b; return nullptr; - } else { - return b; } + + return b; } void @@ -114,7 +116,7 @@ LV2Plugin::load_presets() LilvNodes* presets = lilv_plugin_get_related(_lilv_plugin, uris.pset_Preset); if (presets) { - LILV_FOREACH(nodes, i, presets) { + LILV_FOREACH (nodes, i, presets) { const LilvNode* preset = lilv_nodes_get(presets, i); lilv_world_load_resource(lworld, preset); @@ -140,5 +142,4 @@ LV2Plugin::load_presets() PluginImpl::load_presets(); } -} // namespace server -} // namespace ingen +} // namespace ingen::server diff --git a/src/server/LV2Plugin.hpp b/src/server/LV2Plugin.hpp index 24d764cc..c94e88f7 100644 --- a/src/server/LV2Plugin.hpp +++ b/src/server/LV2Plugin.hpp @@ -19,9 +19,8 @@ #include "PluginImpl.hpp" -#include "ingen/URI.hpp" -#include "lilv/lilv.h" -#include "raul/Symbol.hpp" +#include <ingen/URI.hpp> +#include <lilv/lilv.h> namespace ingen { @@ -29,11 +28,6 @@ class World; namespace server { -class BlockImpl; -class BufferFactory; -class Engine; -class GraphImpl; - /** Implementation of an LV2 plugin (loaded shared library). */ class LV2Plugin : public PluginImpl @@ -42,13 +36,13 @@ public: LV2Plugin(World& world, const LilvPlugin* lplugin); BlockImpl* instantiate(BufferFactory& bufs, - const Raul::Symbol& symbol, + const raul::Symbol& symbol, bool polyphonic, GraphImpl* parent, Engine& engine, const LilvState* state) override; - Raul::Symbol symbol() const override; + raul::Symbol symbol() const override; World& world() const { return _world; } const LilvPlugin* lilv_plugin() const { return _lilv_plugin; } diff --git a/src/server/LV2ResizeFeature.hpp b/src/server/LV2ResizeFeature.hpp index 1bd93ee0..66720e0d 100644 --- a/src/server/LV2ResizeFeature.hpp +++ b/src/server/LV2ResizeFeature.hpp @@ -21,11 +21,12 @@ #include "Buffer.hpp" #include "PortImpl.hpp" -#include "ingen/LV2Features.hpp" -#include "lv2/resize-port/resize-port.h" +#include <ingen/LV2Features.hpp> +#include <lv2/resize-port/resize-port.h> -namespace ingen { -namespace server { +#include <memory> + +namespace ingen::server { struct ResizeFeature : public ingen::LV2Features::Feature { static LV2_Resize_Port_Status resize_port( @@ -44,10 +45,11 @@ struct ResizeFeature : public ingen::LV2Features::Feature { const char* uri() const { return LV2_RESIZE_PORT_URI; } - SPtr<LV2_Feature> feature(World& w, Node* n) { + std::shared_ptr<LV2_Feature> feature(World& w, Node* n) { BlockImpl* block = dynamic_cast<BlockImpl*>(n); - if (!block) - return SPtr<LV2_Feature>(); + if (!block) { + return nullptr; + } LV2_Resize_Port_Resize* data = (LV2_Resize_Port_Resize*)malloc(sizeof(LV2_Resize_Port_Resize)); data->data = block; @@ -55,11 +57,10 @@ struct ResizeFeature : public ingen::LV2Features::Feature { LV2_Feature* f = (LV2_Feature*)malloc(sizeof(LV2_Feature)); f->URI = LV2_RESIZE_PORT_URI; f->data = data; - return SPtr<LV2_Feature>(f, &free_feature); + return std::shared_ptr<LV2_Feature>(f, &free_feature); } }; -} // namespace server -} // namespace ingen +} // namespace ingen::server #endif // INGEN_ENGINE_LV2RESIZEFEATURE_HPP diff --git a/src/server/Load.hpp b/src/server/Load.hpp index 2d806684..a5216f7e 100644 --- a/src/server/Load.hpp +++ b/src/server/Load.hpp @@ -21,11 +21,9 @@ #include <cstdint> #include <limits> -namespace ingen { -namespace server { +namespace ingen::server { -struct Load -{ +struct Load { void update(uint64_t time, uint64_t available) { const uint64_t load = time * 100 / available; if (load < min) { @@ -40,7 +38,9 @@ struct Load mean = load; changed = true; } else { - const float a = mean + ((float)load - mean) / (float)++n; + const float a = mean + ((static_cast<float>(load) - mean) / + static_cast<float>(++n)); + if (a != mean) { changed = floorf(a) != floorf(mean); mean = a; @@ -55,7 +55,6 @@ struct Load bool changed = false; }; -} // namespace server -} // namespace ingen +} // namespace ingen::server #endif // INGEN_ENGINE_LOAD_HPP diff --git a/src/server/NodeImpl.cpp b/src/server/NodeImpl.cpp index 47d4a990..e820a44e 100644 --- a/src/server/NodeImpl.cpp +++ b/src/server/NodeImpl.cpp @@ -20,27 +20,24 @@ #include "GraphImpl.hpp" #include "ThreadManager.hpp" -#include "ingen/Atom.hpp" -#include "ingen/Properties.hpp" -#include "raul/Path.hpp" +#include <ingen/Atom.hpp> +#include <ingen/Node.hpp> +#include <ingen/Properties.hpp> +#include <raul/Path.hpp> #include <map> #include <utility> -namespace Raul { class Symbol; } - -namespace ingen { -namespace server { +namespace ingen::server { NodeImpl::NodeImpl(const ingen::URIs& uris, NodeImpl* parent, - const Raul::Symbol& symbol) - : Node(uris, parent ? parent->path().child(symbol) : Raul::Path("/")) + const raul::Symbol& symbol) + : Node(uris, parent ? parent->path().child(symbol) : raul::Path("/")) , _parent(parent) - , _path(parent ? parent->path().child(symbol) : Raul::Path("/")) + , _path(parent ? parent->path().child(symbol) : raul::Path("/")) , _symbol(symbol) -{ -} +{} const Atom& NodeImpl::get_property(const URI& key) const @@ -54,8 +51,7 @@ NodeImpl::get_property(const URI& key) const GraphImpl* NodeImpl::parent_graph() const { - return dynamic_cast<GraphImpl*>((BlockImpl*)_parent); + return dynamic_cast<GraphImpl*>(reinterpret_cast<BlockImpl*>(_parent)); } -} // namespace server -} // namespace ingen +} // namespace ingen::server diff --git a/src/server/NodeImpl.hpp b/src/server/NodeImpl.hpp index 1b73e792..fcf2f57f 100644 --- a/src/server/NodeImpl.hpp +++ b/src/server/NodeImpl.hpp @@ -17,17 +17,15 @@ #ifndef INGEN_ENGINE_NODEIMPL_HPP #define INGEN_ENGINE_NODEIMPL_HPP -#include "ingen/Node.hpp" -#include "ingen/URI.hpp" -#include "ingen/paths.hpp" -#include "raul/Path.hpp" -#include "raul/Symbol.hpp" +#include <ingen/Node.hpp> +#include <ingen/paths.hpp> +#include <raul/Path.hpp> +#include <raul/Symbol.hpp> #include <cstdint> namespace ingen { -class Atom; class URIs; namespace server { @@ -38,7 +36,7 @@ class RunContext; /** An object on the audio graph (a Graph, Block, or Port). * - * Each of these is a Raul::Deletable and so can be deleted in a realtime safe + * Each of these is a raul::Deletable and so can be deleted in a realtime safe * way from anywhere, and they all have a map of variable for clients to store * arbitrary values in (which the engine puts no significance to whatsoever). * @@ -47,17 +45,17 @@ class RunContext; class NodeImpl : public Node { public: - const Raul::Symbol& symbol() const override { return _symbol; } + const raul::Symbol& symbol() const override { return _symbol; } Node* graph_parent() const override { return _parent; } NodeImpl* parent() const { return _parent; } /** Rename */ - void set_path(const Raul::Path& new_path) override { + void set_path(const raul::Path& new_path) override { _path = new_path; const char* const new_sym = new_path.symbol(); if (new_sym[0] != '\0') { - _symbol = Raul::Symbol(new_sym); + _symbol = raul::Symbol(new_sym); } set_uri(path_to_uri(new_path)); } @@ -67,7 +65,7 @@ public: /** The Graph this object is a child of. */ virtual GraphImpl* parent_graph() const; - const Raul::Path& path() const override { return _path; } + const raul::Path& path() const override { return _path; } /** Prepare for a new (external) polyphony value. * @@ -78,10 +76,10 @@ public: /** Apply a new (external) polyphony value. * - * \param context Process context (process thread only). + * \param ctx Process context (process thread only). * \param poly Must be <= the most recent value passed to prepare_poly. */ - virtual bool apply_poly(RunContext& context, uint32_t poly) = 0; + virtual bool apply_poly(RunContext& ctx, uint32_t poly) = 0; /** Return true iff this is main (the top level Node). * @@ -94,11 +92,11 @@ public: protected: NodeImpl(const ingen::URIs& uris, NodeImpl* parent, - const Raul::Symbol& symbol); + const raul::Symbol& symbol); NodeImpl* _parent; - Raul::Path _path; - Raul::Symbol _symbol; + raul::Path _path; + raul::Symbol _symbol; }; } // namespace server diff --git a/src/server/OutputPort.hpp b/src/server/OutputPort.hpp index 0437c367..b19cd361 100644 --- a/src/server/OutputPort.hpp +++ b/src/server/OutputPort.hpp @@ -18,10 +18,26 @@ #define INGEN_ENGINE_OUTPUTPORT_HPP #include "PortImpl.hpp" +#include "PortType.hpp" + +#include <lv2/urid/urid.h> + +#include <cstddef> +#include <cstdint> + +namespace raul { +class Symbol; +} // namespace raul namespace ingen { + +class Atom; + namespace server { +class BlockImpl; +class BufferFactory; + /** An output port. * * Output ports always have a locally allocated buffer, and buffer() will @@ -34,7 +50,7 @@ class OutputPort : public PortImpl public: OutputPort(BufferFactory& bufs, BlockImpl* parent, - const Raul::Symbol& symbol, + const raul::Symbol& symbol, uint32_t index, uint32_t poly, PortType type, diff --git a/src/server/PluginImpl.hpp b/src/server/PluginImpl.hpp index 3c93aa21..8e3642c0 100644 --- a/src/server/PluginImpl.hpp +++ b/src/server/PluginImpl.hpp @@ -17,10 +17,15 @@ #ifndef INGEN_ENGINE_PLUGINIMPL_HPP #define INGEN_ENGINE_PLUGINIMPL_HPP -#include "ingen/Resource.hpp" -#include "raul/Symbol.hpp" +#include <ingen/Atom.hpp> +#include <ingen/Resource.hpp> +#include <ingen/URI.hpp> +#include <lilv/lilv.h> +#include <raul/Symbol.hpp> -#include <cstdlib> +#include <map> +#include <string> +#include <utility> namespace ingen { @@ -43,19 +48,19 @@ public: PluginImpl(ingen::URIs& uris, const Atom& type, const URI& uri) : Resource(uris, uri) , _type(type) - , _presets_loaded(false) - , _is_zombie(false) - { - } + {} + + PluginImpl(const PluginImpl&) = delete; + PluginImpl& operator=(const PluginImpl&) = delete; virtual BlockImpl* instantiate(BufferFactory& bufs, - const Raul::Symbol& symbol, + const raul::Symbol& symbol, bool polyphonic, GraphImpl* parent, Engine& engine, const LilvState* state) = 0; - virtual Raul::Symbol symbol() const = 0; + virtual raul::Symbol symbol() const = 0; const Atom& type() const { return _type; } void set_type(const Atom& t) { _type = t; } @@ -82,12 +87,8 @@ public: protected: Atom _type; Presets _presets; - bool _presets_loaded; - bool _is_zombie; - -private: - PluginImpl(const PluginImpl&) = delete; - PluginImpl& operator=(const PluginImpl&) = delete; + bool _presets_loaded{false}; + bool _is_zombie{false}; }; } // namespace server diff --git a/src/server/PortAudioDriver.cpp b/src/server/PortAudioDriver.cpp index 38b04842..ef893478 100644 --- a/src/server/PortAudioDriver.cpp +++ b/src/server/PortAudioDriver.cpp @@ -14,17 +14,19 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ +#include "PortAudioDriver.hpp" + #include "DuplexPort.hpp" #include "Engine.hpp" #include "FrameTimer.hpp" -#include "PortAudioDriver.hpp" #include "PortType.hpp" #include "RunContext.hpp" -#include "ingen/Atom.hpp" -#include "ingen/Configuration.hpp" -#include "ingen/URIs.hpp" -#include "ingen/World.hpp" -#include "raul/Path.hpp" + +#include <ingen/Atom.hpp> +#include <ingen/Configuration.hpp> +#include <ingen/URIs.hpp> +#include <ingen/World.hpp> +#include <raul/Path.hpp> #include <portaudio.h> @@ -32,8 +34,7 @@ #include <cstring> #include <string> -namespace ingen { -namespace server { +namespace ingen::server { static bool pa_error(const char* msg, PaError err) @@ -45,17 +46,10 @@ pa_error(const char* msg, PaError err) PortAudioDriver::PortAudioDriver(Engine& engine) : _engine(engine) - , _sem(0) - , _stream(nullptr) - , _seq_size(4096) + , _inputParameters() + , _outputParameters() , _block_length(engine.world().conf().option("buffer-size").get<int32_t>()) - , _sample_rate(48000) - , _n_inputs(0) - , _n_outputs(0) - , _flag(false) - , _is_activated(false) -{ -} +{} PortAudioDriver::~PortAudioDriver() { @@ -76,7 +70,9 @@ PortAudioDriver::attach() _outputParameters.device = Pa_GetDefaultOutputDevice(); if (_inputParameters.device == paNoDevice) { return pa_error("No default input device", paDeviceUnavailable); - } else if (_outputParameters.device == paNoDevice) { + } + + if (_outputParameters.device == paNoDevice) { return pa_error("No default output device", paDeviceUnavailable); } @@ -89,8 +85,7 @@ PortAudioDriver::attach() _sample_rate = in_dev->defaultSampleRate; - _timer = std::unique_ptr<FrameTimer>( - new FrameTimer(_block_length, _sample_rate)); + _timer = std::make_unique<FrameTimer>(_block_length, _sample_rate); return true; } @@ -157,7 +152,7 @@ PortAudioDriver::frame_time() const } EnginePort* -PortAudioDriver::get_port(const Raul::Path& path) +PortAudioDriver::get_port(const raul::Path& path) { for (auto& p : _ports) { if (p.graph_port()->path() == path) { @@ -169,39 +164,35 @@ PortAudioDriver::get_port(const Raul::Path& path) } void -PortAudioDriver::add_port(RunContext& context, EnginePort* port) +PortAudioDriver::add_port(RunContext&, EnginePort* port) { _ports.push_back(*port); } void -PortAudioDriver::remove_port(RunContext& context, EnginePort* port) +PortAudioDriver::remove_port(RunContext&, EnginePort* port) { _ports.erase(_ports.iterator_to(*port)); } void PortAudioDriver::register_port(EnginePort& port) -{ -} +{} void PortAudioDriver::unregister_port(EnginePort& port) -{ -} +{} void -PortAudioDriver::rename_port(const Raul::Path& old_path, - const Raul::Path& new_path) -{ -} +PortAudioDriver::rename_port(const raul::Path& old_path, + const raul::Path& new_path) +{} void -PortAudioDriver::port_property(const Raul::Path& path, +PortAudioDriver::port_property(const raul::Path& path, const URI& uri, const Atom& value) -{ -} +{} EnginePort* PortAudioDriver::create_port(DuplexPort* graph_port) @@ -233,7 +224,7 @@ PortAudioDriver::create_port(DuplexPort* graph_port) } void -PortAudioDriver::pre_process_port(RunContext& context, +PortAudioDriver::pre_process_port(RunContext&, EnginePort* port, const void* inputs, void* outputs) @@ -243,9 +234,14 @@ PortAudioDriver::pre_process_port(RunContext& context, } if (port->is_input()) { - port->set_buffer(((float**)inputs)[port->driver_index()]); + const auto* const* const ins = + static_cast<const float* const*>(inputs); + + port->set_buffer(const_cast<float*>(ins[port->driver_index()])); } else { - port->set_buffer(((float**)outputs)[port->driver_index()]); + auto* const* const outs = static_cast<float* const*>(inputs); + + port->set_buffer(outs[port->driver_index()]); memset(port->buffer(), 0, _block_length * sizeof(float)); } @@ -254,12 +250,11 @@ PortAudioDriver::pre_process_port(RunContext& context, } void -PortAudioDriver::post_process_port(RunContext& context, +PortAudioDriver::post_process_port(RunContext&, EnginePort* port, const void* inputs, void* outputs) -{ -} +{} int PortAudioDriver::process_cb(const void* inputs, @@ -287,5 +282,4 @@ PortAudioDriver::process_cb(const void* inputs, return 0; } -} // namespace server -} // namespace ingen +} // namespace ingen::server diff --git a/src/server/PortAudioDriver.hpp b/src/server/PortAudioDriver.hpp index 679223ad..6c7bfb9e 100644 --- a/src/server/PortAudioDriver.hpp +++ b/src/server/PortAudioDriver.hpp @@ -19,30 +19,20 @@ #include "Driver.hpp" #include "EnginePort.hpp" -#include "ingen_config.h" #include "types.hpp" -#include "ingen/URI.hpp" -#include "lv2/atom/forge.h" -#include "raul/Semaphore.hpp" +#include <raul/Semaphore.hpp> +#include <boost/intrusive/options.hpp> +#include <boost/intrusive/slist.hpp> #include <portaudio.h> #include <atomic> -#include <cstddef> #include <cstdint> #include <memory> -namespace Raul { class Path; } +namespace ingen::server { -namespace ingen { - -class Atom; - -namespace server { - -class Buffer; -class DuplexPort; class Engine; class FrameTimer; class RunContext; @@ -51,7 +41,7 @@ class PortAudioDriver : public Driver { public: explicit PortAudioDriver(Engine& engine); - ~PortAudioDriver(); + ~PortAudioDriver() override; bool attach(); @@ -59,37 +49,37 @@ public: void deactivate() override; EnginePort* create_port(DuplexPort* graph_port) override; - EnginePort* get_port(const Raul::Path& path) override; + EnginePort* get_port(const raul::Path& path) override; - void rename_port(const Raul::Path& old_path, const Raul::Path& new_path) override; - void port_property(const Raul::Path& path, const URI& uri, const Atom& value) override; - void add_port(RunContext& context, EnginePort* port) override; - void remove_port(RunContext& context, EnginePort* port) override; + void rename_port(const raul::Path& old_path, const raul::Path& new_path) override; + void port_property(const raul::Path& path, const URI& uri, const Atom& value) override; + void add_port(RunContext& ctx, EnginePort* port) override; + void remove_port(RunContext& ctx, EnginePort* port) override; void register_port(EnginePort& port) override; void unregister_port(EnginePort& port) override; - void append_time_events(RunContext& context, Buffer& buffer) override {} + void append_time_events(RunContext& ctx, Buffer& buffer) override {} SampleCount frame_time() const override; int real_time_priority() override { return 80; } SampleCount block_length() const override { return _block_length; } - size_t seq_size() const override { return _seq_size; } + uint32_t seq_size() const override { return _seq_size; } SampleCount sample_rate() const override { return _sample_rate; } private: friend class PortAudioPort; - inline static int - pa_process_cb(const void* inputs, - void* outputs, - unsigned long nframes, - const PaStreamCallbackTimeInfo* time, - PaStreamCallbackFlags flags, - void* handle) { - return ((PortAudioDriver*)handle)->process_cb( - inputs, outputs, nframes, time, flags); + static int pa_process_cb(const void* inputs, + void* outputs, + unsigned long nframes, + const PaStreamCallbackTimeInfo* time, + PaStreamCallbackFlags flags, + void* handle) + { + return static_cast<PortAudioDriver*>(handle)->process_cb( + inputs, outputs, nframes, time, flags); } int process_cb(const void* inputs, @@ -98,12 +88,12 @@ private: const PaStreamCallbackTimeInfo* time, PaStreamCallbackFlags flags); - void pre_process_port(RunContext& context, + void pre_process_port(RunContext& ctx, EnginePort* port, const void* inputs, void* outputs); - void post_process_port(RunContext& context, + void post_process_port(RunContext& ctx, EnginePort* port, const void* inputs, void* outputs); @@ -116,19 +106,18 @@ protected: Ports _ports; PaStreamParameters _inputParameters; PaStreamParameters _outputParameters; - Raul::Semaphore _sem; + raul::Semaphore _sem{0U}; std::unique_ptr<FrameTimer> _timer; - PaStream* _stream; - size_t _seq_size; + PaStream* _stream{nullptr}; + uint32_t _seq_size{4096U}; uint32_t _block_length; - uint32_t _sample_rate; - uint32_t _n_inputs; - uint32_t _n_outputs; - std::atomic<bool> _flag; - bool _is_activated; + uint32_t _sample_rate{48000U}; + uint32_t _n_inputs{0U}; + uint32_t _n_outputs{0U}; + std::atomic<bool> _flag{false}; + bool _is_activated{false}; }; -} // namespace server -} // namespace ingen +} // namespace ingen::server #endif // INGEN_ENGINE_PORTAUDIODRIVER_HPP diff --git a/src/server/PortImpl.cpp b/src/server/PortImpl.cpp index 5161750d..f6eed11f 100644 --- a/src/server/PortImpl.cpp +++ b/src/server/PortImpl.cpp @@ -23,22 +23,27 @@ #include "PortType.hpp" #include "ThreadManager.hpp" -#include "ingen/Forge.hpp" -#include "ingen/URIs.hpp" -#include "ingen/World.hpp" -#include "lv2/atom/util.h" -#include "raul/Array.hpp" -#include "raul/Maid.hpp" +#include <ingen/Atom.hpp> +#include <ingen/Forge.hpp> +#include <ingen/Node.hpp> +#include <ingen/URIs.hpp> +#include <ingen/World.hpp> +#include <lv2/atom/atom.h> +#include <lv2/atom/util.h> +#include <lv2/urid/urid.h> +#include <raul/Array.hpp> +#include <raul/Maid.hpp> +#include <raul/Path.hpp> #include <algorithm> #include <cassert> #include <cstdio> +#include <memory> #include <utility> -namespace ingen { -namespace server { +namespace ingen::server { -static const uint32_t monitor_rate = 25.0; // Hz +static const uint32_t monitor_rate = 25.0; // Hz /** The length of time between monitor updates in frames */ static inline uint32_t @@ -50,7 +55,7 @@ monitor_period(const Engine& engine) PortImpl::PortImpl(BufferFactory& bufs, BlockImpl* const block, - const Raul::Symbol& name, + const raul::Symbol& name, uint32_t index, uint32_t poly, PortType type, @@ -63,24 +68,12 @@ PortImpl::PortImpl(BufferFactory& bufs, , _index(index) , _poly(poly) , _buffer_size(buffer_size) - , _frames_since_monitor(0) - , _monitor_value(0.0f) - , _peak(0.0f) , _type(type) , _buffer_type(buffer_type) , _value(value) , _min(bufs.forge().make(0.0f)) , _max(bufs.forge().make(1.0f)) , _voices(bufs.maid().make_managed<Voices>(poly)) - , _connected_flag(false) - , _monitored(false) - , _force_monitor_update(false) - , _is_morph(false) - , _is_auto_morph(false) - , _is_logarithmic(false) - , _is_sample_rate(false) - , _is_toggled(false) - , _is_driver_port(false) , _is_output(is_output) { assert(block != nullptr); @@ -91,7 +84,7 @@ PortImpl::PortImpl(BufferFactory& bufs, set_type(type, buffer_type); remove_property(uris.lv2_index, uris.patch_wildcard); - set_property(uris.lv2_index, bufs.forge().make((int32_t)index)); + set_property(uris.lv2_index, bufs.forge().make(static_cast<int32_t>(index))); if (has_value()) { set_property(uris.ingen_value, value); @@ -103,7 +96,8 @@ PortImpl::PortImpl(BufferFactory& bufs, if (is_output) { if (_parent->graph_type() != Node::GraphType::GRAPH) { - add_property(bufs.uris().rdf_type, bufs.uris().lv2_OutputPort.urid); + add_property(bufs.uris().rdf_type, + bufs.uris().lv2_OutputPort.urid_atom()); } } @@ -111,10 +105,10 @@ PortImpl::PortImpl(BufferFactory& bufs, } bool -PortImpl::get_buffers(BufferFactory& bufs, - GetFn get, - const MPtr<Voices>& voices, - uint32_t poly, +PortImpl::get_buffers(BufferFactory& bufs, + GetFn get, + const raul::managed_ptr<Voices>& voices, + uint32_t poly, size_t) const { for (uint32_t v = 0; v < poly; ++v) { @@ -143,13 +137,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; @@ -211,7 +205,7 @@ PortImpl::deactivate() } void -PortImpl::set_voices(RunContext&, MPtr<Voices>&& voices) +PortImpl::set_voices(RunContext&, raul::managed_ptr<Voices>&& voices) { _voices = std::move(voices); connect_buffers(); @@ -229,56 +223,58 @@ PortImpl::cache_properties() } void -PortImpl::set_control_value(const RunContext& context, +PortImpl::set_control_value(const RunContext& ctx, FrameTime time, Sample value) { for (uint32_t v = 0; v < _poly; ++v) { - update_set_state(context, v); - set_voice_value(context, v, time, value); + update_set_state(ctx, v); + set_voice_value(ctx, v, time, value); } } void -PortImpl::set_voice_value(const RunContext& context, +PortImpl::set_voice_value(const RunContext& ctx, uint32_t voice, FrameTime time, Sample value) { - switch (_type.id()) { + switch (_type) { case PortType::CONTROL: if (buffer(voice)->value()) { - ((LV2_Atom_Float*)buffer(voice)->value())->body = value; + const_cast<LV2_Atom_Float*>( + reinterpret_cast<const LV2_Atom_Float*>(buffer(voice)->value())) + ->body = value; } - _voices->at(voice).set_state.set(context, context.start(), value); + _voices->at(voice).set_state.set(ctx, ctx.start(), value); break; case PortType::AUDIO: case PortType::CV: { // Time may be at end so internal blocks can set triggers - assert(time >= context.start()); - assert(time <= context.start() + context.nframes()); + assert(time >= ctx.start()); + assert(time <= ctx.start() + ctx.nframes()); - const FrameTime offset = time - context.start(); - if (offset < context.nframes()) { - buffer(voice)->set_block(value, offset, context.nframes()); + const FrameTime offset = time - ctx.start(); + if (offset < ctx.nframes()) { + buffer(voice)->set_block(value, offset, ctx.nframes()); } /* else, this is a set at context.nframes(), used to reset a CV port's value for the next block, particularly for triggers on the last frame of a block (set nframes-1 to 1, then nframes to 0). */ - _voices->at(voice).set_state.set(context, time, value); + _voices->at(voice).set_state.set(ctx, time, value); } break; case PortType::ATOM: if (buffer(voice)->is_sequence()) { - const FrameTime offset = time - context.start(); + const FrameTime offset = time - ctx.start(); // Same deal as above - if (offset < context.nframes()) { + if (offset < ctx.nframes()) { buffer(voice)->append_event(offset, sizeof(value), _bufs.uris().atom_Float, - (const uint8_t*)&value); + reinterpret_cast<const uint8_t*>(&value)); } - _voices->at(voice).set_state.set(context, time, value); + _voices->at(voice).set_state.set(ctx, time, value); } else { #ifndef NDEBUG fprintf(stderr, @@ -286,27 +282,28 @@ PortImpl::set_voice_value(const RunContext& context, path().c_str(), buffer(voice)->type()); #endif } + break; default: break; } } void -PortImpl::update_set_state(const RunContext& context, uint32_t v) +PortImpl::update_set_state(const RunContext& ctx, uint32_t v) { - Voice& voice = _voices->at(v); - SetState& state = voice.set_state; - BufferRef buf = voice.buffer; + Voice& voice = _voices->at(v); + SetState& state = voice.set_state; + const BufferRef buf = voice.buffer; switch (state.state) { case SetState::State::SET: break; case SetState::State::SET_CYCLE_1: - if (state.time < context.start() && + if (state.time < ctx.start() && buf->is_sequence() && buf->value_type() == _bufs.uris().atom_Float && !_parent->is_main()) { buf->clear(); - state.time = context.start(); + state.time = ctx.start(); } state.state = SetState::State::SET; break; @@ -318,9 +315,9 @@ PortImpl::update_set_state(const RunContext& context, uint32_t v) buf->clear(); buf->append_event( 0, sizeof(float), _bufs.uris().atom_Float, - (const uint8_t*)&state.value); + reinterpret_cast<const uint8_t*>(&state.value)); } else { - buf->set_block(state.value, 0, context.nframes()); + buf->set_block(state.value, 0, ctx.nframes()); } state.state = SetState::State::SET_CYCLE_1; break; @@ -334,9 +331,13 @@ PortImpl::prepare_poly(BufferFactory& bufs, uint32_t poly) if (_is_driver_port || _parent->is_main() || (_type == PortType::ATOM && !_value.is_valid())) { return false; - } else if (_poly == poly) { + } + + if (_poly == poly) { return true; - } else if (_prepared_voices && _prepared_voices->size() != poly) { + } + + if (_prepared_voices && _prepared_voices->size() != poly) { _prepared_voices.reset(); } @@ -352,12 +353,14 @@ PortImpl::prepare_poly(BufferFactory& bufs, uint32_t poly) } bool -PortImpl::apply_poly(RunContext& context, uint32_t poly) +PortImpl::apply_poly(RunContext& ctx, uint32_t poly) { if (_parent->is_main() || (_type == PortType::ATOM && !_value.is_valid())) { return false; - } else if (!_prepared_voices) { + } + + if (!_prepared_voices) { return true; } @@ -369,7 +372,7 @@ PortImpl::apply_poly(RunContext& context, uint32_t poly) _voices = std::move(_prepared_voices); if (is_a(PortType::CONTROL) || is_a(PortType::CV)) { - set_control_value(context, context.start(), _value.get<float>()); + set_control_value(ctx, ctx.start(), _value.get<float>()); } assert(_voices->size() >= poly); @@ -418,7 +421,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) { @@ -441,32 +444,32 @@ PortImpl::clear_buffers(const RunContext& ctx) } void -PortImpl::monitor(RunContext& context, bool send_now) +PortImpl::monitor(RunContext& ctx, bool send_now) { - if (!context.must_notify(this)) { + if (!ctx.must_notify(this)) { return; } - const uint32_t period = monitor_period(context.engine()); - _frames_since_monitor += context.nframes(); + const uint32_t period = monitor_period(ctx.engine()); + _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; } - Forge& forge = context.engine().world().forge(); - URIs& uris = context.engine().world().uris(); - LV2_URID key = 0; - float val = 0.0f; - switch (_type.id()) { + const Forge& forge = ctx.engine().world().forge(); + const URIs& uris = ctx.engine().world().uris(); + LV2_URID key = 0; + float val = 0.0f; + switch (_type) { case PortType::UNKNOWN: break; case PortType::AUDIO: key = uris.ingen_activity; - val = _peak = std::max(_peak, buffer(0)->peak(context)); + val = _peak = std::max(_peak, buffer(0)->peak(ctx)); break; case PortType::CONTROL: case PortType::CV: @@ -482,28 +485,28 @@ PortImpl::monitor(RunContext& context, bool send_now) uninitialized Chunk, so do nothing. */ } else if (_monitored) { /* Sequence explicitly monitored, send everything. */ - const auto* seq = (const LV2_Atom_Sequence*)atom; - LV2_ATOM_SEQUENCE_FOREACH(seq, ev) { - context.notify(uris.ingen_activity, - context.start() + ev->time.frames, - this, - ev->body.size, - ev->body.type, - LV2_ATOM_BODY(&ev->body)); + const auto* seq = reinterpret_cast<const LV2_Atom_Sequence*>(atom); + LV2_ATOM_SEQUENCE_FOREACH (seq, ev) { + ctx.notify(uris.ingen_activity, + ctx.start() + ev->time.frames, + this, + ev->body.size, + ev->body.type, + LV2_ATOM_BODY(&ev->body)); } } else if (value && value->type == _bufs.uris().atom_Float) { /* Float sequence, monitor as a control. */ key = uris.ingen_value; - val = ((LV2_Atom_Float*)buffer(0)->value())->body; + val = reinterpret_cast<const LV2_Atom_Float*>(buffer(0)->value())->body; } else if (atom->size > sizeof(LV2_Atom_Sequence_Body)) { /* General sequence, send activity for blinkenlights. */ const int32_t one = 1; - context.notify(uris.ingen_activity, - context.start(), - this, - sizeof(int32_t), - (LV2_URID)uris.atom_Bool, - &one); + ctx.notify(uris.ingen_activity, + ctx.start(), + this, + sizeof(int32_t), + static_cast<LV2_URID>(uris.atom_Bool), + &one); _force_monitor_update = false; } } @@ -511,8 +514,7 @@ PortImpl::monitor(RunContext& context, bool send_now) _frames_since_monitor = _frames_since_monitor % period; if (key && val != _monitor_value) { - if (context.notify(key, context.start(), this, - sizeof(float), forge.Float, &val)) { + if (ctx.notify(key, ctx.start(), this, sizeof(float), forge.Float, &val)) { /* Update frames since last update to conceptually zero, but keep the remainder to preserve load balancing. */ _frames_since_monitor = _frames_since_monitor % period; @@ -524,7 +526,7 @@ PortImpl::monitor(RunContext& context, bool send_now) } BufferRef -PortImpl::value_buffer(uint32_t voice) +PortImpl::value_buffer(uint32_t voice) const { return buffer(voice)->value_buffer(); } @@ -535,42 +537,43 @@ PortImpl::next_value_offset(SampleCount offset, SampleCount end) const SampleCount earliest = end; for (uint32_t v = 0; v < _poly; ++v) { const SampleCount o = _voices->at(v).buffer->next_value_offset(offset, end); - if (o < earliest) { - earliest = o; - } + earliest = std::min(o, earliest); } return earliest; } void -PortImpl::update_values(SampleCount offset, uint32_t voice) +PortImpl::update_values(SampleCount offset, uint32_t voice) const { buffer(voice)->update_value_buffer(offset); } void -PortImpl::pre_process(RunContext& context) +PortImpl::pre_process(RunContext& ctx) { if (!_connected_flag.test_and_set(std::memory_order_acquire)) { connect_buffers(); - clear_buffers(context); + clear_buffers(ctx); } for (uint32_t v = 0; v < _poly; ++v) { - _voices->at(v).buffer->prepare_output_write(context); + _voices->at(v).buffer->prepare_output_write(ctx); } } void -PortImpl::post_process(RunContext& context) +PortImpl::pre_run(RunContext&) +{} + +void +PortImpl::post_process(RunContext& ctx) { for (uint32_t v = 0; v < _poly; ++v) { - update_set_state(context, v); + update_set_state(ctx, v); update_values(0, v); } - monitor(context); + monitor(ctx); } -} // namespace server -} // namespace ingen +} // namespace ingen::server diff --git a/src/server/PortImpl.hpp b/src/server/PortImpl.hpp index 5392d9b7..c202d4a0 100644 --- a/src/server/PortImpl.hpp +++ b/src/server/PortImpl.hpp @@ -17,20 +17,34 @@ #ifndef INGEN_ENGINE_PORTIMPL_HPP #define INGEN_ENGINE_PORTIMPL_HPP +#include "BufferFactory.hpp" #include "BufferRef.hpp" #include "NodeImpl.hpp" -#include "PortType.hpp" #include "RunContext.hpp" +#include "server.h" #include "types.hpp" -#include "ingen/Atom.hpp" -#include "raul/Array.hpp" +#include <ingen/Atom.hpp> +#include <ingen/URIs.hpp> +#include <lv2/urid/urid.h> +#include <raul/Array.hpp> +#include <raul/Maid.hpp> #include <atomic> #include <cstdint> #include <cstdlib> +#include <utility> + +namespace raul { +class Symbol; +} // namespace raul namespace ingen { + +enum class PortType; + +class Properties; + namespace server { class BlockImpl; @@ -43,7 +57,7 @@ class BlockImpl; * * \ingroup engine */ -class INGEN_API PortImpl : public NodeImpl +class INGEN_SERVER_API PortImpl : public NodeImpl { public: struct SetState { @@ -61,33 +75,31 @@ public: SET }; - SetState() : state(State::SET), value(0), time(0) {} + SetState() = default; - void set(const RunContext& context, FrameTime t, Sample v) { + void set(const RunContext& ctx, FrameTime t, Sample v) { time = t; value = v; - state = (time == context.start() + state = (time == ctx.start() ? State::SET : State::HALF_SET_CYCLE_1); } - State state; ///< State of buffer for setting control value - Sample value; ///< Value currently being set - FrameTime time; ///< Time value was set + State state = State::SET; ///< State for setting control value + Sample value = 0; ///< Value currently being set + FrameTime time = 0; ///< Time value was set }; struct Voice { - Voice() : buffer(nullptr) {} - SetState set_state; - BufferRef buffer; + BufferRef buffer{nullptr}; }; - using Voices = Raul::Array<Voice>; + using Voices = raul::Array<Voice>; PortImpl(BufferFactory& bufs, BlockImpl* block, - const Raul::Symbol& name, + const raul::Symbol& name, uint32_t index, uint32_t poly, PortType type, @@ -99,10 +111,10 @@ public: GraphType graph_type() const override { return GraphType::PORT; } /** A port's parent is always a block, so static cast should be safe */ - BlockImpl* parent_block() const { return (BlockImpl*)_parent; } + BlockImpl* parent_block() const { return reinterpret_cast<BlockImpl*>(_parent); } /** Set the the voices (buffers) for this port in the audio thread. */ - void set_voices(RunContext& context, MPtr<Voices>&& voices); + void set_voices(RunContext& ctx, raul::managed_ptr<Voices>&& voices); /** Prepare for a new (external) polyphony value. * @@ -115,7 +127,7 @@ public: * Audio thread. * \a poly Must be < the most recent value passed to prepare_poly. */ - bool apply_poly(RunContext& context, uint32_t poly) override; + bool apply_poly(RunContext& ctx, uint32_t poly) override; /** Return the number of arcs (pre-process thraed). */ virtual size_t num_arcs() const { return 0; } @@ -133,21 +145,22 @@ public: void set_minimum(const Atom& min) { _min.set_rt(min); } void set_maximum(const Atom& max) { _max.set_rt(max); } - inline BufferRef buffer(uint32_t voice) const { + BufferRef buffer(uint32_t voice) const { return _voices->at((_poly == 1) ? 0 : voice).buffer; } - inline BufferRef prepared_buffer(uint32_t voice) const { + + BufferRef prepared_buffer(uint32_t voice) const { return _prepared_voices->at(voice).buffer; } - void update_set_state(const RunContext& context, uint32_t v); + void update_set_state(const RunContext& ctx, uint32_t v); - void set_voice_value(const RunContext& context, + void set_voice_value(const RunContext& ctx, uint32_t voice, FrameTime time, Sample value); - void set_control_value(const RunContext& context, + void set_control_value(const RunContext& ctx, FrameTime time, Sample value); @@ -164,9 +177,9 @@ public: bool is_driver_port() const { return _is_driver_port; } /** Called once per process cycle */ - virtual void pre_process(RunContext& context); - virtual void pre_run(RunContext& context) {} - virtual void post_process(RunContext& context); + virtual void pre_process(RunContext& ctx); + virtual void pre_run(RunContext& ctx); + virtual void post_process(RunContext& ctx); /** Clear/silence all buffers */ virtual void clear_buffers(const RunContext& ctx); @@ -193,7 +206,7 @@ public: uint32_t index() const { return _index; } void set_index(RunContext&, uint32_t index) { _index = index; } - inline bool is_a(PortType type) const { return _type == type; } + bool is_a(PortType type) const { return _type == type; } bool has_value() const; @@ -212,7 +225,7 @@ public: return (_prepared_voices) ? _prepared_voices->size() : 1; } - void set_buffer_size(RunContext& context, BufferFactory& bufs, size_t size); + void set_buffer_size(RunContext& ctx, BufferFactory& bufs, size_t size); /** Return true iff this port is explicitly monitored. * @@ -226,21 +239,25 @@ public: void enable_monitoring(bool monitored) { _monitored = monitored; } /** Monitor port value and broadcast to clients periodically. */ - void monitor(RunContext& context, bool send_now=false); + void monitor(RunContext& ctx, bool send_now=false); BufferFactory& bufs() const { return _bufs; } - BufferRef value_buffer(uint32_t voice); + BufferRef value_buffer(uint32_t voice) const; BufferRef user_buffer(RunContext&) const { return _user_buffer; } - void set_user_buffer(RunContext&, BufferRef b) { _user_buffer = b; } + + void set_user_buffer(RunContext&, BufferRef b) + { + _user_buffer = std::move(b); + } /** Return offset of the first value change after `offset`. */ virtual SampleCount next_value_offset(SampleCount offset, SampleCount end) const; /** Update value buffer for `voice` to be current as of `offset`. */ - void update_values(SampleCount offset, uint32_t voice); + void update_values(SampleCount offset, uint32_t voice) const; void force_monitor_update() { _force_monitor_update = true; } @@ -262,7 +279,7 @@ public: bool is_toggled() const { return _is_toggled; } protected: - typedef BufferRef (BufferFactory::*GetFn)(LV2_URID, LV2_URID, uint32_t); + using GetFn = BufferRef (BufferFactory::*)(LV2_URID, LV2_URID, uint32_t); /** Set `voices` as the buffers to be used for this port. * @@ -271,37 +288,37 @@ protected: * * @return true iff buffers are locally owned by the port */ - virtual bool get_buffers(BufferFactory& bufs, - GetFn get, - const MPtr<Voices>& voices, - uint32_t poly, - size_t num_in_arcs) const; - - BufferFactory& _bufs; - uint32_t _index; - uint32_t _poly; - uint32_t _buffer_size; - uint32_t _frames_since_monitor; - float _monitor_value; - float _peak; - PortType _type; - LV2_URID _buffer_type; - Atom _value; - Atom _min; - Atom _max; - MPtr<Voices> _voices; - MPtr<Voices> _prepared_voices; - BufferRef _user_buffer; - std::atomic_flag _connected_flag; - bool _monitored; - bool _force_monitor_update; - bool _is_morph; - bool _is_auto_morph; - bool _is_logarithmic; - bool _is_sample_rate; - bool _is_toggled; - bool _is_driver_port; - bool _is_output; + virtual bool get_buffers(BufferFactory& bufs, + GetFn get, + const raul::managed_ptr<Voices>& voices, + uint32_t poly, + size_t num_in_arcs) const; + + BufferFactory& _bufs; + uint32_t _index; + uint32_t _poly; + uint32_t _buffer_size; + uint32_t _frames_since_monitor{0}; + float _monitor_value{0.0f}; + float _peak{0.0f}; + PortType _type; + LV2_URID _buffer_type; + Atom _value; + Atom _min; + Atom _max; + raul::managed_ptr<Voices> _voices; + raul::managed_ptr<Voices> _prepared_voices; + BufferRef _user_buffer; + std::atomic_flag _connected_flag{false}; + bool _monitored{false}; + bool _force_monitor_update{false}; + bool _is_morph{false}; + bool _is_auto_morph{false}; + bool _is_logarithmic{false}; + bool _is_sample_rate{false}; + bool _is_toggled{false}; + bool _is_driver_port{false}; + bool _is_output; }; } // namespace server diff --git a/src/server/PortType.hpp b/src/server/PortType.hpp index c711ad79..294c056a 100644 --- a/src/server/PortType.hpp +++ b/src/server/PortType.hpp @@ -14,78 +14,60 @@ 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 "lv2/atom/atom.h" -#include "lv2/core/lv2.h" - -#include <cassert> +#include <ingen/URI.hpp> +#include <lv2/atom/atom.h> +#include <lv2/core/lv2.h> 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 - }; - - 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; - } - } - - PortType(ID id) : _id(id) {} - - inline const URI& uri() const { return type_uri(_id); } - inline ID id() const { return _id; } - - inline bool operator==(const ID& id) const { return (_id == id); } - inline bool operator!=(const ID& id) const { return (_id != id); } - inline bool operator==(const PortType& type) const { return (_id == type._id); } - inline bool operator!=(const PortType& type) const { return (_id != type._id); } - inline bool operator<(const PortType& type) const { return (_id < type._id); } - - inline bool is_audio() { return _id == AUDIO; } - inline bool is_control() { return _id == CONTROL; } - inline bool is_cv() { return _id == CV; } - inline bool is_atom() { return _id == ATOM; } +/// The type of a port +enum class PortType { + UNKNOWN, + AUDIO, + CONTROL, + CV, + ATOM, +}; -private: - static inline 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]; +/// 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}; } - ID _id; -}; + return URI{"http://www.w3.org/2002/07/owl#Nothing"}; +} + +/// 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/PostProcessor.cpp b/src/server/PostProcessor.cpp index 5a0a8f3e..4c071ecd 100644 --- a/src/server/PostProcessor.cpp +++ b/src/server/PostProcessor.cpp @@ -21,14 +21,12 @@ #include <cassert> -namespace ingen { -namespace server { +namespace ingen::server { -class PreProcessContext; - -class Sentinel : public Event { +class Sentinel : public Event +{ public: - explicit Sentinel(Engine& engine) : Event(engine) {} + explicit Sentinel(Engine& engine) noexcept : Event(engine) {} bool pre_process(PreProcessContext&) override { return false; } void execute(RunContext&) override {} @@ -40,8 +38,7 @@ PostProcessor::PostProcessor(Engine& engine) , _head(new Sentinel(engine)) , _tail(_head.load()) , _max_time(0) -{ -} +{} PostProcessor::~PostProcessor() { @@ -99,7 +96,7 @@ PostProcessor::process() // Post-process event ev->post_process(); - next = ev->next(); // [1] (see below) + next = ev->next(); // [1] (see below) } while (next && next->time() < end_time); /* Reached the tail (as far as we're concerned). There may be successors @@ -112,5 +109,4 @@ PostProcessor::process() _engine.emit_notifications(end_time); } -} // namespace server -} // namespace ingen +} // namespace ingen::server diff --git a/src/server/PostProcessor.hpp b/src/server/PostProcessor.hpp index 2733b209..7b2a3035 100644 --- a/src/server/PostProcessor.hpp +++ b/src/server/PostProcessor.hpp @@ -17,14 +17,12 @@ #ifndef INGEN_ENGINE_POSTPROCESSOR_HPP #define INGEN_ENGINE_POSTPROCESSOR_HPP +#include "server.h" #include "types.hpp" -#include "ingen/ingen.h" - #include <atomic> -namespace ingen { -namespace server { +namespace ingen::server { class Engine; class Event; @@ -41,7 +39,7 @@ class RunContext; * * \ingroup engine */ -class INGEN_API PostProcessor +class INGEN_SERVER_API PostProcessor { public: explicit PostProcessor(Engine& engine); @@ -50,7 +48,7 @@ public: /** Push a list of events on to the process queue. realtime-safe, not thread-safe. */ - void append(RunContext& context, Event* first, Event* last); + void append(RunContext& ctx, Event* first, Event* last); /** Post-process and delete all pending events */ void process(); @@ -68,7 +66,6 @@ private: std::atomic<FrameTime> _max_time; }; -} // namespace server -} // namespace ingen +} // namespace ingen::server #endif // INGEN_ENGINE_POSTPROCESSOR_HPP diff --git a/src/server/PreProcessContext.hpp b/src/server/PreProcessContext.hpp index 7579e1e2..7c97af3c 100644 --- a/src/server/PreProcessContext.hpp +++ b/src/server/PreProcessContext.hpp @@ -20,12 +20,10 @@ #include "CompiledGraph.hpp" #include "GraphImpl.hpp" +#include <memory> #include <unordered_set> -namespace Raul { class Maid; } - -namespace ingen { -namespace server { +namespace ingen::server { /** Event pre-processing context. * @@ -50,12 +48,14 @@ public: bool must_compile(GraphImpl& graph) { if (!graph.enabled()) { return false; - } else if (_in_bundle) { + } + + if (_in_bundle) { _dirty_graphs.insert(&graph); return false; - } else { - return true; } + + return true; } /** Compile graph and return the result if necessary. @@ -63,11 +63,9 @@ public: * This may return null when an atomic bundle is deferring compilation, in * which case the graph is flagged as dirty for later compilation. */ - MPtr<CompiledGraph> maybe_compile(Raul::Maid& maid, GraphImpl& graph) { - if (must_compile(graph)) { - return compile(maid, graph); - } - return MPtr<CompiledGraph>(); + [[nodiscard]] std::unique_ptr<CompiledGraph> maybe_compile(GraphImpl& graph) + { + return must_compile(graph) ? compile(graph) : nullptr; } /** Return all graphs that require compilation after an atomic bundle. */ @@ -79,7 +77,6 @@ private: bool _in_bundle = false; }; -} // namespace server -} // namespace ingen +} // namespace ingen::server #endif // INGEN_ENGINE_PREPROCESSCONTEXT_HPP diff --git a/src/server/PreProcessor.cpp b/src/server/PreProcessor.cpp index 61a3598e..b3bad0b2 100644 --- a/src/server/PreProcessor.cpp +++ b/src/server/PreProcessor.cpp @@ -24,26 +24,22 @@ #include "ThreadManager.hpp" #include "UndoStack.hpp" -#include "ingen/Atom.hpp" -#include "ingen/AtomWriter.hpp" -#include "ingen/Configuration.hpp" -#include "ingen/World.hpp" +#include <ingen/Atom.hpp> +#include <ingen/AtomWriter.hpp> +#include <ingen/Configuration.hpp> +#include <ingen/World.hpp> +#include <raul/Semaphore.hpp> #include <cassert> #include <cstdint> #include <cstdio> #include <memory> +#include <string> -namespace ingen { -namespace server { +namespace ingen::server { PreProcessor::PreProcessor(Engine& engine) : _engine(engine) - , _sem(0) - , _head(nullptr) - , _tail(nullptr) - , _block_state(BlockState::UNBLOCKED) - , _exit_flag(false) , _thread(&PreProcessor::run, this) {} @@ -61,7 +57,7 @@ PreProcessor::event(Event* const ev, Event::Mode mode) { // TODO: Probably possible to make this lock-free with CAS ThreadManager::assert_not_thread(THREAD_IS_REAL_TIME); - std::lock_guard<std::mutex> lock(_mutex); + const std::lock_guard<std::mutex> lock{_mutex}; assert(!ev->is_prepared()); assert(!ev->next()); @@ -69,7 +65,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; @@ -82,7 +78,7 @@ PreProcessor::event(Event* const ev, Event::Mode mode) } unsigned -PreProcessor::process(RunContext& context, PostProcessor& dest, size_t limit) +PreProcessor::process(RunContext& ctx, PostProcessor& dest, size_t limit) { Event* const head = _head.load(); size_t n_processed = 0; @@ -114,16 +110,18 @@ PreProcessor::process(RunContext& context, PostProcessor& dest, size_t limit) } if (_block_state == BlockState::BLOCKED) { - break; // Waiting for PRE_UNBLOCKED - } else if (ev->time() < context.start()) { - ev->set_time(context.start()); // Too late, nudge to context start + break; // Waiting for PRE_UNBLOCKED + } + + if (ev->time() < ctx.start()) { + ev->set_time(ctx.start()); // Too late, nudge to context start } else if (_block_state != BlockState::PROCESSING && - ev->time() >= context.end()) { - break; // Event is for a future cycle + ev->time() >= ctx.end()) { + break; // Event is for a future cycle } // Execute event - ev->execute(context); + ev->execute(ctx); ++n_processed; // Unblock pre-processing if this is a non-bundled atomic event @@ -144,18 +142,18 @@ PreProcessor::process(RunContext& context, PostProcessor& dest, size_t limit) if (n_processed > 0) { #ifndef NDEBUG - Engine& engine = context.engine(); + const Engine& engine = ctx.engine(); if (engine.world().conf().option("trace").get<int32_t>()) { - const uint64_t start = engine.cycle_start_time(context); + const uint64_t start = engine.cycle_start_time(ctx); const uint64_t end = engine.current_time(); fprintf(stderr, "Processed %zu events in %u us\n", - n_processed, (unsigned)(end - start)); + n_processed, static_cast<unsigned>(end - start)); } #endif - auto* next = (Event*)last->next(); + auto* next = last->next(); last->next(nullptr); - dest.append(context, head, last); + dest.append(ctx, head, last); // Since _head was not null, we know it hasn't been changed since _head = next; @@ -245,9 +243,8 @@ PreProcessor::run() wait_for_block_state(BlockState::UNBLOCKED); } - back = (Event*)ev->next(); + back = ev->next(); } } -} // namespace server -} // namespace ingen +} // namespace ingen::server diff --git a/src/server/PreProcessor.hpp b/src/server/PreProcessor.hpp index 8d15c0a6..03ba5dd7 100644 --- a/src/server/PreProcessor.hpp +++ b/src/server/PreProcessor.hpp @@ -19,7 +19,7 @@ #include "Event.hpp" -#include "raul/Semaphore.hpp" +#include <raul/Semaphore.hpp> #include <atomic> #include <chrono> @@ -27,8 +27,7 @@ #include <mutex> #include <thread> -namespace ingen { -namespace server { +namespace ingen::server { class Engine; class PostProcessor; @@ -42,7 +41,7 @@ public: ~PreProcessor(); /** Return true iff no events are enqueued. */ - inline bool empty() const { return !_head.load(); } + bool empty() const { return !_head.load(); } /** Enqueue an event. * This is safe to call from any non-realtime thread (it locks). @@ -52,7 +51,7 @@ public: /** Process events for a cycle. * @return The number of events processed. */ - unsigned process(RunContext& context, + unsigned process(RunContext& ctx, PostProcessor& dest, size_t limit = 0); @@ -61,11 +60,11 @@ protected: private: enum class BlockState { - UNBLOCKED, ///< Normal, unblocked execution - PRE_BLOCKED, ///< Preprocess thread has enqueued blocking event - BLOCKED, ///< Process thread has reached blocking event - PRE_UNBLOCKED, ///< Preprocess thread has enqueued unblocking event - PROCESSING ///< Process thread is executing all events in-between + UNBLOCKED, ///< Normal, unblocked execution + PRE_BLOCKED, ///< Preprocess thread has enqueued blocking event + BLOCKED, ///< Process thread has reached blocking event + PRE_UNBLOCKED, ///< Preprocess thread has enqueued unblocking event + PROCESSING ///< Process thread is executing all events in-between }; void wait_for_block_state(const BlockState state) { @@ -76,15 +75,14 @@ private: Engine& _engine; std::mutex _mutex; - Raul::Semaphore _sem; - std::atomic<Event*> _head; - std::atomic<Event*> _tail; - std::atomic<BlockState> _block_state; - bool _exit_flag; + raul::Semaphore _sem{0}; + std::atomic<Event*> _head{nullptr}; + std::atomic<Event*> _tail{nullptr}; + std::atomic<BlockState> _block_state{BlockState::UNBLOCKED}; + bool _exit_flag{false}; std::thread _thread; }; -} // namespace server -} // namespace ingen +} // namespace ingen::server #endif // INGEN_ENGINE_PREPROCESSOR_HPP diff --git a/src/server/RunContext.cpp b/src/server/RunContext.cpp index 57aaa299..29985ccf 100644 --- a/src/server/RunContext.cpp +++ b/src/server/RunContext.cpp @@ -22,28 +22,30 @@ #include "PortImpl.hpp" #include "Task.hpp" -#include "ingen/Forge.hpp" -#include "ingen/Log.hpp" -#include "ingen/URIMap.hpp" -#include "ingen/World.hpp" -#include "raul/RingBuffer.hpp" +#include <ingen/Atom.hpp> +#include <ingen/Forge.hpp> +#include <ingen/Log.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIMap.hpp> +#include <ingen/URIs.hpp> +#include <ingen/World.hpp> +#include <lv2/urid/urid.h> +#include <raul/RingBuffer.hpp> #include <cerrno> #include <cstring> #include <pthread.h> #include <sched.h> -namespace ingen { -namespace server { +namespace ingen::server { -struct Notification -{ - explicit inline Notification(PortImpl* p = nullptr, - FrameTime f = 0, - LV2_URID k = 0, - uint32_t s = 0, - LV2_URID t = 0) - : port(p), time(f), key(k), size(s), type(t) +struct Notification { + explicit Notification(PortImpl* p = nullptr, + FrameTime f = 0, + LV2_URID k = 0, + uint32_t s = 0, + LV2_URID t = 0) + : port(p), time(f), key(k), size(s), type(t) {} PortImpl* port; @@ -54,27 +56,18 @@ struct Notification }; RunContext::RunContext(Engine& engine, - Raul::RingBuffer* event_sink, + raul::RingBuffer* event_sink, unsigned id, bool threaded) : _engine(engine) , _event_sink(event_sink) - , _task(nullptr) , _thread(threaded ? new std::thread(&RunContext::run, this) : nullptr) , _id(id) - , _start(0) - , _end(0) - , _offset(0) - , _nframes(0) - , _rate(0) - , _realtime(true) {} RunContext::RunContext(const RunContext& copy) : _engine(copy._engine) , _event_sink(copy._event_sink) - , _task(nullptr) - , _thread(nullptr) , _id(copy._id) , _start(copy._start) , _end(copy._end) @@ -124,8 +117,7 @@ RunContext::emit_notifications(FrameTime end) return; } if (_event_sink->read(sizeof(note), ¬e) == sizeof(note)) { - Atom value = _engine.world().forge().alloc( - note.size, note.type, nullptr); + Atom value = Forge::alloc(note.size, note.type, nullptr); if (_event_sink->read(note.size, value.get_body()) == note.size) { i += note.size; const char* key = _engine.world().uri_map().unmap_uri(note.key); @@ -168,9 +160,9 @@ void RunContext::set_priority(int priority) { if (_thread) { - pthread_t pthread = _thread->native_handle(); - const int policy = (priority > 0) ? SCHED_FIFO : SCHED_OTHER; - sched_param sp{}; + const pthread_t pthread = _thread->native_handle(); + const int policy = (priority > 0) ? SCHED_FIFO : SCHED_OTHER; + sched_param sp{}; sp.sched_priority = (priority > 0) ? priority : 0; if (pthread_setschedparam(pthread, policy, &sp)) { _engine.log().error( @@ -195,11 +187,10 @@ void RunContext::run() { while (_engine.wait_for_tasks()) { - for (Task* t; (t = _engine.steal_task(0));) { + for (Task* t = nullptr; (t = _engine.steal_task(0));) { t->run(*this); } } } -} // namespace server -} // namespace ingen +} // namespace ingen::server diff --git a/src/server/RunContext.hpp b/src/server/RunContext.hpp index 9190d172..44304c5e 100644 --- a/src/server/RunContext.hpp +++ b/src/server/RunContext.hpp @@ -17,17 +17,16 @@ #ifndef INGEN_ENGINE_RUNCONTEXT_HPP #define INGEN_ENGINE_RUNCONTEXT_HPP -#include "ingen/types.hpp" #include "types.hpp" -#include "lv2/urid/urid.h" -#include "raul/RingBuffer.hpp" +#include <lv2/urid/urid.h> +#include <raul/RingBuffer.hpp> #include <cstdint> +#include <memory> #include <thread> -namespace ingen { -namespace server { +namespace ingen::server { class Engine; class PortImpl; @@ -57,7 +56,7 @@ public: * a thread and execute tasks as they become available. */ RunContext(Engine& engine, - Raul::RingBuffer* event_sink, + raul::RingBuffer* event_sink, unsigned id, bool threaded); @@ -68,6 +67,9 @@ public: */ RunContext(const RunContext& copy); + RunContext& operator=(const RunContext&) = delete; + RunContext& operator=(RunContext&&) = delete; + /** Return true iff the given port should broadcast its value. * * Whether or not broadcasting is actually done is a per-client property, @@ -100,17 +102,17 @@ public: * cycle (other than the fact that it must be processed in significantly * less time to avoid a dropout when running in real time). */ - inline uint64_t duration() const { - return (uint64_t)_nframes * 1e6 / _rate; + uint64_t duration() const { + return static_cast<uint64_t>(_nframes) * 1e6 / _rate; } - inline void locate(FrameTime s, SampleCount nframes) { + void locate(FrameTime s, SampleCount nframes) { _start = s; _end = s + nframes; _nframes = nframes; } - inline void slice(SampleCount offset, SampleCount nframes) { + void slice(SampleCount offset, SampleCount nframes) { _offset = offset; _nframes = nframes; } @@ -126,37 +128,34 @@ public: void join(); - inline Engine& engine() const { return _engine; } - inline Task* task() const { return _task; } - inline unsigned id() const { return _id; } - inline FrameTime start() const { return _start; } - inline FrameTime time() const { return _start + _offset; } - inline FrameTime end() const { return _end; } - inline SampleCount offset() const { return _offset; } - inline SampleCount nframes() const { return _nframes; } - inline SampleCount rate() const { return _rate; } - inline bool realtime() const { return _realtime; } + Engine& engine() const { return _engine; } + Task* task() const { return _task; } + unsigned id() const { return _id; } + FrameTime start() const { return _start; } + FrameTime time() const { return _start + _offset; } + FrameTime end() const { return _end; } + SampleCount offset() const { return _offset; } + SampleCount nframes() const { return _nframes; } + SampleCount rate() const { return _rate; } + bool realtime() const { return _realtime; } protected: - const RunContext& operator=(const RunContext& copy) = delete; - void run(); - Engine& _engine; ///< Engine we're running in - Raul::RingBuffer* _event_sink; ///< Port updates from process context - Task* _task; ///< Currently executing task - UPtr<std::thread> _thread; ///< Thread (null for main run context) - unsigned _id; ///< Context ID - - FrameTime _start; ///< Start frame of this cycle, timeline relative - FrameTime _end; ///< End frame of this cycle, timeline relative - SampleCount _offset; ///< Offset into data buffers - SampleCount _nframes; ///< Number of frames past offset to process - SampleCount _rate; ///< Sample rate in Hz - bool _realtime; ///< True iff context is hard realtime + Engine& _engine; ///< Engine we're running in + raul::RingBuffer* _event_sink; ///< Updates from notify() + Task* _task{nullptr}; ///< Currently executing task + std::unique_ptr<std::thread> _thread; ///< Thread (or null for main) + unsigned _id; ///< Context ID + + FrameTime _start{0}; ///< Start frame of this cycle (timeline) + FrameTime _end{0}; ///< End frame of this cycle (timeline) + SampleCount _offset{0}; ///< Offset into data buffers + SampleCount _nframes{0}; ///< Number of frames past offset to process + SampleCount _rate{0}; ///< Sample rate in Hz + bool _realtime{true}; ///< True iff context is hard realtime }; -} // namespace server -} // namespace ingen +} // namespace ingen::server #endif // INGEN_ENGINE_RUNCONTEXT_HPP diff --git a/src/server/SocketListener.cpp b/src/server/SocketListener.cpp index b4b50a14..fb961ee2 100644 --- a/src/server/SocketListener.cpp +++ b/src/server/SocketListener.cpp @@ -19,13 +19,16 @@ #include "Engine.hpp" #include "SocketServer.hpp" -#include "ingen/Configuration.hpp" -#include "ingen/Log.hpp" -#include "ingen/World.hpp" -#include "raul/Socket.hpp" +#include <ingen/Atom.hpp> +#include <ingen/Configuration.hpp> +#include <ingen/Log.hpp> +#include <ingen/URI.hpp> +#include <ingen/World.hpp> +#include <raul/Socket.hpp> #include <poll.h> #include <sys/stat.h> +#include <sys/types.h> #include <unistd.h> #include <cerrno> @@ -33,12 +36,12 @@ #include <cstdint> #include <cstdlib> #include <cstring> +#include <memory> #include <sstream> #include <string> #include <thread> -namespace ingen { -namespace server { +namespace ingen::server { static constexpr const char* const unix_scheme = "unix://"; @@ -48,29 +51,29 @@ get_link_target(const char* link_path) // Stat the link to get the required size for the target path struct stat link_stat{}; if (lstat(link_path, &link_stat)) { - return std::string(); + return {}; } // Allocate buffer and read link target - char* target = (char*)calloc(1, link_stat.st_size + 1); + char* target = static_cast<char*>(calloc(1, link_stat.st_size + 1)); if (readlink(link_path, target, link_stat.st_size) != -1) { - const std::string result(target); + std::string result(target); free(target); return result; } free(target); - return std::string(); + return {}; } static void ingen_listen(Engine* engine, - Raul::Socket* unix_sock, - Raul::Socket* net_sock); + raul::Socket* unix_sock, + raul::Socket* net_sock); SocketListener::SocketListener(Engine& engine) - : unix_sock(Raul::Socket::Type::UNIX) - , net_sock(Raul::Socket::Type::TCP) + : unix_sock(raul::Socket::Type::UNIX) + , net_sock(raul::Socket::Type::TCP) , thread(new std::thread(ingen_listen, &engine, &unix_sock, &net_sock)) {} @@ -82,7 +85,7 @@ SocketListener::~SocketListener() { } static void -ingen_listen(Engine* engine, Raul::Socket* unix_sock, Raul::Socket* net_sock) +ingen_listen(Engine* engine, raul::Socket* unix_sock, raul::Socket* net_sock) { ingen::World& world = engine->world(); @@ -138,7 +141,7 @@ ingen_listen(Engine* engine, Raul::Socket* unix_sock, Raul::Socket* net_sock) } if (unix_sock->fd() == -1 && net_sock->fd() == -1) { - return; // No sockets to listen to, exit thread + return; // No sockets to listen to, exit thread } struct pollfd pfds[2]; @@ -162,22 +165,26 @@ ingen_listen(Engine* engine, Raul::Socket* unix_sock, Raul::Socket* net_sock) if (ret == -1) { world.log().error("Poll error: %1%\n", strerror(errno)); break; - } else if (ret == 0) { + } + + if (ret == 0) { world.log().warn("Poll returned with no data\n"); continue; - } else if ((pfds[0].revents & POLLHUP) || pfds[1].revents & POLLHUP) { + } + + if ((pfds[0].revents & POLLHUP) || pfds[1].revents & POLLHUP) { break; } if (pfds[0].revents & POLLIN) { - SPtr<Raul::Socket> conn = unix_sock->accept(); + auto conn = unix_sock->accept(); if (conn) { new SocketServer(world, *engine, conn); } } if (pfds[1].revents & POLLIN) { - SPtr<Raul::Socket> conn = net_sock->accept(); + auto conn = net_sock->accept(); if (conn) { new SocketServer(world, *engine, conn); } @@ -189,5 +196,4 @@ ingen_listen(Engine* engine, Raul::Socket* unix_sock, Raul::Socket* net_sock) } } -} // namespace server -} // namespace ingen +} // namespace ingen::server diff --git a/src/server/SocketListener.hpp b/src/server/SocketListener.hpp index 21070c23..a96105ef 100644 --- a/src/server/SocketListener.hpp +++ b/src/server/SocketListener.hpp @@ -14,13 +14,12 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "raul/Socket.hpp" +#include <raul/Socket.hpp> #include <memory> #include <thread> -namespace ingen { -namespace server { +namespace ingen::server { class Engine; @@ -28,14 +27,13 @@ class Engine; class SocketListener { public: - SocketListener(Engine& engine); + explicit SocketListener(Engine& engine); ~SocketListener(); private: - Raul::Socket unix_sock; - Raul::Socket net_sock; + raul::Socket unix_sock; + raul::Socket net_sock; std::unique_ptr<std::thread> thread; }; -} // namespace server -} // namespace ingen +} // namespace ingen::server diff --git a/src/server/SocketServer.hpp b/src/server/SocketServer.hpp index f3f02a26..608d180d 100644 --- a/src/server/SocketServer.hpp +++ b/src/server/SocketServer.hpp @@ -21,35 +21,42 @@ #include "Engine.hpp" -#include "ingen/Configuration.hpp" -#include "ingen/SocketReader.hpp" -#include "ingen/SocketWriter.hpp" -#include "ingen/StreamWriter.hpp" -#include "ingen/Tee.hpp" -#include "ingen/World.hpp" -#include "raul/Socket.hpp" +#include <ingen/Atom.hpp> +#include <ingen/ColorContext.hpp> +#include <ingen/Configuration.hpp> +#include <ingen/Interface.hpp> +#include <ingen/SocketReader.hpp> +#include <ingen/SocketWriter.hpp> +#include <ingen/StreamWriter.hpp> +#include <ingen/Tee.hpp> +#include <ingen/URI.hpp> +#include <ingen/World.hpp> +#include <raul/Socket.hpp> -namespace ingen { -namespace server { +#include <cstdint> +#include <cstdio> +#include <memory> + +namespace ingen::server { /** The server side of an Ingen socket connection. */ class SocketServer { public: - SocketServer(World& world, - server::Engine& engine, - SPtr<Raul::Socket> sock) + SocketServer(World& world, + server::Engine& engine, + const std::shared_ptr<raul::Socket>& sock) : _engine(engine) , _sink(world.conf().option("dump").get<int32_t>() - ? SPtr<Interface>( - new Tee({SPtr<Interface>(new EventWriter(engine)), - SPtr<Interface>(new StreamWriter(world.uri_map(), + ? std::shared_ptr<Interface>( + new Tee({std::shared_ptr<Interface>(new EventWriter(engine)), + std::shared_ptr<Interface>(new StreamWriter(world.uri_map(), world.uris(), URI("ingen:/engine"), stderr, ColorContext::Color::CYAN))})) - : SPtr<Interface>(new EventWriter(engine))) - , _reader(new SocketReader(world, *_sink.get(), sock)) + : std::shared_ptr<Interface>(new EventWriter(engine))) + , _reader(new SocketReader(world, *_sink, sock)) , _writer(new SocketWriter(world.uri_map(), world.uris(), URI(sock->uri()), @@ -72,13 +79,12 @@ protected: } private: - server::Engine& _engine; - SPtr<Interface> _sink; - SPtr<SocketReader> _reader; - SPtr<SocketWriter> _writer; + server::Engine& _engine; + std::shared_ptr<Interface> _sink; + std::shared_ptr<SocketReader> _reader; + std::shared_ptr<SocketWriter> _writer; }; -} // namespace ingen -} // namespace Socket +} // namespace ingen::server -#endif // INGEN_SERVER_SOCKET_SERVER_HPP +#endif // INGEN_SERVER_SOCKET_SERVER_HPP diff --git a/src/server/State.hpp b/src/server/State.hpp new file mode 100644 index 00000000..976cf67d --- /dev/null +++ b/src/server/State.hpp @@ -0,0 +1,34 @@ +/* + This file is part of Ingen. + Copyright 2020 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/>. +*/ + +#ifndef INGEN_ENGINE_STATE_HPP +#define INGEN_ENGINE_STATE_HPP + +#include <lilv/lilv.h> + +#include <memory> + +namespace ingen::server { + +struct StateDeleter { + void operator()(LilvState* state) { lilv_state_free(state); } +}; + +using StatePtr = std::unique_ptr<LilvState, StateDeleter>; + +} // namespace ingen::server + +#endif // INGEN_ENGINE_STATE_HPP diff --git a/src/server/Task.cpp b/src/server/Task.cpp index b61a08eb..345a4711 100644 --- a/src/server/Task.cpp +++ b/src/server/Task.cpp @@ -19,24 +19,24 @@ #include "BlockImpl.hpp" #include "RunContext.hpp" -#include "raul/Path.hpp" +#include <raul/Path.hpp> #include <cstddef> +#include <memory> -namespace ingen { -namespace server { +namespace ingen::server { void -Task::run(RunContext& context) +Task::run(RunContext& ctx) { switch (_mode) { case Mode::SINGLE: // fprintf(stderr, "%u run %s\n", context.id(), _block->path().c_str()); - _block->process(context); + _block->process(ctx); break; case Mode::SEQUENTIAL: for (const auto& task : _children) { - task->run(context); + task->run(ctx); } break; case Mode::PARALLEL: @@ -48,16 +48,16 @@ Task::run(RunContext& context) // Grab the first sub-task _next = 0; _done_end = 0; - Task* t = steal(context); + Task* t = steal(ctx); // Allow other threads to steal sub-tasks - context.claim_task(this); + ctx.claim_task(this); // Run available tasks until this task is finished - for (; t; t = get_task(context)) { - t->run(context); + for (; t; t = get_task(ctx)) { + t->run(ctx); } - context.claim_task(nullptr); + ctx.claim_task(nullptr); break; } @@ -78,10 +78,10 @@ Task::steal(RunContext&) } Task* -Task::get_task(RunContext& context) +Task::get_task(RunContext& ctx) { // Attempt to "steal" a task from ourselves - Task* t = steal(context); + Task* t = steal(ctx); if (t) { return t; } @@ -93,11 +93,11 @@ Task::get_task(RunContext& context) } if (_done_end >= _children.size()) { - return nullptr; // All child tasks are finished + return nullptr; // All child tasks are finished } // All child tasks claimed, but some are unfinished, steal a task - if ((t = context.steal_task())) { + if ((t = ctx.steal_task())) { return t; } @@ -116,7 +116,7 @@ Task::simplify(std::unique_ptr<Task>&& task) return std::move(task); } - std::unique_ptr<Task> ret = std::unique_ptr<Task>(new Task(task->mode())); + std::unique_ptr<Task> ret = std::make_unique<Task>(task->mode()); for (auto&& c : task->_children) { auto child = simplify(std::move(c)); if (!child->empty()) { @@ -162,5 +162,4 @@ Task::dump(const std::function<void(const std::string&)>& sink, } } -} // namespace server -} // namespace ingen +} // namespace ingen::server diff --git a/src/server/Task.hpp b/src/server/Task.hpp index e8b658c3..f2141bd5 100644 --- a/src/server/Task.hpp +++ b/src/server/Task.hpp @@ -25,31 +25,33 @@ #include <string> #include <utility> -namespace ingen { -namespace server { +namespace ingen::server { class BlockImpl; class RunContext; -class Task { +class Task +{ public: enum class Mode { - SINGLE, ///< Single block to run - SEQUENTIAL, ///< Elements must be run sequentially in order - PARALLEL ///< Elements may be run in any order in parallel + SINGLE, ///< Single block to run + SEQUENTIAL, ///< Elements must be run sequentially in order + 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) - , _done_end(0) - , _next(0) - , _done(false) { - assert(!(mode == Mode::SINGLE && !block)); + assert(mode != Mode::SINGLE || block); } - Task(Task&& task) + explicit Task(Mode mode) : Task{mode, nullptr} {} + + Task(const Task&) = delete; + Task& operator=(const Task&) = delete; + + Task(Task&& task) noexcept : _children(std::move(task._children)) , _block(task._block) , _mode(task._mode) @@ -58,7 +60,7 @@ public: , _done(task._done.load()) {} - Task& operator=(Task&& task) + Task& operator=(Task&& task) noexcept { _children = std::move(task._children); _block = task._block; @@ -70,7 +72,7 @@ public: } /** Run task in the given context. */ - void run(RunContext& context); + void run(RunContext& ctx); /** Pretty print task to the given stream (recursively). */ void dump(const std::function<void(const std::string&)>& sink, @@ -84,11 +86,11 @@ public: static std::unique_ptr<Task> simplify(std::unique_ptr<Task>&& task); /** Steal a child task from this task (succeeds for PARALLEL only). */ - Task* steal(RunContext& context); + Task* steal(RunContext& ctx); /** Prepend a child to this task. */ void push_front(Task&& task) { - _children.emplace_front(std::unique_ptr<Task>(new Task(std::move(task)))); + _children.emplace_front(std::make_unique<Task>(std::move(task))); } Mode mode() const { return _mode; } @@ -100,24 +102,20 @@ public: private: using Children = std::deque<std::unique_ptr<Task>>; - Task(const Task&) = delete; - Task& operator=(const Task&) = delete; - - Task* get_task(RunContext& context); + Task* get_task(RunContext& ctx); void append(std::unique_ptr<Task>&& t) { _children.emplace_back(std::move(t)); } - Children _children; ///< Vector of child tasks - BlockImpl* _block; ///< Used for SINGLE only - Mode _mode; ///< Execution mode - unsigned _done_end; ///< Index of rightmost done sub-task - std::atomic<unsigned> _next; ///< Index of next sub-task - std::atomic<bool> _done; ///< Completion phase + Children _children; ///< Vector of child tasks + BlockImpl* _block; ///< Used for SINGLE only + Mode _mode; ///< Execution mode + unsigned _done_end{0}; ///< Index of rightmost done sub-task + std::atomic<unsigned> _next{0}; ///< Index of next sub-task + std::atomic<bool> _done{false}; ///< Completion phase }; -} // namespace server -} // namespace ingen +} // namespace ingen::server #endif // INGEN_ENGINE_TASK_HPP diff --git a/src/server/ThreadManager.hpp b/src/server/ThreadManager.hpp index 17f2c6ff..2e0ad966 100644 --- a/src/server/ThreadManager.hpp +++ b/src/server/ThreadManager.hpp @@ -17,14 +17,11 @@ #ifndef INGEN_ENGINE_THREADMANAGER_HPP #define INGEN_ENGINE_THREADMANAGER_HPP -#include "util.hpp" - -#include "ingen/ingen.h" +#include "server.h" #include <cassert> -namespace ingen { -namespace server { +namespace ingen::server { enum ThreadFlag { THREAD_IS_REAL_TIME = 1, @@ -33,36 +30,36 @@ enum ThreadFlag { THREAD_MESSAGE = 1 << 3, }; -class INGEN_API ThreadManager { +class INGEN_SERVER_API ThreadManager +{ public: - static inline void set_flag(ThreadFlag f) { + static void set_flag(ThreadFlag f) { #ifndef NDEBUG - flags = ((unsigned)flags | f); + flags |= static_cast<unsigned>(f); #endif } - static inline void unset_flag(ThreadFlag f) { + static void unset_flag(ThreadFlag f) { #ifndef NDEBUG - flags = ((unsigned)flags & (~f)); + flags &= ~static_cast<unsigned>(f); #endif } - static inline void assert_thread(ThreadFlag f) { + static void assert_thread(ThreadFlag f) { assert(single_threaded || (flags & f)); } - static inline void assert_not_thread(ThreadFlag f) { + static void assert_not_thread(ThreadFlag f) { assert(single_threaded || !(flags & f)); } /** Set to true during initialisation so ensure_thread doesn't fail. * Defined in Engine.cpp */ - static bool single_threaded; - static INGEN_THREAD_LOCAL unsigned flags; + static bool single_threaded; + static thread_local unsigned flags; }; -} // namespace server -} // namespace ingen +} // namespace ingen::server #endif // INGEN_ENGINE_THREADMANAGER_HPP diff --git a/src/server/UndoStack.cpp b/src/server/UndoStack.cpp index a94617a5..c6555123 100644 --- a/src/server/UndoStack.cpp +++ b/src/server/UndoStack.cpp @@ -16,33 +16,31 @@ #include "UndoStack.hpp" -#include "ingen/URIMap.hpp" -#include "ingen/URIs.hpp" -#include "lv2/atom/atom.h" -#include "lv2/atom/util.h" -#include "lv2/patch/patch.h" -#include "lv2/urid/urid.h" -#include "serd/serd.h" -#include "sratom/sratom.h" +#include <ingen/URIMap.hpp> +#include <ingen/URIs.hpp> +#include <ingen/ingen.h> +#include <lv2/atom/atom.h> +#include <lv2/atom/util.h> +#include <lv2/patch/patch.h> +#include <serd/serd.h> +#include <sratom/sratom.h> #include <ctime> #include <iterator> -#include <memory> -#define NS_RDF (const uint8_t*)"http://www.w3.org/1999/02/22-rdf-syntax-ns#" +#define NS_RDF "http://www.w3.org/1999/02/22-rdf-syntax-ns#" -#define USTR(s) ((const uint8_t*)(s)) +#define USTR(s) reinterpret_cast<const uint8_t*>(s) -namespace ingen { -namespace server { +namespace ingen::server { int UndoStack::start_entry() { if (_depth == 0) { - time_t now; + time_t now = {}; time(&now); - _stack.emplace_back(Entry(now)); + _stack.emplace_back(now); } return ++_depth; } @@ -62,22 +60,22 @@ UndoStack::ignore_later_event(const LV2_Atom* first, return false; } - const auto* f = (const LV2_Atom_Object*)first; - const auto* s = (const LV2_Atom_Object*)second; + const auto* f = reinterpret_cast<const LV2_Atom_Object*>(first); + const auto* s = reinterpret_cast<const LV2_Atom_Object*>(second); if (f->body.otype == _uris.patch_Set && f->body.otype == s->body.otype) { const LV2_Atom* f_subject = nullptr; const LV2_Atom* f_property = nullptr; const LV2_Atom* s_subject = nullptr; const LV2_Atom* s_property = nullptr; lv2_atom_object_get(f, - (LV2_URID)_uris.patch_subject, &f_subject, - (LV2_URID)_uris.patch_property, &f_property, + _uris.patch_subject.urid(), &f_subject, + _uris.patch_property.urid(), &f_property, 0); lv2_atom_object_get(s, - (LV2_URID)_uris.patch_subject, &s_subject, - (LV2_URID)_uris.patch_property, &s_property, + _uris.patch_subject.urid(), &s_subject, + _uris.patch_property.urid(), &s_property, 0); - return (lv2_atom_equals(f_subject, s_subject) && + return (lv2_atom_equals(f_subject, s_subject) && lv2_atom_equals(f_property, s_property)); } @@ -87,18 +85,18 @@ UndoStack::ignore_later_event(const LV2_Atom* first, int UndoStack::finish_entry() { - if (--_depth > 0) { - return _depth; - } else if (_stack.back().events.empty()) { - // Disregard empty entry - _stack.pop_back(); - } else if (_stack.size() > 1 && _stack.back().events.size() == 1) { - // This entry and the previous one have one event, attempt to merge - auto i = _stack.rbegin(); - ++i; - if (i->events.size() == 1) { - if (ignore_later_event(i->events[0], _stack.back().events[0])) { - _stack.pop_back(); + if (--_depth == 0) { + if (_stack.back().events.empty()) { + // Disregard empty entry + _stack.pop_back(); + } else if (_stack.size() > 1 && _stack.back().events.size() == 1) { + // This entry and the previous one have one event, attempt to merge + auto i = _stack.rbegin(); + ++i; + if (i->events.size() == 1) { + if (ignore_later_event(i->events[0], _stack.back().events[0])) { + _stack.pop_back(); + } } } } @@ -118,7 +116,7 @@ UndoStack::pop() } struct BlankIDs { - explicit BlankIDs(char c='b') : c(c) {} + explicit BlankIDs(const char prefix = 'b') noexcept : c{prefix} {} SerdNode get() { snprintf(buf, sizeof(buf), "%c%u", c, n++); @@ -127,15 +125,18 @@ struct BlankIDs { char buf[16]{}; unsigned n{0}; - const char c{'b'}; + const char c; }; struct ListContext { - explicit ListContext(BlankIDs& ids, unsigned flags, const SerdNode* s, const SerdNode* p) - : ids(ids) - , s(*s) - , p(*p) - , flags(flags | SERD_LIST_O_BEGIN) + explicit ListContext(BlankIDs& blank_ids, + unsigned statement_flags, + const SerdNode* subject, + const SerdNode* predicate) + : ids(blank_ids) + , s(*subject) + , p(*predicate) + , flags(statement_flags | SERD_LIST_O_BEGIN) {} SerdNode start_node(SerdWriter* writer) { @@ -149,7 +150,7 @@ struct ListContext { const SerdNode node = start_node(writer); // node rdf:first value - p = serd_node_from_string(SERD_URI, NS_RDF "first"); + p = serd_node_from_string(SERD_URI, USTR(NS_RDF "first")); flags = SERD_LIST_CONT; serd_writer_write_statement(writer, flags|oflags, nullptr, &node, &p, value, nullptr, nullptr); @@ -159,12 +160,15 @@ struct ListContext { void end_node(SerdWriter*, const SerdNode* node) { // Prepare for next call: node rdf:rest ... s = *node; - p = serd_node_from_string(SERD_URI, NS_RDF "rest"); + p = serd_node_from_string(SERD_URI, USTR(NS_RDF "rest")); } void end(SerdWriter* writer) { - const SerdNode nil = serd_node_from_string(SERD_URI, NS_RDF "nil"); - serd_writer_write_statement(writer, flags, nullptr, &s, &p, &nil, nullptr, nullptr); + const SerdNode nil = + serd_node_from_string(SERD_URI, USTR(NS_RDF "nil")); + + serd_writer_write_statement( + writer, flags, nullptr, &s, &p, &nil, nullptr, nullptr); } BlankIDs& ids; @@ -183,8 +187,8 @@ UndoStack::write_entry(Sratom* sratom, strftime(time_str, sizeof(time_str), "%FT%T", gmtime(&entry.time)); // entry rdf:type ingen:UndoEntry - SerdNode p = serd_node_from_string(SERD_URI, USTR(INGEN_NS "time")); - SerdNode o = serd_node_from_string(SERD_LITERAL, USTR(time_str)); + SerdNode p = serd_node_from_string(SERD_URI, USTR(INGEN_NS "time")); + const SerdNode o = serd_node_from_string(SERD_LITERAL, USTR(time_str)); serd_writer_write_statement(writer, SERD_ANON_CONT, nullptr, subject, &p, &o, nullptr, nullptr); p = serd_node_from_string(SERD_URI, USTR(INGEN_NS "events")); @@ -195,9 +199,12 @@ UndoStack::write_entry(Sratom* sratom, for (const LV2_Atom* atom : entry.events) { const SerdNode node = ctx.start_node(writer); - p = serd_node_from_string(SERD_URI, NS_RDF "first"); + p = serd_node_from_string(SERD_URI, + reinterpret_cast<const uint8_t*>(NS_RDF + "first")); + ctx.flags = SERD_LIST_CONT; - sratom_write(sratom, &_map.urid_unmap_feature()->urid_unmap, SERD_LIST_CONT, + sratom_write(sratom, &_map.urid_unmap(), SERD_LIST_CONT, &node, &p, atom->type, atom->size, LV2_ATOM_BODY_CONST(atom)); @@ -217,26 +224,28 @@ UndoStack::save(FILE* stream, const char* name) const SerdNode base = serd_node_from_string(SERD_URI, USTR("ingen:/")); SerdURI base_uri; - serd_uri_parse(base.buf, &base_uri); - - SerdWriter* writer = serd_writer_new( - SERD_TURTLE, - (SerdStyle)(SERD_STYLE_RESOLVED|SERD_STYLE_ABBREVIATED|SERD_STYLE_CURIED), - env, - &base_uri, - serd_file_sink, - stream); + serd_uri_parse(USTR("ingen:/"), &base_uri); + + SerdWriter* writer = + serd_writer_new(SERD_TURTLE, + static_cast<SerdStyle>(SERD_STYLE_RESOLVED | + SERD_STYLE_ABBREVIATED | + SERD_STYLE_CURIED), + env, + &base_uri, + serd_file_sink, + stream); // Configure sratom to write directly to the writer (and thus the socket) - Sratom* sratom = sratom_new(&_map.urid_map_feature()->urid_map); + Sratom* sratom = sratom_new(&_map.urid_map()); sratom_set_sink(sratom, - (const char*)base.buf, - (SerdStatementSink)serd_writer_write_statement, - (SerdEndSink)serd_writer_end_anon, + reinterpret_cast<const char*>(base.buf), + reinterpret_cast<SerdStatementSink>(serd_writer_write_statement), + reinterpret_cast<SerdEndSink>(serd_writer_end_anon), writer); - SerdNode s = serd_node_from_string(SERD_BLANK, (const uint8_t*)name); - SerdNode p = serd_node_from_string(SERD_URI, USTR(INGEN_NS "entries")); + const SerdNode s = serd_node_from_string(SERD_BLANK, USTR(name)); + const SerdNode p = serd_node_from_string(SERD_URI, USTR(INGEN_NS "entries")); BlankIDs ids('u'); ListContext ctx(ids, 0, &s, &p); @@ -253,5 +262,4 @@ UndoStack::save(FILE* stream, const char* name) serd_writer_free(writer); } -} // namespace server -} // namespace ingen +} // namespace ingen::server diff --git a/src/server/UndoStack.hpp b/src/server/UndoStack.hpp index 04021b99..443497cc 100644 --- a/src/server/UndoStack.hpp +++ b/src/server/UndoStack.hpp @@ -17,12 +17,12 @@ #ifndef INGEN_ENGINE_UNDOSTACK_HPP #define INGEN_ENGINE_UNDOSTACK_HPP -#include "ingen/AtomSink.hpp" -#include "ingen/ingen.h" -#include "lv2/atom/atom.h" -#include "lv2/atom/util.h" -#include "serd/serd.h" -#include "sratom/sratom.h" +#include <ingen/AtomSink.hpp> +#include <lv2/atom/atom.h> +#include <lv2/atom/util.h> +#include <serd/serd.h> +#include <server.h> +#include <sratom/sratom.h> #include <cstdint> #include <cstdio> @@ -38,10 +38,12 @@ class URIs; namespace server { -class INGEN_API UndoStack : public AtomSink { +class INGEN_SERVER_API UndoStack : public AtomSink +{ public: struct Entry { - Entry(time_t time=0) : time(time) {} + explicit Entry(time_t t) noexcept : time{t} {} + Entry() noexcept : Entry{0} {} Entry(const Entry& copy) : time(copy.time) @@ -54,10 +56,12 @@ public: ~Entry() { clear(); } Entry& operator=(const Entry& rhs) { - clear(); - time = rhs.time; - for (const LV2_Atom* ev : rhs.events) { - push_event(ev); + if (&rhs != this) { + clear(); + time = rhs.time; + for (const LV2_Atom* ev : rhs.events) { + push_event(ev); + } } return *this; } @@ -71,7 +75,7 @@ public: void push_event(const LV2_Atom* ev) { const uint32_t size = lv2_atom_total_size(ev); - LV2_Atom* copy = (LV2_Atom*)malloc(size); + auto* copy = static_cast<LV2_Atom*>(malloc(size)); memcpy(copy, ev, size); events.push_front(copy); } @@ -80,7 +84,7 @@ public: std::deque<LV2_Atom*> events; }; - UndoStack(URIs& uris, URIMap& map) : _uris(uris), _map(map), _depth(0) {} + UndoStack(URIs& uris, URIMap& map) noexcept : _uris(uris), _map(map) {} int start_entry(); bool write(const LV2_Atom* msg, int32_t default_id=0) override; @@ -103,7 +107,7 @@ private: URIs& _uris; URIMap& _map; std::deque<Entry> _stack; - int _depth; + int _depth{0}; }; } // namespace server diff --git a/src/server/Worker.cpp b/src/server/Worker.cpp index 68926278..1c04bb36 100644 --- a/src/server/Worker.cpp +++ b/src/server/Worker.cpp @@ -20,19 +20,23 @@ #include "GraphImpl.hpp" #include "LV2Block.hpp" -#include "ingen/Log.hpp" -#include "lv2/worker/worker.h" +#include <ingen/Log.hpp> +#include <ingen/Node.hpp> +#include <lv2/core/lv2.h> +#include <lv2/worker/worker.h> +#include <raul/RingBuffer.hpp> +#include <raul/Semaphore.hpp> #include <cstdlib> +#include <memory> -namespace ingen { -namespace server { +namespace ingen::server { /// A message in the Worker::_requests ring struct MessageHeader { - LV2Block* block; ///< Node this message is from + LV2Block* block; ///< Node this message is from uint32_t size; ///< Size of following data - // `size' bytes of data follow here + // `size' bytes of data follow here }; static LV2_Worker_Status @@ -40,8 +44,8 @@ schedule(LV2_Worker_Schedule_Handle handle, uint32_t size, const void* data) { - auto* block = (LV2Block*)handle; - Engine& engine = block->parent_graph()->engine(); + auto* block = static_cast<LV2Block*>(handle); + const Engine& engine = block->parent_graph()->engine(); return engine.worker()->request(block, size, data); } @@ -51,8 +55,8 @@ schedule_sync(LV2_Worker_Schedule_Handle handle, uint32_t size, const void* data) { - auto* block = (LV2Block*)handle; - Engine& engine = block->parent_graph()->engine(); + auto* block = static_cast<LV2Block*>(handle); + const Engine& engine = block->parent_graph()->engine(); return engine.sync_worker()->request(block, size, data); } @@ -66,7 +70,7 @@ Worker::request(LV2Block* block, return block->work(size, data); } - Engine& engine = block->parent_graph()->engine(); + const Engine& engine = block->parent_graph()->engine(); if (_requests.write_space() < sizeof(MessageHeader) + size) { engine.log().error("Work request ring overflow\n"); return LV2_WORKER_ERR_NO_SPACE; @@ -87,39 +91,38 @@ Worker::request(LV2Block* block, return LV2_WORKER_SUCCESS; } -SPtr<LV2_Feature> +std::shared_ptr<LV2_Feature> Worker::Schedule::feature(World&, Node* n) { auto* block = dynamic_cast<LV2Block*>(n); if (!block) { - return SPtr<LV2_Feature>(); + return nullptr; } - auto* data = (LV2_Worker_Schedule*)malloc(sizeof(LV2_Worker_Schedule)); + auto* data = static_cast<LV2_Worker_Schedule*>(malloc(sizeof(LV2_Worker_Schedule))); + data->handle = block; data->schedule_work = synchronous ? schedule_sync : schedule; - auto* f = (LV2_Feature*)malloc(sizeof(LV2_Feature)); + auto* f = static_cast<LV2_Feature*>(malloc(sizeof(LV2_Feature))); f->URI = LV2_WORKER__schedule; f->data = data; - return SPtr<LV2_Feature>(f, &free_feature); + return {f, &free_feature}; } Worker::Worker(Log& log, uint32_t buffer_size, bool synchronous) : _schedule(new Schedule(synchronous)) , _log(log) - , _sem(0) , _requests(buffer_size) , _responses(buffer_size) - , _buffer((uint8_t*)malloc(buffer_size)) + , _buffer(static_cast<uint8_t*>(malloc(buffer_size))) , _buffer_size(buffer_size) , _thread(nullptr) - , _exit_flag(false) , _synchronous(synchronous) { if (!synchronous) { - _thread = make_unique<std::thread>(&Worker::run, this); + _thread = std::make_unique<std::thread>(&Worker::run, this); } } @@ -159,5 +162,4 @@ Worker::run() } } -} // namespace server -} // namespace ingen +} // namespace ingen::server diff --git a/src/server/Worker.hpp b/src/server/Worker.hpp index 2e4a965f..08b75509 100644 --- a/src/server/Worker.hpp +++ b/src/server/Worker.hpp @@ -17,13 +17,14 @@ #ifndef INGEN_ENGINE_WORKER_HPP #define INGEN_ENGINE_WORKER_HPP -#include "ingen/LV2Features.hpp" -#include "ingen/types.hpp" -#include "lv2/worker/worker.h" -#include "raul/RingBuffer.hpp" -#include "raul/Semaphore.hpp" +#include <ingen/LV2Features.hpp> +#include <lv2/core/lv2.h> +#include <lv2/worker/worker.h> +#include <raul/RingBuffer.hpp> +#include <raul/Semaphore.hpp> #include <cstdint> +#include <memory> #include <thread> namespace ingen { @@ -41,11 +42,11 @@ public: ~Worker(); struct Schedule : public LV2Features::Feature { - Schedule(bool sync) : synchronous(sync) {} + explicit Schedule(bool sync) noexcept : synchronous(sync) {} const char* uri() const override { return LV2_WORKER__schedule; } - SPtr<LV2_Feature> feature(World& world, Node* n) override; + std::shared_ptr<LV2_Feature> feature(World& world, Node* n) override; const bool synchronous; }; @@ -54,20 +55,20 @@ public: uint32_t size, const void* data); - SPtr<Schedule> schedule_feature() { return _schedule; } + std::shared_ptr<Schedule> schedule_feature() { return _schedule; } private: - SPtr<Schedule> _schedule; - - Log& _log; - Raul::Semaphore _sem; - Raul::RingBuffer _requests; - Raul::RingBuffer _responses; - uint8_t* const _buffer; - const uint32_t _buffer_size; - UPtr<std::thread> _thread; - bool _exit_flag; - bool _synchronous; + std::shared_ptr<Schedule> _schedule; + + Log& _log; + raul::Semaphore _sem{0}; + raul::RingBuffer _requests; + raul::RingBuffer _responses; + uint8_t* const _buffer; + const uint32_t _buffer_size; + std::unique_ptr<std::thread> _thread; + bool _exit_flag{false}; + bool _synchronous; void run(); }; diff --git a/src/server/events.hpp b/src/server/events.hpp index 5f77b431..7ab20ca7 100644 --- a/src/server/events.hpp +++ b/src/server/events.hpp @@ -17,19 +17,19 @@ #ifndef INGEN_ENGINE_EVENTS_HPP #define INGEN_ENGINE_EVENTS_HPP -#include "events/Connect.hpp" -#include "events/Copy.hpp" -#include "events/CreateBlock.hpp" -#include "events/CreateGraph.hpp" -#include "events/CreatePort.hpp" -#include "events/Delete.hpp" -#include "events/Delta.hpp" -#include "events/Disconnect.hpp" -#include "events/DisconnectAll.hpp" -#include "events/Get.hpp" -#include "events/Mark.hpp" -#include "events/Move.hpp" -#include "events/SetPortValue.hpp" -#include "events/Undo.hpp" +#include <events/Connect.hpp> +#include <events/Copy.hpp> +#include <events/CreateBlock.hpp> +#include <events/CreateGraph.hpp> +#include <events/CreatePort.hpp> +#include <events/Delete.hpp> +#include <events/Delta.hpp> +#include <events/Disconnect.hpp> +#include <events/DisconnectAll.hpp> +#include <events/Get.hpp> +#include <events/Mark.hpp> +#include <events/Move.hpp> +#include <events/SetPortValue.hpp> +#include <events/Undo.hpp> #endif // INGEN_ENGINE_EVENTS_HPP diff --git a/src/server/events/Connect.cpp b/src/server/events/Connect.cpp index dd5b32a9..6e20be8f 100644 --- a/src/server/events/Connect.cpp +++ b/src/server/events/Connect.cpp @@ -16,42 +16,50 @@ #include "Connect.hpp" +#include "../internals/BlockDelay.hpp" #include "ArcImpl.hpp" +#include "BlockImpl.hpp" #include "Broadcaster.hpp" #include "BufferFactory.hpp" +#include "CompiledGraph.hpp" #include "Engine.hpp" #include "GraphImpl.hpp" #include "InputPort.hpp" #include "PortImpl.hpp" #include "PreProcessContext.hpp" -#include "internals/BlockDelay.hpp" #include "types.hpp" -#include "ingen/Store.hpp" -#include "raul/Maid.hpp" +#include <ingen/Interface.hpp> +#include <ingen/Message.hpp> +#include <ingen/Node.hpp> +#include <ingen/Properties.hpp> +#include <ingen/Status.hpp> +#include <ingen/Store.hpp> +#include <ingen/paths.hpp> +#include <raul/Maid.hpp> #include <cassert> +#include <memory> #include <mutex> +#include <set> #include <utility> -namespace ingen { -namespace server { -namespace events { - -Connect::Connect(Engine& engine, - const SPtr<Interface>& client, - SampleCount timestamp, - const ingen::Connect& msg) - : Event(engine, client, msg.seq, timestamp) - , _msg(msg) - , _graph(nullptr) - , _head(nullptr) +namespace ingen::server::events { + +Connect::Connect(Engine& engine, + const std::shared_ptr<Interface>& client, + SampleCount timestamp, + const ingen::Connect& msg) + : Event(engine, client, msg.seq, timestamp) + , _msg(msg) {} +Connect::~Connect() = default; + bool Connect::pre_process(PreProcessContext& ctx) { - std::lock_guard<Store::Mutex> lock(_engine.store()->mutex()); + const std::lock_guard<Store::Mutex> lock{_engine.store()->mutex()}; Node* tail = _engine.store()->get(_msg.tail); if (!tail) { @@ -126,7 +134,7 @@ Connect::pre_process(PreProcessContext& ctx) head_block->providers().insert(tail_block); if (ctx.must_compile(*_graph)) { - if (!(_compiled_graph = compile(*_engine.maid(), *_graph))) { + if (!(_compiled_graph = compile(*_graph))) { head_block->providers().erase(tail_block); tail_block->dependants().erase(head_block); return Event::pre_process_done(Status::COMPILATION_FAILED); @@ -150,16 +158,16 @@ Connect::pre_process(PreProcessContext& ctx) } void -Connect::execute(RunContext& context) +Connect::execute(RunContext& ctx) { if (_status == Status::SUCCESS) { - _head->add_arc(context, *_arc.get()); + _head->add_arc(ctx, *_arc); if (!_head->is_driver_port()) { - _head->set_voices(context, std::move(_voices)); + _head->set_voices(ctx, std::move(_voices)); } _head->connect_buffers(); if (_compiled_graph) { - _graph->set_compiled_graph(std::move(_compiled_graph)); + _compiled_graph = _graph->swap_compiled_graph(std::move(_compiled_graph)); } } } @@ -167,7 +175,7 @@ Connect::execute(RunContext& context) void Connect::post_process() { - Broadcaster::Transfer t(*_engine.broadcaster()); + const Broadcaster::Transfer t{*_engine.broadcaster()}; if (respond() == Status::SUCCESS) { _engine.broadcaster()->message(_msg); if (!_tail_remove.empty() || !_tail_add.empty()) { @@ -187,6 +195,4 @@ Connect::undo(Interface& target) target.disconnect(_msg.tail, _msg.head); } -} // namespace events -} // namespace server -} // namespace ingen +} // namespace ingen::server::events diff --git a/src/server/events/Connect.hpp b/src/server/events/Connect.hpp index adc80afc..458df0ef 100644 --- a/src/server/events/Connect.hpp +++ b/src/server/events/Connect.hpp @@ -17,15 +17,25 @@ #ifndef INGEN_EVENTS_CONNECT_HPP #define INGEN_EVENTS_CONNECT_HPP -#include "CompiledGraph.hpp" #include "Event.hpp" #include "PortImpl.hpp" #include "types.hpp" +#include <ingen/Message.hpp> +#include <ingen/Properties.hpp> +#include <raul/Maid.hpp> + +#include <memory> + namespace ingen { + +class Interface; + namespace server { class ArcImpl; +class CompiledGraph; +class Engine; class GraphImpl; class InputPort; @@ -38,27 +48,29 @@ namespace events { class Connect : public Event { public: - Connect(Engine& engine, - const SPtr<Interface>& client, - SampleCount timestamp, - const ingen::Connect& msg); + Connect(Engine& engine, + const std::shared_ptr<Interface>& client, + SampleCount timestamp, + const ingen::Connect& msg); + + ~Connect() override; bool pre_process(PreProcessContext& ctx) override; - void execute(RunContext& context) override; + void execute(RunContext& ctx) override; void post_process() override; void undo(Interface& target) override; private: - const ingen::Connect _msg; - GraphImpl* _graph; - InputPort* _head; - MPtr<CompiledGraph> _compiled_graph; - SPtr<ArcImpl> _arc; - MPtr<PortImpl::Voices> _voices; - Properties _tail_remove; - Properties _tail_add; - Properties _head_remove; - Properties _head_add; + const ingen::Connect _msg; + GraphImpl* _graph{nullptr}; + InputPort* _head{nullptr}; + std::unique_ptr<CompiledGraph> _compiled_graph; + std::shared_ptr<ArcImpl> _arc; + raul::managed_ptr<PortImpl::Voices> _voices; + Properties _tail_remove; + Properties _tail_add; + Properties _head_remove; + Properties _head_add; }; } // namespace events diff --git a/src/server/events/Copy.cpp b/src/server/events/Copy.cpp index 5418af4b..e75bf1c5 100644 --- a/src/server/events/Copy.cpp +++ b/src/server/events/Copy.cpp @@ -14,75 +14,88 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "events/Copy.hpp" +#include "Copy.hpp" #include "BlockImpl.hpp" #include "Broadcaster.hpp" +#include "CompiledGraph.hpp" #include "Engine.hpp" #include "GraphImpl.hpp" #include "PreProcessContext.hpp" -#include "ingen/Parser.hpp" -#include "ingen/Serialiser.hpp" -#include "ingen/Store.hpp" -#include "ingen/World.hpp" -#include "raul/Path.hpp" - +#include <ingen/Interface.hpp> +#include <ingen/Message.hpp> +#include <ingen/Node.hpp> +#include <ingen/Parser.hpp> +#include <ingen/Serialiser.hpp> +#include <ingen/Status.hpp> +#include <ingen/Store.hpp> +#include <ingen/URI.hpp> +#include <ingen/World.hpp> +#include <ingen/paths.hpp> +#include <raul/Path.hpp> +#include <raul/Symbol.hpp> + +#include <map> +#include <memory> #include <mutex> +#include <optional> #include <string> +#include <string_view> #include <utility> -namespace ingen { -namespace server { -namespace events { - -Copy::Copy(Engine& engine, - const SPtr<Interface>& client, - SampleCount timestamp, - const ingen::Copy& msg) - : Event(engine, client, msg.seq, timestamp) - , _msg(msg) - , _old_block(nullptr) - , _parent(nullptr) - , _block(nullptr) +namespace ingen::server::events { + +Copy::Copy(Engine& engine, + const std::shared_ptr<Interface>& client, + SampleCount timestamp, + const ingen::Copy& msg) + : Event(engine, client, msg.seq, timestamp) + , _msg(msg) {} +Copy::~Copy() = default; + bool Copy::pre_process(PreProcessContext& ctx) { - std::lock_guard<Store::Mutex> lock(_engine.store()->mutex()); + const std::lock_guard<Store::Mutex> lock{_engine.store()->mutex()}; if (uri_is_path(_msg.old_uri)) { // Old URI is a path within the engine - const Raul::Path old_path = uri_to_path(_msg.old_uri); + const raul::Path old_path = uri_to_path(_msg.old_uri); // Find the old node - const Store::iterator i = _engine.store()->find(old_path); + const auto i = _engine.store()->find(old_path); if (i == _engine.store()->end()) { return Event::pre_process_done(Status::NOT_FOUND, old_path); } // Ensure it is a block (ports are not supported for now) - if (!(_old_block = dynamic_ptr_cast<BlockImpl>(i->second))) { + if (!(_old_block = std::dynamic_pointer_cast<BlockImpl>(i->second))) { return Event::pre_process_done(Status::BAD_OBJECT_TYPE, old_path); } if (uri_is_path(_msg.new_uri)) { // Copy to path within the engine return engine_to_engine(ctx); - } else if (_msg.new_uri.scheme() == "file") { + } + + if (_msg.new_uri.scheme() == "file") { // Copy to filesystem path (i.e. save) return engine_to_filesystem(ctx); - } else { - return Event::pre_process_done(Status::BAD_REQUEST); } - } else if (_msg.old_uri.scheme() == "file") { + + return Event::pre_process_done(Status::BAD_REQUEST); + } + + if (_msg.old_uri.scheme() == "file") { if (uri_is_path(_msg.new_uri)) { return filesystem_to_engine(ctx); - } else { - // Ingen is not your file manager - return Event::pre_process_done(Status::BAD_REQUEST); } + + // Ingen is not your file manager + return Event::pre_process_done(Status::BAD_REQUEST); } return Event::pre_process_done(Status::BAD_URI); @@ -92,8 +105,8 @@ bool Copy::engine_to_engine(PreProcessContext& ctx) { // Only support a single source for now - const Raul::Path new_path = uri_to_path(_msg.new_uri); - if (!Raul::Symbol::is_valid(new_path.symbol())) { + const raul::Path new_path = uri_to_path(_msg.new_uri); + if (!raul::Symbol::is_valid(new_path.symbol())) { return Event::pre_process_done(Status::BAD_REQUEST); } @@ -103,8 +116,8 @@ Copy::engine_to_engine(PreProcessContext& ctx) } // Find new parent graph - const Raul::Path parent_path = new_path.parent(); - const Store::iterator p = _engine.store()->find(parent_path); + const raul::Path parent_path = new_path.parent(); + const auto p = _engine.store()->find(parent_path); if (p == _engine.store()->end()) { return Event::pre_process_done(Status::NOT_FOUND, parent_path); } @@ -113,8 +126,7 @@ Copy::engine_to_engine(PreProcessContext& ctx) } // Create new block - if (!(_block = dynamic_cast<BlockImpl*>( - _old_block->duplicate(_engine, Raul::Symbol(new_path.symbol()), _parent)))) { + if (!(_block = _old_block->duplicate(_engine, raul::Symbol(new_path.symbol()), _parent))) { return Event::pre_process_done(Status::INTERNAL_ERROR); } @@ -125,7 +137,7 @@ Copy::engine_to_engine(PreProcessContext& ctx) _engine.store()->add(_block); // Compile graph with new block added for insertion in audio thread - _compiled_graph = ctx.maybe_compile(*_engine.maid(), *_parent); + _compiled_graph = ctx.maybe_compile(*_parent); return Event::pre_process_done(Status::SUCCESS); } @@ -143,7 +155,7 @@ bool Copy::engine_to_filesystem(PreProcessContext&) { // Ensure source is a graph - SPtr<GraphImpl> graph = dynamic_ptr_cast<GraphImpl>(_old_block); + auto graph = std::dynamic_pointer_cast<GraphImpl>(_old_block); if (!graph) { return Event::pre_process_done(Status::BAD_OBJECT_TYPE, _msg.old_uri); } @@ -152,7 +164,7 @@ Copy::engine_to_filesystem(PreProcessContext&) return Event::pre_process_done(Status::INTERNAL_ERROR); } - std::lock_guard<std::mutex> lock(_engine.world().rdf_mutex()); + const std::lock_guard<std::mutex> lock{_engine.world().rdf_mutex()}; if (ends_with(_msg.new_uri, ".ingen") || ends_with(_msg.new_uri, ".ingen/")) { _engine.world().serialiser()->write_bundle(graph, URI(_msg.new_uri)); @@ -173,16 +185,16 @@ Copy::filesystem_to_engine(PreProcessContext&) return Event::pre_process_done(Status::INTERNAL_ERROR); } - std::lock_guard<std::mutex> lock(_engine.world().rdf_mutex()); + const std::lock_guard<std::mutex> lock{_engine.world().rdf_mutex()}; // Old URI is a filesystem path and new URI is a path within the engine - const std::string src_path(_msg.old_uri.path()); - const Raul::Path dst_path = uri_to_path(_msg.new_uri); - boost::optional<Raul::Path> dst_parent; - boost::optional<Raul::Symbol> dst_symbol; + const std::string src_path(_msg.old_uri.path()); + const raul::Path dst_path = uri_to_path(_msg.new_uri); + std::optional<raul::Path> dst_parent; + std::optional<raul::Symbol> dst_symbol; if (!dst_path.is_root()) { dst_parent = dst_path.parent(); - dst_symbol = Raul::Symbol(dst_path.symbol()); + dst_symbol = raul::Symbol(dst_path.symbol()); } _engine.world().parser()->parse_file( @@ -196,14 +208,15 @@ void Copy::execute(RunContext&) { if (_block && _compiled_graph) { - _parent->set_compiled_graph(std::move(_compiled_graph)); + _compiled_graph = + _parent->swap_compiled_graph(std::move(_compiled_graph)); } } void Copy::post_process() { - Broadcaster::Transfer t(*_engine.broadcaster()); + const Broadcaster::Transfer t{*_engine.broadcaster()}; if (respond() == Status::SUCCESS) { _engine.broadcaster()->message(_msg); } @@ -217,6 +230,4 @@ Copy::undo(Interface& target) } } -} // namespace events -} // namespace server -} // namespace ingen +} // namespace ingen::server::events diff --git a/src/server/events/Copy.hpp b/src/server/events/Copy.hpp index 26673a55..8031bb42 100644 --- a/src/server/events/Copy.hpp +++ b/src/server/events/Copy.hpp @@ -17,15 +17,24 @@ #ifndef INGEN_EVENTS_COPY_HPP #define INGEN_EVENTS_COPY_HPP -#include "CompiledGraph.hpp" #include "Event.hpp" +#include "types.hpp" + +#include <ingen/Message.hpp> + +#include <memory> namespace ingen { + +class Interface; + namespace server { class BlockImpl; +class CompiledGraph; class Engine; class GraphImpl; +class PreProcessContext; namespace events { @@ -35,13 +44,15 @@ namespace events { class Copy : public Event { public: - Copy(Engine& engine, - const SPtr<Interface>& client, - SampleCount timestamp, - const ingen::Copy& msg); + Copy(Engine& engine, + const std::shared_ptr<Interface>& client, + SampleCount timestamp, + const ingen::Copy& msg); + + ~Copy() override; bool pre_process(PreProcessContext& ctx) override; - void execute(RunContext& context) override; + void execute(RunContext& ctx) override; void post_process() override; void undo(Interface& target) override; @@ -50,11 +61,11 @@ private: bool engine_to_filesystem(PreProcessContext& ctx); bool filesystem_to_engine(PreProcessContext& ctx); - const ingen::Copy _msg; - SPtr<BlockImpl> _old_block; - GraphImpl* _parent; - BlockImpl* _block; - MPtr<CompiledGraph> _compiled_graph; + const ingen::Copy _msg; + std::shared_ptr<BlockImpl> _old_block{nullptr}; + GraphImpl* _parent{nullptr}; + BlockImpl* _block{nullptr}; + std::unique_ptr<CompiledGraph> _compiled_graph; }; } // namespace events diff --git a/src/server/events/CreateBlock.cpp b/src/server/events/CreateBlock.cpp index 4b48cfde..55c9b782 100644 --- a/src/server/events/CreateBlock.cpp +++ b/src/server/events/CreateBlock.cpp @@ -19,57 +19,71 @@ #include "BlockFactory.hpp" #include "BlockImpl.hpp" #include "Broadcaster.hpp" +#include "CompiledGraph.hpp" #include "Engine.hpp" #include "GraphImpl.hpp" #include "LV2Block.hpp" #include "PluginImpl.hpp" #include "PreProcessContext.hpp" - -#include "ingen/Forge.hpp" -#include "ingen/Store.hpp" -#include "ingen/URIs.hpp" -#include "ingen/World.hpp" -#include "raul/Maid.hpp" -#include "raul/Path.hpp" - +#include "State.hpp" +#include "types.hpp" + +#include <ingen/FilePath.hpp> +#include <ingen/Forge.hpp> +#include <ingen/Interface.hpp> +#include <ingen/Node.hpp> +#include <ingen/Properties.hpp> +#include <ingen/Resource.hpp> +#include <ingen/Status.hpp> +#include <ingen/Store.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIs.hpp> +#include <ingen/World.hpp> +#include <ingen/paths.hpp> +#include <raul/Path.hpp> +#include <raul/Symbol.hpp> + +#include <map> +#include <memory> +#include <string> #include <utility> -namespace ingen { -namespace server { -namespace events { - -CreateBlock::CreateBlock(Engine& engine, - const SPtr<Interface>& client, - int32_t id, - SampleCount timestamp, - const Raul::Path& path, - Properties& properties) - : Event(engine, client, id, timestamp) - , _path(path) - , _properties(properties) - , _graph(nullptr) - , _block(nullptr) +namespace ingen::server::events { + +CreateBlock::CreateBlock(Engine& engine, + const std::shared_ptr<Interface>& client, + int32_t id, + SampleCount timestamp, + raul::Path path, + Properties& properties) + : Event(engine, client, id, timestamp) + , _path(std::move(path)) + , _properties(properties) {} +CreateBlock::~CreateBlock() = default; + bool CreateBlock::pre_process(PreProcessContext& ctx) { - using iterator = Properties::const_iterator; - - const ingen::URIs& uris = _engine.world().uris(); - const SPtr<Store> store = _engine.store(); + const ingen::URIs& uris = _engine.world().uris(); + const std::shared_ptr<Store> store = _engine.store(); // Check sanity of target path if (_path.is_root()) { return Event::pre_process_done(Status::BAD_URI, _path); - } else if (store->get(_path)) { + } + + if (store->get(_path)) { return Event::pre_process_done(Status::EXISTS, _path); - } else if (!(_graph = dynamic_cast<GraphImpl*>(store->get(_path.parent())))) { + } + + if (!(_graph = dynamic_cast<GraphImpl*>(store->get(_path.parent())))) { return Event::pre_process_done(Status::PARENT_NOT_FOUND, _path.parent()); } // Map old ingen:prototype to new lv2:prototype - auto range = _properties.equal_range(uris.ingen_prototype); + const auto range = _properties.equal_range(uris.ingen_prototype); for (auto i = range.first; i != range.second;) { const auto value = i->second; auto next = i; @@ -79,7 +93,7 @@ CreateBlock::pre_process(PreProcessContext& ctx) } // Get prototype - iterator t = _properties.find(uris.lv2_prototype); + const auto t = _properties.find(uris.lv2_prototype); if (t == _properties.end() || !uris.forge.is_uri(t->second)) { // Missing/invalid prototype return Event::pre_process_done(Status::BAD_REQUEST); @@ -88,10 +102,10 @@ CreateBlock::pre_process(PreProcessContext& ctx) const URI prototype(uris.forge.str(t->second, false)); // Find polyphony - const iterator p = _properties.find(uris.ingen_polyphonic); - const bool polyphonic = (p != _properties.end() && - p->second.type() == uris.forge.Bool && - p->second.get<int32_t>()); + const auto p = _properties.find(uris.ingen_polyphonic); + const bool polyphonic = (p != _properties.end() && + p->second.type() == uris.forge.Bool && + p->second.get<int32_t>()); // Find and instantiate/duplicate prototype (plugin/existing node) if (uri_is_path(prototype)) { @@ -100,8 +114,11 @@ CreateBlock::pre_process(PreProcessContext& ctx) store->get(uri_to_path(prototype))); if (!ancestor) { return Event::pre_process_done(Status::PROTOTYPE_NOT_FOUND, prototype); - } else if (!(_block = ancestor->duplicate( - _engine, Raul::Symbol(_path.symbol()), _graph))) { + } + + if (!(_block = ancestor->duplicate(_engine, + raul::Symbol(_path.symbol()), + _graph))) { return Event::pre_process_done(Status::CREATION_FAILED, _path); } @@ -119,7 +136,7 @@ CreateBlock::pre_process(PreProcessContext& ctx) } // Load state from directory if given in properties - LilvState* state = nullptr; + StatePtr state{}; auto s = _properties.find(uris.state_state); if (s != _properties.end() && s->second.type() == uris.forge.Path) { state = LV2Block::load_state( @@ -128,11 +145,11 @@ CreateBlock::pre_process(PreProcessContext& ctx) // Instantiate plugin if (!(_block = plugin->instantiate(*_engine.buffer_factory(), - Raul::Symbol(_path.symbol()), + raul::Symbol(_path.symbol()), polyphonic, _graph, _engine, - state))) { + state.get()))) { return Event::pre_process_done(Status::CREATION_FAILED, _path); } } @@ -148,7 +165,7 @@ CreateBlock::pre_process(PreProcessContext& ctx) /* Compile graph with new block added for insertion in audio thread TODO: Since the block is not connected at this point, a full compilation could be avoided and the block simply appended. */ - _compiled_graph = ctx.maybe_compile(*_engine.maid(), *_graph); + _compiled_graph = ctx.maybe_compile(*_graph); _update.put_block(_block); @@ -159,14 +176,15 @@ void CreateBlock::execute(RunContext&) { if (_status == Status::SUCCESS && _compiled_graph) { - _graph->set_compiled_graph(std::move(_compiled_graph)); + _compiled_graph = + _graph->swap_compiled_graph(std::move(_compiled_graph)); } } void CreateBlock::post_process() { - Broadcaster::Transfer t(*_engine.broadcaster()); + const Broadcaster::Transfer t{*_engine.broadcaster()}; if (respond() == Status::SUCCESS) { _update.send(*_engine.broadcaster()); } @@ -178,6 +196,4 @@ CreateBlock::undo(Interface& target) target.del(_block->uri()); } -} // namespace events -} // namespace server -} // namespace ingen +} // namespace ingen::server::events diff --git a/src/server/events/CreateBlock.hpp b/src/server/events/CreateBlock.hpp index 00f58008..0ee6e36f 100644 --- a/src/server/events/CreateBlock.hpp +++ b/src/server/events/CreateBlock.hpp @@ -18,15 +18,24 @@ #define INGEN_EVENTS_CREATEBLOCK_HPP #include "ClientUpdate.hpp" -#include "CompiledGraph.hpp" #include "Event.hpp" +#include "types.hpp" + +#include <raul/Path.hpp> #include <cstdint> +#include <memory> namespace ingen { + +class Interface; +class Properties; + namespace server { class BlockImpl; +class CompiledGraph; +class Engine; class GraphImpl; namespace events { @@ -38,25 +47,27 @@ namespace events { class CreateBlock : public Event { public: - CreateBlock(Engine& engine, - const SPtr<Interface>& client, - int32_t id, - SampleCount timestamp, - const Raul::Path& path, - Properties& properties); + CreateBlock(Engine& engine, + const std::shared_ptr<Interface>& client, + int32_t id, + SampleCount timestamp, + raul::Path path, + Properties& properties); + + ~CreateBlock() override; bool pre_process(PreProcessContext& ctx) override; - void execute(RunContext& context) override; + void execute(RunContext& ctx) override; void post_process() override; void undo(Interface& target) override; private: - Raul::Path _path; - Properties& _properties; - ClientUpdate _update; - GraphImpl* _graph; - BlockImpl* _block; - MPtr<CompiledGraph> _compiled_graph; + raul::Path _path; + Properties& _properties; + ClientUpdate _update; + GraphImpl* _graph{nullptr}; + BlockImpl* _block{nullptr}; + std::unique_ptr<CompiledGraph> _compiled_graph; }; } // namespace events diff --git a/src/server/events/CreateGraph.cpp b/src/server/events/CreateGraph.cpp index 3e847bdd..5df28afa 100644 --- a/src/server/events/CreateGraph.cpp +++ b/src/server/events/CreateGraph.cpp @@ -14,40 +14,53 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "events/CreateGraph.hpp" +#include "CreateGraph.hpp" +#include "BlockImpl.hpp" #include "Broadcaster.hpp" +#include "CompiledGraph.hpp" +#include "CreatePort.hpp" #include "Engine.hpp" #include "GraphImpl.hpp" #include "PreProcessContext.hpp" -#include "events/CreatePort.hpp" - -#include "ingen/Forge.hpp" -#include "ingen/Store.hpp" -#include "ingen/URIs.hpp" -#include "ingen/World.hpp" -#include "raul/Maid.hpp" -#include "raul/Path.hpp" - +#include "types.hpp" + +#include <ingen/Forge.hpp> +#include <ingen/Interface.hpp> +#include <ingen/Node.hpp> +#include <ingen/Properties.hpp> +#include <ingen/Resource.hpp> +#include <ingen/Status.hpp> +#include <ingen/Store.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIs.hpp> +#include <ingen/World.hpp> +#include <ingen/paths.hpp> +#include <raul/Path.hpp> +#include <raul/Symbol.hpp> + +#include <boost/intrusive/slist.hpp> + +#include <map> +#include <memory> +#include <string> #include <utility> -namespace ingen { -namespace server { -namespace events { - -CreateGraph::CreateGraph(Engine& engine, - const SPtr<Interface>& client, - int32_t id, - SampleCount timestamp, - const Raul::Path& path, - const Properties& properties) - : Event(engine, client, id, timestamp) - , _path(path) - , _properties(properties) - , _graph(nullptr) - , _parent(nullptr) +namespace ingen::server::events { + +CreateGraph::CreateGraph(Engine& engine, + const std::shared_ptr<Interface>& client, + int32_t id, + SampleCount timestamp, + raul::Path path, + Properties properties) + : Event(engine, client, id, timestamp) + , _path(std::move(path)) + , _properties(std::move(properties)) {} +CreateGraph::~CreateGraph() = default; + void CreateGraph::build_child_events() { @@ -67,30 +80,40 @@ CreateGraph::build_child_events() in_properties.put(uris.lv2_index, uris.forge.make(0)); in_properties.put(uris.lv2_name, uris.forge.alloc("Control")); in_properties.put(uris.rdf_type, uris.lv2_InputPort); - in_properties.put(uris.ingen_canvasX, uris.forge.make(32.0f), + in_properties.put(uris.ingen_canvasX, + uris.forge.make(32.0f), Resource::Graph::EXTERNAL); - in_properties.put(uris.ingen_canvasY, uris.forge.make(32.0f), + in_properties.put(uris.ingen_canvasY, + uris.forge.make(32.0f), Resource::Graph::EXTERNAL); - _child_events.push_back( - make_unique<events::CreatePort>(_engine, _request_client, -1, _time, - _path.child(Raul::Symbol("control")), - in_properties)); + _child_events.push_back(std::make_unique<events::CreatePort>( + _engine, + _request_client, + -1, + _time, + _path.child(raul::Symbol("control")), + in_properties)); // Add notify port (message respond) Properties out_properties(control_properties); out_properties.put(uris.lv2_index, uris.forge.make(1)); out_properties.put(uris.lv2_name, uris.forge.alloc("Notify")); out_properties.put(uris.rdf_type, uris.lv2_OutputPort); - out_properties.put(uris.ingen_canvasX, uris.forge.make(128.0f), + out_properties.put(uris.ingen_canvasX, + uris.forge.make(128.0f), Resource::Graph::EXTERNAL); - out_properties.put(uris.ingen_canvasY, uris.forge.make(32.0f), + out_properties.put(uris.ingen_canvasY, + uris.forge.make(32.0f), Resource::Graph::EXTERNAL); _child_events.push_back( - make_unique<events::CreatePort>(_engine, _request_client, -1, _time, - _path.child(Raul::Symbol("notify")), - out_properties)); + std::make_unique<events::CreatePort>(_engine, + _request_client, + -1, + _time, + _path.child(raul::Symbol("notify")), + out_properties)); } bool @@ -101,7 +124,7 @@ CreateGraph::pre_process(PreProcessContext& ctx) } if (!_path.is_root()) { - const Raul::Path up(_path.parent()); + const raul::Path up(_path.parent()); if (!(_parent = dynamic_cast<GraphImpl*>(_engine.store()->get(up)))) { return Event::pre_process_done(Status::PARENT_NOT_FOUND, up); } @@ -109,11 +132,9 @@ CreateGraph::pre_process(PreProcessContext& ctx) const ingen::URIs& uris = _engine.world().uris(); - using iterator = Properties::const_iterator; - - uint32_t ext_poly = 1; - uint32_t int_poly = 1; - iterator p = _properties.find(uris.ingen_polyphony); + uint32_t ext_poly = 1; + uint32_t int_poly = 1; + const auto p = _properties.find(uris.ingen_polyphony); if (p != _properties.end() && p->second.type() == uris.forge.Int) { int_poly = p->second.get<int32_t>(); } @@ -126,33 +147,39 @@ CreateGraph::pre_process(PreProcessContext& ctx) ext_poly = int_poly; } - const Raul::Symbol symbol(_path.is_root() ? "graph" : _path.symbol()); + const raul::Symbol symbol(_path.is_root() ? "graph" : _path.symbol()); // Get graph prototype - iterator t = _properties.find(uris.lv2_prototype); + auto t = _properties.find(uris.lv2_prototype); if (t == _properties.end()) { t = _properties.find(uris.lv2_prototype); } - if (t != _properties.end() && - uris.forge.is_uri(t->second) && + if (t != _properties.end() && uris.forge.is_uri(t->second) && URI::is_valid(uris.forge.str(t->second, false)) && uri_is_path(URI(uris.forge.str(t->second, false)))) { // Create a duplicate of an existing graph const URI prototype(uris.forge.str(t->second, false)); GraphImpl* ancestor = dynamic_cast<GraphImpl*>( - _engine.store()->get(uri_to_path(prototype))); + _engine.store()->get(uri_to_path(prototype))); if (!ancestor) { - return Event::pre_process_done(Status::PROTOTYPE_NOT_FOUND, prototype); - } else if (!(_graph = dynamic_cast<GraphImpl*>( - ancestor->duplicate(_engine, symbol, _parent)))) { + return Event::pre_process_done(Status::PROTOTYPE_NOT_FOUND, + prototype); + } + + if (!(_graph = dynamic_cast<GraphImpl*>( + ancestor->duplicate(_engine, symbol, _parent)))) { return Event::pre_process_done(Status::CREATION_FAILED, _path); } } else { // Create a new graph - _graph = new GraphImpl(_engine, symbol, ext_poly, _parent, - _engine.sample_rate(), int_poly); - _graph->add_property(uris.rdf_type, uris.ingen_Graph.urid); + _graph = new GraphImpl(_engine, + symbol, + ext_poly, + _parent, + _engine.sample_rate(), + int_poly); + _graph->add_property(uris.rdf_type, uris.ingen_Graph.urid_atom()); _graph->add_property(uris.rdf_type, Property(uris.ingen_Block, Resource::Graph::EXTERNAL)); @@ -166,7 +193,7 @@ CreateGraph::pre_process(PreProcessContext& ctx) if (_parent->enabled()) { _graph->enable(); } - _compiled_graph = ctx.maybe_compile(*_engine.maid(), *_parent); + _compiled_graph = ctx.maybe_compile(*_parent); } _graph->activate(*_engine.buffer_factory()); @@ -188,12 +215,13 @@ CreateGraph::pre_process(PreProcessContext& ctx) } void -CreateGraph::execute(RunContext& context) +CreateGraph::execute(RunContext& ctx) { if (_graph) { if (_parent) { if (_compiled_graph) { - _parent->set_compiled_graph(std::move(_compiled_graph)); + _compiled_graph = + _parent->swap_compiled_graph(std::move(_compiled_graph)); } } else { _engine.set_root_graph(_graph); @@ -201,7 +229,7 @@ CreateGraph::execute(RunContext& context) } for (const auto& ev : _child_events) { - ev->execute(context); + ev->execute(ctx); } } } @@ -209,7 +237,7 @@ CreateGraph::execute(RunContext& context) void CreateGraph::post_process() { - Broadcaster::Transfer t(*_engine.broadcaster()); + const Broadcaster::Transfer t{*_engine.broadcaster()}; if (respond() == Status::SUCCESS) { _update.send(*_engine.broadcaster()); } @@ -227,6 +255,4 @@ CreateGraph::undo(Interface& target) target.del(_graph->uri()); } -} // namespace events -} // namespace server -} // namespace ingen +} // namespace ingen::server::events diff --git a/src/server/events/CreateGraph.hpp b/src/server/events/CreateGraph.hpp index dadb644e..1d7f04a5 100644 --- a/src/server/events/CreateGraph.hpp +++ b/src/server/events/CreateGraph.hpp @@ -18,17 +18,24 @@ #define INGEN_EVENTS_CREATEGRAPH_HPP #include "ClientUpdate.hpp" -#include "CompiledGraph.hpp" #include "Event.hpp" +#include "types.hpp" -#include "ingen/types.hpp" +#include <ingen/Properties.hpp> +#include <raul/Path.hpp> #include <cstdint> #include <list> +#include <memory> namespace ingen { + +class Interface; + namespace server { +class CompiledGraph; +class Engine; class GraphImpl; namespace events { @@ -40,15 +47,17 @@ namespace events { class CreateGraph : public Event { public: - CreateGraph(Engine& engine, - const SPtr<Interface>& client, - int32_t id, - SampleCount timestamp, - const Raul::Path& path, - const Properties& properties); + CreateGraph(Engine& engine, + const std::shared_ptr<Interface>& client, + int32_t id, + SampleCount timestamp, + raul::Path path, + Properties properties); + + ~CreateGraph() override; bool pre_process(PreProcessContext& ctx) override; - void execute(RunContext& context) override; + void execute(RunContext& ctx) override; void post_process() override; void undo(Interface& target) override; @@ -57,13 +66,13 @@ public: private: void build_child_events(); - const Raul::Path _path; - Properties _properties; - ClientUpdate _update; - GraphImpl* _graph; - GraphImpl* _parent; - MPtr<CompiledGraph> _compiled_graph; - std::list<UPtr<Event>> _child_events; + const raul::Path _path; + Properties _properties; + ClientUpdate _update; + GraphImpl* _graph{nullptr}; + GraphImpl* _parent{nullptr}; + std::unique_ptr<CompiledGraph> _compiled_graph; + std::list<std::unique_ptr<Event>> _child_events; }; } // namespace events diff --git a/src/server/events/CreatePort.cpp b/src/server/events/CreatePort.cpp index d0dcbaf3..b42542f8 100644 --- a/src/server/events/CreatePort.cpp +++ b/src/server/events/CreatePort.cpp @@ -23,45 +23,47 @@ #include "Engine.hpp" #include "GraphImpl.hpp" #include "PortImpl.hpp" - -#include "ingen/Atom.hpp" -#include "ingen/Forge.hpp" -#include "ingen/Store.hpp" -#include "ingen/URIMap.hpp" -#include "ingen/URIs.hpp" -#include "ingen/World.hpp" -#include "raul/Array.hpp" -#include "raul/Path.hpp" +#include "PortType.hpp" + +#include <ingen/Atom.hpp> +#include <ingen/Forge.hpp> +#include <ingen/Interface.hpp> +#include <ingen/Node.hpp> +#include <ingen/Properties.hpp> +#include <ingen/Status.hpp> +#include <ingen/Store.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIMap.hpp> +#include <ingen/URIs.hpp> +#include <ingen/World.hpp> +#include <ingen/paths.hpp> +#include <raul/Array.hpp> +#include <raul/Maid.hpp> +#include <raul/Path.hpp> +#include <raul/Symbol.hpp> #include <cassert> +#include <map> +#include <memory> +#include <string> #include <utility> -namespace ingen { -namespace server { -namespace events { - -CreatePort::CreatePort(Engine& engine, - const SPtr<Interface>& client, - int32_t id, - SampleCount timestamp, - const Raul::Path& path, - const Properties& properties) - : Event(engine, client, id, timestamp) - , _path(path) - , _port_type(PortType::UNKNOWN) - , _buf_type(0) - , _graph(nullptr) - , _graph_port(nullptr) - , _engine_port(nullptr) - , _properties(properties) +namespace ingen::server::events { + +CreatePort::CreatePort(Engine& engine, + const std::shared_ptr<Interface>& client, + int32_t id, + SampleCount timestamp, + raul::Path path, + const Properties& properties) + : Event(engine, client, id, timestamp) + , _path(std::move(path)) + , _properties(properties) { const ingen::URIs& uris = _engine.world().uris(); - using Iterator = Properties::const_iterator; - using Range = std::pair<Iterator, Iterator>; - - const Range types = properties.equal_range(uris.rdf_type); - for (Iterator i = types.first; i != types.second; ++i) { + const auto types = properties.equal_range(uris.rdf_type); + for (auto i = types.first; i != types.second; ++i) { const Atom& type = i->second; if (type == uris.lv2_AudioPort) { _port_type = PortType::AUDIO; @@ -78,8 +80,8 @@ CreatePort::CreatePort(Engine& engine, } } - const Range buffer_types = properties.equal_range(uris.atom_bufferType); - for (Iterator i = buffer_types.first; i != buffer_types.second; ++i) { + const auto buffer_types = properties.equal_range(uris.atom_bufferType); + for (auto i = buffer_types.first; i != buffer_types.second; ++i) { if (uris.forge.is_uri(i->second)) { _buf_type = _engine.world().uri_map().map_uri( uris.forge.str(i->second, false)); @@ -92,20 +94,28 @@ CreatePort::pre_process(PreProcessContext&) { if (_port_type == PortType::UNKNOWN || !_flow) { return Event::pre_process_done(Status::UNKNOWN_TYPE, _path); - } else if (_path.is_root()) { + } + + if (_path.is_root()) { return Event::pre_process_done(Status::BAD_URI, _path); - } else if (_engine.store()->get(_path)) { + } + + if (_engine.store()->get(_path)) { return Event::pre_process_done(Status::EXISTS, _path); } - const Raul::Path parent_path = _path.parent(); + const raul::Path parent_path = _path.parent(); Node* const parent = _engine.store()->get(parent_path); if (!parent) { return Event::pre_process_done(Status::PARENT_NOT_FOUND, parent_path); - } else if (!(_graph = dynamic_cast<GraphImpl*>(parent))) { + } + + if (!(_graph = dynamic_cast<GraphImpl*>(parent))) { return Event::pre_process_done(Status::INVALID_PARENT, parent_path); - } else if (!_graph->parent() && _engine.activated() && - !_engine.driver()->dynamic_ports()) { + } + + if (!_graph->parent() && _engine.activated() && + !_engine.driver()->dynamic_ports()) { return Event::pre_process_done(Status::CREATION_FAILED, _path); } @@ -114,10 +124,8 @@ CreatePort::pre_process(PreProcessContext&) const uint32_t buf_size = bufs.default_size(_buf_type); const int32_t old_n_ports = _graph->num_ports_non_rt(); - using PropIter = Properties::const_iterator; - - PropIter index_i = _properties.find(uris.lv2_index); - int32_t index = 0; + auto index_i = _properties.find(uris.lv2_index); + int32_t index = 0; if (index_i != _properties.end()) { // Ensure given index is sane and not taken if (index_i->second.type() != uris.forge.Int) { @@ -135,7 +143,7 @@ CreatePort::pre_process(PreProcessContext&) _engine.world().forge().make(index)); } - const PropIter poly_i = _properties.find(uris.ingen_polyphonic); + const auto poly_i = _properties.find(uris.ingen_polyphonic); const bool polyphonic = (poly_i != _properties.end() && poly_i->second.type() == uris.forge.Bool && poly_i->second.get<int32_t>()); @@ -147,7 +155,7 @@ CreatePort::pre_process(PreProcessContext&) } // Create port - _graph_port = new DuplexPort(bufs, _graph, Raul::Symbol(_path.symbol()), + _graph_port = new DuplexPort(bufs, _graph, raul::Symbol(_path.symbol()), index, polyphonic, _port_type, _buf_type, buf_size, @@ -172,18 +180,18 @@ CreatePort::pre_process(PreProcessContext&) _update = _graph_port->properties(); - assert(_graph_port->index() == (uint32_t)index_i->second.get<int32_t>()); - assert(_graph->num_ports_non_rt() == (uint32_t)old_n_ports + 1); + assert(_graph_port->index() == static_cast<uint32_t>(index_i->second.get<int32_t>())); + assert(_graph->num_ports_non_rt() == static_cast<uint32_t>(old_n_ports) + 1U); assert(_ports_array->size() == _graph->num_ports_non_rt()); assert(_graph_port->index() < _ports_array->size()); return Event::pre_process_done(Status::SUCCESS); } void -CreatePort::execute(RunContext& context) +CreatePort::execute(RunContext& ctx) { if (_status == Status::SUCCESS) { - const MPtr<GraphImpl::Ports>& old_ports = _graph->external_ports(); + const auto& old_ports = _graph->external_ports(); if (old_ports) { for (uint32_t i = 0; i < old_ports->size(); ++i) { const auto* const old_port = (*old_ports)[i]; @@ -196,7 +204,7 @@ CreatePort::execute(RunContext& context) _graph->set_external_ports(std::move(_ports_array)); if (_engine_port) { - _engine.driver()->add_port(context, _engine_port); + _engine.driver()->add_port(ctx, _engine_port); } } } @@ -204,7 +212,7 @@ CreatePort::execute(RunContext& context) void CreatePort::post_process() { - Broadcaster::Transfer t(*_engine.broadcaster()); + const Broadcaster::Transfer t{*_engine.broadcaster()}; if (respond() == Status::SUCCESS) { _engine.broadcaster()->put(path_to_uri(_path), _update); } @@ -216,6 +224,4 @@ CreatePort::undo(Interface& target) target.del(_graph_port->uri()); } -} // namespace events -} // namespace server -} // namespace ingen +} // namespace ingen::server::events diff --git a/src/server/events/CreatePort.hpp b/src/server/events/CreatePort.hpp index 8137328d..151bf82f 100644 --- a/src/server/events/CreatePort.hpp +++ b/src/server/events/CreatePort.hpp @@ -20,18 +20,25 @@ #include "BlockImpl.hpp" #include "Event.hpp" #include "PortType.hpp" +#include "types.hpp" -#include "lv2/urid/urid.h" -#include "raul/Path.hpp" - -#include <boost/optional/optional.hpp> +#include <ingen/Properties.hpp> +#include <lv2/urid/urid.h> +#include <raul/Maid.hpp> +#include <raul/Path.hpp> #include <cstdint> +#include <memory> +#include <optional> namespace ingen { + +class Interface; + namespace server { class DuplexPort; +class Engine; class EnginePort; class GraphImpl; @@ -44,15 +51,15 @@ namespace events { class CreatePort : public Event { public: - CreatePort(Engine& engine, - const SPtr<Interface>& client, - int32_t id, - SampleCount timestamp, - const Raul::Path& path, - const Properties& properties); + CreatePort(Engine& engine, + const std::shared_ptr<Interface>& client, + int32_t id, + SampleCount timestamp, + raul::Path path, + const Properties& properties); bool pre_process(PreProcessContext& ctx) override; - void execute(RunContext& context) override; + void execute(RunContext& ctx) override; void post_process() override; void undo(Interface& target) override; @@ -62,16 +69,16 @@ private: OUTPUT }; - Raul::Path _path; - PortType _port_type; - LV2_URID _buf_type; - GraphImpl* _graph; - DuplexPort* _graph_port; - MPtr<BlockImpl::Ports> _ports_array; ///< New external port array for Graph - EnginePort* _engine_port; ///< Driver port if on the root - Properties _properties; - Properties _update; - boost::optional<Flow> _flow; + raul::Path _path; + PortType _port_type{PortType::UNKNOWN}; + LV2_URID _buf_type{0}; + GraphImpl* _graph{nullptr}; + DuplexPort* _graph_port{nullptr}; + raul::managed_ptr<BlockImpl::Ports> _ports_array; ///< New external port array for Graph + EnginePort* _engine_port{nullptr}; ///< Driver port if on the root + Properties _properties; + Properties _update; + std::optional<Flow> _flow; }; } // namespace events diff --git a/src/server/events/Delete.cpp b/src/server/events/Delete.cpp index 5d605bca..9e940ea7 100644 --- a/src/server/events/Delete.cpp +++ b/src/server/events/Delete.cpp @@ -19,38 +19,45 @@ #include "BlockImpl.hpp" #include "Broadcaster.hpp" #include "BufferFactory.hpp" +#include "CompiledGraph.hpp" #include "ControlBindings.hpp" #include "DisconnectAll.hpp" #include "Driver.hpp" +#include "DuplexPort.hpp" #include "Engine.hpp" #include "EnginePort.hpp" #include "GraphImpl.hpp" #include "PortImpl.hpp" #include "PreProcessContext.hpp" -#include "ingen/Forge.hpp" -#include "ingen/Store.hpp" -#include "ingen/World.hpp" -#include "raul/Maid.hpp" -#include "raul/Path.hpp" +#include <ingen/Forge.hpp> +#include <ingen/Interface.hpp> +#include <ingen/Message.hpp> +#include <ingen/Node.hpp> +#include <ingen/Status.hpp> +#include <ingen/Store.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIs.hpp> +#include <ingen/World.hpp> +#include <ingen/paths.hpp> +#include <raul/Array.hpp> +#include <raul/Path.hpp> #include <cassert> #include <cstddef> +#include <memory> #include <mutex> #include <string> +#include <string_view> -namespace ingen { -namespace server { -namespace events { +namespace ingen::server::events { -Delete::Delete(Engine& engine, - const SPtr<Interface>& client, - FrameTime timestamp, - const ingen::Del& msg) +Delete::Delete(Engine& engine, + const std::shared_ptr<Interface>& client, + FrameTime timestamp, + const ingen::Del& msg) : Event(engine, client, msg.seq, timestamp) , _msg(msg) - , _engine_port(nullptr) - , _disconnect_event(nullptr) { if (uri_is_path(msg.uri)) { _path = uri_to_path(msg.uri); @@ -59,7 +66,7 @@ Delete::Delete(Engine& engine, Delete::~Delete() { - for (ControlBindings::Binding* b : _removed_bindings) { + for (auto* b : _removed_bindings) { delete b; } } @@ -79,8 +86,8 @@ Delete::pre_process(PreProcessContext& ctx) return Event::pre_process_done(Status::NOT_FOUND, _path); } - if (!(_block = dynamic_ptr_cast<BlockImpl>(iter->second))) { - _port = dynamic_ptr_cast<DuplexPort>(iter->second); + if (!(_block = std::dynamic_pointer_cast<BlockImpl>(iter->second))) { + _port = std::dynamic_pointer_cast<DuplexPort>(iter->second); } if ((!_block && !_port) || (_port && !_engine.driver()->dynamic_ports())) { @@ -93,23 +100,23 @@ Delete::pre_process(PreProcessContext& ctx) } // Take a writer lock while we modify the store - std::lock_guard<Store::Mutex> lock(_engine.store()->mutex()); + const std::lock_guard<Store::Mutex> lock{_engine.store()->mutex()}; _engine.store()->remove(iter, _removed_objects); if (_block) { parent->remove_block(*_block); _disconnect_event = - make_unique<DisconnectAll>(_engine, parent, _block.get()); + std::make_unique<DisconnectAll>(_engine, parent, _block.get()); _disconnect_event->pre_process(ctx); - _compiled_graph = ctx.maybe_compile(*_engine.maid(), *parent); + _compiled_graph = ctx.maybe_compile(*parent); } else if (_port) { parent->remove_port(*_port); _disconnect_event = - make_unique<DisconnectAll>(_engine, parent, _port.get()); + std::make_unique<DisconnectAll>(_engine, parent, _port.get()); _disconnect_event->pre_process(ctx); - _compiled_graph = ctx.maybe_compile(*_engine.maid(), *parent); + _compiled_graph = ctx.maybe_compile(*parent); if (parent->enabled()) { _ports_array = parent->build_ports_array(*_engine.maid()); assert(_ports_array->size() == parent->num_ports_non_rt()); @@ -121,9 +128,9 @@ Delete::pre_process(PreProcessContext& ctx) _port_index_changes.emplace( port->path(), std::make_pair(port->index(), i)); port->remove_property(uris.lv2_index, uris.patch_wildcard); - port->set_property( - uris.lv2_index, - _engine.buffer_factory()->forge().make((int32_t)i)); + port->set_property(uris.lv2_index, + _engine.buffer_factory()->forge().make( + static_cast<int32_t>(i))); } } } @@ -137,27 +144,27 @@ Delete::pre_process(PreProcessContext& ctx) } void -Delete::execute(RunContext& context) +Delete::execute(RunContext& ctx) { if (_status != Status::SUCCESS) { return; } if (_disconnect_event) { - _disconnect_event->execute(context); + _disconnect_event->execute(ctx); } if (!_removed_bindings.empty()) { - _engine.control_bindings()->remove(context, _removed_bindings); + _engine.control_bindings()->remove(ctx, _removed_bindings); } GraphImpl* parent = _block ? _block->parent_graph() : nullptr; - if (_port) { + if (_ports_array && _port) { // Adjust port indices if necessary for (size_t i = 0; i < _ports_array->size(); ++i) { PortImpl* const port = _ports_array->at(i); if (port->index() != i) { - port->set_index(context, i); + port->set_index(ctx, i); } } @@ -166,19 +173,19 @@ Delete::execute(RunContext& context) parent->set_external_ports(std::move(_ports_array)); if (_engine_port) { - _engine.driver()->remove_port(context, _engine_port); + _engine.driver()->remove_port(ctx, _engine_port); } } if (parent && _compiled_graph) { - parent->set_compiled_graph(std::move(_compiled_graph)); + _compiled_graph = parent->swap_compiled_graph(std::move(_compiled_graph)); } } void Delete::post_process() { - Broadcaster::Transfer t(*_engine.broadcaster()); + const Broadcaster::Transfer t{*_engine.broadcaster()}; if (respond() == Status::SUCCESS && (_block || _port)) { if (_block) { _block->deactivate(); @@ -214,12 +221,10 @@ Delete::undo(Interface& target) if (c.first != _msg.uri.path()) { target.set_property(path_to_uri(c.first), uris.lv2_index, - forge.make(int32_t(c.second.first))); + forge.make(static_cast<int32_t>(c.second.first))); } } } } -} // namespace events -} // namespace server -} // namespace ingen +} // namespace ingen::server::events diff --git a/src/server/events/Delete.hpp b/src/server/events/Delete.hpp index 6b3149e9..7e901f4b 100644 --- a/src/server/events/Delete.hpp +++ b/src/server/events/Delete.hpp @@ -20,19 +20,32 @@ #include "ControlBindings.hpp" #include "Event.hpp" #include "GraphImpl.hpp" +#include "types.hpp" -#include "ingen/Store.hpp" +#include <ingen/Message.hpp> +#include <ingen/Store.hpp> +#include <raul/Maid.hpp> +#include <raul/Path.hpp> #include <cstdint> #include <map> +#include <memory> +#include <string> #include <utility> #include <vector> +// IWYU pragma: no_include <iterator> + namespace ingen { + +class Interface; + namespace server { +class BlockImpl; class CompiledGraph; class DuplexPort; +class Engine; class EnginePort; namespace events { @@ -45,32 +58,32 @@ class DisconnectAll; class Delete : public Event { public: - Delete(Engine& engine, - const SPtr<Interface>& client, - FrameTime timestamp, - const ingen::Del& msg); + Delete(Engine& engine, + const std::shared_ptr<Interface>& client, + FrameTime timestamp, + const ingen::Del& msg); - ~Delete(); + ~Delete() override; bool pre_process(PreProcessContext& ctx) override; - void execute(RunContext& context) override; + void execute(RunContext& ctx) override; void post_process() override; void undo(Interface& target) override; private: using IndexChange = std::pair<uint32_t, uint32_t>; - using IndexChanges = std::map<Raul::Path, IndexChange>; - - const ingen::Del _msg; - Raul::Path _path; - SPtr<BlockImpl> _block; ///< Non-null iff a block - SPtr<DuplexPort> _port; ///< Non-null iff a port - EnginePort* _engine_port; - MPtr<GraphImpl::Ports> _ports_array; ///< New (external) ports for Graph - MPtr<CompiledGraph> _compiled_graph; ///< Graph's new process order - UPtr<DisconnectAll> _disconnect_event; - Store::Objects _removed_objects; - IndexChanges _port_index_changes; + using IndexChanges = std::map<raul::Path, IndexChange>; + + const ingen::Del _msg; + raul::Path _path; + std::shared_ptr<BlockImpl> _block; ///< Non-null iff a block + std::shared_ptr<DuplexPort> _port; ///< Non-null iff a port + EnginePort* _engine_port{nullptr}; + raul::managed_ptr<GraphImpl::Ports> _ports_array; ///< New (external) ports for Graph + std::unique_ptr<CompiledGraph> _compiled_graph; ///< Graph's new process order + std::unique_ptr<DisconnectAll> _disconnect_event; + Store::Objects _removed_objects; + IndexChanges _port_index_changes; std::vector<ControlBindings::Binding*> _removed_bindings; }; diff --git a/src/server/events/Delta.cpp b/src/server/events/Delta.cpp index 0a7b05ea..cba21214 100644 --- a/src/server/events/Delta.cpp +++ b/src/server/events/Delta.cpp @@ -16,91 +16,87 @@ #include "Delta.hpp" +#include "BlockFactory.hpp" +#include "BlockImpl.hpp" #include "Broadcaster.hpp" +#include "CompiledGraph.hpp" #include "ControlBindings.hpp" #include "CreateBlock.hpp" #include "CreateGraph.hpp" #include "CreatePort.hpp" #include "Engine.hpp" #include "GraphImpl.hpp" +#include "NodeImpl.hpp" #include "PluginImpl.hpp" #include "PortImpl.hpp" #include "PortType.hpp" #include "SetPortValue.hpp" -#include "ingen/Forge.hpp" -#include "ingen/Log.hpp" -#include "ingen/Store.hpp" -#include "ingen/URIs.hpp" -#include "ingen/World.hpp" -#include "raul/Maid.hpp" - +#include <ingen/Atom.hpp> +#include <ingen/FilePath.hpp> +#include <ingen/Forge.hpp> +#include <ingen/Interface.hpp> +#include <ingen/Log.hpp> +#include <ingen/Message.hpp> +#include <ingen/Node.hpp> +#include <ingen/Properties.hpp> +#include <ingen/Resource.hpp> +#include <ingen/Status.hpp> +#include <ingen/Store.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIs.hpp> +#include <ingen/World.hpp> +#include <ingen/paths.hpp> +#include <lilv/lilv.h> +#include <raul/Path.hpp> + +#include <memory> #include <mutex> #include <set> #include <string> +#include <string_view> #include <utility> #include <vector> -namespace ingen { -namespace server { - -class PreProcessContext; - -namespace events { +namespace ingen::server::events { -Delta::Delta(Engine& engine, - const SPtr<Interface>& client, - SampleCount timestamp, - const ingen::Put& msg) +Delta::Delta(Engine& engine, + const std::shared_ptr<Interface>& client, + SampleCount timestamp, + const ingen::Put& msg) : Event(engine, client, msg.seq, timestamp) - , _create_event(nullptr) , _subject(msg.uri) , _properties(msg.properties) - , _object(nullptr) - , _graph(nullptr) - , _binding(nullptr) - , _state(nullptr) , _context(msg.ctx) , _type(Type::PUT) - , _block(false) { init(); } -Delta::Delta(Engine& engine, - const SPtr<Interface>& client, - SampleCount timestamp, - const ingen::Delta& msg) +Delta::Delta(Engine& engine, + const std::shared_ptr<Interface>& client, + SampleCount timestamp, + const ingen::Delta& msg) : Event(engine, client, msg.seq, timestamp) , _create_event(nullptr) , _subject(msg.uri) , _properties(msg.add) , _remove(msg.remove) - , _object(nullptr) - , _graph(nullptr) - , _binding(nullptr) - , _state(nullptr) , _context(msg.ctx) , _type(Type::PATCH) - , _block(false) { init(); } -Delta::Delta(Engine& engine, - const SPtr<Interface>& client, - SampleCount timestamp, - const ingen::SetProperty& msg) +Delta::Delta(Engine& engine, + const std::shared_ptr<Interface>& client, + SampleCount timestamp, + const ingen::SetProperty& msg) : Event(engine, client, msg.seq, timestamp) , _subject(msg.subject) , _properties{{msg.predicate, msg.value}} - , _object(nullptr) - , _graph(nullptr) - , _binding(nullptr) - , _state(nullptr) , _context(msg.ctx) , _type(Type::SET) - , _block(false) { init(); } @@ -136,7 +132,7 @@ Delta::add_set_event(const char* port_symbol, } _set_events.emplace_back( - make_unique<SetPortValue>( + std::make_unique<SetPortValue>( _engine, _request_client, _request_id, _time, port, Atom(size, type, value), false, true)); } @@ -148,7 +144,7 @@ s_add_set_event(const char* port_symbol, uint32_t size, uint32_t type) { - ((Delta*)user_data)->add_set_event(port_symbol, value, size, type); + static_cast<Delta*>(user_data)->add_set_event(port_symbol, value, size, type); } static LilvNode* @@ -156,12 +152,15 @@ get_file_node(LilvWorld* lworld, const URIs& uris, const Atom& value) { if (value.type() == uris.atom_Path) { return lilv_new_file_uri(lworld, nullptr, value.ptr<char>()); - } else if (uris.forge.is_uri(value)) { + } + + if (uris.forge.is_uri(value)) { const std::string str = uris.forge.str(value, false); if (str.substr(0, 5) == "file:") { return lilv_new_uri(lworld, value.ptr<char>()); } } + return nullptr; } @@ -206,12 +205,12 @@ Delta::pre_process(PreProcessContext& ctx) if ((_preset = block->save_preset(_subject, _properties))) { return Event::pre_process_done(Status::SUCCESS); - } else { - return Event::pre_process_done(Status::FAILURE); } + + return Event::pre_process_done(Status::FAILURE); } - std::lock_guard<Store::Mutex> lock(_engine.store()->mutex()); + const std::lock_guard<Store::Mutex> lock{_engine.store()->mutex()}; _object = is_graph_object ? static_cast<ingen::Resource*>(_engine.store()->get(uri_to_path(_subject))) @@ -223,7 +222,7 @@ Delta::pre_process(PreProcessContext& ctx) } if (is_graph_object && !_object) { - Raul::Path path(uri_to_path(_subject)); + const raul::Path path{uri_to_path(_subject)}; bool is_graph = false; bool is_block = false; @@ -232,19 +231,19 @@ Delta::pre_process(PreProcessContext& ctx) ingen::Resource::type(uris, _properties, is_graph, is_block, is_port, is_output); if (is_graph) { - _create_event = make_unique<CreateGraph>( + _create_event = std::make_unique<CreateGraph>( _engine, _request_client, _request_id, _time, path, _properties); } else if (is_block) { - _create_event = make_unique<CreateBlock>( + _create_event = std::make_unique<CreateBlock>( _engine, _request_client, _request_id, _time, path, _properties); } else if (is_port) { - _create_event = make_unique<CreatePort>( + _create_event = std::make_unique<CreatePort>( _engine, _request_client, _request_id, _time, path, _properties); } if (_create_event) { if (_create_event->pre_process(ctx)) { - _object = _engine.store()->get(path); // Get object for setting + _object = _engine.store()->get(path); // Get object for setting } else { return Event::pre_process_done(Status::CREATION_FAILED, _subject); } @@ -316,8 +315,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); } @@ -334,7 +333,7 @@ Delta::pre_process(PreProcessContext& ctx) } } else if (key == uris.ingen_value || key == uris.ingen_activity) { _set_events.emplace_back( - make_unique<SetPortValue>( + std::make_unique<SetPortValue>( _engine, _request_client, _request_id, _time, port, value, key == uris.ingen_activity)); } else if (key == uris.midi_binding) { @@ -356,7 +355,7 @@ Delta::pre_process(PreProcessContext& ctx) } } else if ((block = dynamic_cast<BlockImpl*>(_object))) { if (key == uris.midi_binding && value == uris.patch_wildcard) { - op = SpecialType::CONTROL_BINDING; // Internal block learn + op = SpecialType::CONTROL_BINDING; // Internal block learn } else if (key == uris.ingen_enabled) { if (value.type() == uris.forge.Bool) { op = SpecialType::ENABLE; @@ -377,8 +376,9 @@ Delta::pre_process(PreProcessContext& ctx) if (!uri.empty()) { op = SpecialType::PRESET; if ((_state = block->load_preset(uri))) { - lilv_state_emit_port_values( - _state, s_add_set_event, this); + lilv_state_emit_port_values(_state.get(), + s_add_set_event, + this); } else { _engine.log().warn("Failed to load preset <%1%>\n", uri); } @@ -392,9 +392,9 @@ Delta::pre_process(PreProcessContext& ctx) if (key == uris.ingen_enabled) { if (value.type() == uris.forge.Bool) { op = SpecialType::ENABLE; - // FIXME: defer this until all other metadata has been processed + // FIXME: defer until all other data has been processed if (value.get<int32_t>() && !_graph->enabled()) { - if (!(_compiled_graph = compile(*_engine.maid(), *_graph))) { + if (!(_compiled_graph = compile(*_graph))) { _status = Status::COMPILATION_FAILED; } } @@ -423,9 +423,8 @@ Delta::pre_process(PreProcessContext& ctx) } else if (value.type() != uris.forge.Bool) { _status = Status::BAD_VALUE_TYPE; } else { - op = SpecialType::POLYPHONIC; + op = SpecialType::POLYPHONIC; obj->set_property(key, value, value.context()); - auto* block = dynamic_cast<BlockImpl*>(obj); if (block) { block->set_polyphonic(value.get<int32_t>()); } @@ -446,9 +445,9 @@ Delta::pre_process(PreProcessContext& ctx) lilv_world_load_bundle(lworld, bundle); const auto new_plugins = _engine.block_factory()->refresh(); - for (const auto& p : new_plugins) { - if (p->bundle_uri() == lilv_node_as_string(bundle)) { - _update.put_plugin(p.get()); + for (const auto& plugin : new_plugins) { + if (plugin->bundle_uri() == lilv_node_as_string(bundle)) { + _update.put_plugin(plugin.get()); } } lilv_node_free(bundle); @@ -474,7 +473,7 @@ Delta::pre_process(PreProcessContext& ctx) } void -Delta::execute(RunContext& context) +Delta::execute(RunContext& ctx) { if (_status != Status::SUCCESS || _preset) { return; @@ -484,23 +483,23 @@ Delta::execute(RunContext& context) if (_create_event) { _create_event->set_time(_time); - _create_event->execute(context); + _create_event->execute(ctx); } for (auto& s : _set_events) { s->set_time(_time); - s->execute(context); + s->execute(ctx); } if (!_removed_bindings.empty()) { - _engine.control_bindings()->remove(context, _removed_bindings); + _engine.control_bindings()->remove(ctx, _removed_bindings); } auto* const object = dynamic_cast<NodeImpl*>(_object); auto* const block = dynamic_cast<BlockImpl*>(_object); auto* const port = dynamic_cast<PortImpl*>(_object); - std::vector<SpecialType>::const_iterator t = _types.begin(); + auto t = _types.begin(); for (const auto& p : _properties) { const URI& key = p.first; const Atom& value = p.second; @@ -514,11 +513,11 @@ Delta::execute(RunContext& context) if (_graph) { if (value.get<int32_t>()) { if (_compiled_graph) { - _graph->set_compiled_graph(std::move(_compiled_graph)); + _compiled_graph = _graph->swap_compiled_graph(std::move(_compiled_graph)); } _graph->enable(); } else { - _graph->disable(context); + _graph->disable(ctx); } } else if (block) { block->set_enabled(value.get<int32_t>()); @@ -528,15 +527,15 @@ Delta::execute(RunContext& context) if (object) { if (value.get<int32_t>()) { auto* parent = reinterpret_cast<GraphImpl*>(object->parent()); - object->apply_poly(context, parent->internal_poly_process()); + object->apply_poly(ctx, parent->internal_poly_process()); } else { - object->apply_poly(context, 1); + object->apply_poly(ctx, 1); } } } break; case SpecialType::POLYPHONY: if (_graph && - !_graph->apply_internal_poly(context, + !_graph->apply_internal_poly(ctx, *_engine.buffer_factory(), *_engine.maid(), value.get<int32_t>())) { @@ -545,12 +544,12 @@ Delta::execute(RunContext& context) break; case SpecialType::PORT_INDEX: if (port) { - port->set_index(context, value.get<int32_t>()); + port->set_index(ctx, value.get<int32_t>()); } break; case SpecialType::CONTROL_BINDING: if (port) { - if (!_engine.control_bindings()->set_port_binding(context, port, _binding, value)) { + if (!_engine.control_bindings()->set_port_binding(ctx, port, _binding, value)) { _status = Status::BAD_VALUE; } } else if (block) { @@ -572,6 +571,7 @@ Delta::execute(RunContext& context) port->set_maximum(value); } } + break; case SpecialType::LOADED_BUNDLE: break; } @@ -584,24 +584,25 @@ Delta::post_process() if (_state) { auto* block = dynamic_cast<BlockImpl*>(_object); if (block) { - block->apply_state(_engine.sync_worker(), _state); + block->apply_state(_engine.sync_worker(), _state.get()); block->set_enabled(true); } - lilv_state_free(_state); + + _state.reset(); } - Broadcaster::Transfer t(*_engine.broadcaster()); + const Broadcaster::Transfer t{*_engine.broadcaster()}; if (_create_event) { _create_event->post_process(); if (_create_event->status() != Status::SUCCESS) { - return; // Creation failed, nothing else to do + return; // Creation failed, nothing else to do } } for (auto& s : _set_events) { if (s->synthetic() || s->status() != Status::SUCCESS) { - s->post_process(); // Set failed, report error + s->post_process(); // Set failed, report error } } @@ -669,6 +670,4 @@ Delta::get_execution() const return _block ? Execution::ATOMIC : Execution::NORMAL; } -} // namespace events -} // namespace server -} // namespace ingen +} // namespace ingen::server::events diff --git a/src/server/events/Delta.hpp b/src/server/events/Delta.hpp index 1dce2663..befbdcc7 100644 --- a/src/server/events/Delta.hpp +++ b/src/server/events/Delta.hpp @@ -18,51 +18,58 @@ #define INGEN_EVENTS_DELTA_HPP #include "ClientUpdate.hpp" +#include "CompiledGraph.hpp" #include "ControlBindings.hpp" #include "Event.hpp" +#include "SetPortValue.hpp" +#include "State.hpp" +#include "types.hpp" -#include "lilv/lilv.h" +#include <ingen/Properties.hpp> +#include <ingen/Resource.hpp> +#include <ingen/URI.hpp> -#include <boost/optional/optional.hpp> - -#include <algorithm> #include <cstdint> +#include <memory> +#include <optional> #include <vector> namespace ingen { + +class Interface; +struct Delta; +struct Put; +struct SetProperty; + namespace server { -class CompiledGraph; class Engine; class GraphImpl; -class RunContext; namespace events { -class SetPortValue; - /** Set properties of a graph object. * \ingroup engine */ class Delta : public Event { public: - Delta(Engine& engine, - const SPtr<Interface>& client, - SampleCount timestamp, - const ingen::Put& msg); + Delta(Engine& engine, + const std::shared_ptr<Interface>& client, + SampleCount timestamp, + const ingen::Put& msg); - Delta(Engine& engine, - const SPtr<Interface>& client, - SampleCount timestamp, - const ingen::Delta& msg); + Delta(Engine& engine, + const std::shared_ptr<Interface>& client, + SampleCount timestamp, + const ingen::Delta& msg); - Delta(Engine& engine, - const SPtr<Interface>& client, - SampleCount timestamp, - const ingen::SetProperty& msg); + Delta(Engine& engine, + const std::shared_ptr<Interface>& client, + SampleCount timestamp, + const ingen::SetProperty& msg); - ~Delta() = default; + ~Delta() override = default; void add_set_event(const char* port_symbol, const void* value, @@ -70,18 +77,14 @@ public: uint32_t type); bool pre_process(PreProcessContext& ctx) override; - void execute(RunContext& context) override; + void execute(RunContext& ctx) override; void post_process() override; void undo(Interface& target) override; Execution get_execution() const override; private: - enum class Type { - SET, - PUT, - PATCH - }; + enum class Type { SET, PUT, PATCH }; enum class SpecialType { NONE, @@ -95,34 +98,34 @@ private: LOADED_BUNDLE }; - using SetEvents = std::vector<UPtr<SetPortValue>>; + using SetEvents = std::vector<std::unique_ptr<SetPortValue>>; void init(); - UPtr<Event> _create_event; - SetEvents _set_events; - std::vector<SpecialType> _types; - std::vector<SpecialType> _remove_types; - URI _subject; - Properties _properties; - Properties _remove; - ClientUpdate _update; - ingen::Resource* _object; - GraphImpl* _graph; - MPtr<CompiledGraph> _compiled_graph; - ControlBindings::Binding* _binding; - LilvState* _state; - Resource::Graph _context; - Type _type; + std::unique_ptr<Event> _create_event; + SetEvents _set_events; + std::vector<SpecialType> _types; + std::vector<SpecialType> _remove_types; + URI _subject; + Properties _properties; + Properties _remove; + ClientUpdate _update; + ingen::Resource* _object{nullptr}; + GraphImpl* _graph{nullptr}; + std::unique_ptr<CompiledGraph> _compiled_graph; + ControlBindings::Binding* _binding{nullptr}; + StatePtr _state; + Resource::Graph _context; + Type _type; Properties _added; Properties _removed; std::vector<ControlBindings::Binding*> _removed_bindings; - boost::optional<Resource> _preset; + std::optional<Resource> _preset; - bool _block; + bool _block{false}; }; } // namespace events diff --git a/src/server/events/Disconnect.cpp b/src/server/events/Disconnect.cpp index 531d70af..7189fdd0 100644 --- a/src/server/events/Disconnect.cpp +++ b/src/server/events/Disconnect.cpp @@ -14,44 +14,55 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "events/Disconnect.hpp" +#include "Disconnect.hpp" -#include "ArcImpl.hpp" +#include "BlockImpl.hpp" #include "Broadcaster.hpp" #include "Buffer.hpp" -#include "DuplexPort.hpp" +#include "BufferFactory.hpp" +#include "BufferRef.hpp" +#include "CompiledGraph.hpp" #include "Engine.hpp" #include "GraphImpl.hpp" #include "InputPort.hpp" #include "PortImpl.hpp" +#include "PortType.hpp" #include "PreProcessContext.hpp" -#include "RunContext.hpp" #include "ThreadManager.hpp" -#include "ingen/Store.hpp" -#include "raul/Maid.hpp" -#include "raul/Path.hpp" +#include <ingen/Atom.hpp> +#include <ingen/Interface.hpp> +#include <ingen/Message.hpp> +#include <ingen/Node.hpp> +#include <ingen/Status.hpp> +#include <ingen/Store.hpp> +#include <raul/Array.hpp> +#include <raul/Maid.hpp> +#include <raul/Path.hpp> #include <cassert> #include <cstdint> +#include <memory> #include <mutex> #include <set> #include <string> #include <utility> -namespace ingen { -namespace server { +namespace ingen::server { + +class RunContext; + namespace events { -Disconnect::Disconnect(Engine& engine, - const SPtr<Interface>& client, - SampleCount timestamp, - const ingen::Disconnect& msg) +Disconnect::Disconnect(Engine& engine, + const std::shared_ptr<Interface>& client, + SampleCount timestamp, + const ingen::Disconnect& msg) : Event(engine, client, msg.seq, timestamp) , _msg(msg) - , _graph(nullptr) -{ -} +{} + +Disconnect::~Disconnect() = default; Disconnect::Impl::Impl(Engine& e, GraphImpl* graph, @@ -107,7 +118,7 @@ Disconnect::Impl::Impl(Engine& e, bool Disconnect::pre_process(PreProcessContext& ctx) { - std::lock_guard<Store::Mutex> lock(_engine.store()->mutex()); + const std::lock_guard<Store::Mutex> lock{_engine.store()->mutex()}; if (_msg.tail.parent().parent() != _msg.head.parent().parent() && _msg.tail.parent() != _msg.head.parent().parent() @@ -146,7 +157,9 @@ Disconnect::pre_process(PreProcessContext& ctx) if (!_graph) { return Event::pre_process_done(Status::INTERNAL_ERROR, _msg.head); - } else if (!_graph->has_arc(tail, head)) { + } + + if (!_graph->has_arc(tail, head)) { return Event::pre_process_done(Status::NOT_FOUND, _msg.head); } @@ -154,33 +167,33 @@ Disconnect::pre_process(PreProcessContext& ctx) return Event::pre_process_done(Status::PARENT_NOT_FOUND, _msg.head); } - _impl = make_unique<Impl>(_engine, - _graph, - dynamic_cast<PortImpl*>(tail), - dynamic_cast<InputPort*>(head)); + _impl = std::make_unique<Impl>(_engine, + _graph, + tail, + dynamic_cast<InputPort*>(head)); - _compiled_graph = ctx.maybe_compile(*_engine.maid(), *_graph); + _compiled_graph = ctx.maybe_compile(*_graph); return Event::pre_process_done(Status::SUCCESS); } bool -Disconnect::Impl::execute(RunContext& context, bool set_head_buffers) +Disconnect::Impl::execute(RunContext& ctx, bool set_head_buffers) { if (!_arc) { return false; } - _head->remove_arc(*_arc.get()); + _head->remove_arc(*_arc); if (_head->is_driver_port()) { return true; } if (set_head_buffers) { if (_voices) { - _head->set_voices(context, std::move(_voices)); + _head->set_voices(ctx, std::move(_voices)); } else { - _head->setup_buffers(context, *_engine.buffer_factory(), _head->poly()); + _head->setup_buffers(ctx, *_engine.buffer_factory(), _head->poly()); } _head->connect_buffers(); } else { @@ -191,12 +204,13 @@ Disconnect::Impl::execute(RunContext& context, bool set_head_buffers) } void -Disconnect::execute(RunContext& context) +Disconnect::execute(RunContext& ctx) { if (_status == Status::SUCCESS) { - if (_impl->execute(context, true)) { + if (_impl->execute(ctx, true)) { if (_compiled_graph) { - _graph->set_compiled_graph(std::move(_compiled_graph)); + _compiled_graph = + _graph->swap_compiled_graph(std::move(_compiled_graph)); } } else { _status = Status::NOT_FOUND; @@ -207,7 +221,7 @@ Disconnect::execute(RunContext& context) void Disconnect::post_process() { - Broadcaster::Transfer t(*_engine.broadcaster()); + const Broadcaster::Transfer t{*_engine.broadcaster()}; if (respond() == Status::SUCCESS) { _engine.broadcaster()->message(_msg); } @@ -220,5 +234,4 @@ Disconnect::undo(Interface& target) } } // namespace events -} // namespace server -} // namespace ingen +} // namespace ingen::server diff --git a/src/server/events/Disconnect.hpp b/src/server/events/Disconnect.hpp index ec638c73..92dd81d3 100644 --- a/src/server/events/Disconnect.hpp +++ b/src/server/events/Disconnect.hpp @@ -17,16 +17,27 @@ #ifndef INGEN_EVENTS_DISCONNECT_HPP #define INGEN_EVENTS_DISCONNECT_HPP -#include "CompiledGraph.hpp" #include "Event.hpp" #include "PortImpl.hpp" #include "types.hpp" +#include <ingen/Message.hpp> +#include <raul/Maid.hpp> + +#include <memory> + namespace ingen { + +class Interface; + namespace server { class ArcImpl; +class CompiledGraph; +class Engine; +class GraphImpl; class InputPort; +class RunContext; namespace events { @@ -37,38 +48,41 @@ namespace events { class Disconnect : public Event { public: - Disconnect(Engine& engine, - const SPtr<Interface>& client, - SampleCount timestamp, - const ingen::Disconnect& msg); + Disconnect(Engine& engine, + const std::shared_ptr<Interface>& client, + SampleCount timestamp, + const ingen::Disconnect& msg); + + ~Disconnect() override; bool pre_process(PreProcessContext& ctx) override; - void execute(RunContext& context) override; + void execute(RunContext& ctx) override; void post_process() override; void undo(Interface& target) override; - class Impl { + class Impl + { public: Impl(Engine& e, GraphImpl* graph, PortImpl* t, InputPort* h); - bool execute(RunContext& context, bool set_head_buffers); + bool execute(RunContext& ctx, bool set_head_buffers); - inline PortImpl* tail() { return _tail; } - inline InputPort* head() { return _head; } + PortImpl* tail() { return _tail; } + InputPort* head() { return _head; } private: - Engine& _engine; - PortImpl* _tail; - InputPort* _head; - SPtr<ArcImpl> _arc; - MPtr<PortImpl::Voices> _voices; + Engine& _engine; + PortImpl* _tail; + InputPort* _head; + std::shared_ptr<ArcImpl> _arc; + raul::managed_ptr<PortImpl::Voices> _voices; }; private: - const ingen::Disconnect _msg; - GraphImpl* _graph; - UPtr<Impl> _impl; - MPtr<CompiledGraph> _compiled_graph; + const ingen::Disconnect _msg; + GraphImpl* _graph{nullptr}; + std::unique_ptr<Impl> _impl; + std::unique_ptr<CompiledGraph> _compiled_graph; }; } // namespace events diff --git a/src/server/events/DisconnectAll.cpp b/src/server/events/DisconnectAll.cpp index 4444bb26..8e7bfbbe 100644 --- a/src/server/events/DisconnectAll.cpp +++ b/src/server/events/DisconnectAll.cpp @@ -14,44 +14,47 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "events/DisconnectAll.hpp" +#include "DisconnectAll.hpp" #include "ArcImpl.hpp" #include "BlockImpl.hpp" #include "Broadcaster.hpp" +#include "CompiledGraph.hpp" +#include "Disconnect.hpp" #include "Engine.hpp" #include "GraphImpl.hpp" #include "InputPort.hpp" +#include "NodeImpl.hpp" #include "PortImpl.hpp" #include "PreProcessContext.hpp" -#include "events/Disconnect.hpp" -#include "util.hpp" -#include "ingen/Store.hpp" -#include "raul/Array.hpp" -#include "raul/Maid.hpp" -#include "raul/Path.hpp" +#include <ingen/Interface.hpp> +#include <ingen/Message.hpp> +#include <ingen/Node.hpp> +#include <ingen/Status.hpp> +#include <ingen/Store.hpp> +#include <raul/Path.hpp> +#include <algorithm> +#include <iterator> +#include <memory> #include <mutex> #include <set> #include <utility> -namespace ingen { -namespace server { -namespace events { - -DisconnectAll::DisconnectAll(Engine& engine, - const SPtr<Interface>& client, - SampleCount timestamp, - const ingen::DisconnectAll& msg) - : Event(engine, client, msg.seq, timestamp) - , _msg(msg) - , _parent(nullptr) - , _block(nullptr) - , _port(nullptr) - , _deleting(false) -{ -} +namespace ingen::server::events { + +DisconnectAll::DisconnectAll(Engine& engine, + const std::shared_ptr<Interface>& client, + SampleCount timestamp, + const ingen::DisconnectAll& msg) + : Event(engine, client, msg.seq, timestamp) + , _msg(msg) + , _parent(nullptr) + , _block(nullptr) + , _port(nullptr) + , _deleting(false) +{} /** Internal version for use by other events. */ @@ -64,12 +67,11 @@ DisconnectAll::DisconnectAll(Engine& engine, , _block(dynamic_cast<BlockImpl*>(object)) , _port(dynamic_cast<PortImpl*>(object)) , _deleting(true) -{ -} +{} DisconnectAll::~DisconnectAll() { - for (auto& i : _impls) { + for (auto* i : _impls) { delete i; } } @@ -109,32 +111,36 @@ DisconnectAll::pre_process(PreProcessContext& ctx) } } - // Find set of arcs to remove - std::set<ArcImpl*> to_remove; - for (const auto& a : _parent->arcs()) { - auto* const arc = static_cast<ArcImpl*>(a.second.get()); - if (_block) { - if (arc->tail()->parent_block() == _block - || arc->head()->parent_block() == _block) { - to_remove.insert(arc); - } - } else if (_port) { - if (arc->tail() == _port || arc->head() == _port) { - to_remove.insert(arc); - } - } - } - - // Create disconnect events (which erases from _parent->arcs()) - for (const auto& a : to_remove) { - _impls.push_back(new Disconnect::Impl( - _engine, _parent, - dynamic_cast<PortImpl*>(a->tail()), - dynamic_cast<InputPort*>(a->head()))); + // Create disconnect events to erase adjacent arcs in parent + 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 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)) { - if (!(_compiled_graph = compile(*_engine.maid(), *_parent))) { + if (!(_compiled_graph = compile(*_parent))) { return Event::pre_process_done(Status::COMPILATION_FAILED); } } @@ -143,24 +149,24 @@ DisconnectAll::pre_process(PreProcessContext& ctx) } void -DisconnectAll::execute(RunContext& context) +DisconnectAll::execute(RunContext& ctx) { if (_status == Status::SUCCESS) { for (auto& i : _impls) { - i->execute(context, + i->execute(ctx, !_deleting || (i->head()->parent_block() != _block)); } } if (_compiled_graph) { - _parent->set_compiled_graph(std::move(_compiled_graph)); + _compiled_graph = _parent->swap_compiled_graph(std::move(_compiled_graph)); } } void DisconnectAll::post_process() { - Broadcaster::Transfer t(*_engine.broadcaster()); + const Broadcaster::Transfer t{*_engine.broadcaster()}; if (respond() == Status::SUCCESS) { _engine.broadcaster()->message(_msg); } @@ -174,6 +180,25 @@ DisconnectAll::undo(Interface& target) } } -} // namespace events -} // namespace server -} // namespace ingen +std::set<ArcImpl*> +DisconnectAll::adjacent_arcs(GraphImpl* const graph) +{ + std::set<ArcImpl*> arcs; + for (const auto& a : graph->arcs()) { + auto* const arc = static_cast<ArcImpl*>(a.second.get()); + if (_block) { + if (arc->tail()->parent_block() == _block + || arc->head()->parent_block() == _block) { + arcs.insert(arc); + } + } else if (_port) { + if (arc->tail() == _port || arc->head() == _port) { + arcs.insert(arc); + } + } + } + + return arcs; +} + +} // namespace ingen::server::events diff --git a/src/server/events/DisconnectAll.hpp b/src/server/events/DisconnectAll.hpp index 9ab908c1..0eeda6f8 100644 --- a/src/server/events/DisconnectAll.hpp +++ b/src/server/events/DisconnectAll.hpp @@ -17,25 +17,32 @@ #ifndef INGEN_EVENTS_DISCONNECTALL_HPP #define INGEN_EVENTS_DISCONNECTALL_HPP -#include "CompiledGraph.hpp" #include "Disconnect.hpp" #include "Event.hpp" +#include "types.hpp" -#include "raul/Path.hpp" +#include <ingen/Message.hpp> #include <list> +#include <memory> +#include <set> namespace ingen { + +class Interface; +class Node; + namespace server { +class ArcImpl; class BlockImpl; +class CompiledGraph; +class Engine; class GraphImpl; class PortImpl; namespace events { -class Disconnect; - /** An event to disconnect all connections to a Block. * * \ingroup engine @@ -43,32 +50,34 @@ class Disconnect; class DisconnectAll : public Event { public: - DisconnectAll(Engine& engine, - const SPtr<Interface>& client, - SampleCount timestamp, - const ingen::DisconnectAll& msg); + DisconnectAll(Engine& engine, + const std::shared_ptr<Interface>& client, + SampleCount timestamp, + const ingen::DisconnectAll& msg); DisconnectAll(Engine& engine, GraphImpl* parent, Node* object); - ~DisconnectAll(); + ~DisconnectAll() override; bool pre_process(PreProcessContext& ctx) override; - void execute(RunContext& context) override; + void execute(RunContext& ctx) override; void post_process() override; void undo(Interface& target) override; private: using Impls = std::list<Disconnect::Impl*>; - const ingen::DisconnectAll _msg; - GraphImpl* _parent; - BlockImpl* _block; - PortImpl* _port; - Impls _impls; - MPtr<CompiledGraph> _compiled_graph; - bool _deleting; + std::set<ArcImpl*> adjacent_arcs(GraphImpl* graph); + + const ingen::DisconnectAll _msg; + GraphImpl* _parent; + BlockImpl* _block; + PortImpl* _port; + Impls _impls; + std::unique_ptr<CompiledGraph> _compiled_graph; + bool _deleting; }; } // namespace events diff --git a/src/server/events/Get.cpp b/src/server/events/Get.cpp index 2335c09f..45e7ea94 100644 --- a/src/server/events/Get.cpp +++ b/src/server/events/Get.cpp @@ -18,47 +18,53 @@ #include "BlockImpl.hpp" #include "Broadcaster.hpp" -#include "BufferFactory.hpp" #include "Engine.hpp" #include "GraphImpl.hpp" -#include "PluginImpl.hpp" #include "PortImpl.hpp" -#include "ingen/Forge.hpp" -#include "ingen/Interface.hpp" -#include "ingen/Node.hpp" -#include "ingen/Store.hpp" -#include "ingen/World.hpp" +#include <ingen/Forge.hpp> +#include <ingen/Interface.hpp> +#include <ingen/Message.hpp> +#include <ingen/Node.hpp> +#include <ingen/Properties.hpp> +#include <ingen/Status.hpp> +#include <ingen/Store.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIs.hpp> +#include <ingen/World.hpp> +#include <ingen/paths.hpp> #include <cstdint> +#include <memory> #include <mutex> +#include <utility> -namespace ingen { -namespace server { -namespace events { +namespace ingen::server::events { -Get::Get(Engine& engine, - const SPtr<Interface>& client, - SampleCount timestamp, - const ingen::Get& msg) +Get::Get(Engine& engine, + const std::shared_ptr<Interface>& client, + SampleCount timestamp, + const ingen::Get& msg) : Event(engine, client, msg.seq, timestamp) , _msg(msg) - , _object(nullptr) - , _plugin(nullptr) {} bool Get::pre_process(PreProcessContext&) { - std::lock_guard<Store::Mutex> lock(_engine.store()->mutex()); + const std::lock_guard<Store::Mutex> lock{_engine.store()->mutex()}; const auto& uri = _msg.subject; if (uri == "ingen:/plugins") { _plugins = _engine.block_factory()->plugins(); return Event::pre_process_done(Status::SUCCESS); - } else if (uri == "ingen:/engine") { + } + + if (uri == "ingen:/engine") { return Event::pre_process_done(Status::SUCCESS); - } else if (uri_is_path(uri)) { + } + + if (uri_is_path(uri)) { if ((_object = _engine.store()->get(uri_to_path(uri)))) { const BlockImpl* block = nullptr; const GraphImpl* graph = nullptr; @@ -75,18 +81,24 @@ Get::pre_process(PreProcessContext&) return Event::pre_process_done(Status::SUCCESS); } return Event::pre_process_done(Status::NOT_FOUND, uri); - } else if ((_plugin = _engine.block_factory()->plugin(uri))) { + } + + if ((_plugin = _engine.block_factory()->plugin(uri))) { _response.put_plugin(_plugin); return Event::pre_process_done(Status::SUCCESS); - } else { - return Event::pre_process_done(Status::NOT_FOUND, uri); } + + return Event::pre_process_done(Status::NOT_FOUND, uri); } void +Get::execute(RunContext&) +{} + +void Get::post_process() { - Broadcaster::Transfer t(*_engine.broadcaster()); + const Broadcaster::Transfer t{*_engine.broadcaster()}; if (respond() == Status::SUCCESS && _request_client) { if (_msg.subject == "ingen:/plugins") { _engine.broadcaster()->send_plugins_to(_request_client.get(), _plugins); @@ -95,11 +107,11 @@ Get::post_process() URIs& uris = _engine.world().uris(); Properties props = { { uris.param_sampleRate, - uris.forge.make(int32_t(_engine.sample_rate())) }, + uris.forge.make(static_cast<int32_t>(_engine.sample_rate())) }, { uris.bufsz_maxBlockLength, - uris.forge.make(int32_t(_engine.block_length())) }, + uris.forge.make(static_cast<int32_t>(_engine.block_length())) }, { uris.ingen_numThreads, - uris.forge.make(int32_t(_engine.n_threads())) } }; + uris.forge.make(static_cast<int32_t>(_engine.n_threads())) } }; const Properties load_props = _engine.load_properties(); props.insert(load_props.begin(), load_props.end()); @@ -110,6 +122,4 @@ Get::post_process() } } -} // namespace events -} // namespace server -} // namespace ingen +} // namespace ingen::server::events diff --git a/src/server/events/Get.hpp b/src/server/events/Get.hpp index e24c9998..0f5ed235 100644 --- a/src/server/events/Get.hpp +++ b/src/server/events/Get.hpp @@ -17,18 +17,24 @@ #ifndef INGEN_EVENTS_GET_HPP #define INGEN_EVENTS_GET_HPP +#include <ingen/Message.hpp> + #include "BlockFactory.hpp" #include "ClientUpdate.hpp" #include "Event.hpp" #include "types.hpp" +#include <memory> + namespace ingen { + +class Interface; +class Node; + namespace server { -class BlockImpl; -class GraphImpl; +class Engine; class PluginImpl; -class PortImpl; namespace events { @@ -39,19 +45,19 @@ namespace events { class Get : public Event { public: - Get(Engine& engine, - const SPtr<Interface>& client, - SampleCount timestamp, - const ingen::Get& msg); + Get(Engine& engine, + const std::shared_ptr<Interface>& client, + SampleCount timestamp, + const ingen::Get& msg); bool pre_process(PreProcessContext& ctx) override; - void execute(RunContext& context) override {} + void execute(RunContext&) override; void post_process() override; private: const ingen::Get _msg; - const Node* _object; - PluginImpl* _plugin; + const Node* _object{nullptr}; + PluginImpl* _plugin{nullptr}; BlockFactory::Plugins _plugins; ClientUpdate _response; }; diff --git a/src/server/events/Mark.cpp b/src/server/events/Mark.cpp index eb50e4a0..b60b0432 100644 --- a/src/server/events/Mark.cpp +++ b/src/server/events/Mark.cpp @@ -14,42 +14,50 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "events/Mark.hpp" +#include "Mark.hpp" +#include "CompiledGraph.hpp" #include "Engine.hpp" +#include "GraphImpl.hpp" #include "PreProcessContext.hpp" #include "UndoStack.hpp" +#include <ingen/Message.hpp> +#include <ingen/Status.hpp> + +#include <cassert> +#include <memory> +#include <unordered_set> #include <utility> -namespace ingen { -namespace server { -namespace events { +namespace ingen::server::events { -Mark::Mark(Engine& engine, - const SPtr<Interface>& client, - SampleCount timestamp, - const ingen::BundleBegin& msg) +Mark::Mark(Engine& engine, + const std::shared_ptr<Interface>& client, + SampleCount timestamp, + const ingen::BundleBegin& msg) : Event(engine, client, msg.seq, timestamp) , _type(Type::BUNDLE_BEGIN) , _depth(-1) {} -Mark::Mark(Engine& engine, - const SPtr<Interface>& client, - SampleCount timestamp, - const ingen::BundleEnd& msg) +Mark::Mark(Engine& engine, + const std::shared_ptr<Interface>& client, + SampleCount timestamp, + const ingen::BundleEnd& msg) : Event(engine, client, msg.seq, timestamp) , _type(Type::BUNDLE_END) , _depth(-1) {} +Mark::~Mark() = default; + void -Mark::mark(PreProcessContext& ctx) +Mark::mark(PreProcessContext&) { - const UPtr<UndoStack>& stack = ((_mode == Mode::UNDO) - ? _engine.redo_stack() - : _engine.undo_stack()); + const std::unique_ptr<UndoStack>& stack = ((_mode == Mode::UNDO) + ? _engine.redo_stack() + : _engine.undo_stack()); switch (_type) { case Type::BUNDLE_BEGIN: @@ -76,7 +84,7 @@ Mark::pre_process(PreProcessContext& ctx) ctx.set_in_bundle(false); if (!ctx.dirty_graphs().empty()) { for (GraphImpl* g : ctx.dirty_graphs()) { - MPtr<CompiledGraph> cg = compile(*_engine.maid(), *g); + auto cg = compile(*g); if (cg) { _compiled_graphs.emplace(g, std::move(cg)); } @@ -93,7 +101,7 @@ void Mark::execute(RunContext&) { for (auto& g : _compiled_graphs) { - g.first->set_compiled_graph(std::move(g.second)); + g.second = g.first->swap_compiled_graph(std::move(g.second)); } } @@ -126,6 +134,4 @@ Mark::get_execution() const return Execution::NORMAL; } -} // namespace events -} // namespace server -} // namespace ingen +} // namespace ingen::server::events diff --git a/src/server/events/Mark.hpp b/src/server/events/Mark.hpp index bff38f06..e7180764 100644 --- a/src/server/events/Mark.hpp +++ b/src/server/events/Mark.hpp @@ -17,14 +17,21 @@ #ifndef INGEN_EVENTS_MARK_HPP #define INGEN_EVENTS_MARK_HPP +#include "CompiledGraph.hpp" #include "Event.hpp" +#include "types.hpp" #include <map> +#include <memory> namespace ingen { + +class Interface; +struct BundleBegin; +struct BundleEnd; + namespace server { -class CompiledGraph; class Engine; class GraphImpl; @@ -40,19 +47,21 @@ namespace events { class Mark : public Event { public: - Mark(Engine& engine, - const SPtr<Interface>& client, - SampleCount timestamp, - const ingen::BundleBegin& msg); + Mark(Engine& engine, + const std::shared_ptr<Interface>& client, + SampleCount timestamp, + const ingen::BundleBegin& msg); + + Mark(Engine& engine, + const std::shared_ptr<Interface>& client, + SampleCount timestamp, + const ingen::BundleEnd& msg); - Mark(Engine& engine, - const SPtr<Interface>& client, - SampleCount timestamp, - const ingen::BundleEnd& msg); + ~Mark() override; void mark(PreProcessContext& ctx) override; bool pre_process(PreProcessContext& ctx) override; - void execute(RunContext& context) override; + void execute(RunContext& ctx) override; void post_process() override; Execution get_execution() const override; @@ -60,7 +69,7 @@ public: private: enum class Type { BUNDLE_BEGIN, BUNDLE_END }; - using CompiledGraphs = std::map<GraphImpl*, MPtr<CompiledGraph>>; + using CompiledGraphs = std::map<GraphImpl*, std::unique_ptr<CompiledGraph>>; CompiledGraphs _compiled_graphs; Type _type; diff --git a/src/server/events/Move.cpp b/src/server/events/Move.cpp index f6a39f1f..80ae5a11 100644 --- a/src/server/events/Move.cpp +++ b/src/server/events/Move.cpp @@ -14,42 +14,46 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "ingen/Store.hpp" -#include "raul/Path.hpp" +#include "Move.hpp" -#include "BlockImpl.hpp" #include "Broadcaster.hpp" #include "Driver.hpp" #include "Engine.hpp" -#include "EnginePort.hpp" -#include "GraphImpl.hpp" -#include "events/Move.hpp" +#include <ingen/Interface.hpp> +#include <ingen/Message.hpp> +#include <ingen/Status.hpp> +#include <ingen/Store.hpp> +#include <raul/Path.hpp> + +#include <map> +#include <memory> #include <mutex> -namespace ingen { -namespace server { +namespace ingen::server { + +class EnginePort; + namespace events { -Move::Move(Engine& engine, - const SPtr<Interface>& client, - SampleCount timestamp, - const ingen::Move& msg) +Move::Move(Engine& engine, + const std::shared_ptr<Interface>& client, + SampleCount timestamp, + const ingen::Move& msg) : Event(engine, client, msg.seq, timestamp) , _msg(msg) -{ -} +{} bool Move::pre_process(PreProcessContext&) { - std::lock_guard<Store::Mutex> lock(_engine.store()->mutex()); + const std::lock_guard<Store::Mutex> lock{_engine.store()->mutex()}; if (!_msg.old_path.parent().is_parent_of(_msg.new_path)) { return Event::pre_process_done(Status::PARENT_DIFFERS, _msg.new_path); } - const Store::iterator i = _engine.store()->find(_msg.old_path); + const auto i = _engine.store()->find(_msg.old_path); if (i == _engine.store()->end()) { return Event::pre_process_done(Status::NOT_FOUND, _msg.old_path); } @@ -69,14 +73,13 @@ Move::pre_process(PreProcessContext&) } void -Move::execute(RunContext& context) -{ -} +Move::execute(RunContext&) +{} void Move::post_process() { - Broadcaster::Transfer t(*_engine.broadcaster()); + const Broadcaster::Transfer t{*_engine.broadcaster()}; if (respond() == Status::SUCCESS) { _engine.broadcaster()->message(_msg); } @@ -89,5 +92,4 @@ Move::undo(Interface& target) } } // namespace events -} // namespace server -} // namespace ingen +} // namespace ingen::server diff --git a/src/server/events/Move.hpp b/src/server/events/Move.hpp index b4487b78..cca4d310 100644 --- a/src/server/events/Move.hpp +++ b/src/server/events/Move.hpp @@ -18,15 +18,19 @@ #define INGEN_EVENTS_MOVE_HPP #include "Event.hpp" +#include "types.hpp" -#include "ingen/Store.hpp" -#include "raul/Path.hpp" +#include <ingen/Message.hpp> + +#include <memory> namespace ingen { + +class Interface; + namespace server { -class GraphImpl; -class PortImpl; +class Engine; namespace events { @@ -36,13 +40,13 @@ namespace events { class Move : public Event { public: - Move(Engine& engine, - const SPtr<Interface>& client, - SampleCount timestamp, - const ingen::Move& msg); + Move(Engine& engine, + const std::shared_ptr<Interface>& client, + SampleCount timestamp, + const ingen::Move& msg); bool pre_process(PreProcessContext& ctx) override; - void execute(RunContext& context) override; + void execute(RunContext& ctx) override; void post_process() override; void undo(Interface& target) override; diff --git a/src/server/events/SetPortValue.cpp b/src/server/events/SetPortValue.cpp index 2eecf9ce..ba6859dd 100644 --- a/src/server/events/SetPortValue.cpp +++ b/src/server/events/SetPortValue.cpp @@ -16,47 +16,46 @@ #include "SetPortValue.hpp" -#include "BlockImpl.hpp" #include "Broadcaster.hpp" #include "Buffer.hpp" +#include "BufferFactory.hpp" #include "ControlBindings.hpp" #include "Engine.hpp" #include "PortImpl.hpp" #include "RunContext.hpp" -#include "ingen/Forge.hpp" -#include "ingen/LV2Features.hpp" -#include "ingen/Store.hpp" -#include "ingen/URIs.hpp" -#include "ingen/World.hpp" +#include <ingen/Atom.hpp> +#include <ingen/Forge.hpp> +#include <ingen/Status.hpp> +#include <ingen/URIs.hpp> +#include <ingen/World.hpp> +#include <lv2/atom/atom.h> #include <cassert> +#include <memory> -namespace ingen { -namespace server { -namespace events { +namespace ingen::server::events { /** Internal */ -SetPortValue::SetPortValue(Engine& engine, - const SPtr<Interface>& client, - int32_t id, - SampleCount timestamp, - PortImpl* port, - const Atom& value, - bool activity, - bool synthetic) +SetPortValue::SetPortValue(Engine& engine, + const std::shared_ptr<Interface>& client, + int32_t id, + SampleCount timestamp, + PortImpl* port, + const Atom& value, + bool activity, + bool synthetic) : Event(engine, client, id, timestamp) , _port(port) , _value(value) , _activity(activity) , _synthetic(synthetic) -{ -} +{} bool SetPortValue::pre_process(PreProcessContext&) { - ingen::URIs& uris = _engine.world().uris(); + const ingen::URIs& uris = _engine.world().uris(); if (_port->is_output()) { return Event::pre_process_done(Status::DIRECTION_MISMATCH, _port->path()); } @@ -80,43 +79,43 @@ SetPortValue::pre_process(PreProcessContext&) } void -SetPortValue::execute(RunContext& context) +SetPortValue::execute(RunContext& ctx) { - assert(_time >= context.start() && _time <= context.end()); - apply(context); - _engine.control_bindings()->port_value_changed(context, _port, _binding, _value); + assert(_time >= ctx.start() && _time <= ctx.end()); + apply(ctx); + _engine.control_bindings()->port_value_changed(ctx, _port, _binding, _value); } void -SetPortValue::apply(RunContext& context) +SetPortValue::apply(RunContext& ctx) { if (_status != Status::SUCCESS) { return; } - ingen::URIs& uris = _engine.world().uris(); - Buffer* buf = _port->buffer(0).get(); + const ingen::URIs& uris = _engine.world().uris(); + Buffer* buf = _port->buffer(0).get(); if (_buffer) { - if (_port->user_buffer(context)) { - buf = _port->user_buffer(context).get(); + if (_port->user_buffer(ctx)) { + buf = _port->user_buffer(ctx).get(); } else { - _port->set_user_buffer(context, _buffer); + _port->set_user_buffer(ctx, _buffer); buf = _buffer.get(); } } if (buf->type() == uris.atom_Sound || buf->type() == uris.atom_Float) { if (_value.type() == uris.forge.Float) { - _port->set_control_value(context, _time, _value.get<float>()); + _port->set_control_value(ctx, _time, _value.get<float>()); } else { _status = Status::TYPE_MISMATCH; } } else if (buf->type() == uris.atom_Sequence) { - if (!buf->append_event(_time - context.start(), + if (!buf->append_event(_time - ctx.start(), _value.size(), _value.type(), - (const uint8_t*)_value.get_body())) { + reinterpret_cast<const uint8_t*>(_value.get_body()))) { _status = Status::NO_SPACE; } } else if (buf->type() == uris.atom_URID) { @@ -129,7 +128,7 @@ SetPortValue::apply(RunContext& context) void SetPortValue::post_process() { - Broadcaster::Transfer t(*_engine.broadcaster()); + const Broadcaster::Transfer t{*_engine.broadcaster()}; if (respond() == Status::SUCCESS && !_activity) { _engine.broadcaster()->set_property( _port->uri(), @@ -138,6 +137,4 @@ SetPortValue::post_process() } } -} // namespace events -} // namespace server -} // namespace ingen +} // namespace ingen::server::events diff --git a/src/server/events/SetPortValue.hpp b/src/server/events/SetPortValue.hpp index 99d55af3..32a8b761 100644 --- a/src/server/events/SetPortValue.hpp +++ b/src/server/events/SetPortValue.hpp @@ -22,14 +22,20 @@ #include "Event.hpp" #include "types.hpp" -#include "ingen/Atom.hpp" +#include <ingen/Atom.hpp> #include <cstdint> +#include <memory> namespace ingen { + +class Interface; + namespace server { +class Engine; class PortImpl; +class RunContext; namespace events { @@ -40,23 +46,23 @@ namespace events { class SetPortValue : public Event { public: - SetPortValue(Engine& engine, - const SPtr<Interface>& client, - int32_t id, - SampleCount timestamp, - PortImpl* port, - const Atom& value, - bool activity, - bool synthetic = false); + SetPortValue(Engine& engine, + const std::shared_ptr<Interface>& client, + int32_t id, + SampleCount timestamp, + PortImpl* port, + const Atom& value, + bool activity, + bool synthetic = false); bool pre_process(PreProcessContext& ctx) override; - void execute(RunContext& context) override; + void execute(RunContext& ctx) override; void post_process() override; bool synthetic() const { return _synthetic; } private: - void apply(RunContext& context); + void apply(RunContext& ctx); PortImpl* _port; const Atom _value; diff --git a/src/server/events/Undo.cpp b/src/server/events/Undo.cpp index 0741e60d..db7c1c86 100644 --- a/src/server/events/Undo.cpp +++ b/src/server/events/Undo.cpp @@ -19,26 +19,29 @@ #include "Engine.hpp" #include "EventWriter.hpp" -#include "ingen/AtomReader.hpp" +#include <ingen/AtomReader.hpp> +#include <ingen/Interface.hpp> +#include <ingen/Message.hpp> +#include <ingen/Status.hpp> +#include <lv2/atom/atom.h> #include <deque> +#include <memory> -namespace ingen { -namespace server { -namespace events { +namespace ingen::server::events { -Undo::Undo(Engine& engine, - const SPtr<Interface>& client, - SampleCount timestamp, - const ingen::Undo& msg) +Undo::Undo(Engine& engine, + const std::shared_ptr<Interface>& client, + SampleCount timestamp, + const ingen::Undo& msg) : Event(engine, client, msg.seq, timestamp) , _is_redo(false) {} -Undo::Undo(Engine& engine, - const SPtr<Interface>& client, - SampleCount timestamp, - const ingen::Redo& msg) +Undo::Undo(Engine& engine, + const std::shared_ptr<Interface>& client, + SampleCount timestamp, + const ingen::Redo& msg) : Event(engine, client, msg.seq, timestamp) , _is_redo(true) {} @@ -46,8 +49,10 @@ Undo::Undo(Engine& engine, bool Undo::pre_process(PreProcessContext&) { - const UPtr<UndoStack>& stack = _is_redo ? _engine.redo_stack() : _engine.undo_stack(); - const Event::Mode mode = _is_redo ? Event::Mode::REDO : Event::Mode::UNDO; + const std::unique_ptr<UndoStack>& stack = + _is_redo ? _engine.redo_stack() : _engine.undo_stack(); + + const Event::Mode mode = _is_redo ? Event::Mode::REDO : Event::Mode::UNDO; if (stack->empty()) { return Event::pre_process_done(Status::NOT_FOUND); @@ -73,9 +78,8 @@ Undo::pre_process(PreProcessContext&) } void -Undo::execute(RunContext& context) -{ -} +Undo::execute(RunContext&) +{} void Undo::post_process() @@ -83,6 +87,4 @@ Undo::post_process() respond(); } -} // namespace events -} // namespace server -} // namespace ingen +} // namespace ingen::server::events diff --git a/src/server/events/Undo.hpp b/src/server/events/Undo.hpp index e36ebaad..818dc754 100644 --- a/src/server/events/Undo.hpp +++ b/src/server/events/Undo.hpp @@ -21,8 +21,18 @@ #include "UndoStack.hpp" #include "types.hpp" +#include <memory> + namespace ingen { + +class Interface; +struct Redo; +struct Undo; + namespace server { + +class Engine; + namespace events { /** A request to undo the last change to the engine. @@ -32,18 +42,18 @@ namespace events { class Undo : public Event { public: - Undo(Engine& engine, - const SPtr<Interface>& client, - SampleCount timestamp, - const ingen::Undo& msg); + Undo(Engine& engine, + const std::shared_ptr<Interface>& client, + SampleCount timestamp, + const ingen::Undo& msg); - Undo(Engine& engine, - const SPtr<Interface>& client, - SampleCount timestamp, - const ingen::Redo& msg); + Undo(Engine& engine, + const std::shared_ptr<Interface>& client, + SampleCount timestamp, + const ingen::Redo& msg); bool pre_process(PreProcessContext& ctx) override; - void execute(RunContext& context) override; + void execute(RunContext& ctx) override; void post_process() override; private: diff --git a/src/server/ingen_engine.cpp b/src/server/ingen_engine.cpp index fba2e434..48955143 100644 --- a/src/server/ingen_engine.cpp +++ b/src/server/ingen_engine.cpp @@ -15,18 +15,19 @@ */ #include "Engine.hpp" -#include "EventWriter.hpp" #include "util.hpp" -#include "ingen/Module.hpp" -#include "ingen/World.hpp" +#include <ingen/Module.hpp> +#include <ingen/World.hpp> -using namespace ingen; +#include <memory> -struct IngenEngineModule : public ingen::Module { - void load(ingen::World& world) override { +namespace ingen { + +struct EngineModule : public Module { + void load(World& world) override { server::set_denormal_flags(world.log()); - SPtr<server::Engine> engine(new server::Engine(world)); + auto engine = std::make_shared<server::Engine>(world); world.set_engine(engine); if (!world.interface()) { world.set_interface(engine->interface()); @@ -34,12 +35,14 @@ struct IngenEngineModule : public ingen::Module { } }; +} // namespace ingen + extern "C" { -ingen::Module* +INGEN_MODULE_EXPORT ingen::Module* ingen_module_load() { - return new IngenEngineModule(); + return new ingen::EngineModule(); } } // extern "C" diff --git a/src/server/ingen_jack.cpp b/src/server/ingen_jack.cpp index 37aa9c7b..16369d0c 100644 --- a/src/server/ingen_jack.cpp +++ b/src/server/ingen_jack.cpp @@ -14,44 +14,52 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "JackDriver.hpp" #include "Engine.hpp" +#include "JackDriver.hpp" -#include "ingen/Atom.hpp" -#include "ingen/Configuration.hpp" -#include "ingen/Log.hpp" -#include "ingen/Module.hpp" -#include "ingen/World.hpp" +#include <ingen/Atom.hpp> +#include <ingen/Configuration.hpp> +#include <ingen/Log.hpp> +#include <ingen/Module.hpp> +#include <ingen/World.hpp> +#include <memory> #include <string> -using namespace ingen; +namespace ingen::server { + +class Driver; + +struct JackModule : public Module { + void load(World& world) override { + server::Engine* const engine = + static_cast<server::Engine*>(world.engine().get()); -struct IngenJackModule : public ingen::Module { - void load(ingen::World& world) override { - if (((server::Engine*)world.engine().get())->driver()) { + if (engine->driver()) { world.log().warn("Engine already has a driver\n"); return; } - server::JackDriver* driver = new server::JackDriver( - *(server::Engine*)world.engine().get()); - const Atom& s = world.conf().option("jack-server"); + auto* driver = new server::JackDriver(*engine); + const Atom& s = world.conf().option("jack-server"); const std::string server_name = s.is_valid() ? s.ptr<char>() : ""; + driver->attach(server_name, world.conf().option("jack-name").ptr<char>(), nullptr); - ((server::Engine*)world.engine().get())->set_driver( - SPtr<server::Driver>(driver)); + + engine->set_driver(std::shared_ptr<server::Driver>(driver)); } }; +} // namespace ingen::server + extern "C" { -ingen::Module* +INGEN_MODULE_EXPORT ingen::Module* ingen_module_load() { - return new IngenJackModule(); + return new ingen::server::JackModule(); } } // extern "C" diff --git a/src/server/ingen_lv2.cpp b/src/server/ingen_lv2.cpp index 57663344..658f759b 100644 --- a/src/server/ingen_lv2.cpp +++ b/src/server/ingen_lv2.cpp @@ -15,7 +15,6 @@ */ #include "Buffer.hpp" -#include "BufferRef.hpp" #include "Driver.hpp" #include "DuplexPort.hpp" #include "Engine.hpp" @@ -26,47 +25,47 @@ #include "ThreadManager.hpp" #include "types.hpp" -#include "ingen/AtomReader.hpp" -#include "ingen/AtomSink.hpp" -#include "ingen/AtomWriter.hpp" -#include "ingen/Configuration.hpp" -#include "ingen/EngineBase.hpp" -#include "ingen/FilePath.hpp" -#include "ingen/Forge.hpp" -#include "ingen/Interface.hpp" -#include "ingen/Log.hpp" -#include "ingen/Node.hpp" -#include "ingen/Parser.hpp" -#include "ingen/Serialiser.hpp" -#include "ingen/Store.hpp" -#include "ingen/URI.hpp" -#include "ingen/URIs.hpp" -#include "ingen/World.hpp" -#include "ingen/ingen.h" -#include "ingen/runtime_paths.hpp" -#include "ingen/types.hpp" -#include "lv2/atom/atom.h" -#include "lv2/atom/atom.h" -#include "lv2/atom/util.h" -#include "lv2/buf-size/buf-size.h" -#include "lv2/core/lv2.h" -#include "lv2/log/log.h" -#include "lv2/log/logger.h" -#include "lv2/options/options.h" -#include "lv2/state/state.h" -#include "lv2/urid/urid.h" -#include "raul/Maid.hpp" -#include "raul/Path.hpp" -#include "raul/RingBuffer.hpp" -#include "raul/Semaphore.hpp" -#include "raul/Symbol.hpp" -#include "serd/serd.h" -#include "sord/sordmm.hpp" +#include <ingen/AtomReader.hpp> +#include <ingen/AtomSink.hpp> +#include <ingen/AtomWriter.hpp> +#include <ingen/Configuration.hpp> +#include <ingen/EngineBase.hpp> +#include <ingen/FilePath.hpp> +#include <ingen/Forge.hpp> +#include <ingen/Interface.hpp> +#include <ingen/Log.hpp> +#include <ingen/Node.hpp> +#include <ingen/Parser.hpp> +#include <ingen/Serialiser.hpp> +#include <ingen/Store.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIs.hpp> +#include <ingen/World.hpp> +#include <ingen/ingen.h> +#include <ingen/memory.hpp> +#include <ingen/runtime_paths.hpp> +#include <lv2/atom/atom.h> +#include <lv2/atom/util.h> +#include <lv2/buf-size/buf-size.h> +#include <lv2/core/lv2.h> +#include <lv2/log/log.h> +#include <lv2/log/logger.h> +#include <lv2/options/options.h> +#include <lv2/state/state.h> +#include <lv2/urid/urid.h> +#include <raul/Maid.hpp> +#include <raul/Path.hpp> +#include <raul/RingBuffer.hpp> +#include <raul/Semaphore.hpp> +#include <raul/Symbol.hpp> +#include <serd/serd.h> +#include <sord/sordmm.hpp> #include <algorithm> #include <cstdint> #include <cstdlib> #include <cstring> +#include <iterator> #include <memory> #include <mutex> #include <set> @@ -75,75 +74,69 @@ #include <utility> #include <vector> -#define NS_RDF "http://www.w3.org/1999/02/22-rdf-syntax-ns#" -#define NS_RDFS "http://www.w3.org/2000/01/rdf-schema#" +// #define CLEAR_GRAPH_ON_RESTORE 1 -namespace ingen { +namespace ingen::server { + +class GraphImpl; /** Record of a graph in this bundle. */ struct LV2Graph : public Parser::ResourceRecord { - LV2Graph(Parser::ResourceRecord record); + explicit LV2Graph(Parser::ResourceRecord record); LV2_Descriptor descriptor; }; /** Ingen LV2 library. */ -class Lib { +class Lib +{ public: explicit Lib(const char* bundle_path); - using Graphs = std::vector<SPtr<const LV2Graph>>; + using Graphs = std::vector<std::shared_ptr<const LV2Graph>>; Graphs graphs; }; -namespace server { - -class LV2Driver; - -void signal_main(RunContext& context, LV2Driver* driver); +namespace { inline size_t ui_ring_size(SampleCount block_length) { - return std::max((size_t)8192, (size_t)block_length * 16); + return std::max(static_cast<size_t>(8192U), + static_cast<size_t>(block_length) * 16U); } -class LV2Driver : public ingen::server::Driver - , public ingen::AtomSink +} // namespace + +class LV2Driver : public Driver, public ingen::AtomSink { public: LV2Driver(Engine& engine, SampleCount block_length, - size_t seq_size, + uint32_t seq_size, SampleCount sample_rate) : _engine(engine) , _main_sem(0) , _reader(engine.world().uri_map(), engine.world().uris(), engine.world().log(), - *engine.world().interface().get()) + *engine.world().interface()) , _writer(engine.world().uri_map(), engine.world().uris(), *this) , _from_ui(ui_ring_size(block_length)) , _to_ui(ui_ring_size(block_length)) - , _root_graph(nullptr) - , _notify_capacity(0) , _block_length(block_length) , _seq_size(seq_size) , _sample_rate(sample_rate) - , _frame_time(0) - , _to_ui_overflow_sem(0) - , _to_ui_overflow(false) - , _instantiated(false) {} bool dynamic_ports() const override { return !_instantiated; } - void pre_process_port(RunContext& context, EnginePort* port) { + void pre_process_port(RunContext& ctx, EnginePort* port) { const URIs& uris = _engine.world().uris(); - const SampleCount nframes = context.nframes(); + const SampleCount nframes = ctx.nframes(); DuplexPort* graph_port = port->graph_port(); Buffer* graph_buf = graph_port->buffer(0).get(); void* lv2_buf = port->buffer(); @@ -151,11 +144,16 @@ public: if (graph_port->is_a(PortType::AUDIO) || graph_port->is_a(PortType::CV)) { graph_port->set_driver_buffer(lv2_buf, nframes * sizeof(float)); } else if (graph_port->buffer_type() == uris.atom_Sequence) { - graph_port->set_driver_buffer(lv2_buf, lv2_atom_total_size((LV2_Atom*)lv2_buf)); - if (graph_port->symbol() == "control") { // TODO: Safe to use index? - LV2_Atom_Sequence* seq = (LV2_Atom_Sequence*)lv2_buf; - bool enqueued = false; - LV2_ATOM_SEQUENCE_FOREACH(seq, ev) { + graph_port->set_driver_buffer(lv2_buf, + lv2_atom_total_size( + static_cast<LV2_Atom*>(lv2_buf))); + + if (graph_port->symbol() == "control") { // TODO: Safe to use index? + auto* seq = reinterpret_cast<LV2_Atom_Sequence*>(lv2_buf); + + bool enqueued = false; + LV2_ATOM_SEQUENCE_FOREACH (seq, ev) + { if (AtomReader::is_message(uris, &ev->body)) { enqueued = enqueue_message(&ev->body) || enqueued; } @@ -169,13 +167,13 @@ public: } if (graph_port->is_input()) { - graph_port->monitor(context); + graph_port->monitor(ctx); } else { - graph_buf->prepare_write(context); + graph_buf->prepare_write(ctx); } } - void post_process_port(RunContext& context, EnginePort* port) { + static void post_process_port(RunContext&, EnginePort* port) { DuplexPort* graph_port = port->graph_port(); // No copying necessary, host buffers are used directly @@ -189,7 +187,8 @@ public: _engine.locate(_frame_time, nframes); // Notify buffer is a Chunk with size set to the available space - _notify_capacity = ((LV2_Atom_Sequence*)_ports[1]->buffer())->atom.size; + _notify_capacity = + static_cast<LV2_Atom_Sequence*>(_ports[1]->buffer())->atom.size; for (auto& p : _ports) { pre_process_port(_engine.run_context(), p); @@ -217,18 +216,17 @@ public: virtual void set_root_graph(GraphImpl* graph) { _root_graph = graph; } 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; - } - } + EnginePort* get_port(const raul::Path& path) override { + 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. */ - void add_port(RunContext& context, EnginePort* port) override { + void add_port(RunContext&, EnginePort* port) override { const uint32_t index = port->graph_port()->index(); if (_ports.size() <= index) { _ports.resize(index + 1); @@ -237,7 +235,7 @@ public: } /** Remove a port. Called only during init or restore. */ - void remove_port(RunContext& context, EnginePort* port) override { + void remove_port(RunContext&, EnginePort* port) override { const uint32_t index = port->graph_port()->index(); _ports[index] = nullptr; } @@ -249,11 +247,11 @@ public: void unregister_port(EnginePort& port) override {} /** Unused since LV2 has no dynamic ports. */ - void rename_port(const Raul::Path& old_path, - const Raul::Path& new_path) override {} + void rename_port(const raul::Path& old_path, + const raul::Path& new_path) override {} /** Unused since LV2 has no dynamic ports. */ - void port_property(const Raul::Path& path, + void port_property(const raul::Path& path, const URI& uri, const Atom& value) override {} @@ -262,17 +260,20 @@ public: return new EnginePort(graph_port); } - void append_time_events(RunContext& context, Buffer& buffer) override { - const URIs& uris = _engine.world().uris(); - LV2_Atom_Sequence* seq = (LV2_Atom_Sequence*)_ports[0]->buffer(); - LV2_ATOM_SEQUENCE_FOREACH(seq, ev) { + void append_time_events(RunContext&, Buffer& buffer) override { + const URIs& uris = _engine.world().uris(); + auto* seq = static_cast<LV2_Atom_Sequence*>(_ports[0]->buffer()); + + LV2_ATOM_SEQUENCE_FOREACH (seq, ev) { if (ev->body.type == uris.atom_Object) { - const LV2_Atom_Object* obj = (LV2_Atom_Object*)&ev->body; + const LV2_Atom_Object* obj = + reinterpret_cast<LV2_Atom_Object*>(&ev->body); + if (obj->body.otype == uris.time_Position) { buffer.append_event(ev->time.frames, ev->body.size, ev->body.type, - (const uint8_t*)(&ev->body + 1)); + reinterpret_cast<const uint8_t*>(&ev->body + 1)); } } } @@ -291,7 +292,7 @@ public: return true; } - Raul::Semaphore& main_sem() { return _main_sem; } + raul::Semaphore& main_sem() { return _main_sem; } /** AtomSink::write implementation called by the PostProcessor in the main * thread to write responses to the UI. @@ -317,27 +318,35 @@ 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, (char*)buf + sizeof(LV2_Atom))) { - _engine.log().rt_error("Error reading body from from-UI ring\n"); + if (!_from_ui.read(atom.size, + static_cast<char*>(buf) + sizeof(LV2_Atom))) { + _engine.log().rt_error( + "Error reading body from from-UI ring\n"); break; } - _reader.write((LV2_Atom*)buf); + _reader.write(static_cast<LV2_Atom*>(buf)); read += sizeof(LV2_Atom) + atom.size; } free(buf); } - void flush_to_ui(RunContext& context) { + void flush_to_ui(RunContext&) { if (_ports.size() < 2) { _engine.log().rt_error("Standard control ports are not present\n"); return; } - LV2_Atom_Sequence* seq = (LV2_Atom_Sequence*)_ports[1]->buffer(); + auto* seq = static_cast<LV2_Atom_Sequence*>(_ports[1]->buffer()); if (!seq) { _engine.log().rt_error("Notify output not connected\n"); return; @@ -358,13 +367,14 @@ public: if (seq->atom.size + lv2_atom_pad_size( sizeof(LV2_Atom_Event) + atom.size) > _notify_capacity) { - break; // Output port buffer full, resume next time + break; // Output port buffer full, resume next time } - LV2_Atom_Event* ev = (LV2_Atom_Event*)( - (uint8_t*)seq + lv2_atom_total_size(&seq->atom)); + auto* ev = reinterpret_cast<LV2_Atom_Event*>( + reinterpret_cast<uint8_t*>(seq) + + lv2_atom_total_size(&seq->atom)); - ev->time.frames = 0; // TODO: Time? + ev->time.frames = 0; // TODO: Time? ev->body = atom; _to_ui.skip(sizeof(LV2_Atom)); @@ -384,7 +394,7 @@ public: } SampleCount block_length() const override { return _block_length; } - size_t seq_size() const override { return _seq_size; } + uint32_t seq_size() const override { return _seq_size; } SampleCount sample_rate() const override { return _sample_rate; } SampleCount frame_time() const override { return _frame_time; } @@ -400,32 +410,36 @@ public: private: Engine& _engine; Ports _ports; - Raul::Semaphore _main_sem; + raul::Semaphore _main_sem; AtomReader _reader; AtomWriter _writer; - Raul::RingBuffer _from_ui; - Raul::RingBuffer _to_ui; - GraphImpl* _root_graph; - uint32_t _notify_capacity; + raul::RingBuffer _from_ui; + raul::RingBuffer _to_ui; + GraphImpl* _root_graph{nullptr}; + uint32_t _notify_capacity{0}; SampleCount _block_length; - size_t _seq_size; + uint32_t _seq_size; SampleCount _sample_rate; - SampleCount _frame_time; - Raul::Semaphore _to_ui_overflow_sem; - bool _to_ui_overflow; - bool _instantiated; + SampleCount _frame_time{0}; + raul::Semaphore _to_ui_overflow_sem{0}; + bool _to_ui_overflow{false}; + bool _instantiated{false}; }; -} // namespace server -} // namespace ingen +struct IngenPlugin { + std::unique_ptr<World> world; + std::shared_ptr<Engine> engine; + std::unique_ptr<std::thread> main; + LV2_URID_Map* map = nullptr; + int argc = 0; + char** argv = nullptr; +}; extern "C" { -using namespace ingen; -using namespace ingen::server; - static void -ingen_lv2_main(const SPtr<Engine>& engine, const SPtr<LV2Driver>& driver) +ingen_lv2_main(const std::shared_ptr<Engine>& engine, + const std::shared_ptr<LV2Driver>& driver) { while (true) { // Wait until there is work to be done @@ -441,22 +455,6 @@ ingen_lv2_main(const SPtr<Engine>& engine, const SPtr<LV2Driver>& driver) } } -struct IngenPlugin { - IngenPlugin() - : main(nullptr) - , map(nullptr) - , argc(0) - , argv(nullptr) - {} - - UPtr<ingen::World> world; - SPtr<Engine> engine; - UPtr<std::thread> main; - LV2_URID_Map* map; - int argc; - char** argv; -}; - static Lib::Graphs find_graphs(const URI& manifest_uri) { @@ -469,9 +467,10 @@ find_graphs(const URI& manifest_uri) URI(INGEN__Graph)); Lib::Graphs graphs; - for (const auto& r : resources) { - graphs.push_back(SPtr<const LV2Graph>(new LV2Graph(r))); - } + std::transform(resources.begin(), + resources.end(), + std::back_inserter(graphs), + [](const auto& r) { return std::make_shared<LV2Graph>(r); }); return graphs; } @@ -489,13 +488,13 @@ ingen_instantiate(const LV2_Descriptor* descriptor, const LV2_Options_Option* options = nullptr; for (int i = 0; features[i]; ++i) { if (!strcmp(features[i]->URI, LV2_URID__map)) { - map = (LV2_URID_Map*)features[i]->data; + map = static_cast<LV2_URID_Map*>(features[i]->data); } else if (!strcmp(features[i]->URI, LV2_URID__unmap)) { - unmap = (LV2_URID_Unmap*)features[i]->data; + unmap = static_cast<LV2_URID_Unmap*>(features[i]->data); } else if (!strcmp(features[i]->URI, LV2_LOG__log)) { - log = (LV2_Log_Log*)features[i]->data; + log = static_cast<LV2_Log_Log*>(features[i]->data); } else if (!strcmp(features[i]->URI, LV2_OPTIONS__options)) { - options = (const LV2_Options_Option*)features[i]->data; + options = static_cast<const LV2_Options_Option*>(features[i]->data); } } @@ -505,48 +504,54 @@ ingen_instantiate(const LV2_Descriptor* descriptor, if (!map) { lv2_log_error(&logger, "host did not provide URI map feature\n"); return nullptr; - } else if (!unmap) { + } + + if (!unmap) { lv2_log_error(&logger, "host did not provide URI unmap feature\n"); return nullptr; } set_bundle_path(bundle_path); const std::string manifest_path = ingen::bundle_file_path("manifest.ttl"); - SerdNode manifest_node = serd_node_new_file_uri( - (const uint8_t*)manifest_path.c_str(), nullptr, nullptr, true); - - Lib::Graphs graphs = find_graphs(URI((const char*)manifest_node.buf)); + SerdNode manifest_node = + serd_node_new_file_uri(reinterpret_cast<const uint8_t*>( + manifest_path.c_str()), + nullptr, + nullptr, + true); + + 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); return nullptr; } - IngenPlugin* plugin = new IngenPlugin(); + auto* plugin = new IngenPlugin(); plugin->map = map; - plugin->world = UPtr<ingen::World>(new ingen::World(map, unmap, log)); + plugin->world = std::make_unique<ingen::World>(map, unmap, log); plugin->world->load_configuration(plugin->argc, plugin->argv); - LV2_URID bufsz_max = map->map(map->handle, LV2_BUF_SIZE__maxBlockLength); - LV2_URID bufsz_seq = map->map(map->handle, LV2_BUF_SIZE__sequenceSize); - LV2_URID atom_Int = map->map(map->handle, LV2_ATOM__Int); - int32_t block_length = 0; - int32_t seq_size = 0; + const LV2_URID bufsz_max = map->map(map->handle, LV2_BUF_SIZE__maxBlockLength); + const LV2_URID bufsz_seq = map->map(map->handle, LV2_BUF_SIZE__sequenceSize); + const LV2_URID atom_Int = map->map(map->handle, LV2_ATOM__Int); + int32_t block_length = 0; + int32_t seq_size = 0; if (options) { for (const LV2_Options_Option* o = options; o->key; ++o) { if (o->key == bufsz_max && o->type == atom_Int) { - block_length = *(const int32_t*)o->value; + block_length = *static_cast<const int32_t*>(o->value); } else if (o->key == bufsz_seq && o->type == atom_Int) { - seq_size = *(const int32_t*)o->value; + seq_size = *static_cast<const int32_t*>(o->value); } } } @@ -554,7 +559,7 @@ ingen_instantiate(const LV2_Descriptor* descriptor, block_length = 4096; plugin->world->log().warn("No maximum block length given\n"); } - if (seq_size == 0) { + if (seq_size < 1) { seq_size = 16384; plugin->world->log().warn("No maximum sequence size given\n"); } @@ -566,24 +571,25 @@ ingen_instantiate(const LV2_Descriptor* descriptor, "queue-size", plugin->world->forge().make(std::max(block_length, seq_size) * 4)); - SPtr<server::Engine> engine(new server::Engine(*plugin->world)); + auto engine = std::make_shared<Engine>(*plugin->world); plugin->engine = engine; plugin->world->set_engine(engine); - SPtr<Interface> interface = engine->interface(); + const std::shared_ptr<Interface> interface = engine->interface(); plugin->world->set_interface(interface); - server::ThreadManager::set_flag(server::THREAD_PRE_PROCESS); - server::ThreadManager::single_threaded = true; + ThreadManager::set_flag(THREAD_PRE_PROCESS); + ThreadManager::single_threaded = true; - LV2Driver* driver = new LV2Driver(*engine.get(), block_length, seq_size, rate); - engine->set_driver(SPtr<ingen::server::Driver>(driver)); + auto* driver = new LV2Driver( + *engine, block_length, static_cast<uint32_t>(seq_size), rate); + engine->set_driver(std::shared_ptr<Driver>(driver)); engine->activate(); - server::ThreadManager::single_threaded = true; + ThreadManager::single_threaded = true; - std::lock_guard<std::mutex> lock(plugin->world->rdf_mutex()); + const std::lock_guard<std::mutex> lock{plugin->world->rdf_mutex()}; // Locate to time 0 to process initialization events engine->locate(0, block_length); @@ -605,22 +611,20 @@ ingen_instantiate(const LV2_Descriptor* descriptor, /* Register client after loading graph so the to-ui ring does not overflow. Since we are not yet rolling, it won't be drained, causing a deadlock. */ - SPtr<Interface> client(&driver->writer(), NullDeleter<Interface>); + const std::shared_ptr<Interface> client{&driver->writer(), NullDeleter<Interface>}; interface->set_respondee(client); engine->register_client(client); driver->set_instantiated(true); - return (LV2_Handle)plugin; + return static_cast<LV2_Handle>(plugin); } static void ingen_connect_port(LV2_Handle instance, uint32_t port, void* data) { - using namespace ingen::server; - - IngenPlugin* me = (IngenPlugin*)instance; - server::Engine* engine = (server::Engine*)me->world->engine().get(); - const SPtr<LV2Driver>& driver = static_ptr_cast<LV2Driver>(engine->driver()); + 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); } else { @@ -631,22 +635,22 @@ ingen_connect_port(LV2_Handle instance, uint32_t port, void* data) static void ingen_activate(LV2_Handle instance) { - IngenPlugin* me = (IngenPlugin*)instance; - SPtr<server::Engine> engine = static_ptr_cast<server::Engine>(me->world->engine()); - const SPtr<LV2Driver>& driver = static_ptr_cast<LV2Driver>(engine->driver()); + auto* me = static_cast<IngenPlugin*>(instance); + auto engine = std::static_pointer_cast<Engine>(me->world->engine()); + const auto driver = std::static_pointer_cast<LV2Driver>(engine->driver()); engine->activate(); - me->main = make_unique<std::thread>(ingen_lv2_main, engine, driver); + me->main = std::make_unique<std::thread>(ingen_lv2_main, engine, driver); } static void ingen_run(LV2_Handle instance, uint32_t sample_count) { - IngenPlugin* me = (IngenPlugin*)instance; - SPtr<server::Engine> engine = static_ptr_cast<server::Engine>(me->world->engine()); - const SPtr<LV2Driver>& driver = static_ptr_cast<LV2Driver>(engine->driver()); + auto* me = static_cast<IngenPlugin*>(instance); + auto engine = std::static_pointer_cast<Engine>(me->world->engine()); + const auto driver = std::static_pointer_cast<LV2Driver>(engine->driver()); - server::ThreadManager::set_flag(ingen::server::THREAD_PROCESS); - server::ThreadManager::set_flag(ingen::server::THREAD_IS_REAL_TIME); + ThreadManager::set_flag(THREAD_PROCESS); + ThreadManager::set_flag(THREAD_IS_REAL_TIME); driver->run(sample_count); } @@ -654,7 +658,7 @@ ingen_run(LV2_Handle instance, uint32_t sample_count) static void ingen_deactivate(LV2_Handle instance) { - IngenPlugin* me = (IngenPlugin*)instance; + auto* me = static_cast<IngenPlugin*>(instance); me->world->engine()->deactivate(); if (me->main) { me->main->join(); @@ -665,9 +669,9 @@ ingen_deactivate(LV2_Handle instance) static void ingen_cleanup(LV2_Handle instance) { - IngenPlugin* me = (IngenPlugin*)instance; - me->world->set_engine(SPtr<ingen::server::Engine>()); - me->world->set_interface(SPtr<ingen::Interface>()); + auto* me = static_cast<IngenPlugin*>(instance); + me->world->set_engine(nullptr); + me->world->set_interface(nullptr); if (me->main) { me->main->join(); me->main.reset(); @@ -675,6 +679,7 @@ ingen_cleanup(LV2_Handle instance) auto world = std::move(me->world); delete me; + world.reset(); } static void @@ -684,9 +689,9 @@ get_state_features(const LV2_Feature* const* features, { for (int i = 0; features[i]; ++i) { if (map && !strcmp(features[i]->URI, LV2_STATE__mapPath)) { - *map = (LV2_State_Map_Path*)features[i]->data; + *map = static_cast<LV2_State_Map_Path*>(features[i]->data); } else if (make && !strcmp(features[i]->URI, LV2_STATE__makePath)) { - *make = (LV2_State_Make_Path*)features[i]->data; + *make = static_cast<LV2_State_Make_Path*>(features[i]->data); } } } @@ -698,7 +703,7 @@ ingen_save(LV2_Handle instance, uint32_t flags, const LV2_Feature* const* features) { - IngenPlugin* plugin = (IngenPlugin*)instance; + auto* plugin = static_cast<IngenPlugin*>(instance); LV2_State_Map_Path* map_path = nullptr; LV2_State_Make_Path* make_path = nullptr; @@ -708,17 +713,17 @@ ingen_save(LV2_Handle instance, return LV2_STATE_ERR_NO_FEATURE; } - LV2_URID ingen_file = plugin->map->map(plugin->map->handle, INGEN__file); - LV2_URID atom_Path = plugin->map->map(plugin->map->handle, - LV2_ATOM__Path); + const LV2_URID ingen_file = plugin->map->map(plugin->map->handle, INGEN__file); + const LV2_URID atom_Path = plugin->map->map(plugin->map->handle, + LV2_ATOM__Path); char* real_path = make_path->path(make_path->handle, "main.ttl"); char* state_path = map_path->abstract_path(map_path->handle, real_path); - auto root = plugin->world->store()->find(Raul::Path("/")); + auto root = plugin->world->store()->find(raul::Path("/")); { - std::lock_guard<std::mutex> lock(plugin->world->rdf_mutex()); + const std::lock_guard<std::mutex> lock{plugin->world->rdf_mutex()}; plugin->world->serialiser()->start_to_file( root->second->path(), FilePath{real_path}); @@ -745,7 +750,7 @@ ingen_restore(LV2_Handle instance, uint32_t flags, const LV2_Feature* const* features) { - IngenPlugin* plugin = (IngenPlugin*)instance; + auto* plugin = static_cast<IngenPlugin*>(instance); LV2_State_Map_Path* map_path = nullptr; get_state_features(features, &map_path, nullptr); @@ -754,14 +759,14 @@ ingen_restore(LV2_Handle instance, return LV2_STATE_ERR_NO_FEATURE; } - LV2_URID ingen_file = plugin->map->map(plugin->map->handle, INGEN__file); - size_t size; - uint32_t type; - uint32_t valflags; + const LV2_URID ingen_file = plugin->map->map(plugin->map->handle, INGEN__file); + size_t size = 0; + uint32_t type = 0; + uint32_t valflags = 0; // Get abstract path to graph file - const char* path = (const char*)retrieve( - handle, ingen_file, &size, &type, &valflags); + const char* path = static_cast<const char*>( + retrieve(handle, ingen_file, &size, &type, &valflags)); if (!path) { return LV2_STATE_ERR_NO_PROPERTY; } @@ -772,9 +777,9 @@ ingen_restore(LV2_Handle instance, return LV2_STATE_ERR_UNKNOWN; } -#if 0 +#ifdef CLEAR_GRAPH_ON_RESTORE // Remove existing root graph contents - SPtr<Engine> engine = plugin->engine; + std::shared_ptr<Engine> engine = plugin->engine; for (const auto& b : engine->root_graph()->blocks()) { plugin->world->interface()->del(b.uri()); } @@ -789,7 +794,7 @@ ingen_restore(LV2_Handle instance, #endif // Load new graph - std::lock_guard<std::mutex> lock(plugin->world->rdf_mutex()); + const std::lock_guard<std::mutex> lock{plugin->world->rdf_mutex()}; plugin->world->parser()->parse_file( *plugin->world, *plugin->world->interface(), real_path); @@ -809,6 +814,7 @@ ingen_extension_data(const char* uri) LV2Graph::LV2Graph(Parser::ResourceRecord record) : Parser::ResourceRecord(std::move(record)) + , descriptor() { descriptor.URI = uri.c_str(); descriptor.instantiate = ingen_instantiate; @@ -824,10 +830,14 @@ Lib::Lib(const char* bundle_path) { ingen::set_bundle_path(bundle_path); const std::string manifest_path = ingen::bundle_file_path("manifest.ttl"); - SerdNode manifest_node = serd_node_new_file_uri( - (const uint8_t*)manifest_path.c_str(), nullptr, nullptr, true); + SerdNode manifest_node = + serd_node_new_file_uri(reinterpret_cast<const uint8_t*>( + manifest_path.c_str()), + nullptr, + nullptr, + true); - graphs = find_graphs(URI((const char*)manifest_node.buf)); + graphs = find_graphs(URI(reinterpret_cast<const char*>(manifest_node.buf))); serd_node_free(&manifest_node); } @@ -835,17 +845,23 @@ Lib::Lib(const char* bundle_path) static void lib_cleanup(LV2_Lib_Handle handle) { - Lib* lib = (Lib*)handle; + Lib* lib = static_cast<Lib*>(handle); delete lib; } static const LV2_Descriptor* lib_get_plugin(LV2_Lib_Handle handle, uint32_t index) { - Lib* lib = (Lib*)handle; + Lib* lib = static_cast<Lib*>(handle); return index < lib->graphs.size() ? &lib->graphs[index]->descriptor : nullptr; } +} // extern "C" + +} // namespace ingen::server + +extern "C" { + /** LV2 plugin library entry point */ LV2_SYMBOL_EXPORT const LV2_Lib_Descriptor* @@ -853,16 +869,16 @@ lv2_lib_descriptor(const char* bundle_path, const LV2_Feature*const* features) { static const uint32_t desc_size = sizeof(LV2_Lib_Descriptor); - Lib* lib = new Lib(bundle_path); + auto* lib = new ingen::server::Lib(bundle_path); // FIXME: memory leak. I think the LV2_Lib_Descriptor API is botched :( - LV2_Lib_Descriptor* desc = (LV2_Lib_Descriptor*)malloc(desc_size); + auto* desc = static_cast<LV2_Lib_Descriptor*>(malloc(desc_size)); desc->handle = lib; desc->size = desc_size; - desc->cleanup = lib_cleanup; - desc->get_plugin = lib_get_plugin; + desc->cleanup = ingen::server::lib_cleanup; + desc->get_plugin = ingen::server::lib_get_plugin; return desc; } -} // extern "C" +} diff --git a/src/server/ingen_portaudio.cpp b/src/server/ingen_portaudio.cpp index f4e633d0..68b1b0bc 100644 --- a/src/server/ingen_portaudio.cpp +++ b/src/server/ingen_portaudio.cpp @@ -14,39 +14,43 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "PortAudioDriver.hpp" #include "Engine.hpp" +#include "PortAudioDriver.hpp" + +#include <ingen/Log.hpp> +#include <ingen/Module.hpp> +#include <ingen/World.hpp> -#include "ingen/Log.hpp" -#include "ingen/Module.hpp" -#include "ingen/World.hpp" -#include "ingen/types.hpp" +#include <memory> -namespace ingen { namespace server { class Driver; } } +namespace ingen::server { -using namespace ingen; +class Driver; -struct IngenPortAudioModule : public ingen::Module { - void load(ingen::World& world) override { - if (((server::Engine*)world.engine().get())->driver()) { +struct PortAudioModule : public Module { + void load(World& world) override { + server::Engine* const engine = + static_cast<server::Engine*>(world.engine().get()); + + if (engine->driver()) { world.log().warn("Engine already has a driver\n"); return; } - server::PortAudioDriver* driver = new server::PortAudioDriver( - *(server::Engine*)world.engine().get()); + auto* driver = new server::PortAudioDriver(*engine); driver->attach(); - ((server::Engine*)world.engine().get())->set_driver( - SPtr<server::Driver>(driver)); + engine->set_driver(std::shared_ptr<server::Driver>(driver)); } }; +} // namespace ingen::server + extern "C" { -ingen::Module* +INGEN_MODULE_EXPORT ingen::Module* ingen_module_load() { - return new IngenPortAudioModule(); + return new ingen::server::PortAudioModule(); } } // extern "C" diff --git a/src/server/internals/BlockDelay.cpp b/src/server/internals/BlockDelay.cpp index 0176c9b1..acc68851 100644 --- a/src/server/internals/BlockDelay.cpp +++ b/src/server/internals/BlockDelay.cpp @@ -14,33 +14,35 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "internals/BlockDelay.hpp" +#include "BlockDelay.hpp" +#include "BlockImpl.hpp" #include "Buffer.hpp" +#include "BufferFactory.hpp" #include "InputPort.hpp" #include "InternalPlugin.hpp" #include "OutputPort.hpp" +#include "PortType.hpp" -#include "ingen/Forge.hpp" -#include "ingen/URIs.hpp" -#include "raul/Array.hpp" -#include "raul/Maid.hpp" +#include <ingen/Forge.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIs.hpp> +#include <raul/Array.hpp> +#include <raul/Maid.hpp> +#include <raul/Symbol.hpp> -namespace ingen { -namespace server { +#include <memory> -class RunContext; - -namespace internals { +namespace ingen::server::internals { InternalPlugin* BlockDelayNode::internal_plugin(URIs& uris) { return new InternalPlugin( - uris, URI(NS_INTERNALS "BlockDelay"), Raul::Symbol("blockDelay")); + uris, URI(NS_INTERNALS "BlockDelay"), raul::Symbol("blockDelay")); } BlockDelayNode::BlockDelayNode(InternalPlugin* plugin, BufferFactory& bufs, - const Raul::Symbol& symbol, + const raul::Symbol& symbol, bool polyphonic, GraphImpl* parent, SampleRate srate) @@ -49,12 +51,12 @@ BlockDelayNode::BlockDelayNode(InternalPlugin* plugin, const ingen::URIs& uris = bufs.uris(); _ports = bufs.maid().make_managed<Ports>(2); - _in_port = new InputPort(bufs, this, Raul::Symbol("in"), 0, 1, + _in_port = new InputPort(bufs, this, raul::Symbol("in"), 0, 1, PortType::AUDIO, 0, bufs.forge().make(0.0f)); _in_port->set_property(uris.lv2_name, bufs.forge().alloc("In")); _ports->at(0) = _in_port; - _out_port = new OutputPort(bufs, this, Raul::Symbol("out"), 0, 1, + _out_port = new OutputPort(bufs, this, raul::Symbol("out"), 0, 1, PortType::AUDIO, 0, bufs.forge().make(0.0f)); _out_port->set_property(uris.lv2_name, bufs.forge().alloc("Out")); _ports->at(1) = _out_port; @@ -75,15 +77,13 @@ BlockDelayNode::activate(BufferFactory& bufs) } void -BlockDelayNode::run(RunContext& context) +BlockDelayNode::run(RunContext& ctx) { // Copy buffer from last cycle to output - _out_port->buffer(0)->copy(context, _buffer.get()); + _out_port->buffer(0)->copy(ctx, _buffer.get()); // Copy input from this cycle to buffer - _buffer->copy(context, _in_port->buffer(0).get()); + _buffer->copy(ctx, _in_port->buffer(0).get()); } -} // namespace internals -} // namespace server -} // namespace ingen +} // namespace ingen::server::internals diff --git a/src/server/internals/BlockDelay.hpp b/src/server/internals/BlockDelay.hpp index 0e8fadce..a9667fa0 100644 --- a/src/server/internals/BlockDelay.hpp +++ b/src/server/internals/BlockDelay.hpp @@ -21,13 +21,21 @@ #include "InternalBlock.hpp" #include "types.hpp" +namespace raul { +class Symbol; +} // namespace raul + namespace ingen { + +class URIs; + namespace server { +class BufferFactory; +class GraphImpl; class InputPort; -class OutputPort; class InternalPlugin; -class BufferFactory; +class OutputPort; namespace internals { @@ -36,16 +44,16 @@ class BlockDelayNode : public InternalBlock public: BlockDelayNode(InternalPlugin* plugin, BufferFactory& bufs, - const Raul::Symbol& symbol, + const raul::Symbol& symbol, bool polyphonic, GraphImpl* parent, SampleRate srate); - ~BlockDelayNode(); + ~BlockDelayNode() override; void activate(BufferFactory& bufs) override; - void run(RunContext& context) override; + void run(RunContext& ctx) override; static InternalPlugin* internal_plugin(URIs& uris); @@ -55,8 +63,8 @@ private: BufferRef _buffer; }; +} // namespace internals } // namespace server } // namespace ingen -} // namespace internals #endif // INGEN_INTERNALS_BLOCKDELAY_HPP diff --git a/src/server/internals/Controller.cpp b/src/server/internals/Controller.cpp index b8738e1e..9103649e 100644 --- a/src/server/internals/Controller.cpp +++ b/src/server/internals/Controller.cpp @@ -14,42 +14,51 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ +#include "Controller.hpp" + #include "Buffer.hpp" -#include "Engine.hpp" +#include "BufferFactory.hpp" +#include "BufferRef.hpp" #include "InputPort.hpp" #include "InternalPlugin.hpp" #include "OutputPort.hpp" -#include "PostProcessor.hpp" +#include "PortType.hpp" #include "RunContext.hpp" -#include "util.hpp" -#include "ingen/Forge.hpp" -#include "ingen/URIs.hpp" -#include "internals/Controller.hpp" -#include "lv2/atom/util.h" -#include "lv2/midi/midi.h" +#include <ingen/Atom.hpp> +#include <ingen/Forge.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIs.hpp> +#include <lv2/atom/atom.h> +#include <lv2/atom/util.h> +#include <lv2/midi/midi.h> +#include <raul/Array.hpp> +#include <raul/Maid.hpp> +#include <raul/Symbol.hpp> #include <cassert> #include <cmath> #include <initializer_list> +#include <memory> + +namespace ingen::server { + +class GraphImpl; -namespace ingen { -namespace server { namespace internals { InternalPlugin* ControllerNode::internal_plugin(URIs& uris) { return new InternalPlugin( - uris, URI(NS_INTERNALS "Controller"), Raul::Symbol("controller")); + uris, URI(NS_INTERNALS "Controller"), raul::Symbol("controller")); } ControllerNode::ControllerNode(InternalPlugin* plugin, BufferFactory& bufs, - const Raul::Symbol& symbol, + const raul::Symbol& symbol, bool polyphonic, GraphImpl* parent, SampleRate srate) : InternalBlock(plugin, symbol, false, parent, srate) - , _learning(false) { const ingen::URIs& uris = bufs.uris(); _ports = bufs.maid().make_managed<Ports>(7); @@ -58,21 +67,21 @@ ControllerNode::ControllerNode(InternalPlugin* plugin, const Atom one = bufs.forge().make(1.0f); const Atom atom_Float = bufs.forge().make_urid(URI(LV2_ATOM__Float)); - _midi_in_port = new InputPort(bufs, this, Raul::Symbol("input"), 0, 1, + _midi_in_port = new InputPort(bufs, this, raul::Symbol("input"), 0, 1, PortType::ATOM, uris.atom_Sequence, Atom()); _midi_in_port->set_property(uris.lv2_name, bufs.forge().alloc("Input")); _midi_in_port->set_property(uris.atom_supports, bufs.forge().make_urid(uris.midi_MidiEvent)); _ports->at(0) = _midi_in_port; - _midi_out_port = new OutputPort(bufs, this, Raul::Symbol("event"), 1, 1, + _midi_out_port = new OutputPort(bufs, this, raul::Symbol("event"), 1, 1, PortType::ATOM, uris.atom_Sequence, Atom()); _midi_out_port->set_property(uris.lv2_name, bufs.forge().alloc("Event")); _midi_out_port->set_property(uris.atom_supports, bufs.forge().make_urid(uris.midi_MidiEvent)); _ports->at(1) = _midi_out_port; - _param_port = new InputPort(bufs, this, Raul::Symbol("controller"), 2, 1, + _param_port = new InputPort(bufs, this, raul::Symbol("controller"), 2, 1, PortType::ATOM, uris.atom_Sequence, zero); _param_port->set_property(uris.atom_supports, atom_Float); _param_port->set_property(uris.lv2_minimum, zero); @@ -81,26 +90,26 @@ ControllerNode::ControllerNode(InternalPlugin* plugin, _param_port->set_property(uris.lv2_name, bufs.forge().alloc("Controller")); _ports->at(2) = _param_port; - _log_port = new InputPort(bufs, this, Raul::Symbol("logarithmic"), 3, 1, + _log_port = new InputPort(bufs, this, raul::Symbol("logarithmic"), 3, 1, PortType::ATOM, uris.atom_Sequence, zero); _log_port->set_property(uris.atom_supports, atom_Float); _log_port->set_property(uris.lv2_portProperty, uris.lv2_toggled); _log_port->set_property(uris.lv2_name, bufs.forge().alloc("Logarithmic")); _ports->at(3) = _log_port; - _min_port = new InputPort(bufs, this, Raul::Symbol("minimum"), 4, 1, + _min_port = new InputPort(bufs, this, raul::Symbol("minimum"), 4, 1, PortType::ATOM, uris.atom_Sequence, zero); _min_port->set_property(uris.atom_supports, atom_Float); _min_port->set_property(uris.lv2_name, bufs.forge().alloc("Minimum")); _ports->at(4) = _min_port; - _max_port = new InputPort(bufs, this, Raul::Symbol("maximum"), 5, 1, + _max_port = new InputPort(bufs, this, raul::Symbol("maximum"), 5, 1, PortType::ATOM, uris.atom_Sequence, one); _max_port->set_property(uris.atom_supports, atom_Float); _max_port->set_property(uris.lv2_name, bufs.forge().alloc("Maximum")); _ports->at(5) = _max_port; - _audio_port = new OutputPort(bufs, this, Raul::Symbol("output"), 6, 1, + _audio_port = new OutputPort(bufs, this, raul::Symbol("output"), 6, 1, PortType::ATOM, uris.atom_Sequence, zero); _audio_port->set_property(uris.atom_supports, atom_Float); _audio_port->set_property(uris.lv2_name, bufs.forge().alloc("Output")); @@ -108,17 +117,18 @@ ControllerNode::ControllerNode(InternalPlugin* plugin, } void -ControllerNode::run(RunContext& context) +ControllerNode::run(RunContext& ctx) { - const BufferRef midi_in = _midi_in_port->buffer(0); - LV2_Atom_Sequence* seq = midi_in->get<LV2_Atom_Sequence>(); - const BufferRef midi_out = _midi_out_port->buffer(0); - LV2_ATOM_SEQUENCE_FOREACH(seq, ev) { - const uint8_t* buf = (const uint8_t*)LV2_ATOM_BODY(&ev->body); + const BufferRef midi_in = _midi_in_port->buffer(0); + auto* seq = midi_in->get<LV2_Atom_Sequence>(); + const BufferRef midi_out = _midi_out_port->buffer(0); + + LV2_ATOM_SEQUENCE_FOREACH (seq, ev) { + const auto* buf = static_cast<const uint8_t*>(LV2_ATOM_BODY_CONST(&ev->body)); if (ev->body.type == _midi_in_port->bufs().uris().midi_MidiEvent && ev->body.size >= 3 && lv2_midi_message_type(buf) == LV2_MIDI_MSG_CONTROLLER) { - if (control(context, buf[1], buf[2], ev->time.frames + context.start())) { + if (control(ctx, buf[1], buf[2], ev->time.frames + ctx.start())) { midi_out->append_event(ev->time.frames, &ev->body); } } @@ -126,15 +136,15 @@ ControllerNode::run(RunContext& context) } bool -ControllerNode::control(RunContext& context, uint8_t control_num, uint8_t val, FrameTime time) +ControllerNode::control(RunContext& ctx, uint8_t control_num, uint8_t val, FrameTime time) { - assert(time >= context.start() && time <= context.end()); - const uint32_t offset = time - context.start(); + assert(time >= ctx.start() && time <= ctx.end()); + const uint32_t offset = time - ctx.start(); const Sample nval = (val / 127.0f); // normalized [0, 1] if (_learning) { - _param_port->set_control_value(context, time, control_num); + _param_port->set_control_value(ctx, time, control_num); _param_port->force_monitor_update(); _learning = false; } else { @@ -153,25 +163,24 @@ ControllerNode::control(RunContext& context, uint8_t control_num, uint8_t val, F const Sample max_port_val = _max_port->buffer(0)->value_at(offset); const Sample log_port_val = _log_port->buffer(0)->value_at(offset); - Sample scaled_value; + Sample scaled_value = 0.0f; if (log_port_val > 0.0f) { // haaaaack, stupid negatives and logarithms - Sample log_offset = 0; + Sample log_offset = 0.0f; if (min_port_val < 0) { - log_offset = fabs(min_port_val); + log_offset = fabsf(min_port_val); } - const Sample min = log(min_port_val + 1 + log_offset); - const Sample max = log(max_port_val + 1 + log_offset); - scaled_value = expf(nval * (max - min) + min) - 1 - log_offset; + const Sample min = logf(min_port_val + 1 + log_offset); + const Sample max = logf(max_port_val + 1 + log_offset); + scaled_value = expf((nval * (max - min)) + min) - 1 - log_offset; } else { scaled_value = ((nval) * (max_port_val - min_port_val)) + min_port_val; } - _audio_port->set_control_value(context, time, scaled_value); + _audio_port->set_control_value(ctx, time, scaled_value); return true; } } // namespace internals -} // namespace server -} // namespace ingen +} // namespace ingen::server diff --git a/src/server/internals/Controller.hpp b/src/server/internals/Controller.hpp index 0a62b235..2a0bc834 100644 --- a/src/server/internals/Controller.hpp +++ b/src/server/internals/Controller.hpp @@ -18,15 +18,26 @@ #define INGEN_INTERNALS_CONTROLLER_HPP #include "InternalBlock.hpp" +#include "types.hpp" #include <cstdint> +namespace raul { +class Symbol; +} // namespace raul + namespace ingen { + +class URIs; + namespace server { +class BufferFactory; +class GraphImpl; class InputPort; -class OutputPort; class InternalPlugin; +class OutputPort; +class RunContext; namespace internals { @@ -42,14 +53,14 @@ class ControllerNode : public InternalBlock public: ControllerNode(InternalPlugin* plugin, BufferFactory& bufs, - const Raul::Symbol& symbol, + const raul::Symbol& symbol, bool polyphonic, GraphImpl* parent, SampleRate srate); - void run(RunContext& context) override; + void run(RunContext& ctx) override; - bool control(RunContext& context, uint8_t control_num, uint8_t val, FrameTime time); + bool control(RunContext& ctx, uint8_t control_num, uint8_t val, FrameTime time); void learn() override { _learning = true; } @@ -63,11 +74,11 @@ private: InputPort* _min_port; InputPort* _max_port; OutputPort* _audio_port; - bool _learning; + bool _learning{false}; }; +} // namespace internals } // namespace server } // namespace ingen -} // namespace internals #endif // INGEN_INTERNALS_CONTROLLER_HPP diff --git a/src/server/internals/Note.cpp b/src/server/internals/Note.cpp index cfc0c157..960bca85 100644 --- a/src/server/internals/Note.cpp +++ b/src/server/internals/Note.cpp @@ -14,45 +14,54 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "internals/Note.hpp" +#include "Note.hpp" +#include "BlockImpl.hpp" #include "Buffer.hpp" +#include "BufferFactory.hpp" #include "InputPort.hpp" #include "InternalPlugin.hpp" #include "OutputPort.hpp" +#include "PortType.hpp" #include "RunContext.hpp" -#include "ingen/Forge.hpp" -#include "ingen/URIs.hpp" -#include "lv2/atom/util.h" -#include "lv2/midi/midi.h" -#include "raul/Array.hpp" -#include "raul/Maid.hpp" +#include <ingen/Atom.hpp> +#include <ingen/Forge.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIs.hpp> +#include <lv2/atom/atom.h> +#include <lv2/atom/util.h> +#include <lv2/midi/midi.h> +#include <raul/Array.hpp> +#include <raul/Maid.hpp> +#include <raul/Symbol.hpp> #include <cassert> #include <cmath> +#include <memory> #include <utility> // #define NOTE_DEBUG 1 -namespace ingen { -namespace server { +namespace ingen::server { + +class GraphImpl; + namespace internals { InternalPlugin* NoteNode::internal_plugin(URIs& uris) { return new InternalPlugin( - uris, URI(NS_INTERNALS "Note"), Raul::Symbol("note")); + uris, URI(NS_INTERNALS "Note"), raul::Symbol("note")); } NoteNode::NoteNode(InternalPlugin* plugin, BufferFactory& bufs, - const Raul::Symbol& symbol, + const raul::Symbol& symbol, bool polyphonic, GraphImpl* parent, SampleRate srate) : InternalBlock(plugin, symbol, polyphonic, parent, srate) , _voices(bufs.maid().make_managed<Voices>(_polyphony)) - , _sustain(false) { const ingen::URIs& uris = bufs.uris(); _ports = bufs.maid().make_managed<Ports>(8); @@ -60,14 +69,14 @@ NoteNode::NoteNode(InternalPlugin* plugin, const Atom zero = bufs.forge().make(0.0f); const Atom one = bufs.forge().make(1.0f); - _midi_in_port = new InputPort(bufs, this, Raul::Symbol("input"), 0, 1, + _midi_in_port = new InputPort(bufs, this, raul::Symbol("input"), 0, 1, PortType::ATOM, uris.atom_Sequence, Atom()); _midi_in_port->set_property(uris.lv2_name, bufs.forge().alloc("Input")); _midi_in_port->set_property(uris.atom_supports, bufs.forge().make_urid(uris.midi_MidiEvent)); _ports->at(0) = _midi_in_port; - _freq_port = new OutputPort(bufs, this, Raul::Symbol("frequency"), 1, _polyphony, + _freq_port = new OutputPort(bufs, this, raul::Symbol("frequency"), 1, _polyphony, PortType::ATOM, uris.atom_Sequence, bufs.forge().make(440.0f)); _freq_port->set_property(uris.atom_supports, bufs.uris().atom_Float); @@ -76,7 +85,7 @@ NoteNode::NoteNode(InternalPlugin* plugin, _freq_port->set_property(uris.lv2_maximum, bufs.forge().make(25088.0f)); _ports->at(1) = _freq_port; - _num_port = new OutputPort(bufs, this, Raul::Symbol("number"), 1, _polyphony, + _num_port = new OutputPort(bufs, this, raul::Symbol("number"), 1, _polyphony, PortType::ATOM, uris.atom_Sequence, zero); _num_port->set_property(uris.atom_supports, bufs.uris().atom_Float); _num_port->set_property(uris.lv2_minimum, zero); @@ -85,7 +94,7 @@ NoteNode::NoteNode(InternalPlugin* plugin, _num_port->set_property(uris.lv2_name, bufs.forge().alloc("Number")); _ports->at(2) = _num_port; - _vel_port = new OutputPort(bufs, this, Raul::Symbol("velocity"), 2, _polyphony, + _vel_port = new OutputPort(bufs, this, raul::Symbol("velocity"), 2, _polyphony, PortType::ATOM, uris.atom_Sequence, zero); _vel_port->set_property(uris.atom_supports, bufs.uris().atom_Float); _vel_port->set_property(uris.lv2_minimum, zero); @@ -93,21 +102,21 @@ NoteNode::NoteNode(InternalPlugin* plugin, _vel_port->set_property(uris.lv2_name, bufs.forge().alloc("Velocity")); _ports->at(3) = _vel_port; - _gate_port = new OutputPort(bufs, this, Raul::Symbol("gate"), 3, _polyphony, + _gate_port = new OutputPort(bufs, this, raul::Symbol("gate"), 3, _polyphony, PortType::ATOM, uris.atom_Sequence, zero); _gate_port->set_property(uris.atom_supports, bufs.uris().atom_Float); _gate_port->set_property(uris.lv2_portProperty, uris.lv2_toggled); _gate_port->set_property(uris.lv2_name, bufs.forge().alloc("Gate")); _ports->at(4) = _gate_port; - _trig_port = new OutputPort(bufs, this, Raul::Symbol("trigger"), 4, _polyphony, + _trig_port = new OutputPort(bufs, this, raul::Symbol("trigger"), 4, _polyphony, PortType::ATOM, uris.atom_Sequence, zero); _trig_port->set_property(uris.atom_supports, bufs.uris().atom_Float); _trig_port->set_property(uris.lv2_portProperty, uris.lv2_toggled); _trig_port->set_property(uris.lv2_name, bufs.forge().alloc("Trigger")); _ports->at(5) = _trig_port; - _bend_port = new OutputPort(bufs, this, Raul::Symbol("bend"), 5, _polyphony, + _bend_port = new OutputPort(bufs, this, raul::Symbol("bend"), 5, _polyphony, PortType::ATOM, uris.atom_Sequence, zero); _bend_port->set_property(uris.atom_supports, bufs.uris().atom_Float); _bend_port->set_property(uris.lv2_name, bufs.forge().alloc("Bender")); @@ -116,7 +125,7 @@ NoteNode::NoteNode(InternalPlugin* plugin, _bend_port->set_property(uris.lv2_maximum, one); _ports->at(6) = _bend_port; - _pressure_port = new OutputPort(bufs, this, Raul::Symbol("pressure"), 6, _polyphony, + _pressure_port = new OutputPort(bufs, this, raul::Symbol("pressure"), 6, _polyphony, PortType::ATOM, uris.atom_Sequence, zero); _pressure_port->set_property(uris.atom_supports, bufs.uris().atom_Float); _pressure_port->set_property(uris.lv2_name, bufs.forge().alloc("Pressure")); @@ -146,9 +155,9 @@ NoteNode::prepare_poly(BufferFactory& bufs, uint32_t poly) } bool -NoteNode::apply_poly(RunContext& context, uint32_t poly) +NoteNode::apply_poly(RunContext& ctx, uint32_t poly) { - if (!BlockImpl::apply_poly(context, poly)) { + if (!BlockImpl::apply_poly(ctx, poly)) { return false; } @@ -162,50 +171,58 @@ NoteNode::apply_poly(RunContext& context, uint32_t poly) } void -NoteNode::run(RunContext& context) +NoteNode::run(RunContext& ctx) { - Buffer* const midi_in = _midi_in_port->buffer(0).get(); - LV2_Atom_Sequence* seq = midi_in->get<LV2_Atom_Sequence>(); - LV2_ATOM_SEQUENCE_FOREACH(seq, ev) { - const uint8_t* buf = (const uint8_t*)LV2_ATOM_BODY_CONST(&ev->body); - const FrameTime time = context.start() + (FrameTime)ev->time.frames; + Buffer* const midi_in = _midi_in_port->buffer(0).get(); + auto* seq = midi_in->get<LV2_Atom_Sequence>(); + + LV2_ATOM_SEQUENCE_FOREACH (seq, ev) { + const auto* buf = + static_cast<const uint8_t*>(LV2_ATOM_BODY_CONST(&ev->body)); + + const FrameTime time = + ctx.start() + static_cast<FrameTime>(ev->time.frames); + if (ev->body.type == _midi_in_port->bufs().uris().midi_MidiEvent && ev->body.size >= 3) { switch (lv2_midi_message_type(buf)) { case LV2_MIDI_MSG_NOTE_ON: if (buf[2] == 0) { - note_off(context, buf[1], time); + note_off(ctx, buf[1], time); } else { - note_on(context, buf[1], buf[2], time); + note_on(ctx, buf[1], buf[2], time); } break; case LV2_MIDI_MSG_NOTE_OFF: - note_off(context, buf[1], time); + note_off(ctx, buf[1], time); break; case LV2_MIDI_MSG_CONTROLLER: switch (buf[1]) { case LV2_MIDI_CTL_ALL_NOTES_OFF: case LV2_MIDI_CTL_ALL_SOUNDS_OFF: - all_notes_off(context, time); + all_notes_off(ctx, time); break; case LV2_MIDI_CTL_SUSTAIN: if (buf[2] > 63) { - sustain_on(context, time); + sustain_on(ctx, time); } else { - sustain_off(context, time); + sustain_off(ctx, time); } break; } break; case LV2_MIDI_MSG_BENDER: - bend(context, time, (((((uint16_t)buf[2] << 7) | buf[1]) - 8192.0f) - / 8192.0f)); + bend(ctx, + time, + ((((static_cast<uint16_t>(buf[2]) << 7) | buf[1]) - + 8192.0f) / + 8192.0f)); break; case LV2_MIDI_MSG_CHANNEL_PRESSURE: - channel_pressure(context, time, buf[1] / 127.0f); + channel_pressure(ctx, time, buf[1] / 127.0f); break; case LV2_MIDI_MSG_NOTE_PRESSURE: - note_pressure(context, time, buf[1], buf[2] / 127.0f); + note_pressure(ctx, time, buf[1], buf[2] / 127.0f); break; default: break; @@ -218,13 +235,13 @@ static inline float note_to_freq(uint8_t num) { static const float A4 = 440.0f; - return A4 * powf(2.0f, (float)(num - 57.0f) / 12.0f); + return A4 * powf(2.0f, static_cast<float>(num - 57.0f) / 12.0f); } void -NoteNode::note_on(RunContext& context, uint8_t note_num, uint8_t velocity, FrameTime time) +NoteNode::note_on(RunContext& ctx, uint8_t note_num, uint8_t velocity, FrameTime time) { - assert(time >= context.start() && time <= context.end()); + assert(time >= ctx.start() && time <= ctx.end()); assert(note_num <= 127); Key* key = &_keys[note_num]; @@ -285,13 +302,13 @@ NoteNode::note_on(RunContext& context, uint8_t note_num, uint8_t velocity, Frame assert(_keys[voice->note].state == Key::State::ON_ASSIGNED); assert(_keys[voice->note].voice == voice_num); - _freq_port->set_voice_value(context, voice_num, time, note_to_freq(note_num)); - _num_port->set_voice_value(context, voice_num, time, (float)note_num); - _vel_port->set_voice_value(context, voice_num, time, velocity / 127.0f); - _gate_port->set_voice_value(context, voice_num, time, 1.0f); + _freq_port->set_voice_value(ctx, voice_num, time, note_to_freq(note_num)); + _num_port->set_voice_value(ctx, voice_num, time, static_cast<float>(note_num)); + _vel_port->set_voice_value(ctx, voice_num, time, velocity / 127.0f); + _gate_port->set_voice_value(ctx, voice_num, time, 1.0f); if (!double_trigger) { - _trig_port->set_voice_value(context, voice_num, time, 1.0f); - _trig_port->set_voice_value(context, voice_num, time + 1, 0.0f); + _trig_port->set_voice_value(ctx, voice_num, time, 1.0f); + _trig_port->set_voice_value(ctx, voice_num, time + 1, 0.0f); } assert(key->state == Key::State::ON_ASSIGNED); @@ -301,9 +318,9 @@ NoteNode::note_on(RunContext& context, uint8_t note_num, uint8_t velocity, Frame } void -NoteNode::note_off(RunContext& context, uint8_t note_num, FrameTime time) +NoteNode::note_off(RunContext& ctx, uint8_t note_num, FrameTime time) { - assert(time >= context.start() && time <= context.end()); + assert(time >= ctx.start() && time <= ctx.end()); Key* key = &_keys[note_num]; @@ -312,7 +329,7 @@ NoteNode::note_off(RunContext& context, uint8_t note_num, FrameTime time) if ((*_voices)[key->voice].state == Voice::State::ACTIVE) { assert((*_voices)[key->voice].note == note_num); if ( ! _sustain) { - free_voice(context, key->voice, time); + free_voice(ctx, key->voice, time); } else { (*_voices)[key->voice].state = Voice::State::HOLDING; } @@ -323,9 +340,9 @@ NoteNode::note_off(RunContext& context, uint8_t note_num, FrameTime time) } void -NoteNode::free_voice(RunContext& context, uint32_t voice, FrameTime time) +NoteNode::free_voice(RunContext& ctx, uint32_t voice, FrameTime time) { - assert(time >= context.start() && time <= context.end()); + assert(time >= ctx.start() && time <= ctx.end()); // Find a key to reassign to the freed voice (the newest, if there is one) Key* replace_key = nullptr; @@ -340,13 +357,13 @@ NoteNode::free_voice(RunContext& context, uint32_t voice, FrameTime time) } } - if (replace_key != nullptr) { // Found a key to assign to freed voice + if (replace_key != nullptr) { // Found a key to assign to freed voice assert(&_keys[replace_key_num] == replace_key); assert(replace_key->state == Key::State::ON_UNASSIGNED); // Change the freq but leave the gate high and don't retrigger - _freq_port->set_voice_value(context, voice, time, note_to_freq(replace_key_num)); - _num_port->set_voice_value(context, voice, time, replace_key_num); + _freq_port->set_voice_value(ctx, voice, time, note_to_freq(replace_key_num)); + _num_port->set_voice_value(ctx, voice, time, replace_key_num); replace_key->state = Key::State::ON_ASSIGNED; replace_key->voice = voice; @@ -355,67 +372,66 @@ NoteNode::free_voice(RunContext& context, uint32_t voice, FrameTime time) (*_voices)[voice].state = Voice::State::ACTIVE; } else { // No new note for voice, deactivate (set gate low) - _gate_port->set_voice_value(context, voice, time, 0.0f); + _gate_port->set_voice_value(ctx, voice, time, 0.0f); (*_voices)[voice].state = Voice::State::FREE; } } void -NoteNode::all_notes_off(RunContext& context, FrameTime time) +NoteNode::all_notes_off(RunContext& ctx, FrameTime time) { - assert(time >= context.start() && time <= context.end()); + assert(time >= ctx.start() && time <= ctx.end()); // FIXME: set all keys to Key::OFF? for (uint32_t i = 0; i < _polyphony; ++i) { - _gate_port->set_voice_value(context, i, time, 0.0f); + _gate_port->set_voice_value(ctx, i, time, 0.0f); (*_voices)[i].state = Voice::State::FREE; } } void -NoteNode::sustain_on(RunContext& context, FrameTime time) +NoteNode::sustain_on(RunContext&, FrameTime) { _sustain = true; } void -NoteNode::sustain_off(RunContext& context, FrameTime time) +NoteNode::sustain_off(RunContext& ctx, FrameTime time) { - assert(time >= context.start() && time <= context.end()); + assert(time >= ctx.start() && time <= ctx.end()); _sustain = false; for (uint32_t i=0; i < _polyphony; ++i) { if ((*_voices)[i].state == Voice::State::HOLDING) { - free_voice(context, i, time); + free_voice(ctx, i, time); } } } void -NoteNode::bend(RunContext& context, FrameTime time, float amount) +NoteNode::bend(RunContext& ctx, FrameTime time, float amount) { - _bend_port->set_control_value(context, time, amount); + _bend_port->set_control_value(ctx, time, amount); } void -NoteNode::note_pressure(RunContext& context, FrameTime time, uint8_t note_num, float amount) +NoteNode::note_pressure(RunContext& ctx, FrameTime time, uint8_t note_num, float amount) { for (uint32_t i=0; i < _polyphony; ++i) { if ((*_voices)[i].state != Voice::State::FREE && (*_voices)[i].note == note_num) { - _pressure_port->set_voice_value(context, i, time, amount); + _pressure_port->set_voice_value(ctx, i, time, amount); return; } } } void -NoteNode::channel_pressure(RunContext& context, FrameTime time, float amount) +NoteNode::channel_pressure(RunContext& ctx, FrameTime time, float amount) { - _pressure_port->set_control_value(context, time, amount); + _pressure_port->set_control_value(ctx, time, amount); } } // namespace internals -} // namespace server -} // namespace ingen +} // namespace ingen::server diff --git a/src/server/internals/Note.hpp b/src/server/internals/Note.hpp index eed5dda7..2cf6c1e2 100644 --- a/src/server/internals/Note.hpp +++ b/src/server/internals/Note.hpp @@ -20,14 +20,27 @@ #include "InternalBlock.hpp" #include "types.hpp" +#include <raul/Array.hpp> +#include <raul/Maid.hpp> + #include <cstdint> +namespace raul { +class Symbol; +} // namespace raul + namespace ingen { + +class URIs; + namespace server { +class BufferFactory; +class GraphImpl; class InputPort; -class OutputPort; class InternalPlugin; +class OutputPort; +class RunContext; namespace internals { @@ -42,26 +55,26 @@ class NoteNode : public InternalBlock public: NoteNode(InternalPlugin* plugin, BufferFactory& bufs, - const Raul::Symbol& symbol, + const raul::Symbol& symbol, bool polyphonic, GraphImpl* parent, SampleRate srate); bool prepare_poly(BufferFactory& bufs, uint32_t poly) override; - bool apply_poly(RunContext& context, uint32_t poly) override; + bool apply_poly(RunContext& ctx, uint32_t poly) override; - void run(RunContext& context) override; + void run(RunContext& ctx) override; - void note_on(RunContext& context, uint8_t note_num, uint8_t velocity, FrameTime time); - void note_off(RunContext& context, uint8_t note_num, FrameTime time); - void all_notes_off(RunContext& context, FrameTime time); + void note_on(RunContext& ctx, uint8_t note_num, uint8_t velocity, FrameTime time); + void note_off(RunContext& ctx, uint8_t note_num, FrameTime time); + void all_notes_off(RunContext& ctx, FrameTime time); - void sustain_on(RunContext& context, FrameTime time); - void sustain_off(RunContext& context, FrameTime time); + void sustain_on(RunContext& ctx, FrameTime time); + void sustain_off(RunContext& ctx, FrameTime time); - void bend(RunContext& context, FrameTime time, float amount); - void note_pressure(RunContext& context, FrameTime time, uint8_t note_num, float amount); - void channel_pressure(RunContext& context, FrameTime time, float amount); + void bend(RunContext& ctx, FrameTime time, float amount); + void note_pressure(RunContext& ctx, FrameTime time, uint8_t note_num, float amount); + void channel_pressure(RunContext& ctx, FrameTime time, float amount); static InternalPlugin* internal_plugin(URIs& uris); @@ -69,30 +82,30 @@ private: /** Key, one for each key on the keyboard */ struct Key { enum class State { OFF, ON_ASSIGNED, ON_UNASSIGNED }; - Key() : state(State::OFF), voice(0), time(0) {} - State state; - uint32_t voice; - SampleCount time; + + State state = State::OFF; + uint32_t voice = 0; + SampleCount time = 0; }; /** Voice, one of these always exists for each voice */ struct Voice { enum class State { FREE, ACTIVE, HOLDING }; - Voice() : state(State::FREE), note(0), time(0) {} - State state; - uint8_t note; - SampleCount time; + + State state = State::FREE; + uint8_t note = 0; + SampleCount time = 0; }; - using Voices = Raul::Array<Voice>; + using Voices = raul::Array<Voice>; - void free_voice(RunContext& context, uint32_t voice, FrameTime time); + void free_voice(RunContext& ctx, uint32_t voice, FrameTime time); - MPtr<Voices> _voices; - MPtr<Voices> _prepared_voices; + raul::managed_ptr<Voices> _voices; + raul::managed_ptr<Voices> _prepared_voices; Key _keys[128]; - bool _sustain; ///< Whether or not hold pedal is depressed + bool _sustain{false}; ///< Whether or not hold pedal is depressed InputPort* _midi_in_port; OutputPort* _freq_port; @@ -104,8 +117,8 @@ private: OutputPort* _pressure_port; }; +} // namespace internals } // namespace server } // namespace ingen -} // namespace internals #endif // INGEN_INTERNALS_NOTE_HPP diff --git a/src/server/internals/Time.cpp b/src/server/internals/Time.cpp index 3b6f12ba..2ea09b0b 100644 --- a/src/server/internals/Time.cpp +++ b/src/server/internals/Time.cpp @@ -14,33 +14,43 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "internals/Time.hpp" +#include "Time.hpp" #include "Buffer.hpp" +#include "BufferFactory.hpp" +#include "BufferRef.hpp" #include "Driver.hpp" #include "Engine.hpp" #include "InternalPlugin.hpp" #include "OutputPort.hpp" +#include "PortType.hpp" #include "RunContext.hpp" -#include "util.hpp" -#include "ingen/Forge.hpp" -#include "ingen/URIs.hpp" -#include "lv2/atom/util.h" -#include "lv2/midi/midi.h" +#include <ingen/Atom.hpp> +#include <ingen/Forge.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIs.hpp> +#include <lv2/atom/atom.h> +#include <raul/Array.hpp> +#include <raul/Maid.hpp> +#include <raul/Symbol.hpp> + +#include <memory> + +namespace ingen::server { + +class GraphImpl; -namespace ingen { -namespace server { namespace internals { InternalPlugin* TimeNode::internal_plugin(URIs& uris) { return new InternalPlugin( - uris, URI(NS_INTERNALS "Time"), Raul::Symbol("time")); + uris, URI(NS_INTERNALS "Time"), raul::Symbol("time")); } TimeNode::TimeNode(InternalPlugin* plugin, BufferFactory& bufs, - const Raul::Symbol& symbol, + const raul::Symbol& symbol, bool polyphonic, GraphImpl* parent, SampleRate srate) @@ -50,7 +60,7 @@ TimeNode::TimeNode(InternalPlugin* plugin, _ports = bufs.maid().make_managed<Ports>(1); _notify_port = new OutputPort( - bufs, this, Raul::Symbol("notify"), 0, 1, + bufs, this, raul::Symbol("notify"), 0, 1, PortType::ATOM, uris.atom_Sequence, Atom(), 1024); _notify_port->set_property(uris.lv2_name, bufs.forge().alloc("Notify")); _notify_port->set_property(uris.atom_supports, @@ -59,10 +69,10 @@ TimeNode::TimeNode(InternalPlugin* plugin, } void -TimeNode::run(RunContext& context) +TimeNode::run(RunContext& ctx) { - BufferRef buf = _notify_port->buffer(0); - LV2_Atom_Sequence* seq = buf->get<LV2_Atom_Sequence>(); + const BufferRef buf = _notify_port->buffer(0); + auto* const seq = buf->get<LV2_Atom_Sequence>(); // Initialise output to the empty sequence seq->atom.type = _notify_port->bufs().uris().atom_Sequence; @@ -71,10 +81,8 @@ TimeNode::run(RunContext& context) seq->body.pad = 0; // Ask the driver to append any time events for this cycle - context.engine().driver()->append_time_events( - context, *_notify_port->buffer(0)); + ctx.engine().driver()->append_time_events(ctx, *_notify_port->buffer(0)); } } // namespace internals -} // namespace server -} // namespace ingen +} // namespace ingen::server diff --git a/src/server/internals/Time.hpp b/src/server/internals/Time.hpp index 958cd239..228e67a8 100644 --- a/src/server/internals/Time.hpp +++ b/src/server/internals/Time.hpp @@ -18,13 +18,22 @@ #define INGEN_INTERNALS_TIME_HPP #include "InternalBlock.hpp" +#include "types.hpp" + +namespace raul { +class Symbol; +} // namespace raul namespace ingen { + +class URIs; + namespace server { -class InputPort; -class OutputPort; +class BufferFactory; +class GraphImpl; class InternalPlugin; +class OutputPort; namespace internals { @@ -39,12 +48,12 @@ class TimeNode : public InternalBlock public: TimeNode(InternalPlugin* plugin, BufferFactory& bufs, - const Raul::Symbol& symbol, + const raul::Symbol& symbol, bool polyphonic, GraphImpl* parent, SampleRate srate); - void run(RunContext& context) override; + void run(RunContext& ctx) override; static InternalPlugin* internal_plugin(URIs& uris); @@ -52,8 +61,8 @@ private: OutputPort* _notify_port; }; +} // namespace internals } // namespace server } // namespace ingen -} // namespace internals #endif // INGEN_INTERNALS_TIME_HPP diff --git a/src/server/internals/Trigger.cpp b/src/server/internals/Trigger.cpp index 4ceae3c8..f033a345 100644 --- a/src/server/internals/Trigger.cpp +++ b/src/server/internals/Trigger.cpp @@ -14,63 +14,71 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#include "internals/Trigger.hpp" +#include "Trigger.hpp" #include "Buffer.hpp" -#include "Engine.hpp" +#include "BufferFactory.hpp" +#include "BufferRef.hpp" #include "InputPort.hpp" #include "InternalPlugin.hpp" #include "OutputPort.hpp" +#include "PortType.hpp" #include "RunContext.hpp" -#include "ingen_config.h" -#include "util.hpp" -#include "ingen/Forge.hpp" -#include "ingen/URIs.hpp" -#include "lv2/atom/util.h" -#include "lv2/midi/midi.h" +#include <ingen/Atom.hpp> +#include <ingen/Forge.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIs.hpp> +#include <lv2/atom/atom.h> +#include <lv2/atom/util.h> +#include <lv2/midi/midi.h> +#include <raul/Array.hpp> +#include <raul/Maid.hpp> +#include <raul/Symbol.hpp> #include <cassert> #include <cmath> +#include <memory> + +namespace ingen::server { + +class GraphImpl; -namespace ingen { -namespace server { namespace internals { InternalPlugin* TriggerNode::internal_plugin(URIs& uris) { return new InternalPlugin( - uris, URI(NS_INTERNALS "Trigger"), Raul::Symbol("trigger")); + uris, URI(NS_INTERNALS "Trigger"), raul::Symbol("trigger")); } TriggerNode::TriggerNode(InternalPlugin* plugin, BufferFactory& bufs, - const Raul::Symbol& symbol, + const raul::Symbol& symbol, bool polyphonic, GraphImpl* parent, SampleRate srate) : InternalBlock(plugin, symbol, false, parent, srate) - , _learning(false) { const ingen::URIs& uris = bufs.uris(); _ports = bufs.maid().make_managed<Ports>(6); const Atom zero = bufs.forge().make(0.0f); - _midi_in_port = new InputPort(bufs, this, Raul::Symbol("input"), 0, 1, + _midi_in_port = new InputPort(bufs, this, raul::Symbol("input"), 0, 1, PortType::ATOM, uris.atom_Sequence, Atom()); _midi_in_port->set_property(uris.lv2_name, bufs.forge().alloc("Input")); _midi_in_port->set_property(uris.atom_supports, bufs.forge().make_urid(uris.midi_MidiEvent)); _ports->at(0) = _midi_in_port; - _midi_out_port = new OutputPort(bufs, this, Raul::Symbol("event"), 1, 1, + _midi_out_port = new OutputPort(bufs, this, raul::Symbol("event"), 1, 1, PortType::ATOM, uris.atom_Sequence, Atom()); _midi_out_port->set_property(uris.lv2_name, bufs.forge().alloc("Event")); _midi_out_port->set_property(uris.atom_supports, bufs.forge().make_urid(uris.midi_MidiEvent)); _ports->at(1) = _midi_out_port; - _note_port = new InputPort(bufs, this, Raul::Symbol("note"), 2, 1, + _note_port = new InputPort(bufs, this, raul::Symbol("note"), 2, 1, PortType::ATOM, uris.atom_Sequence, bufs.forge().make(60.0f)); _note_port->set_property(uris.atom_supports, bufs.uris().atom_Float); @@ -80,21 +88,21 @@ TriggerNode::TriggerNode(InternalPlugin* plugin, _note_port->set_property(uris.lv2_name, bufs.forge().alloc("Note")); _ports->at(2) = _note_port; - _gate_port = new OutputPort(bufs, this, Raul::Symbol("gate"), 3, 1, + _gate_port = new OutputPort(bufs, this, raul::Symbol("gate"), 3, 1, PortType::ATOM, uris.atom_Sequence, zero); _gate_port->set_property(uris.atom_supports, bufs.uris().atom_Float); _gate_port->set_property(uris.lv2_portProperty, uris.lv2_toggled); _gate_port->set_property(uris.lv2_name, bufs.forge().alloc("Gate")); _ports->at(3) = _gate_port; - _trig_port = new OutputPort(bufs, this, Raul::Symbol("trigger"), 4, 1, + _trig_port = new OutputPort(bufs, this, raul::Symbol("trigger"), 4, 1, PortType::ATOM, uris.atom_Sequence, zero); _trig_port->set_property(uris.atom_supports, bufs.uris().atom_Float); _trig_port->set_property(uris.lv2_portProperty, uris.lv2_toggled); _trig_port->set_property(uris.lv2_name, bufs.forge().alloc("Trigger")); _ports->at(4) = _trig_port; - _vel_port = new OutputPort(bufs, this, Raul::Symbol("velocity"), 5, 1, + _vel_port = new OutputPort(bufs, this, raul::Symbol("velocity"), 5, 1, PortType::ATOM, uris.atom_Sequence, zero); _vel_port->set_property(uris.atom_supports, bufs.uris().atom_Float); _vel_port->set_property(uris.lv2_minimum, zero); @@ -104,40 +112,42 @@ TriggerNode::TriggerNode(InternalPlugin* plugin, } void -TriggerNode::run(RunContext& context) +TriggerNode::run(RunContext& ctx) { - const BufferRef midi_in = _midi_in_port->buffer(0); - LV2_Atom_Sequence* const seq = midi_in->get<LV2_Atom_Sequence>(); - const BufferRef midi_out = _midi_out_port->buffer(0); + const BufferRef midi_in = _midi_in_port->buffer(0); + auto* const seq = midi_in->get<LV2_Atom_Sequence>(); + const BufferRef midi_out = _midi_out_port->buffer(0); // Initialise output to the empty sequence - midi_out->prepare_write(context); + midi_out->prepare_write(ctx); - LV2_ATOM_SEQUENCE_FOREACH(seq, ev) { - const int64_t t = ev->time.frames; - const uint8_t* buf = (const uint8_t*)LV2_ATOM_BODY(&ev->body); - bool emit = false; + LV2_ATOM_SEQUENCE_FOREACH (seq, ev) { + const int64_t t = ev->time.frames; + const auto* buf = + static_cast<const uint8_t*>(LV2_ATOM_BODY_CONST(&ev->body)); + bool emit = false; if (ev->body.type == _midi_in_port->bufs().uris().midi_MidiEvent && ev->body.size >= 3) { - const FrameTime time = context.start() + t; + const FrameTime time = ctx.start() + t; switch (lv2_midi_message_type(buf)) { case LV2_MIDI_MSG_NOTE_ON: if (buf[2] == 0) { - emit = note_off(context, buf[1], time); + emit = note_off(ctx, buf[1], time); } else { - emit = note_on(context, buf[1], buf[2], time); + emit = note_on(ctx, buf[1], buf[2], time); } break; case LV2_MIDI_MSG_NOTE_OFF: - emit = note_off(context, buf[1], time); + emit = note_off(ctx, buf[1], time); break; case LV2_MIDI_MSG_CONTROLLER: switch (buf[1]) { case LV2_MIDI_CTL_ALL_NOTES_OFF: case LV2_MIDI_CTL_ALL_SOUNDS_OFF: - _gate_port->set_control_value(context, time, 0.0f); + _gate_port->set_control_value(ctx, time, 0.0f); emit = true; } + break; default: break; } @@ -150,35 +160,35 @@ TriggerNode::run(RunContext& context) } bool -TriggerNode::note_on(RunContext& context, uint8_t note_num, uint8_t velocity, FrameTime time) +TriggerNode::note_on(RunContext& ctx, uint8_t note_num, uint8_t velocity, FrameTime time) { - assert(time >= context.start() && time <= context.end()); - const uint32_t offset = time - context.start(); + assert(time >= ctx.start() && time <= ctx.end()); + const uint32_t offset = time - ctx.start(); if (_learning) { - _note_port->set_control_value(context, time, (float)note_num); + _note_port->set_control_value(ctx, time, static_cast<float>(note_num)); _note_port->force_monitor_update(); _learning = false; } if (note_num == lrintf(_note_port->buffer(0)->value_at(offset))) { - _gate_port->set_control_value(context, time, 1.0f); - _trig_port->set_control_value(context, time, 1.0f); - _trig_port->set_control_value(context, time + 1, 0.0f); - _vel_port->set_control_value(context, time, velocity / 127.0f); + _gate_port->set_control_value(ctx, time, 1.0f); + _trig_port->set_control_value(ctx, time, 1.0f); + _trig_port->set_control_value(ctx, time + 1, 0.0f); + _vel_port->set_control_value(ctx, time, velocity / 127.0f); return true; } return false; } bool -TriggerNode::note_off(RunContext& context, uint8_t note_num, FrameTime time) +TriggerNode::note_off(RunContext& ctx, uint8_t note_num, FrameTime time) { - assert(time >= context.start() && time <= context.end()); - const uint32_t offset = time - context.start(); + assert(time >= ctx.start() && time <= ctx.end()); + const uint32_t offset = time - ctx.start(); if (note_num == lrintf(_note_port->buffer(0)->value_at(offset))) { - _gate_port->set_control_value(context, time, 0.0f); + _gate_port->set_control_value(ctx, time, 0.0f); return true; } @@ -186,5 +196,4 @@ TriggerNode::note_off(RunContext& context, uint8_t note_num, FrameTime time) } } // namespace internals -} // namespace server -} // namespace ingen +} // namespace ingen::server diff --git a/src/server/internals/Trigger.hpp b/src/server/internals/Trigger.hpp index 0508b615..74634202 100644 --- a/src/server/internals/Trigger.hpp +++ b/src/server/internals/Trigger.hpp @@ -18,15 +18,26 @@ #define INGEN_INTERNALS_TRIGGER_HPP #include "InternalBlock.hpp" +#include "types.hpp" #include <cstdint> +namespace raul { +class Symbol; +} // namespace raul + namespace ingen { + +class URIs; + namespace server { +class BufferFactory; +class GraphImpl; class InputPort; -class OutputPort; class InternalPlugin; +class OutputPort; +class RunContext; namespace internals { @@ -45,22 +56,22 @@ class TriggerNode : public InternalBlock public: TriggerNode(InternalPlugin* plugin, BufferFactory& bufs, - const Raul::Symbol& symbol, + const raul::Symbol& symbol, bool polyphonic, GraphImpl* parent, SampleRate srate); - void run(RunContext& context) override; + void run(RunContext& ctx) override; - bool note_on(RunContext& context, uint8_t note_num, uint8_t velocity, FrameTime time); - bool note_off(RunContext& context, uint8_t note_num, FrameTime time); + bool note_on(RunContext& ctx, uint8_t note_num, uint8_t velocity, FrameTime time); + bool note_off(RunContext& ctx, uint8_t note_num, FrameTime time); void learn() override { _learning = true; } static InternalPlugin* internal_plugin(URIs& uris); private: - bool _learning; + bool _learning{false}; InputPort* _midi_in_port; OutputPort* _midi_out_port; @@ -70,8 +81,8 @@ private: OutputPort* _vel_port; }; +} // namespace internals } // namespace server } // namespace ingen -} // namespace internals #endif // INGEN_INTERNALS_TRIGGER_HPP diff --git a/src/server/meson.build b/src/server/meson.build new file mode 100644 index 00000000..c1fccf5e --- /dev/null +++ b/src/server/meson.build @@ -0,0 +1,135 @@ +# Copyright 2022 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: 0BSD OR GPL-3.0-or-later + +########## +# Module # +########## + +server_sources = files( + 'events/Connect.cpp', + 'events/Copy.cpp', + 'events/CreateBlock.cpp', + 'events/CreateGraph.cpp', + 'events/CreatePort.cpp', + 'events/Delete.cpp', + 'events/Delta.cpp', + 'events/Disconnect.cpp', + 'events/DisconnectAll.cpp', + 'events/Get.cpp', + 'events/Mark.cpp', + 'events/Move.cpp', + 'events/SetPortValue.cpp', + 'events/Undo.cpp', + 'internals/BlockDelay.cpp', + 'internals/Controller.cpp', + 'internals/Note.cpp', + 'internals/Time.cpp', + 'internals/Trigger.cpp', + 'ArcImpl.cpp', + 'BlockFactory.cpp', + 'BlockImpl.cpp', + 'Broadcaster.cpp', + 'Buffer.cpp', + 'BufferFactory.cpp', + 'ClientUpdate.cpp', + 'CompiledGraph.cpp', + 'ControlBindings.cpp', + 'DuplexPort.cpp', + 'Engine.cpp', + 'EventWriter.cpp', + 'GraphImpl.cpp', + 'InputPort.cpp', + 'InternalBlock.cpp', + 'InternalPlugin.cpp', + 'LV2Block.cpp', + 'LV2Plugin.cpp', + 'NodeImpl.cpp', + 'PortImpl.cpp', + 'PostProcessor.cpp', + 'PreProcessor.cpp', + 'RunContext.cpp', + 'SocketListener.cpp', + 'Task.cpp', + 'UndoStack.cpp', + 'Worker.cpp', + 'ingen_engine.cpp', + 'mix.cpp', +) + +server_dependencies = [ + boost_dep, + ingen_dep, + lilv_dep, + raul_dep, + serd_dep, + sord_dep, + sratom_dep, + thread_dep, +] + +server_include_dirs = include_directories( + '.', + '../../include', + '../include', +) + +libingen_server = shared_library( + 'ingen_server', + server_sources, + cpp_args: cpp_suppressions + platform_defines + ['-DINGEN_SERVER_INTERNAL'], + dependencies: server_dependencies, + gnu_symbol_visibility: 'hidden', + implicit_include_directories: false, + include_directories: server_include_dirs, + install: true, + install_dir: ingen_module_dir, +) + +ingen_server_dep = declare_dependency( + dependencies: server_dependencies, + link_with: libingen_server, +) + +########### +# Drivers # +########### + +if jack_dep.found() + shared_module( + 'ingen_jack', + files('JackDriver.cpp', 'ingen_jack.cpp'), + cpp_args: cpp_suppressions + platform_defines, + dependencies: [ingen_server_dep, jack_dep], + gnu_symbol_visibility: 'hidden', + implicit_include_directories: false, + include_directories: ingen_include_dirs, + install: true, + install_dir: ingen_module_dir, + ) +endif + +if portaudio_dep.found() + shared_module( + 'ingen_portaudio', + files('PortAudioDriver.cpp', 'ingen_portaudio.cpp'), + cpp_args: cpp_suppressions + platform_defines, + dependencies: [ingen_server_dep, portaudio_dep], + gnu_symbol_visibility: 'hidden', + implicit_include_directories: false, + include_directories: ingen_include_dirs, + install: true, + install_dir: ingen_module_dir, + ) +endif + +shared_module( + 'ingen_lv2', + files('ingen_lv2.cpp'), + cpp_args: cpp_suppressions + platform_defines, + dependencies: [ingen_server_dep, lv2_dep], + gnu_symbol_visibility: 'hidden', + implicit_include_directories: false, + include_directories: ingen_include_dirs, + install: true, + install_dir: lv2dir / 'ingen.lv2', +) diff --git a/src/server/mix.cpp b/src/server/mix.cpp index 5f77eda2..32500f97 100644 --- a/src/server/mix.cpp +++ b/src/server/mix.cpp @@ -18,30 +18,31 @@ #include "Buffer.hpp" #include "RunContext.hpp" +#include "types.hpp" -#include "lv2/atom/util.h" +#include <lv2/atom/atom.h> +#include <lv2/atom/util.h> -namespace ingen { -namespace server { +namespace ingen::server { static inline bool is_end(const Buffer* buf, const LV2_Atom_Event* ev) { - const LV2_Atom* atom = buf->get<const LV2_Atom>(); + const auto* atom = buf->get<const LV2_Atom>(); return lv2_atom_sequence_is_end( - (const LV2_Atom_Sequence_Body*)LV2_ATOM_BODY_CONST(atom), + static_cast<const LV2_Atom_Sequence_Body*>(LV2_ATOM_BODY_CONST(atom)), atom->size, ev); } void -mix(const RunContext& context, +mix(const RunContext& ctx, Buffer* dst, const Buffer*const* srcs, uint32_t num_srcs) { if (num_srcs == 1) { - dst->copy(context, srcs[0]); + dst->copy(ctx, srcs[0]); } else if (dst->is_control()) { Sample* const out = dst->samples(); out[0] = srcs[0]->value_at(0); @@ -50,23 +51,23 @@ mix(const RunContext& context, } } else if (dst->is_audio()) { // Copy the first source - dst->copy(context, srcs[0]); + dst->copy(ctx, srcs[0]); // Mix in the rest Sample* __restrict const out = dst->samples(); - const SampleCount end = context.nframes(); + const SampleCount end = ctx.nframes(); for (uint32_t i = 1; i < num_srcs; ++i) { const Sample* __restrict const in = srcs[i]->samples(); - if (srcs[i]->is_control()) { // control => audio - for (SampleCount i = 0; i < end; ++i) { - out[i] += in[0]; + if (srcs[i]->is_control()) { // control => audio + for (SampleCount j = 0; j < end; ++j) { + out[j] += in[0]; } - } else if (srcs[i]->is_audio()) { // audio => audio - for (SampleCount i = 0; i < end; ++i) { - out[i] += in[i]; + } else if (srcs[i]->is_audio()) { // audio => audio + for (SampleCount j = 0; j < end; ++j) { + out[j] += in[j]; } - } else if (srcs[i]->is_sequence()) { // sequence => audio - dst->render_sequence(context, srcs[i], true); + } else if (srcs[i]->is_sequence()) { // sequence => audio + dst->render_sequence(ctx, srcs[i], true); } } } else if (dst->is_sequence()) { @@ -74,7 +75,7 @@ mix(const RunContext& context, for (uint32_t i = 0; i < num_srcs; ++i) { iters[i] = nullptr; if (srcs[i]->is_sequence()) { - const LV2_Atom_Sequence* seq = srcs[i]->get<const LV2_Atom_Sequence>(); + const auto* seq = srcs[i]->get<const LV2_Atom_Sequence>(); iters[i] = lv2_atom_sequence_begin(&seq->body); if (is_end(srcs[i], iters[i])) { iters[i] = nullptr; @@ -96,7 +97,7 @@ mix(const RunContext& context, if (first) { dst->append_event( first->time.frames, first->body.size, first->body.type, - (const uint8_t*)LV2_ATOM_BODY_CONST(&first->body)); + static_cast<const uint8_t*>(LV2_ATOM_BODY_CONST(&first->body))); iters[first_i] = lv2_atom_sequence_next(first); if (is_end(srcs[first_i], iters[first_i])) { @@ -109,5 +110,4 @@ mix(const RunContext& context, } } -} // namespace server -} // namespace ingen +} // namespace ingen::server diff --git a/src/server/mix.hpp b/src/server/mix.hpp index 1878200c..11a9a1d2 100644 --- a/src/server/mix.hpp +++ b/src/server/mix.hpp @@ -19,19 +19,17 @@ #include <cstdint> -namespace ingen { -namespace server { +namespace ingen::server { class Buffer; class RunContext; void -mix(const RunContext& context, +mix(const RunContext& ctx, Buffer* dst, const Buffer*const* srcs, uint32_t num_srcs); -} // namespace server -} // namespace ingen +} // namespace ingen::server #endif // INGEN_ENGINE_MIX_HPP diff --git a/src/server/server.h b/src/server/server.h new file mode 100644 index 00000000..d4ca5155 --- /dev/null +++ b/src/server/server.h @@ -0,0 +1,31 @@ +/* + This file is part of Ingen. + Copyright 2014-2022 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/>. +*/ + +#ifndef INGEN_SERVER_SERVER_H +#define INGEN_SERVER_SERVER_H + +#if defined(_WIN32) && !defined(INGEN_SERVER_STATIC) && \ + defined(INGEN_SERVER_INTERNAL) +# define INGEN_SERVER_API __declspec(dllexport) +#elif defined(_WIN32) && !defined(INGEN_SERVER_STATIC) +# define INGEN_SERVER_API __declspec(dllimport) +#elif defined(__GNUC__) +# define INGEN_SERVER_API __attribute__((visibility("default"))) +#else +# define INGEN_SERVER_API +#endif + +#endif // INGEN_SERVER_SERVER_H diff --git a/src/server/util.hpp b/src/server/util.hpp index 34e2ee79..abfa06b6 100644 --- a/src/server/util.hpp +++ b/src/server/util.hpp @@ -17,34 +17,19 @@ #ifndef INGEN_ENGINE_UTIL_HPP #define INGEN_ENGINE_UTIL_HPP -#include "ingen_config.h" - -#include "ingen/Log.hpp" -#include "raul/Path.hpp" +#include <ingen/Log.hpp> #ifdef __SSE__ #include <xmmintrin.h> #endif -#include <fenv.h> -#include <cstdlib> - #ifdef __clang__ # define REALTIME __attribute__((annotate("realtime"))) #else # define REALTIME #endif -#if defined(INGEN_HAVE_THREAD_LOCAL) -# define INGEN_THREAD_LOCAL thread_local -#elif defined(INGEN_HAVE_THREAD_BUILTIN) -# define INGEN_THREAD_LOCAL __thread -#else -# define INGEN_THREAD_LOCAL -#endif - -namespace ingen { -namespace server { +namespace ingen::server { /** Set flags to disable denormal processing. */ @@ -57,7 +42,6 @@ set_denormal_flags(ingen::Log& log) #endif } -} // namespace server -} // namespace ingen +} // namespace ingen::server #endif // INGEN_ENGINE_UTIL_HPP diff --git a/src/server/wscript b/src/server/wscript deleted file mode 100644 index 00588915..00000000 --- a/src/server/wscript +++ /dev/null @@ -1,106 +0,0 @@ -#!/usr/bin/env python - - -def build(bld): - core_source = ''' - ArcImpl.cpp - BlockFactory.cpp - BlockImpl.cpp - Broadcaster.cpp - Buffer.cpp - BufferFactory.cpp - CompiledGraph.cpp - ClientUpdate.cpp - ControlBindings.cpp - DuplexPort.cpp - Engine.cpp - EventWriter.cpp - GraphImpl.cpp - InputPort.cpp - InternalBlock.cpp - InternalPlugin.cpp - LV2Block.cpp - LV2Plugin.cpp - NodeImpl.cpp - PortImpl.cpp - PostProcessor.cpp - PreProcessor.cpp - RunContext.cpp - SocketListener.cpp - Task.cpp - UndoStack.cpp - Worker.cpp - events/Connect.cpp - events/Copy.cpp - events/CreateBlock.cpp - events/CreateGraph.cpp - events/CreatePort.cpp - events/Delete.cpp - events/Delta.cpp - events/Disconnect.cpp - events/DisconnectAll.cpp - events/Get.cpp - events/Mark.cpp - events/Move.cpp - events/SetPortValue.cpp - events/Undo.cpp - ingen_engine.cpp - internals/BlockDelay.cpp - internals/Controller.cpp - internals/Note.cpp - internals/Time.cpp - internals/Trigger.cpp - mix.cpp - ''' - - core_libs = 'LV2 LILV RAUL SERD SORD SRATOM' - - bld(features = 'cxx cxxshlib', - source = core_source, - export_includes = ['../..'], - includes = ['.', '../..'], - name = 'libingen_server', - target = 'ingen_server', - install_path = '${LIBDIR}', - use = 'libingen libingen_socket', - uselib = core_libs, - cxxflags = bld.env.PTHREAD_CFLAGS + bld.env.INGEN_TEST_CXXFLAGS, - linkflags = bld.env.PTHREAD_LINKFLAGS + bld.env.INGEN_TEST_LINKFLAGS) - - if bld.env.HAVE_JACK: - bld(features = 'cxx cxxshlib', - source = 'JackDriver.cpp ingen_jack.cpp', - includes = ['.', '../..'], - name = 'libingen_jack', - target = 'ingen_jack', - install_path = '${LIBDIR}', - use = 'libingen_server', - uselib = core_libs + ' JACK', - cxxflags = ['-fvisibility=hidden'] + bld.env.PTHREAD_CFLAGS, - linkflags = bld.env.PTHREAD_LINKFLAGS) - - if bld.env.HAVE_PORTAUDIO: - bld(features = 'cxx cxxshlib', - source = 'PortAudioDriver.cpp ingen_portaudio.cpp', - includes = ['.', '../..'], - name = 'libingen_portaudio', - target = 'ingen_portaudio', - install_path = '${LIBDIR}', - use = 'libingen_server', - uselib = core_libs + ' PORTAUDIO', - cxxflags = ['-fvisibility=hidden'] + bld.env.PTHREAD_CFLAGS, - linkflags = bld.env.PTHREAD_LINKFLAGS) - - # Ingen LV2 wrapper - if bld.env.INGEN_BUILD_LV2: - bld(features = 'cxx cxxshlib', - source = ' ingen_lv2.cpp ', - cflags = ['-fvisibility=hidden'], - includes = ['.', '../..'], - name = 'libingen_lv2', - target = 'ingen_lv2', - install_path = '${LV2DIR}/ingen.lv2/', - use = 'libingen libingen_server', - uselib = core_libs, - cxxflags = ['-fvisibility=hidden'] + bld.env.PTHREAD_CFLAGS, - linkflags = bld.env.PTHREAD_LINKFLAGS) diff --git a/src/wscript b/src/wscript deleted file mode 100644 index 72c7d48c..00000000 --- a/src/wscript +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/env python - - -def build(bld): - sources = [ - 'AtomReader.cpp', - 'AtomWriter.cpp', - 'ClashAvoider.cpp', - 'ColorContext.cpp', - 'Configuration.cpp', - 'FilePath.cpp', - 'Forge.cpp', - 'LV2Features.cpp', - 'Library.cpp', - 'Log.cpp', - 'Parser.cpp', - 'Resource.cpp', - 'Serialiser.cpp', - 'Store.cpp', - 'StreamWriter.cpp', - 'TurtleWriter.cpp', - 'URI.cpp', - 'URIMap.cpp', - 'URIs.cpp', - 'World.cpp', - 'runtime_paths.cpp' - ] - if bld.is_defined('HAVE_SOCKET'): - sources += ['SocketReader.cpp', 'SocketWriter.cpp'] - - lib = [] - if bld.is_defined('HAVE_LIBDL'): - lib += ['dl'] - - bld(features = 'cxx cxxshlib', - source = sources, - export_includes = ['..'], - includes = ['..'], - name = 'libingen', - target = 'ingen-%s' % bld.env.INGEN_MAJOR_VERSION, - vnum = bld.env.INGEN_VERSION, - install_path = '${LIBDIR}', - lib = lib, - uselib = 'LV2 LILV RAUL SERD SORD SRATOM', - cxxflags = (['-fvisibility=hidden'] + - bld.env.PTHREAD_CFLAGS + bld.env.INGEN_TEST_CXXFLAGS), - linkflags = bld.env.PTHREAD_LINKFLAGS + bld.env.INGEN_TEST_LINKFLAGS) |