diff options
author | David Robillard <d@drobilla.net> | 2011-01-08 05:20:34 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2011-01-08 05:20:34 +0000 |
commit | 79fceb7b387cf45deab770a12f116493a24e5350 (patch) | |
tree | 7c12f6103b4772622cf10d18039b08655d0986b3 /src/engine | |
parent | e1f6dcf7dca9363f901cd96fc389e03f4cf75e12 (diff) | |
download | ingen-79fceb7b387cf45deab770a12f116493a24e5350.tar.gz ingen-79fceb7b387cf45deab770a12f116493a24e5350.tar.bz2 ingen-79fceb7b387cf45deab770a12f116493a24e5350.zip |
Support "request run" feature from contexts extension.
git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@2791 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'src/engine')
-rw-r--r-- | src/engine/ConnectionImpl.cpp | 2 | ||||
-rw-r--r-- | src/engine/JackDriver.cpp | 2 | ||||
-rw-r--r-- | src/engine/LV2BlobFeature.hpp | 2 | ||||
-rw-r--r-- | src/engine/LV2EventFeature.hpp | 2 | ||||
-rw-r--r-- | src/engine/LV2Info.cpp | 17 | ||||
-rw-r--r-- | src/engine/LV2Node.cpp | 9 | ||||
-rw-r--r-- | src/engine/LV2RequestRunFeature.hpp | 82 | ||||
-rw-r--r-- | src/engine/LV2ResizeFeature.hpp | 2 | ||||
-rw-r--r-- | src/engine/MessageContext.cpp | 28 | ||||
-rw-r--r-- | src/engine/MessageContext.hpp | 10 | ||||
-rw-r--r-- | src/engine/events/SetPortValue.cpp | 2 |
11 files changed, 123 insertions, 35 deletions
diff --git a/src/engine/ConnectionImpl.cpp b/src/engine/ConnectionImpl.cpp index a69a9e05..6c899796 100644 --- a/src/engine/ConnectionImpl.cpp +++ b/src/engine/ConnectionImpl.cpp @@ -119,7 +119,7 @@ ConnectionImpl::queue(Context& context) debug << endl;*/ _queue->write(sizeof(LV2_Atom) + obj->size, obj); - context.engine().message_context()->run(_dst_port, context.start() + ev->frames); + context.engine().message_context()->run(_dst_port->parent_node(), context.start() + ev->frames); } } diff --git a/src/engine/JackDriver.cpp b/src/engine/JackDriver.cpp index a432e789..3e546c46 100644 --- a/src/engine/JackDriver.cpp +++ b/src/engine/JackDriver.cpp @@ -415,7 +415,7 @@ JackDriver::_process_cb(jack_nframes_t nframes) // FIXME: all of this time stuff is screwy // FIXME: support nframes != buffer_size, even though that never damn well happens - assert(nframes == _block_length); + //assert(nframes == _block_length); // Note that Jack can not call this function for a cycle, if overloaded const jack_nframes_t start_of_current_cycle = jack_last_frame_time(_client); diff --git a/src/engine/LV2BlobFeature.hpp b/src/engine/LV2BlobFeature.hpp index 8d2977c1..c40dd985 100644 --- a/src/engine/LV2BlobFeature.hpp +++ b/src/engine/LV2BlobFeature.hpp @@ -51,7 +51,7 @@ struct BlobFeature : public Shared::LV2Features::Feature { uint32_t type, size_t size) {} - SharedPtr<LV2_Feature> feature(Shared::Node*) { + SharedPtr<LV2_Feature> feature(Shared::World*, Shared::Node*) { return SharedPtr<LV2_Feature>(&_feature, NullDeleter<LV2_Feature>); } diff --git a/src/engine/LV2EventFeature.hpp b/src/engine/LV2EventFeature.hpp index f58ecfbb..768e583c 100644 --- a/src/engine/LV2EventFeature.hpp +++ b/src/engine/LV2EventFeature.hpp @@ -39,7 +39,7 @@ struct EventFeature : public Shared::LV2Features::Feature { static uint32_t event_unref(LV2_Event_Callback_Data callback_data, LV2_Event* event) { return 0; } - SharedPtr<LV2_Feature> feature(Shared::Node*) { + SharedPtr<LV2_Feature> feature(Shared::World*, Shared::Node*) { return SharedPtr<LV2_Feature>(&_feature, NullDeleter<LV2_Feature>); } diff --git a/src/engine/LV2Info.cpp b/src/engine/LV2Info.cpp index f736dffb..e67c207d 100644 --- a/src/engine/LV2Info.cpp +++ b/src/engine/LV2Info.cpp @@ -16,14 +16,21 @@ */ #define __STDC_LIMIT_MACROS 1 -#include <cassert> + #include <stdint.h> + +#include <cassert> + #include "lv2/lv2plug.in/ns/ext/atom/atom.h" -#include "LV2Info.hpp" +#include "lv2/lv2plug.in/ns/ext/contexts/contexts.h" + #include "module/World.hpp" -#include "LV2Features.hpp" -#include "LV2EventFeature.hpp" + #include "LV2BlobFeature.hpp" +#include "LV2EventFeature.hpp" +#include "LV2Features.hpp" +#include "LV2Info.hpp" +#include "LV2RequestRunFeature.hpp" #include "LV2ResizeFeature.hpp" using namespace std; @@ -50,6 +57,8 @@ LV2Info::LV2Info(Ingen::Shared::World* world) SharedPtr<Shared::LV2Features::Feature>(new BlobFeature())); world->lv2_features()->add_feature(LV2_RESIZE_PORT_URI, SharedPtr<Shared::LV2Features::Feature>(new ResizeFeature())); + world->lv2_features()->add_feature(LV2_CONTEXTS_URI "#RequestRunFeature", + SharedPtr<Shared::LV2Features::Feature>(new RequestRunFeature())); } LV2Info::~LV2Info() diff --git a/src/engine/LV2Node.cpp b/src/engine/LV2Node.cpp index 8291adf2..26ad0b77 100644 --- a/src/engine/LV2Node.cpp +++ b/src/engine/LV2Node.cpp @@ -149,10 +149,11 @@ LV2Node::instantiate(BufferFactory& bufs) _ports = new Raul::Array<PortImpl*>(num_ports, NULL); _instances = new Instances(_polyphony, SharedPtr<void>()); - _features = info->world().lv2_features()->lv2_features(this); + _features = info->world().lv2_features()->lv2_features(&info->world(), this); uint32_t port_buffer_size = 0; - SLV2Value ctx_ext_uri = slv2_value_new_uri(info->lv2_world(), LV2_CONTEXT_MESSAGE); + SLV2Value ctx_ext_uri = slv2_value_new_uri(info->lv2_world(), + LV2_CONTEXTS_URI "#MessageContext"); for (uint32_t i = 0; i < _polyphony; ++i) { (*_instances)[i] = SharedPtr<void>( @@ -169,7 +170,7 @@ LV2Node::instantiate(BufferFactory& bufs) continue; const void* ctx_ext = slv2_instance_get_extension_data( - instance(i), LV2_CONTEXT_MESSAGE); + instance(i), LV2_CONTEXTS_URI "#MessageContext"); if (i == 0 && ctx_ext) { assert(!_message_funcs); @@ -320,7 +321,7 @@ LV2Node::instantiate(BufferFactory& bufs) for (uint32_t i = 0; i < slv2_values_size(contexts); ++i) { SLV2Value c = slv2_values_get_at(contexts, i); const char* context = slv2_value_as_string(c); - if (!strcmp(LV2_CONTEXT_MESSAGE, context)) { + if (!strcmp(LV2_CONTEXTS_URI "#MessageContext", context)) { if (!_message_funcs) { warn << _lv2_plugin->uri() << " has a message port, but no context extension data." << endl; diff --git a/src/engine/LV2RequestRunFeature.hpp b/src/engine/LV2RequestRunFeature.hpp new file mode 100644 index 00000000..40de2cfb --- /dev/null +++ b/src/engine/LV2RequestRunFeature.hpp @@ -0,0 +1,82 @@ +/* This file is part of Ingen. + * Copyright (C) 2010 David Robillard <http://drobilla.net> + * + * Ingen is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) 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 General Public License for details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef INGEN_ENGINE_LV2_REQUEST_RUN_FEATURE_HPP +#define INGEN_ENGINE_LV2_REQUEST_RUN_FEATURE_HPP + +#include "lv2/lv2plug.in/ns/ext/contexts/contexts.h" + +#include "raul/log.hpp" + +#include "shared/LV2Features.hpp" + +#include "Driver.hpp" +#include "Engine.hpp" +#include "MessageContext.hpp" +#include "NodeImpl.hpp" +#include "PortImpl.hpp" + +using namespace std; +using namespace Raul; + +namespace Ingen { + +struct RequestRunFeature : public Shared::LV2Features::Feature { + struct Data { + inline Data(Shared::World* w, Shared::Node* n) : world(w), node(n) {} + Shared::World* world; + Shared::Node* node; + }; + + static void request_run(LV2_Contexts_Request_Run_Data data_ptr, + uint32_t context_uri) { + Data* data = reinterpret_cast<Data*>(data_ptr); + if (!data->world->local_engine()) + return; + + data->world->local_engine()->message_context()->run( + dynamic_cast<NodeImpl*>(data->node), + data->world->local_engine()->driver()->frame_time()); + } + + static void delete_feature(LV2_Feature* feature) { + delete (Data*)feature->data; + free(feature); + } + + SharedPtr<LV2_Feature> feature(Shared::World* world, Shared::Node* n) { + info << "REQUEST RUN FEATURE FOR NODE " << n->path() << endl; + NodeImpl* node = dynamic_cast<NodeImpl*>(n); + if (!node) + return SharedPtr<LV2_Feature>(); + + typedef LV2_Contexts_Request_Run_Feature Feature; + Feature* data = (Feature*)malloc(sizeof(Feature)); + data->data = new Data(world, n); + data->request_run = &request_run; + + LV2_Feature* f = (LV2_Feature*)malloc(sizeof(LV2_Feature)); + f->URI = LV2_CONTEXTS_URI "#RequestRunFeature"; + f->data = data; + + return SharedPtr<LV2_Feature>(f, &delete_feature); + } +}; + +} // namespace Ingen + +#endif // INGEN_ENGINE_LV2_REQUEST_RUN_FEATURE_HPP diff --git a/src/engine/LV2ResizeFeature.hpp b/src/engine/LV2ResizeFeature.hpp index 46ca74ec..14f2237a 100644 --- a/src/engine/LV2ResizeFeature.hpp +++ b/src/engine/LV2ResizeFeature.hpp @@ -51,7 +51,7 @@ struct ResizeFeature : public Shared::LV2Features::Feature { free(feature); } - SharedPtr<LV2_Feature> feature(Shared::Node* n) { + SharedPtr<LV2_Feature> feature(Shared::World* w, Shared::Node* n) { NodeImpl* node = dynamic_cast<NodeImpl*>(n); if (!node) return SharedPtr<LV2_Feature>(); diff --git a/src/engine/MessageContext.cpp b/src/engine/MessageContext.cpp index 5a032884..541f457f 100644 --- a/src/engine/MessageContext.cpp +++ b/src/engine/MessageContext.cpp @@ -34,22 +34,18 @@ namespace Ingen { void -MessageContext::run(PortImpl* port, FrameTime time) +MessageContext::run(NodeImpl* node, FrameTime time) { - if (ThreadManager::thread_is(THREAD_PRE_PROCESS)) { - assert(port); - Glib::Mutex::Lock lock(_mutex); - _non_rt_request = Request(time, port); - _sem.post(); - _cond.wait(_mutex); - } else if (ThreadManager::thread_is(THREAD_PROCESS)) { - Request r(time, port); + if (ThreadManager::thread_is(THREAD_PROCESS)) { + const Request r(time, node); _requests.write(sizeof(Request), &r); // signal() will be called at the end of this process cycle - } else if (ThreadManager::thread_is(THREAD_MESSAGE)) { - warn << "Message context recursion at " << port->path() << endl; } else { - error << "Run requested from unknown thread" << endl; + assert(node); + Glib::Mutex::Lock lock(_mutex); + _non_rt_request = Request(time, node); + _sem.post(); + _cond.wait(_mutex); } } @@ -66,7 +62,7 @@ MessageContext::_run() { Glib::Mutex::Lock lock(_mutex); const Request req = _non_rt_request; - if (req.port) { + if (req.node) { _queue.insert(req); _end_time = std::max(_end_time, req.time); _cond.broadcast(); // Notify caller we got the message @@ -76,7 +72,7 @@ MessageContext::_run() // Enqueue (and thereby sort) requests from audio thread while (has_requests()) { _requests.full_read(sizeof(Request), &req); - if (req.port) { + if (req.node) { _queue.insert(req); } else { _end_time = req.time; @@ -105,7 +101,7 @@ MessageContext::_run() void MessageContext::execute(const Request& req) { - NodeImpl* node = req.port->parent_node(); + NodeImpl* node = req.node; node->message_run(*this); void* valid_ports = node->valid_ports(); @@ -119,7 +115,7 @@ MessageContext::execute(const Request& req) for (PatchImpl::Connections::iterator c = wires.begin(); c != wires.end(); ++c) { ConnectionImpl* ci = (ConnectionImpl*)c->second.get(); if (ci->src_port() == p && ci->dst_port()->context() == Context::MESSAGE) { - _queue.insert(Request(req.time, ci->dst_port())); + _queue.insert(Request(req.time, ci->dst_port()->parent_node())); } } } diff --git a/src/engine/MessageContext.hpp b/src/engine/MessageContext.hpp index a33f8836..1eb92ff5 100644 --- a/src/engine/MessageContext.hpp +++ b/src/engine/MessageContext.hpp @@ -31,7 +31,7 @@ namespace Ingen { -class PortImpl; +class NodeImpl; /** Context of a message_run() call. * @@ -55,16 +55,16 @@ public: Thread::set_context(THREAD_MESSAGE); } - /** Schedule a port value change at a certain time. + /** Schedule a message context run at a certain time. * Safe to call from either process thread or pre-process thread. */ - void run(PortImpl* port, FrameTime time); + void run(NodeImpl* node, FrameTime time); protected: struct Request { - Request(FrameTime t=0, PortImpl* p=0) : time(t), port(p) {} + Request(FrameTime t=0, NodeImpl* n=0) : time(t), node(n) {} FrameTime time; - PortImpl* port; + NodeImpl* node; }; public: diff --git a/src/engine/events/SetPortValue.cpp b/src/engine/events/SetPortValue.cpp index 86623888..a0c432c4 100644 --- a/src/engine/events/SetPortValue.cpp +++ b/src/engine/events/SetPortValue.cpp @@ -96,7 +96,7 @@ SetPortValue::pre_process() if (_port && _port->context() == Context::MESSAGE) { apply(*_engine.message_context()); _port->parent_node()->set_port_valid(_port->index()); - _engine.message_context()->run(_port, + _engine.message_context()->run(_port->parent_node(), _engine.driver()->frame_time() + _engine.driver()->block_length()); } |