summaryrefslogtreecommitdiffstats
path: root/src/server
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2015-02-19 09:44:41 +0000
committerDavid Robillard <d@drobilla.net>2015-02-19 09:44:41 +0000
commitaef939ff10362285ce1ebd872518627e524917bc (patch)
treec3bf4fac85ff91f63748432fd7d668116efe97a0 /src/server
parent5c035574e0fabf961aa3275e366f295dcf0716f2 (diff)
downloadingen-aef939ff10362285ce1ebd872518627e524917bc.tar.gz
ingen-aef939ff10362285ce1ebd872518627e524917bc.tar.bz2
ingen-aef939ff10362285ce1ebd872518627e524917bc.zip
Server side presets.
git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@5587 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'src/server')
-rw-r--r--src/server/BlockImpl.cpp11
-rw-r--r--src/server/BlockImpl.hpp11
-rw-r--r--src/server/LV2Block.cpp27
-rw-r--r--src/server/LV2Block.hpp4
-rw-r--r--src/server/events/Delta.cpp63
-rw-r--r--src/server/events/Delta.hpp11
-rw-r--r--src/server/events/SetPortValue.cpp4
-rw-r--r--src/server/events/SetPortValue.hpp6
8 files changed, 133 insertions, 4 deletions
diff --git a/src/server/BlockImpl.cpp b/src/server/BlockImpl.cpp
index ce6b169c..d21514ef 100644
--- a/src/server/BlockImpl.cpp
+++ b/src/server/BlockImpl.cpp
@@ -160,6 +160,17 @@ BlockImpl::nth_port_by_type(uint32_t n, bool input, PortType type)
return NULL;
}
+PortImpl*
+BlockImpl::port_by_symbol(const char* symbol)
+{
+ for (uint32_t p = 0; _ports && p < _ports->size(); ++p) {
+ if (_ports->at(p)->symbol() == symbol) {
+ return _ports->at(p);
+ }
+ }
+ return NULL;
+}
+
void
BlockImpl::pre_process(ProcessContext& context)
{
diff --git a/src/server/BlockImpl.hpp b/src/server/BlockImpl.hpp
index b3064168..965adbcc 100644
--- a/src/server/BlockImpl.hpp
+++ b/src/server/BlockImpl.hpp
@@ -21,6 +21,8 @@
#include <boost/intrusive/slist.hpp>
+#include "lilv/lilv.h"
+
#include "raul/Array.hpp"
#include "BufferRef.hpp"
@@ -98,6 +100,12 @@ public:
/** Enable or disable (bypass) this block. */
void set_enabled(bool e) { _enabled = e; }
+ /** Load a preset from the world for this block. */
+ virtual LilvState* load_preset(const Raul::URI& uri) { return NULL; }
+
+ /** Restore `state`. */
+ virtual void apply_state(LilvState* state) {}
+
/** Learn the next incoming MIDI event (for internals) */
virtual void learn() {}
@@ -122,6 +130,9 @@ public:
virtual Node* port(uint32_t index) const;
virtual PortImpl* port_impl(uint32_t index) const { return (*_ports)[index]; }
+ /** Get a port by symbol. */
+ virtual PortImpl* port_by_symbol(const char* symbol);
+
/** Blocks that are connected to this Block's inputs. */
std::list<BlockImpl*>& providers() { return _providers; }
diff --git a/src/server/LV2Block.cpp b/src/server/LV2Block.cpp
index 3f6f4be1..64c80764 100644
--- a/src/server/LV2Block.cpp
+++ b/src/server/LV2Block.cpp
@@ -20,6 +20,7 @@
#include <cmath>
#include "lv2/lv2plug.in/ns/ext/morph/morph.h"
+#include "lv2/lv2plug.in/ns/ext/presets/presets.h"
#include "lv2/lv2plug.in/ns/ext/options/options.h"
#include "lv2/lv2plug.in/ns/ext/resize-port/resize-port.h"
#include "lv2/lv2plug.in/ns/ext/state/state.h"
@@ -541,6 +542,32 @@ LV2Block::post_process(ProcessContext& context)
}
}
+LilvState*
+LV2Block::load_preset(const Raul::URI& uri)
+{
+ World* world = &_lv2_plugin->lv2_info()->world();
+ LilvWorld* lworld = _lv2_plugin->lv2_info()->lv2_world();
+ LilvNode* preset = lilv_new_uri(lworld, uri.c_str());
+
+ // Load preset into world if necessary
+ lilv_world_load_resource(lworld, preset);
+
+ // Load preset from world
+ LV2_URID_Map* map = &world->uri_map().urid_map_feature()->urid_map;
+ LilvState* state = lilv_state_new_from_world(lworld, map, preset);
+
+ lilv_node_free(preset);
+ return state;
+}
+
+void
+LV2Block::apply_state(LilvState* state)
+{
+ for (uint32_t v = 0; v < _polyphony; ++v) {
+ lilv_state_restore(state, instance(v), NULL, NULL, 0, NULL);
+ }
+}
+
void
LV2Block::set_port_buffer(uint32_t voice,
uint32_t port_num,
diff --git a/src/server/LV2Block.hpp b/src/server/LV2Block.hpp
index ec2f99f4..6b343df7 100644
--- a/src/server/LV2Block.hpp
+++ b/src/server/LV2Block.hpp
@@ -63,6 +63,10 @@ public:
void run(ProcessContext& context);
void post_process(ProcessContext& context);
+ LilvState* load_preset(const Raul::URI& uri);
+
+ void apply_state(LilvState* state);
+
void set_port_buffer(uint32_t voice,
uint32_t port_num,
BufferRef buf,
diff --git a/src/server/events/Delta.cpp b/src/server/events/Delta.cpp
index 03a7ccd5..8df79994 100644
--- a/src/server/events/Delta.cpp
+++ b/src/server/events/Delta.cpp
@@ -17,6 +17,7 @@
#include <vector>
#include <thread>
+#include "ingen/Log.hpp"
#include "ingen/Store.hpp"
#include "ingen/URIs.hpp"
#include "raul/Maid.hpp"
@@ -60,6 +61,7 @@ Delta::Delta(Engine& engine,
, _object(NULL)
, _graph(NULL)
, _compiled_graph(NULL)
+ , _state(NULL)
, _context(context)
, _type(type)
, _poly_lock(engine.store()->mutex(), std::defer_lock)
@@ -98,6 +100,37 @@ Delta::~Delta()
delete _create_event;
}
+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), true);
+
+ ev->pre_process();
+ _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);
+}
+
bool
Delta::pre_process()
{
@@ -216,6 +249,22 @@ Delta::pre_process()
} else {
_status = Status::BAD_VALUE_TYPE;
}
+ } else if (key == uris.pset_preset) {
+ if (value.type() == uris.forge.URI) {
+ const char* str = value.ptr<char>();
+ if (Raul::URI::is_valid(str)) {
+ op = SpecialType::PRESET;
+ const Raul::URI uri(str);
+ if ((_state = block->load_preset(Raul::URI(str)))) {
+ lilv_state_emit_port_values(
+ _state, s_add_set_event, this);
+ }
+ } else {
+ _status = Status::BAD_VALUE;
+ }
+ } else {
+ _status = Status::BAD_VALUE_TYPE;
+ }
}
}
@@ -362,6 +411,9 @@ Delta::execute(ProcessContext& context)
}
}
break;
+ case SpecialType::PRESET:
+ block->set_enabled(false);
+ break;
case SpecialType::NONE:
if (port) {
if (key == uris.lv2_minimum) {
@@ -382,6 +434,15 @@ Delta::post_process()
_poly_lock.unlock();
}
+ if (_state) {
+ BlockImpl* block = dynamic_cast<BlockImpl*>(_object);
+ if (block) {
+ block->apply_state(_state);
+ block->set_enabled(true);
+ }
+ lilv_state_free(_state);
+ }
+
Broadcaster::Transfer t(*_engine.broadcaster());
if (_create_event) {
@@ -392,7 +453,7 @@ Delta::post_process()
}
for (auto& s : _set_events) {
- if (s->status() != Status::SUCCESS) {
+ if (s->synthetic() || s->status() != Status::SUCCESS) {
s->post_process(); // Set failed, report error
}
}
diff --git a/src/server/events/Delta.hpp b/src/server/events/Delta.hpp
index 43edacbf..750411ff 100644
--- a/src/server/events/Delta.hpp
+++ b/src/server/events/Delta.hpp
@@ -19,6 +19,8 @@
#include <vector>
+#include "lilv/lilv.h"
+
#include "raul/URI.hpp"
#include "ControlBindings.hpp"
@@ -87,6 +89,11 @@ public:
~Delta();
+ void add_set_event(const char* port_symbol,
+ const void* value,
+ uint32_t size,
+ uint32_t type);
+
bool pre_process();
void execute(ProcessContext& context);
void post_process();
@@ -98,7 +105,8 @@ private:
ENABLE_BROADCAST,
POLYPHONY,
POLYPHONIC,
- CONTROL_BINDING
+ CONTROL_BINDING,
+ PRESET
};
typedef std::vector<SetPortValue*> SetEvents;
@@ -113,6 +121,7 @@ private:
Ingen::Resource* _object;
GraphImpl* _graph;
CompiledGraph* _compiled_graph;
+ LilvState* _state;
Resource::Graph _context;
ControlBindings::Key _binding;
Type _type;
diff --git a/src/server/events/SetPortValue.cpp b/src/server/events/SetPortValue.cpp
index df0cb06d..655ff281 100644
--- a/src/server/events/SetPortValue.cpp
+++ b/src/server/events/SetPortValue.cpp
@@ -39,10 +39,12 @@ SetPortValue::SetPortValue(Engine& engine,
int32_t id,
SampleCount timestamp,
PortImpl* port,
- const Atom& value)
+ const Atom& value,
+ bool synthetic)
: Event(engine, client, id, timestamp)
, _port(port)
, _value(value)
+ , _synthetic(synthetic)
{
}
diff --git a/src/server/events/SetPortValue.hpp b/src/server/events/SetPortValue.hpp
index 852c694e..ed81db47 100644
--- a/src/server/events/SetPortValue.hpp
+++ b/src/server/events/SetPortValue.hpp
@@ -42,7 +42,8 @@ public:
int32_t id,
SampleCount timestamp,
PortImpl* port,
- const Atom& value);
+ const Atom& value,
+ bool synthetic = false);
~SetPortValue();
@@ -50,12 +51,15 @@ public:
void execute(ProcessContext& context);
void post_process();
+ bool synthetic() const { return _synthetic; }
+
private:
void apply(Context& context);
PortImpl* _port;
const Atom _value;
ControlBindings::Key _binding;
+ bool _synthetic;
};
} // namespace Events