diff options
Diffstat (limited to 'src/server/events')
28 files changed, 0 insertions, 3931 deletions
diff --git a/src/server/events/Connect.cpp b/src/server/events/Connect.cpp deleted file mode 100644 index 8937b327..00000000 --- a/src/server/events/Connect.cpp +++ /dev/null @@ -1,188 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2016 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/Store.hpp" -#include "raul/Maid.hpp" -#include "raul/Path.hpp" - -#include "ArcImpl.hpp" -#include "Broadcaster.hpp" -#include "BufferFactory.hpp" -#include "Connect.hpp" -#include "Engine.hpp" -#include "GraphImpl.hpp" -#include "InputPort.hpp" -#include "PortImpl.hpp" -#include "PreProcessContext.hpp" -#include "internals/BlockDelay.hpp" -#include "types.hpp" - -namespace Ingen { -namespace Server { -namespace Events { - -Connect::Connect(Engine& engine, - SPtr<Interface> client, - SampleCount timestamp, - const Ingen::Connect& msg) - : Event(engine, client, msg.seq, timestamp) - , _msg(msg) - , _graph(nullptr) - , _head(nullptr) -{} - -bool -Connect::pre_process(PreProcessContext& ctx) -{ - std::lock_guard<Store::Mutex> lock(_engine.store()->mutex()); - - Node* tail = _engine.store()->get(_msg.tail); - if (!tail) { - return Event::pre_process_done(Status::NOT_FOUND, _msg.tail); - } - - Node* head = _engine.store()->get(_msg.head); - if (!head) { - return Event::pre_process_done(Status::NOT_FOUND, _msg.head); - } - - PortImpl* tail_output = dynamic_cast<PortImpl*>(tail); - _head = dynamic_cast<InputPort*>(head); - if (!tail_output || !_head) { - return Event::pre_process_done(Status::BAD_REQUEST, _msg.head); - } - - BlockImpl* const tail_block = tail_output->parent_block(); - BlockImpl* const head_block = _head->parent_block(); - if (!tail_block || !head_block) { - return Event::pre_process_done(Status::PARENT_NOT_FOUND, _msg.head); - } - - if (tail_block->parent() != head_block->parent() - && tail_block != head_block->parent() - && tail_block->parent() != head_block) { - return Event::pre_process_done(Status::PARENT_DIFFERS, _msg.head); - } - - if (!ArcImpl::can_connect(tail_output, _head)) { - return Event::pre_process_done(Status::TYPE_MISMATCH, _msg.head); - } - - if (tail_block->parent_graph() != head_block->parent_graph()) { - // Arc to a graph port from inside the graph - assert(tail_block->parent() == head_block || head_block->parent() == tail_block); - if (tail_block->parent() == head_block) { - _graph = dynamic_cast<GraphImpl*>(head_block); - } else { - _graph = dynamic_cast<GraphImpl*>(tail_block); - } - } else if (tail_block == head_block && dynamic_cast<GraphImpl*>(tail_block)) { - // Arc from a graph input to a graph output (pass through) - _graph = dynamic_cast<GraphImpl*>(tail_block); - } else { - // Normal arc between blocks with the same parent - _graph = tail_block->parent_graph(); - } - - if (_graph->has_arc(tail_output, _head)) { - return Event::pre_process_done(Status::EXISTS, _msg.head); - } - - _arc = SPtr<ArcImpl>(new ArcImpl(tail_output, _head)); - - /* Need to be careful about graph port arcs here and adding a - block's parent as a dependant/provider, or adding a graph as its own - provider... - */ - if (tail_block != head_block && tail_block->parent() == head_block->parent()) { - // Connection is between blocks inside a graph, compile graph - - // The tail block is now a dependency (provider) of the head block - head_block->providers().insert(tail_block); - - if (!dynamic_cast<Internals::BlockDelayNode*>(tail_block)) { - /* Arcs leaving a delay node are ignored for the purposes of - compilation, since the output is from the previous cycle and - does not affect execution order. Otherwise, the head block is - now a dependant of the head block. */ - tail_block->dependants().insert(head_block); - } - - if (ctx.must_compile(*_graph)) { - if (!(_compiled_graph = compile(*_engine.maid(), *_graph))) { - head_block->providers().erase(tail_block); - tail_block->dependants().erase(head_block); - return Event::pre_process_done(Status::COMPILATION_FAILED); - } - } - } - - _graph->add_arc(_arc); - _head->increment_num_arcs(); - - if (!_head->is_driver_port()) { - BufferFactory& bufs = *_engine.buffer_factory(); - _voices = bufs.maid().make_managed<PortImpl::Voices>(_head->poly()); - _head->pre_get_buffers(bufs, _voices, _head->poly()); - } - - tail_output->inherit_neighbour(_head, _tail_remove, _tail_add); - _head->inherit_neighbour(tail_output, _head_remove, _head_add); - - return Event::pre_process_done(Status::SUCCESS); -} - -void -Connect::execute(RunContext& context) -{ - if (_status == Status::SUCCESS) { - _head->add_arc(context, *_arc.get()); - if (!_head->is_driver_port()) { - _head->set_voices(context, std::move(_voices)); - } - _head->connect_buffers(); - if (_compiled_graph) { - _graph->set_compiled_graph(std::move(_compiled_graph)); - } - } -} - -void -Connect::post_process() -{ - Broadcaster::Transfer t(*_engine.broadcaster()); - if (respond() == Status::SUCCESS) { - _engine.broadcaster()->message(_msg); - if (!_tail_remove.empty() || !_tail_add.empty()) { - _engine.broadcaster()->delta( - path_to_uri(_msg.tail), _tail_remove, _tail_add); - } - if (!_tail_remove.empty() || !_tail_add.empty()) { - _engine.broadcaster()->delta( - path_to_uri(_msg.tail), _tail_remove, _tail_add); - } - } -} - -void -Connect::undo(Interface& target) -{ - target.disconnect(_msg.tail, _msg.head); -} - -} // namespace Events -} // namespace Server -} // namespace Ingen diff --git a/src/server/events/Connect.hpp b/src/server/events/Connect.hpp deleted file mode 100644 index 8a42b984..00000000 --- a/src/server/events/Connect.hpp +++ /dev/null @@ -1,74 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2016 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_EVENTS_CONNECT_HPP -#define INGEN_EVENTS_CONNECT_HPP - -#include "raul/Path.hpp" - -#include "CompiledGraph.hpp" -#include "Event.hpp" -#include "PortImpl.hpp" -#include "types.hpp" - -namespace Raul { -template <typename T> class Array; -} - -namespace Ingen { -namespace Server { - -class ArcImpl; -class GraphImpl; -class InputPort; - -namespace Events { - -/** Make an Arc between two Ports. - * - * \ingroup engine - */ -class Connect : public Event -{ -public: - Connect(Engine& engine, - SPtr<Interface> client, - SampleCount timestamp, - const Ingen::Connect& msg); - - bool pre_process(PreProcessContext& ctx); - void execute(RunContext& context); - void post_process(); - void undo(Interface& target); - -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; -}; - -} // namespace Events -} // namespace Server -} // namespace Ingen - -#endif // INGEN_EVENTS_CONNECT_HPP diff --git a/src/server/events/Copy.cpp b/src/server/events/Copy.cpp deleted file mode 100644 index fc9d40f7..00000000 --- a/src/server/events/Copy.cpp +++ /dev/null @@ -1,216 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2016 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/Parser.hpp" -#include "ingen/Serialiser.hpp" -#include "ingen/Store.hpp" -#include "raul/Path.hpp" - -#include "BlockImpl.hpp" -#include "Broadcaster.hpp" -#include "Engine.hpp" -#include "EnginePort.hpp" -#include "GraphImpl.hpp" -#include "PreProcessContext.hpp" -#include "events/Copy.hpp" - -namespace Ingen { -namespace Server { -namespace Events { - -Copy::Copy(Engine& engine, - SPtr<Interface> client, - SampleCount timestamp, - const Ingen::Copy& msg) - : Event(engine, client, msg.seq, timestamp) - , _msg(msg) - , _old_block(nullptr) - , _parent(nullptr) - , _block(nullptr) -{} - -bool -Copy::pre_process(PreProcessContext& ctx) -{ - 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); - - // Find the old node - const Store::iterator 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))) { - 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") { - // 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") { - 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); - } - } - - return Event::pre_process_done(Status::BAD_URI); -} - -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())) { - return Event::pre_process_done(Status::BAD_REQUEST); - } - - // Ensure the new node doesn't already exist - if (_engine.store()->find(new_path) != _engine.store()->end()) { - return Event::pre_process_done(Status::EXISTS, new_path); - } - - // Find new parent graph - const Raul::Path parent_path = new_path.parent(); - const Store::iterator p = _engine.store()->find(parent_path); - if (p == _engine.store()->end()) { - return Event::pre_process_done(Status::NOT_FOUND, parent_path); - } - if (!(_parent = dynamic_cast<GraphImpl*>(p->second.get()))) { - return Event::pre_process_done(Status::BAD_OBJECT_TYPE, parent_path); - } - - // Create new block - if (!(_block = dynamic_cast<BlockImpl*>( - _old_block->duplicate(_engine, Raul::Symbol(new_path.symbol()), _parent)))) { - return Event::pre_process_done(Status::INTERNAL_ERROR); - } - - _block->activate(*_engine.buffer_factory()); - - // Add block to the store and the graph's pre-processor only block list - _parent->add_block(*_block); - _engine.store()->add(_block); - - // Compile graph with new block added for insertion in audio thread - _compiled_graph = ctx.maybe_compile(*_engine.maid(), *_parent); - - return Event::pre_process_done(Status::SUCCESS); -} - -static bool -ends_with(const std::string& str, const std::string& end) -{ - if (str.length() >= end.length()) { - return !str.compare(str.length() - end.length(), end.length(), end); - } - return false; -} - -bool -Copy::engine_to_filesystem(PreProcessContext& ctx) -{ - // Ensure source is a graph - SPtr<GraphImpl> graph = dynamic_ptr_cast<GraphImpl>(_old_block); - if (!graph) { - return Event::pre_process_done(Status::BAD_OBJECT_TYPE, _msg.old_uri); - } - - if (!_engine.world()->serialiser()) { - return Event::pre_process_done(Status::INTERNAL_ERROR); - } - - 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)); - } else { - _engine.world()->serialiser()->start_to_file(graph->path(), _msg.new_uri); - _engine.world()->serialiser()->serialise(graph); - _engine.world()->serialiser()->finish(); - } - - return Event::pre_process_done(Status::SUCCESS); -} - -bool -Copy::filesystem_to_engine(PreProcessContext& ctx) -{ - if (!_engine.world()->parser()) { - return Event::pre_process_done(Status::INTERNAL_ERROR); - } - - 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; - if (!dst_path.is_root()) { - dst_parent = dst_path.parent(); - dst_symbol = Raul::Symbol(dst_path.symbol()); - } - - _engine.world()->parser()->parse_file( - _engine.world(), _engine.world()->interface().get(), src_path, - dst_parent, dst_symbol); - - return Event::pre_process_done(Status::SUCCESS); -} - -void -Copy::execute(RunContext& context) -{ - if (_block && _compiled_graph) { - _parent->set_compiled_graph(std::move(_compiled_graph)); - } -} - -void -Copy::post_process() -{ - Broadcaster::Transfer t(*_engine.broadcaster()); - if (respond() == Status::SUCCESS) { - _engine.broadcaster()->message(_msg); - } -} - -void -Copy::undo(Interface& target) -{ - if (uri_is_path(_msg.new_uri)) { - target.del(_msg.new_uri); - } -} - -} // namespace Events -} // namespace Server -} // namespace Ingen diff --git a/src/server/events/Copy.hpp b/src/server/events/Copy.hpp deleted file mode 100644 index 5216b56e..00000000 --- a/src/server/events/Copy.hpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2016 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_EVENTS_COPY_HPP -#define INGEN_EVENTS_COPY_HPP - -#include <list> - -#include "ingen/Store.hpp" -#include "raul/Path.hpp" - -#include "CompiledGraph.hpp" -#include "Event.hpp" - -namespace Ingen { -namespace Server { - -class BlockImpl; -class GraphImpl; - -namespace Events { - -/** Copy a graph object to a new path. - * \ingroup engine - */ -class Copy : public Event -{ -public: - Copy(Engine& engine, - SPtr<Interface> client, - SampleCount timestamp, - const Ingen::Copy& msg); - - bool pre_process(PreProcessContext& ctx); - void execute(RunContext& context); - void post_process(); - void undo(Interface& target); - -private: - bool engine_to_engine(PreProcessContext& ctx); - 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; -}; - -} // namespace Events -} // namespace Server -} // namespace Ingen - -#endif // INGEN_EVENTS_COPY_HPP diff --git a/src/server/events/CreateBlock.cpp b/src/server/events/CreateBlock.cpp deleted file mode 100644 index d678bea3..00000000 --- a/src/server/events/CreateBlock.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2016 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/Forge.hpp" -#include "ingen/Store.hpp" -#include "ingen/URIs.hpp" -#include "raul/Maid.hpp" -#include "raul/Path.hpp" - -#include "BlockFactory.hpp" -#include "BlockImpl.hpp" -#include "Broadcaster.hpp" -#include "CreateBlock.hpp" -#include "Engine.hpp" -#include "GraphImpl.hpp" -#include "PluginImpl.hpp" -#include "PortImpl.hpp" -#include "PreProcessContext.hpp" -#include "LV2Block.hpp" - -namespace Ingen { -namespace Server { -namespace Events { - -CreateBlock::CreateBlock(Engine& engine, - 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) -{} - -bool -CreateBlock::pre_process(PreProcessContext& ctx) -{ - typedef Properties::const_iterator iterator; - - const Ingen::URIs& uris = _engine.world()->uris(); - const SPtr<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)) { - return Event::pre_process_done(Status::EXISTS, _path); - } else 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); - for (auto i = range.first; i != range.second;) { - const auto value = i->second; - auto next = i; - next = _properties.erase(i); - _properties.emplace(uris.lv2_prototype, value); - i = next; - } - - // Get prototype - iterator 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); - } - - 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>()); - - // Find and instantiate/duplicate prototype (plugin/existing node) - if (uri_is_path(prototype)) { - // Prototype is an existing block - BlockImpl* const ancestor = dynamic_cast<BlockImpl*>( - 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))) { - return Event::pre_process_done(Status::CREATION_FAILED, _path); - } - - /* Replace prototype with the ancestor's. This is less informative, - but the client expects an actual LV2 plugin as prototype. */ - _properties.erase(uris.ingen_prototype); - _properties.erase(uris.lv2_prototype); - _properties.emplace(uris.lv2_prototype, - uris.forge.make_urid(ancestor->plugin()->uri())); - } else { - // Prototype is a plugin - PluginImpl* const plugin = _engine.block_factory()->plugin(prototype); - if (!plugin) { - return Event::pre_process_done(Status::PROTOTYPE_NOT_FOUND, prototype); - } - - // Load state from directory if given in properties - LilvState* state = nullptr; - auto s = _properties.find(uris.state_state); - if (s != _properties.end() && s->second.type() == uris.forge.Path) { - state = LV2Block::load_state( - _engine.world(), FilePath(s->second.ptr<char>())); - } - - // Instantiate plugin - if (!(_block = plugin->instantiate(*_engine.buffer_factory(), - Raul::Symbol(_path.symbol()), - polyphonic, - _graph, - _engine, - state))) { - return Event::pre_process_done(Status::CREATION_FAILED, _path); - } - } - - // Activate block - _block->properties().insert(_properties.begin(), _properties.end()); - _block->activate(*_engine.buffer_factory()); - - // Add block to the store and the graph's pre-processor only block list - _graph->add_block(*_block); - store->add(_block); - - /* 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); - - _update.put_block(_block); - - return Event::pre_process_done(Status::SUCCESS); -} - -void -CreateBlock::execute(RunContext& context) -{ - if (_status == Status::SUCCESS && _compiled_graph) { - _graph->set_compiled_graph(std::move(_compiled_graph)); - } -} - -void -CreateBlock::post_process() -{ - Broadcaster::Transfer t(*_engine.broadcaster()); - if (respond() == Status::SUCCESS) { - _update.send(*_engine.broadcaster()); - } -} - -void -CreateBlock::undo(Interface& target) -{ - target.del(_block->uri()); -} - -} // namespace Events -} // namespace Server -} // namespace Ingen diff --git a/src/server/events/CreateBlock.hpp b/src/server/events/CreateBlock.hpp deleted file mode 100644 index 0a29e68c..00000000 --- a/src/server/events/CreateBlock.hpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2016 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_EVENTS_CREATEBLOCK_HPP -#define INGEN_EVENTS_CREATEBLOCK_HPP - -#include "ingen/Resource.hpp" - -#include "ClientUpdate.hpp" -#include "CompiledGraph.hpp" -#include "Event.hpp" - -namespace Ingen { -namespace Server { - -class BlockImpl; -class GraphImpl; - -namespace Events { - -/** An event to load a Block and insert it into a Graph. - * - * \ingroup engine - */ -class CreateBlock : public Event -{ -public: - CreateBlock(Engine& engine, - SPtr<Interface> client, - int32_t id, - SampleCount timestamp, - const Raul::Path& path, - Properties& properties); - - bool pre_process(PreProcessContext& ctx); - void execute(RunContext& context); - void post_process(); - void undo(Interface& target); - -private: - Raul::Path _path; - Properties& _properties; - ClientUpdate _update; - GraphImpl* _graph; - BlockImpl* _block; - MPtr<CompiledGraph> _compiled_graph; -}; - -} // namespace Events -} // namespace Server -} // namespace Ingen - -#endif // INGEN_EVENTS_CREATEBLOCK_HPP diff --git a/src/server/events/CreateGraph.cpp b/src/server/events/CreateGraph.cpp deleted file mode 100644 index 390fdd9a..00000000 --- a/src/server/events/CreateGraph.cpp +++ /dev/null @@ -1,236 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2016 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/Forge.hpp" -#include "ingen/Store.hpp" -#include "ingen/URIs.hpp" -#include "raul/Maid.hpp" -#include "raul/Path.hpp" - -#include "Broadcaster.hpp" -#include "Engine.hpp" -#include "GraphImpl.hpp" -#include "PreProcessContext.hpp" -#include "events/CreateGraph.hpp" -#include "events/CreatePort.hpp" - -namespace Ingen { -namespace Server { -namespace Events { - -CreateGraph::CreateGraph(Engine& engine, - 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) -{} - -CreateGraph::~CreateGraph() -{ - for (Event* ev : _child_events) { - delete ev; - } -} - -void -CreateGraph::build_child_events() -{ - const Ingen::URIs& uris = _engine.world()->uris(); - - // Properties common to both ports - Properties control_properties; - control_properties.put(uris.atom_bufferType, uris.atom_Sequence); - control_properties.put(uris.atom_supports, uris.patch_Message); - control_properties.put(uris.lv2_designation, uris.lv2_control); - control_properties.put(uris.lv2_portProperty, uris.lv2_connectionOptional); - control_properties.put(uris.rdf_type, uris.atom_AtomPort); - control_properties.put(uris.rsz_minimumSize, uris.forge.make(4096)); - - // Add control port (message receive) - Properties in_properties(control_properties); - 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), - Resource::Graph::EXTERNAL); - in_properties.put(uris.ingen_canvasY, uris.forge.make(32.0f), - Resource::Graph::EXTERNAL); - - _child_events.push_back( - new 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), - Resource::Graph::EXTERNAL); - out_properties.put(uris.ingen_canvasY, uris.forge.make(32.0f), - Resource::Graph::EXTERNAL); - - _child_events.push_back( - new Events::CreatePort(_engine, _request_client, -1, _time, - _path.child(Raul::Symbol("notify")), - out_properties)); -} - -bool -CreateGraph::pre_process(PreProcessContext& ctx) -{ - if (_engine.store()->get(_path)) { - return Event::pre_process_done(Status::EXISTS, _path); - } - - if (!_path.is_root()) { - 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); - } - } - - const Ingen::URIs& uris = _engine.world()->uris(); - - typedef Properties::const_iterator iterator; - - uint32_t ext_poly = 1; - uint32_t int_poly = 1; - iterator p = _properties.find(uris.ingen_polyphony); - if (p != _properties.end() && p->second.type() == uris.forge.Int) { - int_poly = p->second.get<int32_t>(); - } - - if (int_poly < 1 || int_poly > 128) { - return Event::pre_process_done(Status::INVALID_POLY, _path); - } - - if (!_parent || int_poly == _parent->internal_poly()) { - ext_poly = int_poly; - } - - const Raul::Symbol symbol(_path.is_root() ? "graph" : _path.symbol()); - - // Get graph prototype - iterator 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) && - 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))); - 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::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->add_property(uris.rdf_type, - Property(uris.ingen_Block, - Resource::Graph::EXTERNAL)); - } - - _graph->set_properties(_properties); - - if (_parent) { - // Add graph to parent - _parent->add_block(*_graph); - if (_parent->enabled()) { - _graph->enable(); - } - _compiled_graph = ctx.maybe_compile(*_engine.maid(), *_parent); - } - - _graph->activate(*_engine.buffer_factory()); - - // Insert into store and build update to send to clients - _engine.store()->add(_graph); - _update.put_graph(_graph); - for (BlockImpl& block : _graph->blocks()) { - _engine.store()->add(&block); - } - - // Build and pre-process child events to create standard ports - build_child_events(); - for (Event* ev : _child_events) { - ev->pre_process(ctx); - } - - return Event::pre_process_done(Status::SUCCESS); -} - -void -CreateGraph::execute(RunContext& context) -{ - if (_graph) { - if (_parent) { - if (_compiled_graph) { - _parent->set_compiled_graph(std::move(_compiled_graph)); - } - } else { - _engine.set_root_graph(_graph); - _graph->enable(); - } - - for (Event* ev : _child_events) { - ev->execute(context); - } - } -} - -void -CreateGraph::post_process() -{ - Broadcaster::Transfer t(*_engine.broadcaster()); - if (respond() == Status::SUCCESS) { - _update.send(*_engine.broadcaster()); - } - - if (_graph) { - for (Event* ev : _child_events) { - ev->post_process(); - } - } -} - -void -CreateGraph::undo(Interface& target) -{ - target.del(_graph->uri()); -} - -} // namespace Events -} // namespace Server -} // namespace Ingen diff --git a/src/server/events/CreateGraph.hpp b/src/server/events/CreateGraph.hpp deleted file mode 100644 index 564d553b..00000000 --- a/src/server/events/CreateGraph.hpp +++ /dev/null @@ -1,74 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 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_EVENTS_CREATEGRAPH_HPP -#define INGEN_EVENTS_CREATEGRAPH_HPP - -#include <list> - -#include "ingen/Resource.hpp" - -#include "CompiledGraph.hpp" -#include "Event.hpp" -#include "events/Get.hpp" - -namespace Ingen { -namespace Server { - -class GraphImpl; - -namespace Events { - -/** Creates a new Graph. - * - * \ingroup engine - */ -class CreateGraph : public Event -{ -public: - CreateGraph(Engine& engine, - SPtr<Interface> client, - int32_t id, - SampleCount timestamp, - const Raul::Path& path, - const Properties& properties); - - ~CreateGraph(); - - bool pre_process(PreProcessContext& ctx); - void execute(RunContext& context); - void post_process(); - void undo(Interface& target); - - GraphImpl* graph() { return _graph; } - -private: - void build_child_events(); - - const Raul::Path _path; - Properties _properties; - ClientUpdate _update; - GraphImpl* _graph; - GraphImpl* _parent; - MPtr<CompiledGraph> _compiled_graph; - std::list<Event*> _child_events; -}; - -} // namespace Events -} // namespace Server -} // namespace Ingen - -#endif // INGEN_EVENTS_CREATEGRAPH_HPP diff --git a/src/server/events/CreatePort.cpp b/src/server/events/CreatePort.cpp deleted file mode 100644 index e17b8b01..00000000 --- a/src/server/events/CreatePort.cpp +++ /dev/null @@ -1,219 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2016 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 <utility> - -#include "ingen/Atom.hpp" -#include "ingen/Store.hpp" -#include "ingen/URIMap.hpp" -#include "ingen/URIs.hpp" -#include "raul/Array.hpp" -#include "raul/Path.hpp" - -#include "Broadcaster.hpp" -#include "BufferFactory.hpp" -#include "CreatePort.hpp" -#include "Driver.hpp" -#include "DuplexPort.hpp" -#include "Engine.hpp" -#include "GraphImpl.hpp" -#include "PortImpl.hpp" - -namespace Ingen { -namespace Server { -namespace Events { - -CreatePort::CreatePort(Engine& engine, - 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) -{ - const Ingen::URIs& uris = _engine.world()->uris(); - - typedef Properties::const_iterator Iterator; - typedef std::pair<Iterator, Iterator> Range; - - const Range types = properties.equal_range(uris.rdf_type); - for (Iterator i = types.first; i != types.second; ++i) { - const Atom& type = i->second; - if (type == uris.lv2_AudioPort) { - _port_type = PortType::AUDIO; - } else if (type == uris.lv2_ControlPort) { - _port_type = PortType::CONTROL; - } else if (type == uris.lv2_CVPort) { - _port_type = PortType::CV; - } else if (type == uris.atom_AtomPort) { - _port_type = PortType::ATOM; - } else if (type == uris.lv2_InputPort) { - _flow = Flow::INPUT; - } else if (type == uris.lv2_OutputPort) { - _flow = Flow::OUTPUT; - } - } - - const Range buffer_types = properties.equal_range(uris.atom_bufferType); - for (Iterator 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)); - } - } -} - -bool -CreatePort::pre_process(PreProcessContext& ctx) -{ - if (_port_type == PortType::UNKNOWN) { - return Event::pre_process_done(Status::UNKNOWN_TYPE, _path); - } else if (!_flow) { - return Event::pre_process_done(Status::UNKNOWN_TYPE, _path); - } else if (_path.is_root()) { - return Event::pre_process_done(Status::BAD_URI, _path); - } else if (_engine.store()->get(_path)) { - return Event::pre_process_done(Status::EXISTS, _path); - } - - 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))) { - return Event::pre_process_done(Status::INVALID_PARENT, parent_path); - } else if (!_graph->parent() && _engine.activated() && - !_engine.driver()->dynamic_ports()) { - return Event::pre_process_done(Status::CREATION_FAILED, _path); - } - - const URIs& uris = _engine.world()->uris(); - BufferFactory& bufs = *_engine.buffer_factory(); - const uint32_t buf_size = bufs.default_size(_buf_type); - const int32_t old_n_ports = _graph->num_ports_non_rt(); - - typedef Properties::const_iterator PropIter; - - PropIter 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) { - return Event::pre_process_done(Status::BAD_REQUEST); - } - - index = index_i->second.get<int32_t>(); - if (_graph->has_port_with_index(index)) { - return Event::pre_process_done(Status::BAD_INDEX); - } - } else { - // No index given, append - index = old_n_ports; - index_i = _properties.emplace(uris.lv2_index, - _engine.world()->forge().make(index)); - } - - const PropIter 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>()); - - // Create 0 value if the port requires one - Atom value; - if (_port_type == PortType::CONTROL || _port_type == PortType::CV) { - value = bufs.forge().make(0.0f); - } - - // Create port - _graph_port = new DuplexPort(bufs, _graph, Raul::Symbol(_path.symbol()), - index, - polyphonic, - _port_type, _buf_type, buf_size, - value, _flow == Flow::OUTPUT); - assert((_flow == Flow::OUTPUT && _graph_port->is_output()) || - (_flow == Flow::INPUT && _graph_port->is_input())); - _graph_port->properties().insert(_properties.begin(), _properties.end()); - - _engine.store()->add(_graph_port); - if (_flow == Flow::OUTPUT) { - _graph->add_output(*_graph_port); - } else { - _graph->add_input(*_graph_port); - } - - if (!_graph->parent()) { - _engine_port = _engine.driver()->create_port(_graph_port); - } - - _ports_array = bufs.maid().make_managed<GraphImpl::Ports>( - old_n_ports + 1, nullptr); - - _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(_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) -{ - if (_status == Status::SUCCESS) { - const MPtr<GraphImpl::Ports>& 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]; - assert(old_port->index() < _ports_array->size()); - (*_ports_array)[old_port->index()] = (*old_ports)[i]; - } - } - assert(!(*_ports_array)[_graph_port->index()]); - (*_ports_array)[_graph_port->index()] = _graph_port; - _graph->set_external_ports(std::move(_ports_array)); - - if (_engine_port) { - _engine.driver()->add_port(context, _engine_port); - } - } -} - -void -CreatePort::post_process() -{ - Broadcaster::Transfer t(*_engine.broadcaster()); - if (respond() == Status::SUCCESS) { - _engine.broadcaster()->put(path_to_uri(_path), _update); - } -} - -void -CreatePort::undo(Interface& target) -{ - target.del(_graph_port->uri()); -} - -} // namespace Events -} // namespace Server -} // namespace Ingen diff --git a/src/server/events/CreatePort.hpp b/src/server/events/CreatePort.hpp deleted file mode 100644 index a2ea7682..00000000 --- a/src/server/events/CreatePort.hpp +++ /dev/null @@ -1,82 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2016 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_EVENTS_CREATEPORT_HPP -#define INGEN_EVENTS_CREATEPORT_HPP - -#include <boost/optional.hpp> - -#include "ingen/Resource.hpp" -#include "lv2/lv2plug.in/ns/ext/urid/urid.h" -#include "raul/Array.hpp" -#include "raul/Path.hpp" - -#include "BlockImpl.hpp" -#include "Event.hpp" -#include "PortType.hpp" - -namespace Ingen { -namespace Server { - -class DuplexPort; -class EnginePort; -class GraphImpl; -class PortImpl; - -namespace Events { - -/** An event to add a Port to a Graph. - * - * \ingroup engine - */ -class CreatePort : public Event -{ -public: - CreatePort(Engine& engine, - SPtr<Interface> client, - int32_t id, - SampleCount timestamp, - const Raul::Path& path, - const Properties& properties); - - bool pre_process(PreProcessContext& ctx); - void execute(RunContext& context); - void post_process(); - void undo(Interface& target); - -private: - enum class Flow { - INPUT, - 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; -}; - -} // namespace Events -} // namespace Server -} // namespace Ingen - -#endif // INGEN_EVENTS_CREATEPORT_HPP diff --git a/src/server/events/Delete.cpp b/src/server/events/Delete.cpp deleted file mode 100644 index e8f9582c..00000000 --- a/src/server/events/Delete.cpp +++ /dev/null @@ -1,216 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2016 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/Store.hpp" -#include "raul/Maid.hpp" -#include "raul/Path.hpp" - -#include "BlockImpl.hpp" -#include "Broadcaster.hpp" -#include "ControlBindings.hpp" -#include "Delete.hpp" -#include "DisconnectAll.hpp" -#include "Driver.hpp" -#include "Engine.hpp" -#include "EnginePort.hpp" -#include "GraphImpl.hpp" -#include "PluginImpl.hpp" -#include "PortImpl.hpp" -#include "PreProcessContext.hpp" - -namespace Ingen { -namespace Server { -namespace Events { - -Delete::Delete(Engine& engine, - SPtr<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); - } -} - -Delete::~Delete() -{ - delete _disconnect_event; - for (ControlBindings::Binding* b : _removed_bindings) { - delete b; - } -} - -bool -Delete::pre_process(PreProcessContext& ctx) -{ - const Ingen::URIs& uris = _engine.world()->uris(); - if (_path.is_root() || _path == "/control" || _path == "/notify") { - return Event::pre_process_done(Status::NOT_DELETABLE, _path); - } - - _engine.control_bindings()->get_all(_path, _removed_bindings); - - auto iter = _engine.store()->find(_path); - if (iter == _engine.store()->end()) { - 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 && !_port) || (_port && !_engine.driver()->dynamic_ports())) { - return Event::pre_process_done(Status::NOT_DELETABLE, _path); - } - - GraphImpl* parent = _block ? _block->parent_graph() : _port->parent_graph(); - if (!parent) { - return Event::pre_process_done(Status::INTERNAL_ERROR, _path); - } - - // Take a writer lock while we modify the store - std::lock_guard<Store::Mutex> lock(_engine.store()->mutex()); - - _engine.store()->remove(iter, _removed_objects); - - if (_block) { - parent->remove_block(*_block); - _disconnect_event = new DisconnectAll(_engine, parent, _block.get()); - _disconnect_event->pre_process(ctx); - _compiled_graph = ctx.maybe_compile(*_engine.maid(), *parent); - } else if (_port) { - parent->remove_port(*_port); - _disconnect_event = new DisconnectAll(_engine, parent, _port.get()); - _disconnect_event->pre_process(ctx); - - _compiled_graph = ctx.maybe_compile(*_engine.maid(), *parent); - if (parent->enabled()) { - _ports_array = parent->build_ports_array(*_engine.maid()); - assert(_ports_array->size() == parent->num_ports_non_rt()); - - // Adjust port indices if necessary and record changes for later - for (size_t i = 0; i < _ports_array->size(); ++i) { - PortImpl* const port = _ports_array->at(i); - if (port->index() != i) { - _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)); - } - } - } - - if (!parent->parent()) { - _engine_port = _engine.driver()->get_port(_port->path()); - } - } - - return Event::pre_process_done(Status::SUCCESS); -} - -void -Delete::execute(RunContext& context) -{ - if (_status != Status::SUCCESS) { - return; - } - - if (_disconnect_event) { - _disconnect_event->execute(context); - } - - if (!_removed_bindings.empty()) { - _engine.control_bindings()->remove(context, _removed_bindings); - } - - GraphImpl* parent = _block ? _block->parent_graph() : nullptr; - if (_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); - } - } - - // Replace ports array in graph - parent = _port->parent_graph(); - parent->set_external_ports(std::move(_ports_array)); - - if (_engine_port) { - _engine.driver()->remove_port(context, _engine_port); - } - } - - if (parent && _compiled_graph) { - parent->set_compiled_graph(std::move(_compiled_graph)); - } -} - -void -Delete::post_process() -{ - Broadcaster::Transfer t(*_engine.broadcaster()); - if (respond() == Status::SUCCESS && (_block || _port)) { - if (_block) { - _block->deactivate(); - } - - _engine.broadcaster()->message(_msg); - } - - if (_engine_port) { - _engine.driver()->unregister_port(*_engine_port); - delete _engine_port; - } -} - -void -Delete::undo(Interface& target) -{ - const Ingen::URIs& uris = _engine.world()->uris(); - Ingen::Forge& forge = _engine.buffer_factory()->forge(); - - auto i = _removed_objects.find(_path); - if (i != _removed_objects.end()) { - // Undo disconnect - if (_disconnect_event) { - _disconnect_event->undo(target); - } - - // Put deleted item back - target.put(_msg.uri, i->second->properties()); - - // Adjust port indices - for (const auto& c : _port_index_changes) { - if (c.first != _msg.uri.path()) { - target.set_property(path_to_uri(c.first), - uris.lv2_index, - forge.make(int32_t(c.second.first))); - } - } - } -} - -} // namespace Events -} // namespace Server -} // namespace Ingen diff --git a/src/server/events/Delete.hpp b/src/server/events/Delete.hpp deleted file mode 100644 index 8b2a0a91..00000000 --- a/src/server/events/Delete.hpp +++ /dev/null @@ -1,86 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2016 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_EVENTS_DELETE_HPP -#define INGEN_EVENTS_DELETE_HPP - -#include <map> -#include <vector> - -#include "ingen/Store.hpp" - -#include "CompiledGraph.hpp" -#include "ControlBindings.hpp" -#include "Event.hpp" -#include "GraphImpl.hpp" - -namespace Raul { -template<typename T> class Array; -} - -namespace Ingen { -namespace Server { - -class BlockImpl; -class DuplexPort; -class EnginePort; -class PortImpl; - -namespace Events { - -class DisconnectAll; - -/** Delete a graph object. - * \ingroup engine - */ -class Delete : public Event -{ -public: - Delete(Engine& engine, - SPtr<Interface> client, - FrameTime timestamp, - const Ingen::Del& msg); - - ~Delete(); - - bool pre_process(PreProcessContext& ctx); - void execute(RunContext& context); - void post_process(); - void undo(Interface& target); - -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 - DisconnectAll* _disconnect_event; - Store::Objects _removed_objects; - IndexChanges _port_index_changes; - - std::vector<ControlBindings::Binding*> _removed_bindings; -}; - -} // namespace Events -} // namespace Server -} // namespace Ingen - -#endif // INGEN_EVENTS_DELETE_HPP diff --git a/src/server/events/Delta.cpp b/src/server/events/Delta.cpp deleted file mode 100644 index b23ae884..00000000 --- a/src/server/events/Delta.cpp +++ /dev/null @@ -1,670 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2016 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 <vector> -#include <thread> - -#include "ingen/Log.hpp" -#include "ingen/Store.hpp" -#include "ingen/URIs.hpp" -#include "raul/Maid.hpp" - -#include "Broadcaster.hpp" -#include "ControlBindings.hpp" -#include "CreateBlock.hpp" -#include "CreateGraph.hpp" -#include "CreatePort.hpp" -#include "Delta.hpp" -#include "Engine.hpp" -#include "GraphImpl.hpp" -#include "PluginImpl.hpp" -#include "PortImpl.hpp" -#include "PortType.hpp" -#include "SetPortValue.hpp" -#include "events/Get.hpp" - -namespace Ingen { -namespace Server { -namespace Events { - -Delta::Delta(Engine& engine, - SPtr<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, - SPtr<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, - SPtr<Interface> client, - SampleCount timestamp, - const Ingen::SetProperty& msg) - : Event(engine, client, msg.seq, timestamp) - , _create_event(nullptr) - , _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(); -} - -Delta::~Delta() -{ - for (auto& s : _set_events) { - delete s; - } - - delete _create_event; -} - -void -Delta::init() -{ - if (_context != Resource::Graph::DEFAULT) { - for (auto& p : _properties) { - p.second.set_context(_context); - } - } - - // Set atomic execution if polyphony is to be changed - const Ingen::URIs& uris = _engine.world()->uris(); - if (_properties.count(uris.ingen_polyphonic) || - _properties.count(uris.ingen_polyphony)) { - _block = true; - } -} - -void -Delta::add_set_event(const char* port_symbol, - const void* value, - uint32_t size, - uint32_t type) -{ - BlockImpl* block = dynamic_cast<BlockImpl*>(_object); - PortImpl* port = block->port_by_symbol(port_symbol); - if (!port) { - _engine.log().warn(fmt("Unknown port `%1%' in state") % port_symbol); - return; - } - - SetPortValue* ev = new SetPortValue( - _engine, _request_client, _request_id, _time, - port, Atom(size, type, value), false, true); - - _set_events.push_back(ev); -} - -static void -s_add_set_event(const char* port_symbol, - void* user_data, - const void* value, - uint32_t size, - uint32_t type) -{ - ((Delta*)user_data)->add_set_event(port_symbol, value, size, type); -} - -static LilvNode* -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)) { - 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; -} - -bool -Delta::pre_process(PreProcessContext& ctx) -{ - const Ingen::URIs& uris = _engine.world()->uris(); - - const bool is_graph_object = uri_is_path(_subject); - const bool is_client = (_subject == "ingen:/clients/this"); - const bool is_engine = (_subject == "ingen:/"); - const bool is_file = (_subject.scheme() == "file"); - - if (_type == Type::PUT && is_file) { - // Ensure type is Preset, the only supported file put - const auto t = _properties.find(uris.rdf_type); - if (t == _properties.end() || t->second != uris.pset_Preset) { - return Event::pre_process_done(Status::BAD_REQUEST, _subject); - } - - // Get "prototype" for preset (node to save state for) - const auto p = _properties.find(uris.lv2_prototype); - if (p == _properties.end()) { - return Event::pre_process_done(Status::BAD_REQUEST, _subject); - } else if (!_engine.world()->forge().is_uri(p->second)) { - return Event::pre_process_done(Status::BAD_REQUEST, _subject); - } - - const URI prot(_engine.world()->forge().str(p->second, false)); - if (!uri_is_path(prot)) { - return Event::pre_process_done(Status::BAD_URI, _subject); - } - - Node* node = _engine.store()->get(uri_to_path(prot)); - if (!node) { - return Event::pre_process_done(Status::NOT_FOUND, prot); - } - - BlockImpl* block = dynamic_cast<BlockImpl*>(node); - if (!block) { - return Event::pre_process_done(Status::BAD_OBJECT_TYPE, prot); - } - - if ((_preset = block->save_preset(_subject, _properties))) { - return Event::pre_process_done(Status::SUCCESS); - } else { - return Event::pre_process_done(Status::FAILURE); - } - } - - std::lock_guard<Store::Mutex> lock(_engine.store()->mutex()); - - _object = is_graph_object - ? static_cast<Ingen::Resource*>(_engine.store()->get(uri_to_path(_subject))) - : static_cast<Ingen::Resource*>(_engine.block_factory()->plugin(_subject)); - - if (!_object && !is_client && !is_engine && - (!is_graph_object || _type != Type::PUT)) { - return Event::pre_process_done(Status::NOT_FOUND, _subject); - } - - if (is_graph_object && !_object) { - Raul::Path path(uri_to_path(_subject)); - bool is_graph = false, is_block = false, is_port = false, is_output = false; - Ingen::Resource::type(uris, _properties, is_graph, is_block, is_port, is_output); - - if (is_graph) { - _create_event = new CreateGraph( - _engine, _request_client, _request_id, _time, path, _properties); - } else if (is_block) { - _create_event = new CreateBlock( - _engine, _request_client, _request_id, _time, path, _properties); - } else if (is_port) { - _create_event = new 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 - } else { - return Event::pre_process_done(Status::CREATION_FAILED, _subject); - } - } else { - return Event::pre_process_done(Status::BAD_OBJECT_TYPE, _subject); - } - } - - _types.reserve(_properties.size()); - - NodeImpl* obj = dynamic_cast<NodeImpl*>(_object); - - // Remove any properties removed in delta - for (const auto& r : _remove) { - const URI& key = r.first; - const Atom& value = r.second; - if (key == uris.midi_binding && value == uris.patch_wildcard) { - PortImpl* port = dynamic_cast<PortImpl*>(_object); - if (port) { - _engine.control_bindings()->get_all(port->path(), _removed_bindings); - } - } - if (_object) { - _removed.emplace(key, value); - _object->remove_property(key, value); - } else if (is_engine && key == uris.ingen_loadedBundle) { - LilvWorld* lworld = _engine.world()->lilv_world(); - LilvNode* bundle = get_file_node(lworld, uris, value); - if (bundle) { - for (const auto& p : _engine.block_factory()->plugins()) { - if (p.second->bundle_uri() == lilv_node_as_string(bundle)) { - p.second->set_is_zombie(true); - _update.del(p.second->uri()); - } - } - lilv_world_unload_bundle(lworld, bundle); - _engine.block_factory()->refresh(); - lilv_node_free(bundle); - } else { - _status = Status::BAD_VALUE; - } - } - } - - // Remove all added properties if this is a put or set - if (_object && (_type == Type::PUT || _type == Type::SET)) { - for (auto p = _properties.begin(); - p != _properties.end(); - p = _properties.upper_bound(p->first)) { - for (auto q = _object->properties().find(p->first); - q != _object->properties().end() && q->first == p->first;) { - auto next = q; - ++next; - - if (!_properties.contains(q->first, q->second)) { - const auto r = std::make_pair(q->first, q->second); - _object->properties().erase(q); - _object->on_property_removed(r.first, r.second); - _removed.insert(r); - } - - q = next; - } - } - } - - for (const auto& p : _properties) { - const URI& key = p.first; - const Property& value = p.second; - SpecialType op = SpecialType::NONE; - if (obj) { - Resource& resource = *obj; - if (value != uris.patch_wildcard) { - if (resource.add_property(key, value, value.context())) { - _added.emplace(key, value); - } - } - - BlockImpl* block = nullptr; - PortImpl* port = dynamic_cast<PortImpl*>(_object); - if (port) { - if (key == uris.ingen_broadcast) { - if (value.type() == uris.forge.Bool) { - op = SpecialType::ENABLE_BROADCAST; - } else { - _status = Status::BAD_VALUE_TYPE; - } - } else if (key == uris.ingen_value || key == uris.ingen_activity) { - SetPortValue* ev = new SetPortValue( - _engine, _request_client, _request_id, _time, port, value, - key == uris.ingen_activity); - _set_events.push_back(ev); - } else if (key == uris.midi_binding) { - if (port->is_a(PortType::CONTROL) || port->is_a(PortType::CV)) { - if (value == uris.patch_wildcard) { - _engine.control_bindings()->start_learn(port); - } else if (value.type() == uris.atom_Object) { - op = SpecialType::CONTROL_BINDING; - _binding = new ControlBindings::Binding(); - } else { - _status = Status::BAD_VALUE_TYPE; - } - } else { - _status = Status::BAD_OBJECT_TYPE; - } - } else if (key == uris.lv2_index) { - op = SpecialType::PORT_INDEX; - port->set_property(key, value); - } - } else if ((block = dynamic_cast<BlockImpl*>(_object))) { - if (key == uris.midi_binding && value == uris.patch_wildcard) { - op = SpecialType::CONTROL_BINDING; // Internal block learn - } else if (key == uris.ingen_enabled) { - if (value.type() == uris.forge.Bool) { - op = SpecialType::ENABLE; - } else { - _status = Status::BAD_VALUE_TYPE; - } - } else if (key == uris.pset_preset) { - URI uri; - if (uris.forge.is_uri(value)) { - const std::string uri_str = uris.forge.str(value, false); - if (URI::is_valid(uri_str)) { - uri = URI(uri_str); - } - } else if (value.type() == uris.forge.Path) { - uri = URI(FilePath(value.ptr<char>())); - } - - if (!uri.empty()) { - op = SpecialType::PRESET; - if ((_state = block->load_preset(uri))) { - lilv_state_emit_port_values( - _state, s_add_set_event, this); - } else { - _engine.log().warn(fmt("Failed to load preset <%1%>\n") % uri); - } - } else { - _status = Status::BAD_VALUE; - } - } - } - - if ((_graph = dynamic_cast<GraphImpl*>(_object))) { - if (key == uris.ingen_enabled) { - if (value.type() == uris.forge.Bool) { - op = SpecialType::ENABLE; - // FIXME: defer this until all other metadata has been processed - if (value.get<int32_t>() && !_graph->enabled()) { - if (!(_compiled_graph = compile(*_engine.maid(), *_graph))) { - _status = Status::COMPILATION_FAILED; - } - } - } else { - _status = Status::BAD_VALUE_TYPE; - } - } else if (key == uris.ingen_polyphony) { - if (value.type() == uris.forge.Int) { - if (value.get<int32_t>() < 1 || value.get<int32_t>() > 128) { - _status = Status::INVALID_POLY; - } else { - op = SpecialType::POLYPHONY; - _graph->prepare_internal_poly( - *_engine.buffer_factory(), value.get<int32_t>()); - } - } else { - _status = Status::BAD_VALUE_TYPE; - } - } - } - - if (!_create_event && key == uris.ingen_polyphonic) { - GraphImpl* parent = dynamic_cast<GraphImpl*>(obj->parent()); - if (!parent) { - _status = Status::BAD_OBJECT_TYPE; - } else if (value.type() != uris.forge.Bool) { - _status = Status::BAD_VALUE_TYPE; - } else { - op = SpecialType::POLYPHONIC; - obj->set_property(key, value, value.context()); - BlockImpl* block = dynamic_cast<BlockImpl*>(obj); - if (block) { - block->set_polyphonic(value.get<int32_t>()); - } - if (value.get<int32_t>()) { - obj->prepare_poly(*_engine.buffer_factory(), parent->internal_poly()); - } else { - obj->prepare_poly(*_engine.buffer_factory(), 1); - } - } - } - } else if (is_client && key == uris.ingen_broadcast) { - _engine.broadcaster()->set_broadcast( - _request_client, value.get<int32_t>()); - } else if (is_engine && key == uris.ingen_loadedBundle) { - LilvWorld* lworld = _engine.world()->lilv_world(); - LilvNode* bundle = get_file_node(lworld, uris, value); - if (bundle) { - lilv_world_load_bundle(lworld, bundle); - const std::set<PluginImpl*> new_plugins = - _engine.block_factory()->refresh(); - - for (PluginImpl* p : new_plugins) { - if (p->bundle_uri() == lilv_node_as_string(bundle)) { - _update.put_plugin(p); - } - } - lilv_node_free(bundle); - } else { - _status = Status::BAD_VALUE; - } - } - - if (_status != Status::NOT_PREPARED) { - break; - } - - _types.push_back(op); - } - - for (auto& s : _set_events) { - s->pre_process(ctx); - } - - return Event::pre_process_done( - _status == Status::NOT_PREPARED ? Status::SUCCESS : _status, - _subject); -} - -void -Delta::execute(RunContext& context) -{ - if (_status != Status::SUCCESS || _preset) { - return; - } - - const Ingen::URIs& uris = _engine.world()->uris(); - - if (_create_event) { - _create_event->set_time(_time); - _create_event->execute(context); - } - - for (auto& s : _set_events) { - s->set_time(_time); - s->execute(context); - } - - if (!_removed_bindings.empty()) { - _engine.control_bindings()->remove(context, _removed_bindings); - } - - NodeImpl* const object = dynamic_cast<NodeImpl*>(_object); - BlockImpl* const block = dynamic_cast<BlockImpl*>(_object); - PortImpl* const port = dynamic_cast<PortImpl*>(_object); - - std::vector<SpecialType>::const_iterator t = _types.begin(); - for (const auto& p : _properties) { - const URI& key = p.first; - const Atom& value = p.second; - switch (*t++) { - case SpecialType::ENABLE_BROADCAST: - if (port) { - port->enable_monitoring(value.get<int32_t>()); - } - break; - case SpecialType::ENABLE: - if (_graph) { - if (value.get<int32_t>()) { - if (_compiled_graph) { - _graph->set_compiled_graph(std::move(_compiled_graph)); - } - _graph->enable(); - } else { - _graph->disable(context); - } - } else if (block) { - block->set_enabled(value.get<int32_t>()); - } - break; - case SpecialType::POLYPHONIC: { - GraphImpl* parent = reinterpret_cast<GraphImpl*>(object->parent()); - if (value.get<int32_t>()) { - object->apply_poly(context, parent->internal_poly_process()); - } else { - object->apply_poly(context, 1); - } - } break; - case SpecialType::POLYPHONY: - if (!_graph->apply_internal_poly(context, - *_engine.buffer_factory(), - *_engine.maid(), - value.get<int32_t>())) { - _status = Status::INTERNAL_ERROR; - } - break; - case SpecialType::PORT_INDEX: - if (port) { - port->set_index(context, value.get<int32_t>()); - } - break; - case SpecialType::CONTROL_BINDING: - if (port) { - if (!_engine.control_bindings()->set_port_binding(context, port, _binding, value)) { - _status = Status::BAD_VALUE; - } - } else if (block) { - if (uris.ingen_Internal == block->plugin_impl()->type()) { - block->learn(); - } - } - break; - case SpecialType::PRESET: - block->set_enabled(false); - break; - case SpecialType::NONE: - if (port) { - if (key == uris.lv2_minimum) { - port->set_minimum(value); - } else if (key == uris.lv2_maximum) { - port->set_maximum(value); - } - } - case SpecialType::LOADED_BUNDLE: - break; - } - } -} - -void -Delta::post_process() -{ - if (_state) { - BlockImpl* block = dynamic_cast<BlockImpl*>(_object); - if (block) { - block->apply_state(_engine.sync_worker(), _state); - block->set_enabled(true); - } - lilv_state_free(_state); - } - - 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 - } - } - - for (auto& s : _set_events) { - if (s->synthetic() || s->status() != Status::SUCCESS) { - s->post_process(); // Set failed, report error - } - } - - if (respond() == Status::SUCCESS) { - _update.send(*_engine.broadcaster()); - - switch (_type) { - case Type::SET: - /* Kludge to avoid feedback for set events only. The GUI - depends on put responses to e.g. initially place blocks. - Some more sensible way of controlling this is needed. */ - if (_mode == Mode::NORMAL) { - _engine.broadcaster()->set_ignore_client(_request_client); - } - _engine.broadcaster()->set_property( - _subject, - _properties.begin()->first, - _properties.begin()->second); - if (_mode == Mode::NORMAL) { - _engine.broadcaster()->clear_ignore_client(); - } - break; - case Type::PUT: - if (_type == Type::PUT && _subject.scheme() == "file") { - // Preset save - ClientUpdate response; - response.put(_preset->uri(), _preset->properties()); - response.send(*_engine.broadcaster()); - } else { - // Graph object put - _engine.broadcaster()->put(_subject, _properties, _context); - } - break; - case Type::PATCH: - _engine.broadcaster()->delta(_subject, _remove, _properties, _context); - break; - } - } -} - -void -Delta::undo(Interface& target) -{ - if (_create_event) { - _create_event->undo(target); - } else if (_type == Type::PATCH) { - target.delta(_subject, _added, _removed, _context); - } else if (_type == Type::SET || _type == Type::PUT) { - if (_removed.size() == 1) { - target.set_property(_subject, - _removed.begin()->first, - _removed.begin()->second, - _context); - } else if (_removed.empty()) { - target.delta(_subject, _added, {}, _context); - } else { - target.put(_subject, _removed, _context); - } - } -} - -Event::Execution -Delta::get_execution() const -{ - return _block ? Execution::ATOMIC : Execution::NORMAL; -} - -} // namespace Events -} // namespace Server -} // namespace Ingen diff --git a/src/server/events/Delta.hpp b/src/server/events/Delta.hpp deleted file mode 100644 index af337b57..00000000 --- a/src/server/events/Delta.hpp +++ /dev/null @@ -1,133 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2016 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_EVENTS_DELTA_HPP -#define INGEN_EVENTS_DELTA_HPP - -#include <vector> - -#include <boost/optional.hpp> - -#include "lilv/lilv.h" - -#include "CompiledGraph.hpp" -#include "ControlBindings.hpp" -#include "Event.hpp" -#include "PluginImpl.hpp" - -namespace Ingen { - -class Resource; - -namespace Server { - -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, - SPtr<Interface> client, - SampleCount timestamp, - const Ingen::Put& msg); - - Delta(Engine& engine, - SPtr<Interface> client, - SampleCount timestamp, - const Ingen::Delta& msg); - - Delta(Engine& engine, - SPtr<Interface> client, - SampleCount timestamp, - const Ingen::SetProperty& msg); - - ~Delta(); - - void add_set_event(const char* port_symbol, - const void* value, - uint32_t size, - uint32_t type); - - bool pre_process(PreProcessContext& ctx); - void execute(RunContext& context); - void post_process(); - void undo(Interface& target); - - Execution get_execution() const; - -private: - enum class Type { - SET, - PUT, - PATCH - }; - - enum class SpecialType { - NONE, - ENABLE, - ENABLE_BROADCAST, - POLYPHONY, - POLYPHONIC, - PORT_INDEX, - CONTROL_BINDING, - PRESET, - LOADED_BUNDLE - }; - - typedef std::vector<SetPortValue*> SetEvents; - - void init(); - - 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; - - Properties _added; - Properties _removed; - - std::vector<ControlBindings::Binding*> _removed_bindings; - - boost::optional<Resource> _preset; - - bool _block; -}; - -} // namespace Events -} // namespace Server -} // namespace Ingen - -#endif // INGEN_EVENTS_DELTA_HPP diff --git a/src/server/events/Disconnect.cpp b/src/server/events/Disconnect.cpp deleted file mode 100644 index 4553c8a2..00000000 --- a/src/server/events/Disconnect.cpp +++ /dev/null @@ -1,224 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2016 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 <set> - -#include "ingen/Store.hpp" -#include "raul/Maid.hpp" -#include "raul/Path.hpp" - -#include "ArcImpl.hpp" -#include "Broadcaster.hpp" -#include "Buffer.hpp" -#include "DuplexPort.hpp" -#include "Engine.hpp" -#include "GraphImpl.hpp" -#include "InputPort.hpp" -#include "PortImpl.hpp" -#include "PreProcessContext.hpp" -#include "RunContext.hpp" -#include "ThreadManager.hpp" -#include "events/Disconnect.hpp" - -namespace Ingen { -namespace Server { -namespace Events { - -Disconnect::Disconnect(Engine& engine, - SPtr<Interface> client, - SampleCount timestamp, - const Ingen::Disconnect& msg) - : Event(engine, client, msg.seq, timestamp) - , _msg(msg) - , _graph(nullptr) - , _impl(nullptr) -{ -} - -Disconnect::~Disconnect() -{ - delete _impl; -} - -Disconnect::Impl::Impl(Engine& e, - GraphImpl* graph, - PortImpl* t, - InputPort* h) - : _engine(e) - , _tail(t) - , _head(h) - , _arc(graph->remove_arc(_tail, _head)) -{ - ThreadManager::assert_thread(THREAD_PRE_PROCESS); - - BlockImpl* const tail_block = _tail->parent_block(); - BlockImpl* const head_block = _head->parent_block(); - - // Remove tail from head's providers - auto hp = head_block->providers().find(tail_block); - if (hp != head_block->providers().end()) { - head_block->providers().erase(hp); - } - - // Remove head from tail's providers - auto td = tail_block->dependants().find(head_block); - if (td != tail_block->dependants().end()) { - tail_block->dependants().erase(td); - } - - _head->decrement_num_arcs(); - - if (_head->num_arcs() == 0) { - if (!_head->is_driver_port()) { - BufferFactory& bufs = *_engine.buffer_factory(); - _voices = bufs.maid().make_managed<PortImpl::Voices>(_head->poly()); - _head->pre_get_buffers(bufs, _voices, _head->poly()); - - if (_head->is_a(PortType::CONTROL) || - _head->is_a(PortType::CV)) { - // Reset buffer to control value - const float value = _head->value().get<float>(); - for (uint32_t i = 0; i < _voices->size(); ++i) { - Buffer* buf = _voices->at(i).buffer.get(); - buf->set_block(value, 0, e.block_length()); - } - } else { - for (uint32_t i = 0; i < _voices->size(); ++i) { - _voices->at(i).buffer->clear(); - } - } - } - } -} - -bool -Disconnect::pre_process(PreProcessContext& ctx) -{ - 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() - && _msg.tail.parent().parent() != _msg.head.parent()) { - return Event::pre_process_done(Status::PARENT_DIFFERS, _msg.head); - } - - PortImpl* tail = dynamic_cast<PortImpl*>(_engine.store()->get(_msg.tail)); - if (!tail) { - return Event::pre_process_done(Status::PORT_NOT_FOUND, _msg.tail); - } - - PortImpl* head = dynamic_cast<PortImpl*>(_engine.store()->get(_msg.head)); - if (!head) { - return Event::pre_process_done(Status::PORT_NOT_FOUND, _msg.head); - } - - BlockImpl* const tail_block = tail->parent_block(); - BlockImpl* const head_block = head->parent_block(); - - if (tail_block->parent_graph() != head_block->parent_graph()) { - // Arc to a graph port from inside the graph - assert(tail_block->parent() == head_block || head_block->parent() == tail_block); - if (tail_block->parent() == head_block) { - _graph = dynamic_cast<GraphImpl*>(head_block); - } else { - _graph = dynamic_cast<GraphImpl*>(tail_block); - } - } else if (tail_block == head_block && dynamic_cast<GraphImpl*>(tail_block)) { - // Arc from a graph input to a graph output (pass through) - _graph = dynamic_cast<GraphImpl*>(tail_block); - } else { - // Normal arc between blocks with the same parent - _graph = tail_block->parent_graph(); - } - - if (!_graph) { - return Event::pre_process_done(Status::INTERNAL_ERROR, _msg.head); - } else if (!_graph->has_arc(tail, head)) { - return Event::pre_process_done(Status::NOT_FOUND, _msg.head); - } - - if (tail_block == nullptr || head_block == nullptr) { - return Event::pre_process_done(Status::PARENT_NOT_FOUND, _msg.head); - } - - _impl = new Impl(_engine, - _graph, - dynamic_cast<PortImpl*>(tail), - dynamic_cast<InputPort*>(head)); - - _compiled_graph = ctx.maybe_compile(*_engine.maid(), *_graph); - - return Event::pre_process_done(Status::SUCCESS); -} - -bool -Disconnect::Impl::execute(RunContext& context, bool set_head_buffers) -{ - if (!_arc) { - return false; - } - - _head->remove_arc(*_arc.get()); - if (_head->is_driver_port()) { - return true; - } - - if (set_head_buffers) { - if (_voices) { - _head->set_voices(context, std::move(_voices)); - } else { - _head->setup_buffers(context, *_engine.buffer_factory(), _head->poly()); - } - _head->connect_buffers(); - } else { - _head->recycle_buffers(); - } - - return true; -} - -void -Disconnect::execute(RunContext& context) -{ - if (_status == Status::SUCCESS) { - if (_impl->execute(context, true)) { - if (_compiled_graph) { - _graph->set_compiled_graph(std::move(_compiled_graph)); - } - } else { - _status = Status::NOT_FOUND; - } - } -} - -void -Disconnect::post_process() -{ - Broadcaster::Transfer t(*_engine.broadcaster()); - if (respond() == Status::SUCCESS) { - _engine.broadcaster()->message(_msg); - } -} - -void -Disconnect::undo(Interface& target) -{ - target.connect(_msg.tail, _msg.head); -} - -} // namespace Events -} // namespace Server -} // namespace Ingen diff --git a/src/server/events/Disconnect.hpp b/src/server/events/Disconnect.hpp deleted file mode 100644 index 44290d7c..00000000 --- a/src/server/events/Disconnect.hpp +++ /dev/null @@ -1,87 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2016 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_EVENTS_DISCONNECT_HPP -#define INGEN_EVENTS_DISCONNECT_HPP - -#include "raul/Path.hpp" - -#include "BufferFactory.hpp" -#include "CompiledGraph.hpp" -#include "Event.hpp" -#include "GraphImpl.hpp" -#include "types.hpp" - -namespace Raul { -template <typename T> class Array; -} - -namespace Ingen { -namespace Server { - -class InputPort; -class PortImpl; - -namespace Events { - -/** Remove an Arc between two Ports. - * - * \ingroup engine - */ -class Disconnect : public Event -{ -public: - Disconnect(Engine& engine, - SPtr<Interface> client, - SampleCount timestamp, - const Ingen::Disconnect& msg); - - ~Disconnect(); - - bool pre_process(PreProcessContext& ctx); - void execute(RunContext& context); - void post_process(); - void undo(Interface& target); - - class Impl { - public: - Impl(Engine& e, GraphImpl* graph, PortImpl* t, InputPort* h); - - bool execute(RunContext& context, bool set_head_buffers); - - inline PortImpl* tail() { return _tail; } - inline InputPort* head() { return _head; } - - private: - Engine& _engine; - PortImpl* _tail; - InputPort* _head; - SPtr<ArcImpl> _arc; - MPtr<PortImpl::Voices> _voices; - }; - -private: - const Ingen::Disconnect _msg; - GraphImpl* _graph; - Impl* _impl; - MPtr<CompiledGraph> _compiled_graph; -}; - -} // namespace Events -} // namespace Server -} // namespace Ingen - -#endif // INGEN_EVENTS_DISCONNECT_HPP diff --git a/src/server/events/DisconnectAll.cpp b/src/server/events/DisconnectAll.cpp deleted file mode 100644 index 11311d12..00000000 --- a/src/server/events/DisconnectAll.cpp +++ /dev/null @@ -1,176 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2016 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 <set> - -#include "ingen/Store.hpp" -#include "raul/Array.hpp" -#include "raul/Maid.hpp" -#include "raul/Path.hpp" - -#include "ArcImpl.hpp" -#include "BlockImpl.hpp" -#include "Broadcaster.hpp" -#include "Engine.hpp" -#include "GraphImpl.hpp" -#include "InputPort.hpp" -#include "PortImpl.hpp" -#include "PreProcessContext.hpp" -#include "events/Disconnect.hpp" -#include "events/DisconnectAll.hpp" -#include "util.hpp" - -namespace Ingen { -namespace Server { -namespace Events { - -DisconnectAll::DisconnectAll(Engine& engine, - 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) -{ -} - -/** Internal version for use by other events. - */ -DisconnectAll::DisconnectAll(Engine& engine, - GraphImpl* parent, - Node* object) - : Event(engine) - , _msg{0, parent->path(), object->path()} - , _parent(parent) - , _block(dynamic_cast<BlockImpl*>(object)) - , _port(dynamic_cast<PortImpl*>(object)) - , _deleting(true) -{ -} - -DisconnectAll::~DisconnectAll() -{ - for (auto& i : _impls) { - delete i; - } -} - -bool -DisconnectAll::pre_process(PreProcessContext& ctx) -{ - std::unique_lock<Store::Mutex> lock(_engine.store()->mutex(), - std::defer_lock); - - if (!_deleting) { - lock.lock(); - - _parent = dynamic_cast<GraphImpl*>(_engine.store()->get(_msg.graph)); - if (!_parent) { - return Event::pre_process_done(Status::PARENT_NOT_FOUND, - _msg.graph); - } - - NodeImpl* const object = dynamic_cast<NodeImpl*>( - _engine.store()->get(_msg.path)); - if (!object) { - return Event::pre_process_done(Status::NOT_FOUND, _msg.path); - } - - if (object->parent_graph() != _parent - && object->parent()->parent_graph() != _parent) { - return Event::pre_process_done(Status::INVALID_PARENT, _msg.graph); - } - - // Only one of these will succeed - _block = dynamic_cast<BlockImpl*>(object); - _port = dynamic_cast<PortImpl*>(object); - - if (!_block && !_port) { - return Event::pre_process_done(Status::INTERNAL_ERROR, _msg.path); - } - } - - // Find set of arcs to remove - std::set<ArcImpl*> to_remove; - for (const auto& a : _parent->arcs()) { - ArcImpl* const arc = (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()))); - } - - if (!_deleting && ctx.must_compile(*_parent)) { - if (!(_compiled_graph = compile(*_engine.maid(), *_parent))) { - return Event::pre_process_done(Status::COMPILATION_FAILED); - } - } - - return Event::pre_process_done(Status::SUCCESS); -} - -void -DisconnectAll::execute(RunContext& context) -{ - if (_status == Status::SUCCESS) { - for (auto& i : _impls) { - i->execute(context, - !_deleting || (i->head()->parent_block() != _block)); - } - } - - if (_compiled_graph) { - _parent->set_compiled_graph(std::move(_compiled_graph)); - } -} - -void -DisconnectAll::post_process() -{ - Broadcaster::Transfer t(*_engine.broadcaster()); - if (respond() == Status::SUCCESS) { - _engine.broadcaster()->message(_msg); - } -} - -void -DisconnectAll::undo(Interface& target) -{ - for (auto& i : _impls) { - target.connect(i->tail()->path(), i->head()->path()); - } -} - -} // namespace Events -} // namespace Server -} // namespace Ingen diff --git a/src/server/events/DisconnectAll.hpp b/src/server/events/DisconnectAll.hpp deleted file mode 100644 index 947e538f..00000000 --- a/src/server/events/DisconnectAll.hpp +++ /dev/null @@ -1,78 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2016 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_EVENTS_DISCONNECTALL_HPP -#define INGEN_EVENTS_DISCONNECTALL_HPP - -#include <list> - -#include "raul/Path.hpp" - -#include "CompiledGraph.hpp" -#include "Disconnect.hpp" -#include "Event.hpp" - -namespace Ingen { -namespace Server { - -class BlockImpl; -class GraphImpl; -class PortImpl; - -namespace Events { - -class Disconnect; - -/** An event to disconnect all connections to a Block. - * - * \ingroup engine - */ -class DisconnectAll : public Event -{ -public: - DisconnectAll(Engine& engine, - SPtr<Interface> client, - SampleCount timestamp, - const Ingen::DisconnectAll& msg); - - DisconnectAll(Engine& engine, - GraphImpl* parent, - Node* object); - - ~DisconnectAll(); - - bool pre_process(PreProcessContext& ctx); - void execute(RunContext& context); - void post_process(); - void undo(Interface& target); - -private: - typedef std::list<Disconnect::Impl*> Impls; - - const Ingen::DisconnectAll _msg; - GraphImpl* _parent; - BlockImpl* _block; - PortImpl* _port; - Impls _impls; - MPtr<CompiledGraph> _compiled_graph; - bool _deleting; -}; - -} // namespace Events -} // namespace Server -} // namespace Ingen - -#endif // INGEN_EVENTS_DISCONNECTALL_HPP diff --git a/src/server/events/Get.cpp b/src/server/events/Get.cpp deleted file mode 100644 index e53e8c41..00000000 --- a/src/server/events/Get.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/* - 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/>. -*/ - -#include <utility> - -#include "ingen/Interface.hpp" -#include "ingen/Node.hpp" -#include "ingen/Store.hpp" - -#include "BlockImpl.hpp" -#include "Broadcaster.hpp" -#include "BufferFactory.hpp" -#include "Engine.hpp" -#include "Get.hpp" -#include "GraphImpl.hpp" -#include "PluginImpl.hpp" -#include "PortImpl.hpp" - -namespace Ingen { -namespace Server { -namespace Events { - -Get::Get(Engine& engine, - SPtr<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& ctx) -{ - 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") { - return Event::pre_process_done(Status::SUCCESS); - } else if (uri_is_path(uri)) { - if ((_object = _engine.store()->get(uri_to_path(uri)))) { - const BlockImpl* block = nullptr; - const GraphImpl* graph = nullptr; - const PortImpl* port = nullptr; - if ((graph = dynamic_cast<const GraphImpl*>(_object))) { - _response.put_graph(graph); - } else if ((block = dynamic_cast<const BlockImpl*>(_object))) { - _response.put_block(block); - } else if ((port = dynamic_cast<const PortImpl*>(_object))) { - _response.put_port(port); - } else { - return Event::pre_process_done(Status::BAD_OBJECT_TYPE, uri); - } - return Event::pre_process_done(Status::SUCCESS); - } - return Event::pre_process_done(Status::NOT_FOUND, uri); - } else 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); - } -} - -void -Get::post_process() -{ - 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); - } else if (_msg.subject == "ingen:/engine") { - // TODO: Keep a proper RDF model of the engine - URIs& uris = _engine.world()->uris(); - Properties props = { - { uris.param_sampleRate, - uris.forge.make(int32_t(_engine.sample_rate())) }, - { uris.bufsz_maxBlockLength, - uris.forge.make(int32_t(_engine.block_length())) }, - { uris.ingen_numThreads, - uris.forge.make(int32_t(_engine.n_threads())) } }; - - const Properties load_props = _engine.load_properties(); - props.insert(load_props.begin(), load_props.end()); - _request_client->put(URI("ingen:/engine"), props); - } else { - _response.send(*_request_client); - } - } -} - -} // namespace Events -} // namespace Server -} // namespace Ingen diff --git a/src/server/events/Get.hpp b/src/server/events/Get.hpp deleted file mode 100644 index 7392550f..00000000 --- a/src/server/events/Get.hpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 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_EVENTS_GET_HPP -#define INGEN_EVENTS_GET_HPP - -#include <vector> - -#include "BlockFactory.hpp" -#include "ClientUpdate.hpp" -#include "Event.hpp" -#include "types.hpp" - -namespace Ingen { -namespace Server { - -class BlockImpl; -class GraphImpl; -class PluginImpl; -class PortImpl; - -namespace Events { - -/** A request from a client to send an object. - * - * \ingroup engine - */ -class Get : public Event -{ -public: - Get(Engine& engine, - SPtr<Interface> client, - SampleCount timestamp, - const Ingen::Get& msg); - - bool pre_process(PreProcessContext& ctx); - void execute(RunContext& context) {} - void post_process(); - -private: - const Ingen::Get _msg; - const Node* _object; - PluginImpl* _plugin; - BlockFactory::Plugins _plugins; - ClientUpdate _response; -}; - -} // namespace Events -} // namespace Server -} // namespace Ingen - -#endif // INGEN_EVENTS_GET_HPP diff --git a/src/server/events/Mark.cpp b/src/server/events/Mark.cpp deleted file mode 100644 index 3c0dfaaf..00000000 --- a/src/server/events/Mark.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2016 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 "Engine.hpp" -#include "PreProcessContext.hpp" -#include "UndoStack.hpp" -#include "events/Mark.hpp" - -namespace Ingen { -namespace Server { -namespace Events { - -Mark::Mark(Engine& engine, - SPtr<Interface> client, - SampleCount timestamp, - const Ingen::BundleBegin& msg) - : Event(engine, client, msg.seq, timestamp) - , _type(Type::BUNDLE_BEGIN) - , _depth(0) -{} - -Mark::Mark(Engine& engine, - SPtr<Interface> client, - SampleCount timestamp, - const Ingen::BundleEnd& msg) - : Event(engine, client, msg.seq, timestamp) - , _type(Type::BUNDLE_END) - , _depth(0) -{} - -bool -Mark::pre_process(PreProcessContext& ctx) -{ - const UPtr<UndoStack>& stack = ((_mode == Mode::UNDO) - ? _engine.redo_stack() - : _engine.undo_stack()); - - switch (_type) { - case Type::BUNDLE_BEGIN: - ctx.set_in_bundle(true); - _depth = stack->start_entry(); - break; - case Type::BUNDLE_END: - _depth = stack->finish_entry(); - ctx.set_in_bundle(false); - if (!ctx.dirty_graphs().empty()) { - for (GraphImpl* g : ctx.dirty_graphs()) { - MPtr<CompiledGraph> cg = compile(*_engine.maid(), *g); - if (cg) { - _compiled_graphs.emplace(g, std::move(cg)); - } - } - ctx.dirty_graphs().clear(); - } - break; - } - - return Event::pre_process_done(Status::SUCCESS); -} - -void -Mark::execute(RunContext& context) -{ - for (auto& g : _compiled_graphs) { - g.first->set_compiled_graph(std::move(g.second)); - } -} - -void -Mark::post_process() -{ - respond(); -} - -Event::Execution -Mark::get_execution() const -{ - if (!_engine.atomic_bundles()) { - return Execution::NORMAL; - } - - switch (_type) { - case Type::BUNDLE_BEGIN: - if (_depth == 1) { - return Execution::BLOCK; - } - break; - case Type::BUNDLE_END: - if (_depth == 0) { - return Execution::UNBLOCK; - } - break; - } - return Execution::NORMAL; -} - -} // namespace Events -} // namespace Server -} // namespace Ingen diff --git a/src/server/events/Mark.hpp b/src/server/events/Mark.hpp deleted file mode 100644 index eaeb9332..00000000 --- a/src/server/events/Mark.hpp +++ /dev/null @@ -1,69 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2016 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_EVENTS_MARK_HPP -#define INGEN_EVENTS_MARK_HPP - -#include "Event.hpp" - -namespace Ingen { -namespace Server { - -class Engine; - -namespace Events { - -/** Delineate the start or end of a bundle of events. - * - * This is used to mark the ends of an undo transaction, so a single undo can - * undo the effects of many events (such as a paste or a graph load). - * - * \ingroup engine - */ -class Mark : public Event -{ -public: - Mark(Engine& engine, - SPtr<Interface> client, - SampleCount timestamp, - const Ingen::BundleBegin& msg); - - Mark(Engine& engine, - SPtr<Interface> client, - SampleCount timestamp, - const Ingen::BundleEnd& msg); - - bool pre_process(PreProcessContext& ctx); - void execute(RunContext& context); - void post_process(); - - Execution get_execution() const; - -private: - enum class Type { BUNDLE_BEGIN, BUNDLE_END }; - - typedef std::map<GraphImpl*, MPtr<CompiledGraph>> CompiledGraphs; - - CompiledGraphs _compiled_graphs; - Type _type; - int _depth; -}; - -} // namespace Events -} // namespace Server -} // namespace Ingen - -#endif // INGEN_EVENTS_MARK_HPP diff --git a/src/server/events/Move.cpp b/src/server/events/Move.cpp deleted file mode 100644 index b0935675..00000000 --- a/src/server/events/Move.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2016 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/Store.hpp" -#include "raul/Path.hpp" - -#include "BlockImpl.hpp" -#include "Broadcaster.hpp" -#include "Driver.hpp" -#include "Engine.hpp" -#include "EnginePort.hpp" -#include "GraphImpl.hpp" -#include "events/Move.hpp" - -namespace Ingen { -namespace Server { -namespace Events { - -Move::Move(Engine& engine, - SPtr<Interface> client, - SampleCount timestamp, - const Ingen::Move& msg) - : Event(engine, client, msg.seq, timestamp) - , _msg(msg) -{ -} - -bool -Move::pre_process(PreProcessContext& ctx) -{ - 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); - if (i == _engine.store()->end()) { - return Event::pre_process_done(Status::NOT_FOUND, _msg.old_path); - } - - if (_engine.store()->find(_msg.new_path) != _engine.store()->end()) { - return Event::pre_process_done(Status::EXISTS, _msg.new_path); - } - - EnginePort* eport = _engine.driver()->get_port(_msg.old_path); - if (eport) { - _engine.driver()->rename_port(_msg.old_path, _msg.new_path); - } - - _engine.store()->rename(i, _msg.new_path); - - return Event::pre_process_done(Status::SUCCESS); -} - -void -Move::execute(RunContext& context) -{ -} - -void -Move::post_process() -{ - Broadcaster::Transfer t(*_engine.broadcaster()); - if (respond() == Status::SUCCESS) { - _engine.broadcaster()->message(_msg); - } -} - -void -Move::undo(Interface& target) -{ - target.move(_msg.new_path, _msg.old_path); -} - -} // namespace Events -} // namespace Server -} // namespace Ingen diff --git a/src/server/events/Move.hpp b/src/server/events/Move.hpp deleted file mode 100644 index 459d2709..00000000 --- a/src/server/events/Move.hpp +++ /dev/null @@ -1,57 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2016 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_EVENTS_MOVE_HPP -#define INGEN_EVENTS_MOVE_HPP - -#include "ingen/Store.hpp" -#include "raul/Path.hpp" - -#include "Event.hpp" - -namespace Ingen { -namespace Server { - -class GraphImpl; -class PortImpl; - -namespace Events { - -/** Move a graph object to a new path. - * \ingroup engine - */ -class Move : public Event -{ -public: - Move(Engine& engine, - SPtr<Interface> client, - SampleCount timestamp, - const Ingen::Move& msg); - - bool pre_process(PreProcessContext& ctx); - void execute(RunContext& context); - void post_process(); - void undo(Interface& target); - -private: - const Ingen::Move _msg; -}; - -} // namespace Events -} // namespace Server -} // namespace Ingen - -#endif // INGEN_EVENTS_MOVE_HPP diff --git a/src/server/events/SetPortValue.cpp b/src/server/events/SetPortValue.cpp deleted file mode 100644 index 62f2def6..00000000 --- a/src/server/events/SetPortValue.cpp +++ /dev/null @@ -1,139 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 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/LV2Features.hpp" -#include "ingen/Store.hpp" -#include "ingen/URIs.hpp" -#include "ingen/World.hpp" - -#include "BlockImpl.hpp" -#include "Broadcaster.hpp" -#include "Buffer.hpp" -#include "ControlBindings.hpp" -#include "Engine.hpp" -#include "PortImpl.hpp" -#include "RunContext.hpp" -#include "SetPortValue.hpp" - -namespace Ingen { -namespace Server { -namespace Events { - -/** Internal */ -SetPortValue::SetPortValue(Engine& engine, - SPtr<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& ctx) -{ - Ingen::URIs& uris = _engine.world()->uris(); - if (_port->is_output()) { - return Event::pre_process_done(Status::DIRECTION_MISMATCH, _port->path()); - } - - if (!_activity) { - // Set value metadata (does not affect buffers) - _port->set_value(_value); - _port->set_property(_engine.world()->uris().ingen_value, _value); - } - - _binding = _engine.control_bindings()->port_binding(_port); - - if (_port->buffer_type() == uris.atom_Sequence) { - _buffer = _engine.buffer_factory()->get_buffer( - _port->buffer_type(), - _value.type() == uris.atom_Float ? _value.type() : 0, - _engine.buffer_factory()->default_size(_port->buffer_type())); - } - - return Event::pre_process_done(Status::SUCCESS); -} - -void -SetPortValue::execute(RunContext& context) -{ - assert(_time >= context.start() && _time <= context.end()); - apply(context); - _engine.control_bindings()->port_value_changed(context, _port, _binding, _value); -} - -void -SetPortValue::apply(RunContext& context) -{ - if (_status != Status::SUCCESS) { - return; - } - - 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(); - } else { - _port->set_user_buffer(context, _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>()); - } else { - _status = Status::TYPE_MISMATCH; - } - } else if (buf->type() == uris.atom_Sequence) { - if (!buf->append_event(_time - context.start(), - _value.size(), - _value.type(), - (const uint8_t*)_value.get_body())) { - _status = Status::NO_SPACE; - } - } else if (buf->type() == uris.atom_URID) { - buf->get<LV2_Atom_URID>()->body = _value.get<int32_t>(); - } else { - _status = Status::BAD_VALUE_TYPE; - } -} - -void -SetPortValue::post_process() -{ - Broadcaster::Transfer t(*_engine.broadcaster()); - if (respond() == Status::SUCCESS && !_activity) { - _engine.broadcaster()->set_property( - _port->uri(), - _engine.world()->uris().ingen_value, - _value); - } -} - -} // namespace Events -} // namespace Server -} // namespace Ingen diff --git a/src/server/events/SetPortValue.hpp b/src/server/events/SetPortValue.hpp deleted file mode 100644 index 4df60019..00000000 --- a/src/server/events/SetPortValue.hpp +++ /dev/null @@ -1,71 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 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_EVENTS_SETPORTVALUE_HPP -#define INGEN_EVENTS_SETPORTVALUE_HPP - -#include "ingen/Atom.hpp" - -#include "BufferRef.hpp" -#include "ControlBindings.hpp" -#include "Event.hpp" -#include "types.hpp" - -namespace Ingen { -namespace Server { - -class PortImpl; - -namespace Events { - -/** An event to change the value of a port. - * - * \ingroup engine - */ -class SetPortValue : public Event -{ -public: - SetPortValue(Engine& engine, - SPtr<Interface> client, - int32_t id, - SampleCount timestamp, - PortImpl* port, - const Atom& value, - bool activity, - bool synthetic = false); - - bool pre_process(PreProcessContext& ctx); - void execute(RunContext& context); - void post_process(); - - bool synthetic() const { return _synthetic; } - -private: - void apply(RunContext& context); - - PortImpl* _port; - const Atom _value; - BufferRef _buffer; - ControlBindings::Key _binding; - bool _activity; - bool _synthetic; -}; - -} // namespace Events -} // namespace Server -} // namespace Ingen - -#endif // INGEN_EVENTS_SETPORTVALUE_HPP diff --git a/src/server/events/Undo.cpp b/src/server/events/Undo.cpp deleted file mode 100644 index e06a5951..00000000 --- a/src/server/events/Undo.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2016 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/AtomReader.hpp" - -#include "Engine.hpp" -#include "EventWriter.hpp" -#include "Undo.hpp" - -namespace Ingen { -namespace Server { -namespace Events { - -Undo::Undo(Engine& engine, - SPtr<Interface> client, - SampleCount timestamp, - const Ingen::Undo& msg) - : Event(engine, client, msg.seq, timestamp) - , _is_redo(false) -{} - -Undo::Undo(Engine& engine, - SPtr<Interface> client, - SampleCount timestamp, - const Ingen::Redo& msg) - : Event(engine, client, msg.seq, timestamp) - , _is_redo(true) -{} - -bool -Undo::pre_process(PreProcessContext& ctx) -{ - const UPtr<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); - } - - const Event::Mode orig_mode = _engine.event_writer()->get_event_mode(); - _entry = stack->pop(); - _engine.event_writer()->set_event_mode(mode); - if (_entry.events.size() > 1) { - _engine.interface()->bundle_begin(); - } - - for (const LV2_Atom* ev : _entry.events) { - _engine.atom_interface()->write(ev); - } - - if (_entry.events.size() > 1) { - _engine.interface()->bundle_end(); - } - _engine.event_writer()->set_event_mode(orig_mode); - - return Event::pre_process_done(Status::SUCCESS); -} - -void -Undo::execute(RunContext& context) -{ -} - -void -Undo::post_process() -{ - respond(); -} - -} // namespace Events -} // namespace Server -} // namespace Ingen diff --git a/src/server/events/Undo.hpp b/src/server/events/Undo.hpp deleted file mode 100644 index af4b0d65..00000000 --- a/src/server/events/Undo.hpp +++ /dev/null @@ -1,58 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2016 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_EVENTS_UNDO_HPP -#define INGEN_EVENTS_UNDO_HPP - -#include "Event.hpp" -#include "UndoStack.hpp" -#include "types.hpp" - -namespace Ingen { -namespace Server { -namespace Events { - -/** A request to undo the last change to the engine. - * - * \ingroup engine - */ -class Undo : public Event -{ -public: - Undo(Engine& engine, - SPtr<Interface> client, - SampleCount timestamp, - const Ingen::Undo& msg); - - Undo(Engine& engine, - SPtr<Interface> client, - SampleCount timestamp, - const Ingen::Redo& msg); - - bool pre_process(PreProcessContext& ctx); - void execute(RunContext& context); - void post_process(); - -private: - UndoStack::Entry _entry; - bool _is_redo; -}; - -} // namespace Events -} // namespace Server -} // namespace Ingen - -#endif // INGEN_EVENTS_UNDO_HPP |