/* This file is part of Ingen. Copyright 2016 David Robillard 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 . */ #ifndef INGEN_ENGINE_UNDOSTACK_HPP #define INGEN_ENGINE_UNDOSTACK_HPP #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 #include #include #include #include #include namespace ingen { class URIMap; class URIs; namespace server { class INGEN_SERVER_API UndoStack : public AtomSink { public: struct Entry { explicit Entry(time_t t) noexcept : time{t} {} Entry() noexcept : Entry{0} {} Entry(const Entry& copy) : time(copy.time) { for (const LV2_Atom* ev : copy.events) { push_event(ev); } } ~Entry() { clear(); } Entry& operator=(const Entry& rhs) { if (&rhs != this) { clear(); time = rhs.time; for (const LV2_Atom* ev : rhs.events) { push_event(ev); } } return *this; } void clear() { for (LV2_Atom* ev : events) { free(ev); } events.clear(); } void push_event(const LV2_Atom* ev) { const uint32_t size = lv2_atom_total_size(ev); auto* copy = static_cast(malloc(size)); memcpy(copy, ev, size); events.push_front(copy); } time_t time; std::deque events; }; 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; int finish_entry(); bool empty() const { return _stack.empty(); } Entry pop(); void save(FILE* stream, const char* name="undo"); private: bool ignore_later_event(const LV2_Atom* first, const LV2_Atom* second) const; void write_entry(Sratom* sratom, SerdWriter* writer, const SerdNode* subject, const Entry& entry); URIs& _uris; URIMap& _map; std::deque _stack; int _depth{0}; }; } // namespace server } // namespace ingen #endif // INGEN_ENGINE_UNDOSTACK_HPP