diff options
-rw-r--r-- | ingen/AtomForgeSink.hpp | 97 | ||||
-rw-r--r-- | ingen/AtomReader.hpp | 1 | ||||
-rw-r--r-- | ingen/AtomWriter.hpp | 6 | ||||
-rw-r--r-- | src/AtomWriter.cpp | 29 | ||||
-rw-r--r-- | src/Parser.cpp | 12 | ||||
-rw-r--r-- | src/SocketReader.cpp | 13 | ||||
-rw-r--r-- | src/server/ControlBindings.cpp | 8 | ||||
-rw-r--r-- | src/server/JackDriver.cpp | 6 | ||||
-rw-r--r-- | src/server/events/Copy.cpp | 1 | ||||
-rw-r--r-- | tests/ingen_test.cpp | 15 |
10 files changed, 130 insertions, 58 deletions
diff --git a/ingen/AtomForgeSink.hpp b/ingen/AtomForgeSink.hpp new file mode 100644 index 00000000..5520906c --- /dev/null +++ b/ingen/AtomForgeSink.hpp @@ -0,0 +1,97 @@ +/* + This file is part of Ingen. + Copyright 2007-2017 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_ATOMFORGESINK_HPP +#define INGEN_ATOMFORGESINK_HPP + +#include <cstdlib> + +#include "lv2/lv2plug.in/ns/ext/atom/forge.h" + +namespace Ingen { + +/** A resizing sink for LV2_Atom_Forge. */ +class AtomForgeSink +{ +public: + AtomForgeSink(LV2_Atom_Forge* forge = nullptr) + : _capacity(8 * sizeof(LV2_Atom)) + , _size(0) + , _buf((LV2_Atom*)calloc(8, sizeof(LV2_Atom))) + { + if (forge) { + set_forge_sink(forge); + } + } + + ~AtomForgeSink() { free(_buf); } + + void set_forge_sink(LV2_Atom_Forge* forge) { + lv2_atom_forge_set_sink(forge, c_append, c_deref, this); + } + + /** Append some data and return a reference to its start. */ + intptr_t append(const void* buf, uint32_t len) { + // Record offset of the start of this write (+1 to avoid NULL) + const intptr_t ref = _size + 1; + + // Update size and reallocate if necessary + if (lv2_atom_pad_size(_size + len) > _capacity) { + _capacity = lv2_atom_pad_size(_size + len); + _buf = (LV2_Atom*)realloc(_buf, _capacity); + } + + // Append new data + memcpy((uint8_t*)_buf + _size, buf, len); + _size += len; + return ref; + } + + /** Dereference a reference previously returned by append. */ + LV2_Atom* deref(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. */ + assert((ref - 1) % sizeof(LV2_Atom) == 0); + return (LV2_Atom*)(_buf + (ref - 1) / sizeof(LV2_Atom)); + + // Alternatively: + // return (LV2_Atom*)((uint8_t*)_buf + ref - 1); + } + + const LV2_Atom* atom() const { return _buf; } + + void clear() { _buf->type = 0; _buf->size = 0; _size = 0; } + + static LV2_Atom_Forge_Ref + c_append(void* handle, const void* buf, uint32_t len) { + return ((AtomForgeSink*)handle)->append(buf, len); + } + + static LV2_Atom* + c_deref(void* handle, LV2_Atom_Forge_Ref ref) { + return ((AtomForgeSink*)handle)->deref(ref); + } + +private: + size_t _capacity; + size_t _size; + LV2_Atom* _buf; +}; + +} // namespace Ingen + +#endif // INGEN_ATOMFORGESINK_HPP diff --git a/ingen/AtomReader.hpp b/ingen/AtomReader.hpp index 09aa672a..1c1dea5b 100644 --- a/ingen/AtomReader.hpp +++ b/ingen/AtomReader.hpp @@ -23,7 +23,6 @@ #include "ingen/AtomSink.hpp" #include "ingen/URIs.hpp" #include "ingen/ingen.h" -#include "serd/serd.h" namespace Ingen { diff --git a/ingen/AtomWriter.hpp b/ingen/AtomWriter.hpp index 9ea5fa27..4246e884 100644 --- a/ingen/AtomWriter.hpp +++ b/ingen/AtomWriter.hpp @@ -1,6 +1,6 @@ /* This file is part of Ingen. - Copyright 2007-2016 David Robillard <http://drobilla.net/> + Copyright 2007-2017 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 @@ -19,11 +19,11 @@ #include <string> +#include "ingen/AtomForgeSink.hpp" #include "ingen/Interface.hpp" #include "ingen/URIs.hpp" #include "ingen/ingen.h" #include "lv2/lv2plug.in/ns/ext/atom/forge.h" -#include "serd/serd.h" namespace Ingen { @@ -98,7 +98,7 @@ private: URIMap& _map; URIs& _uris; AtomSink& _sink; - SerdChunk _out; + AtomForgeSink _out; LV2_Atom_Forge _forge; int32_t _id; }; diff --git a/src/AtomWriter.cpp b/src/AtomWriter.cpp index f477adcc..4f342edf 100644 --- a/src/AtomWriter.cpp +++ b/src/AtomWriter.cpp @@ -1,6 +1,6 @@ /* This file is part of Ingen. - Copyright 2007-2016 David Robillard <http://drobilla.net/> + Copyright 2007-2017 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 @@ -60,47 +60,26 @@ namespace Ingen { -static LV2_Atom_Forge_Ref -forge_sink(LV2_Atom_Forge_Sink_Handle handle, - const void* buf, - uint32_t size) -{ - SerdChunk* chunk = (SerdChunk*)handle; - const LV2_Atom_Forge_Ref ref = chunk->len + 1; - serd_chunk_sink(buf, size, chunk); - return ref; -} - -static LV2_Atom* -forge_deref(LV2_Atom_Forge_Sink_Handle handle, LV2_Atom_Forge_Ref ref) -{ - SerdChunk* chunk = (SerdChunk*)handle; - return (LV2_Atom*)(chunk->buf + ref - 1); -} - AtomWriter::AtomWriter(URIMap& map, URIs& uris, AtomSink& sink) : _map(map) , _uris(uris) , _sink(sink) , _id(0) { - _out.buf = NULL; - _out.len = 0; lv2_atom_forge_init(&_forge, &map.urid_map_feature()->urid_map); - lv2_atom_forge_set_sink(&_forge, forge_sink, forge_deref, &_out); + _out.set_forge_sink(&_forge); } AtomWriter::~AtomWriter() { - free((void*)_out.buf); } void AtomWriter::finish_msg() { assert(!_forge.stack); - _sink.write((const LV2_Atom*)_out.buf); - _out.len = 0; + _sink.write(_out.atom()); + _out.clear(); } /** @page protocol diff --git a/src/Parser.cpp b/src/Parser.cpp index 765f9bd4..0e3a031e 100644 --- a/src/Parser.cpp +++ b/src/Parser.cpp @@ -1,6 +1,6 @@ /* This file is part of Ingen. - Copyright 2007-2016 David Robillard <http://drobilla.net/> + Copyright 2007-2017 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 @@ -24,6 +24,7 @@ #include <glibmm/miscutils.h> #include "ingen/Atom.hpp" +#include "ingen/AtomForgeSink.hpp" #include "ingen/Interface.hpp" #include "ingen/Log.hpp" #include "ingen/Parser.hpp" @@ -127,22 +128,22 @@ get_properties(Ingen::World* world, const Sord::Node& subject, Resource::Graph ctx) { - SerdChunk out = { NULL, 0 }; LV2_URID_Map* map = &world->uri_map().urid_map_feature()->urid_map; Sratom* sratom = sratom_new(map); LV2_Atom_Forge forge; lv2_atom_forge_init(&forge, map); - lv2_atom_forge_set_sink(&forge, sratom_forge_sink, sratom_forge_deref, &out); + + AtomForgeSink out(&forge); const Sord::Node nil; Resource::Properties props; for (Sord::Iter i = model.find(subject, nil, nil); !i.end(); ++i) { if (!skip_property(world->uris(), i.get_predicate())) { - out.len = 0; + out.clear(); sratom_read(sratom, &forge, world->rdf_world()->c_obj(), model.c_obj(), i.get_object().c_obj()); - const LV2_Atom* atom = (const LV2_Atom*)out.buf; + const LV2_Atom* atom = out.atom(); Atom atomm; atomm = world->forge().alloc( atom->size, atom->type, LV2_ATOM_BODY_CONST(atom)); @@ -151,7 +152,6 @@ get_properties(Ingen::World* world, } } - free((uint8_t*)out.buf); sratom_free(sratom); return props; } diff --git a/src/SocketReader.cpp b/src/SocketReader.cpp index 32552c24..381a5305 100644 --- a/src/SocketReader.cpp +++ b/src/SocketReader.cpp @@ -1,6 +1,6 @@ /* This file is part of Ingen. - Copyright 2007-2015 David Robillard <http://drobilla.net/> + Copyright 2007-2017 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,6 +17,7 @@ #include <errno.h> #include <poll.h> +#include "ingen/AtomForgeSink.hpp" #include "ingen/AtomReader.hpp" #include "ingen/Interface.hpp" #include "ingen/Log.hpp" @@ -101,11 +102,10 @@ SocketReader::run() // Set up sratom and a forge to build LV2 atoms from model Sratom* sratom = sratom_new(map); - SerdChunk chunk = { NULL, 0 }; LV2_Atom_Forge forge; lv2_atom_forge_init(&forge, map); - lv2_atom_forge_set_sink( - &forge, sratom_forge_sink, sratom_forge_deref, &chunk); + + AtomForgeSink buffer(&forge); SordNode* base_uri = NULL; SordModel* model = NULL; @@ -173,10 +173,10 @@ SocketReader::run() sratom_read(sratom, &forge, world->c_obj(), model, _msg_node); // Call _iface methods based on atom content - ar.write((const LV2_Atom*)chunk.buf); + ar.write(buffer.atom()); // Reset everything for the next iteration - chunk.len = 0; + buffer.clear(); sord_node_free(world->c_obj(), _msg_node); _msg_node = NULL; } @@ -191,7 +191,6 @@ SocketReader::run() sratom_free(sratom); serd_reader_free(reader); sord_free(model); - free((uint8_t*)chunk.buf); _socket.reset(); } diff --git a/src/server/ControlBindings.cpp b/src/server/ControlBindings.cpp index 9e3d2fae..6ae4f856 100644 --- a/src/server/ControlBindings.cpp +++ b/src/server/ControlBindings.cpp @@ -1,6 +1,6 @@ /* This file is part of Ingen. - Copyright 2007-2016 David Robillard <http://drobilla.net/> + Copyright 2007-2017 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 @@ -349,11 +349,11 @@ ControlBindings::finish_learn(RunContext& context, Key key) binding->key = key; _bindings->insert(*binding); - uint8_t buf[128]; + LV2_Atom buf[16]; memset(buf, 0, sizeof(buf)); - lv2_atom_forge_set_buffer(&_forge, buf, sizeof(buf)); + lv2_atom_forge_set_buffer(&_forge, (uint8_t*)buf, sizeof(buf)); forge_binding(uris, &_forge, key.type, key.num); - const LV2_Atom* atom = (const LV2_Atom*)buf; + const LV2_Atom* atom = buf; context.notify(uris.midi_binding, context.start(), binding->port, diff --git a/src/server/JackDriver.cpp b/src/server/JackDriver.cpp index c03bf42c..77eb62b3 100644 --- a/src/server/JackDriver.cpp +++ b/src/server/JackDriver.cpp @@ -1,6 +1,6 @@ /* This file is part of Ingen. - Copyright 2007-2016 David Robillard <http://drobilla.net/> + Copyright 2007-2017 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 @@ -422,9 +422,9 @@ JackDriver::append_time_events(RunContext& context, _old_bpm = pos->beats_per_minute; // Build an LV2 position object to append to the buffer - uint8_t pos_buf[256]; + LV2_Atom pos_buf[16]; LV2_Atom_Forge_Frame frame; - lv2_atom_forge_set_buffer(&_forge, pos_buf, sizeof(pos_buf)); + lv2_atom_forge_set_buffer(&_forge, (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); diff --git a/src/server/events/Copy.cpp b/src/server/events/Copy.cpp index 58c9a89c..668a6fca 100644 --- a/src/server/events/Copy.cpp +++ b/src/server/events/Copy.cpp @@ -18,7 +18,6 @@ #include "ingen/Serialiser.hpp" #include "ingen/Store.hpp" #include "raul/Path.hpp" -#include "serd/serd.h" #include "BlockImpl.hpp" #include "Broadcaster.hpp" diff --git a/tests/ingen_test.cpp b/tests/ingen_test.cpp index 446afa79..d0cf77c3 100644 --- a/tests/ingen_test.cpp +++ b/tests/ingen_test.cpp @@ -1,6 +1,6 @@ /* This file is part of Ingen. - Copyright 2007-2016 David Robillard <http://drobilla.net/> + Copyright 2007-2017 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 @@ -202,7 +202,6 @@ main(int argc, char** argv) // Read commands - SerdChunk out = { NULL, 0 }; LV2_URID_Map* map = &world->uri_map().urid_map_feature()->urid_map; Sratom* sratom = sratom_new(map); @@ -210,7 +209,8 @@ main(int argc, char** argv) LV2_Atom_Forge forge; lv2_atom_forge_init(&forge, map); - lv2_atom_forge_set_sink(&forge, sratom_forge_sink, sratom_forge_deref, &out); + + AtomForgeSink out(&forge); // AtomReader to read commands from a file and send them to engine AtomReader atom_reader(world->uri_map(), @@ -243,13 +243,13 @@ main(int argc, char** argv) break; } - out.len = 0; + out.clear(); sratom_read(sratom, &forge, world->rdf_world()->c_obj(), cmds->c_obj(), subject.c_obj()); #if 0 - cerr << "READ " << out.len << " BYTES" << endl; - const LV2_Atom* atom = (const LV2_Atom*)out.buf; + const LV2_Atom* atom = out.atom(); + cerr << "READ " << atom->size << " BYTES" << endl; cerr << sratom_to_turtle( sratom, &world->uri_map().urid_unmap_feature()->urid_unmap, @@ -257,7 +257,7 @@ main(int argc, char** argv) NULL, NULL, atom->type, atom->size, LV2_ATOM_BODY(atom)) << endl; #endif - if (!atom_reader.write((const LV2_Atom*)out.buf, n_events + 1)) { + if (!atom_reader.write(out.atom(), n_events + 1)) { return EXIT_FAILURE; } @@ -297,7 +297,6 @@ main(int argc, char** argv) const std::string redo_path = Glib::build_filename(Glib::get_current_dir(), redo_name); world->serialiser()->write_bundle(r->second, Glib::filename_to_uri(redo_path)); - free((void*)out.buf); serd_env_free(env); sratom_free(sratom); serd_node_free(&cmds_file_uri); |