diff options
Diffstat (limited to 'src/server/ClientUpdate.cpp')
-rw-r--r-- | src/server/ClientUpdate.cpp | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/src/server/ClientUpdate.cpp b/src/server/ClientUpdate.cpp new file mode 100644 index 00000000..60dd02e3 --- /dev/null +++ b/src/server/ClientUpdate.cpp @@ -0,0 +1,155 @@ +/* + 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/Interface.hpp" +#include "ingen/URIs.hpp" + +#include "BlockImpl.hpp" +#include "BufferFactory.hpp" +#include "ClientUpdate.hpp" +#include "GraphImpl.hpp" +#include "PortImpl.hpp" + +namespace Ingen { +namespace Server { + +void +ClientUpdate::put(const URI& uri, + const Properties& props, + Resource::Graph ctx) +{ + const ClientUpdate::Put put = { uri, props, ctx }; + puts.push_back(put); +} + +void +ClientUpdate::put_port(const PortImpl* port) +{ + const URIs& uris = port->bufs().uris(); + if (port->is_a(PortType::CONTROL) || port->is_a(PortType::CV)) { + Properties props = port->properties(); + props.erase(uris.ingen_value); + props.emplace(uris.ingen_value, port->value()); + put(port->uri(), props); + } else { + put(port->uri(), port->properties()); + } +} + +void +ClientUpdate::put_block(const BlockImpl* block) +{ + const PluginImpl* const plugin = block->plugin_impl(); + const URIs& uris = plugin->uris(); + + if (uris.ingen_Graph == plugin->type()) { + put_graph((const GraphImpl*)block); + } else { + put(block->uri(), block->properties()); + for (size_t j = 0; j < block->num_ports(); ++j) { + put_port(block->port_impl(j)); + } + } +} + +void +ClientUpdate::put_graph(const GraphImpl* graph) +{ + put(graph->uri(), + graph->properties(Resource::Graph::INTERNAL), + Resource::Graph::INTERNAL); + + put(graph->uri(), + graph->properties(Resource::Graph::EXTERNAL), + Resource::Graph::EXTERNAL); + + // Enqueue blocks + for (const auto& b : graph->blocks()) { + put_block(&b); + } + + // Enqueue ports + for (uint32_t i = 0; i < graph->num_ports_non_rt(); ++i) { + put_port(graph->port_impl(i)); + } + + // Enqueue arcs + for (const auto& a : graph->arcs()) { + const SPtr<const Arc> arc = a.second; + const Connect connect = { arc->tail_path(), arc->head_path() }; + connects.push_back(connect); + } +} + +void +ClientUpdate::put_plugin(PluginImpl* plugin) +{ + put(plugin->uri(), plugin->properties()); + + for (const auto& p : plugin->presets()) { + put_preset(plugin->uris(), plugin->uri(), p.first, p.second); + } +} + +void +ClientUpdate::put_preset(const URIs& uris, + const URI& plugin, + const URI& preset, + const std::string& label) +{ + const Properties props{ + { uris.rdf_type, uris.pset_Preset.urid }, + { uris.rdfs_label, uris.forge.alloc(label) }, + { uris.lv2_appliesTo, uris.forge.make_urid(plugin) }}; + put(preset, props); +} + +void +ClientUpdate::del(const URI& subject) +{ + dels.push_back(subject); +} + +/** Returns true if a is closer to the root than b. */ +static inline bool +put_higher_than(const ClientUpdate::Put& a, const ClientUpdate::Put& b) +{ + return (std::count(a.uri.begin(), a.uri.end(), '/') < + std::count(b.uri.begin(), b.uri.end(), '/')); +} + +void +ClientUpdate::send(Interface& dest) +{ + // Send deletions + for (const URI& subject : dels) { + dest.del(subject); + } + + // Send puts in increasing depth order so parents are sent first + std::stable_sort(puts.begin(), puts.end(), put_higher_than); + for (const ClientUpdate::Put& put : puts) { + dest.put(put.uri, put.properties, put.ctx); + } + + // Send connections + for (const ClientUpdate::Connect& connect : connects) { + dest.connect(connect.tail, connect.head); + } +} + +} // namespace Server +} // namespace Ingen |