diff options
Diffstat (limited to 'src/server')
-rw-r--r-- | src/server/BlockImpl.cpp | 11 | ||||
-rw-r--r-- | src/server/BlockImpl.hpp | 11 | ||||
-rw-r--r-- | src/server/LV2Block.cpp | 27 | ||||
-rw-r--r-- | src/server/LV2Block.hpp | 4 | ||||
-rw-r--r-- | src/server/events/Delta.cpp | 63 | ||||
-rw-r--r-- | src/server/events/Delta.hpp | 11 | ||||
-rw-r--r-- | src/server/events/SetPortValue.cpp | 4 | ||||
-rw-r--r-- | src/server/events/SetPortValue.hpp | 6 |
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 |