summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2017-12-16 22:27:22 +0100
committerDavid Robillard <d@drobilla.net>2017-12-16 22:27:22 +0100
commitf2d3c77c9a470f20506c90098ab5cf4d3e5c9eff (patch)
tree38b27fed96f39bd1a3b255206f3af93c8f4708af
parentd078741456bacf08e2bc3e5d6cda58c2d16ef029 (diff)
downloadingen-f2d3c77c9a470f20506c90098ab5cf4d3e5c9eff.tar.gz
ingen-f2d3c77c9a470f20506c90098ab5cf4d3e5c9eff.tar.bz2
ingen-f2d3c77c9a470f20506c90098ab5cf4d3e5c9eff.zip
Adjust indices when ports are deleted
-rw-r--r--src/server/GraphImpl.cpp38
-rw-r--r--src/server/GraphImpl.hpp1
-rw-r--r--src/server/PortImpl.cpp4
-rw-r--r--src/server/PortImpl.hpp1
-rw-r--r--src/server/events/CreatePort.cpp29
-rw-r--r--src/server/events/Delete.cpp38
-rw-r--r--src/server/events/Delete.hpp7
-rw-r--r--src/server/events/Delta.cpp8
-rw-r--r--src/server/events/Delta.hpp1
9 files changed, 110 insertions, 17 deletions
diff --git a/src/server/GraphImpl.cpp b/src/server/GraphImpl.cpp
index adfb433d..389fd182 100644
--- a/src/server/GraphImpl.cpp
+++ b/src/server/GraphImpl.cpp
@@ -312,6 +312,27 @@ GraphImpl::num_ports_non_rt() const
return _inputs.size() + _outputs.size();
}
+bool
+GraphImpl::has_port_with_index(uint32_t index) const
+{
+ BufferFactory& bufs = *_engine.buffer_factory();
+ const auto index_atom = bufs.forge().make(int32_t(index));
+
+ for (auto p = _inputs.begin(); p != _inputs.end(); ++p) {
+ if (p->has_property(bufs.uris().lv2_index, index_atom)) {
+ return true;
+ }
+ }
+
+ for (auto p = _outputs.begin(); p != _outputs.end(); ++p) {
+ if (p->has_property(bufs.uris().lv2_index, index_atom)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
void
GraphImpl::remove_port(DuplexPort& port)
{
@@ -337,13 +358,18 @@ GraphImpl::build_ports_array(Raul::Maid& maid)
const size_t n = _inputs.size() + _outputs.size();
MPtr<Ports> result = maid.make_managed<Ports>(n);
- size_t i = 0;
-
- for (PortList::iterator p = _inputs.begin(); p != _inputs.end(); ++p, ++i)
- result->at(i) = &*p;
+ std::map<size_t, DuplexPort*> ports;
+ for (PortList::iterator p = _inputs.begin(); p != _inputs.end(); ++p) {
+ ports.emplace(p->index(), &*p);
+ }
+ for (PortList::iterator p = _outputs.begin(); p != _outputs.end(); ++p) {
+ ports.emplace(p->index(), &*p);
+ }
- for (PortList::iterator p = _outputs.begin(); p != _outputs.end(); ++p, ++i)
- result->at(i) = &*p;
+ size_t i = 0;
+ for (const auto& p : ports) {
+ result->at(i++) = p.second;
+ }
assert(i == n);
diff --git a/src/server/GraphImpl.hpp b/src/server/GraphImpl.hpp
index 6064624a..352c0957 100644
--- a/src/server/GraphImpl.hpp
+++ b/src/server/GraphImpl.hpp
@@ -117,6 +117,7 @@ public:
const Blocks& blocks() const { return _blocks; }
uint32_t num_ports_non_rt() const;
+ bool has_port_with_index(uint32_t index) const;
typedef boost::intrusive::slist<
DuplexPort, boost::intrusive::constant_time_size<true> > PortList;
diff --git a/src/server/PortImpl.cpp b/src/server/PortImpl.cpp
index 9a701d39..3302ff95 100644
--- a/src/server/PortImpl.cpp
+++ b/src/server/PortImpl.cpp
@@ -84,7 +84,9 @@ PortImpl::PortImpl(BufferFactory& bufs,
set_type(type, buffer_type);
- set_property(uris.lv2_index, bufs.forge().make((int32_t)index), Resource::Graph::INTERNAL);
+ remove_property(uris.lv2_index, uris.patch_wildcard);
+ set_property(uris.lv2_index, bufs.forge().make((int32_t)index));
+
if (has_value()) {
set_property(uris.ingen_value, value);
}
diff --git a/src/server/PortImpl.hpp b/src/server/PortImpl.hpp
index 33c4adac..6f04a552 100644
--- a/src/server/PortImpl.hpp
+++ b/src/server/PortImpl.hpp
@@ -194,6 +194,7 @@ public:
virtual void recycle_buffers();
uint32_t index() const { return _index; }
+ void set_index(RunContext&, uint32_t index) { _index = index; }
inline bool is_a(PortType type) const { return _type == type; }
diff --git a/src/server/events/CreatePort.cpp b/src/server/events/CreatePort.cpp
index 3adf2f8b..bc43ca41 100644
--- a/src/server/events/CreatePort.cpp
+++ b/src/server/events/CreatePort.cpp
@@ -115,14 +115,22 @@ CreatePort::pre_process(PreProcessContext& ctx)
typedef Properties::const_iterator PropIter;
PropIter index_i = _properties.find(uris.lv2_index);
- if (index_i == _properties.end()) {
+ 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_i = _properties.insert(
- std::make_pair(uris.lv2_index,
- _engine.world()->forge().make(old_n_ports)));
- } else if (index_i->second.type() != uris.forge.Int ||
- index_i->second.get<int32_t>() != old_n_ports) {
- return Event::pre_process_done(Status::BAD_INDEX, _path);
+ 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);
@@ -138,7 +146,7 @@ CreatePort::pre_process(PreProcessContext& ctx)
// Create port
_graph_port = new DuplexPort(bufs, _graph, Raul::Symbol(_path.symbol()),
- _graph->num_ports_non_rt(),
+ index,
polyphonic,
_port_type, _buf_type, buf_size,
value, _flow == Flow::OUTPUT);
@@ -164,7 +172,6 @@ CreatePort::pre_process(PreProcessContext& ctx)
assert(_graph_port->index() == (uint32_t)index_i->second.get<int32_t>());
assert(_graph->num_ports_non_rt() == (uint32_t)old_n_ports + 1);
- assert(_graph_port->index() == (uint32_t)old_n_ports);
assert(_ports_array->size() == _graph->num_ports_non_rt());
assert(_graph_port->index() < _ports_array->size());
return Event::pre_process_done(Status::SUCCESS);
@@ -177,7 +184,9 @@ CreatePort::execute(RunContext& context)
const MPtr<GraphImpl::Ports>& old_ports = _graph->external_ports();
if (old_ports) {
for (uint32_t i = 0; i < old_ports->size(); ++i) {
- (*_ports_array)[i] = (*old_ports)[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()]);
diff --git a/src/server/events/Delete.cpp b/src/server/events/Delete.cpp
index 6153540e..0a065a8a 100644
--- a/src/server/events/Delete.cpp
+++ b/src/server/events/Delete.cpp
@@ -61,6 +61,7 @@ Delete::~Delete()
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);
}
@@ -104,6 +105,19 @@ Delete::pre_process(PreProcessContext& ctx)
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()) {
@@ -131,6 +145,15 @@ Delete::execute(RunContext& context)
GraphImpl* parent = _block ? _block->parent_graph() : NULL;
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));
@@ -165,12 +188,27 @@ Delete::post_process()
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(_uri, i->second->properties());
+
+ // Adjust port indices
+ for (const auto& c : _port_index_changes) {
+ if (c.first != _uri) {
+ target.set_property(path_to_uri(c.first),
+ uris.lv2_index,
+ forge.make(int32_t(c.second.first)));
+ }
+ }
}
}
diff --git a/src/server/events/Delete.hpp b/src/server/events/Delete.hpp
index 0003e821..03c994fe 100644
--- a/src/server/events/Delete.hpp
+++ b/src/server/events/Delete.hpp
@@ -17,6 +17,9 @@
#ifndef INGEN_EVENTS_DELETE_HPP
#define INGEN_EVENTS_DELETE_HPP
+#include <map>
+#include <vector>
+
#include "ingen/Store.hpp"
#include "CompiledGraph.hpp"
@@ -60,6 +63,9 @@ public:
void undo(Interface& target);
private:
+ using IndexChange = std::pair<uint32_t, uint32_t>;
+ using IndexChanges = std::map<Raul::Path, IndexChange>;
+
Raul::URI _uri;
Raul::Path _path;
SPtr<BlockImpl> _block; ///< Non-NULL iff a block
@@ -69,6 +75,7 @@ private:
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;
};
diff --git a/src/server/events/Delta.cpp b/src/server/events/Delta.cpp
index 0c50aabc..fccb887c 100644
--- a/src/server/events/Delta.cpp
+++ b/src/server/events/Delta.cpp
@@ -312,6 +312,9 @@ Delta::pre_process(PreProcessContext& ctx)
} 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) {
@@ -498,6 +501,11 @@ Delta::execute(RunContext& context)
_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)) {
diff --git a/src/server/events/Delta.hpp b/src/server/events/Delta.hpp
index 40c65ef8..24d58b99 100644
--- a/src/server/events/Delta.hpp
+++ b/src/server/events/Delta.hpp
@@ -87,6 +87,7 @@ private:
ENABLE_BROADCAST,
POLYPHONY,
POLYPHONIC,
+ PORT_INDEX,
CONTROL_BINDING,
PRESET,
LOADED_BUNDLE