From 79fceb7b387cf45deab770a12f116493a24e5350 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sat, 8 Jan 2011 05:20:34 +0000 Subject: Support "request run" feature from contexts extension. git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@2791 a436a847-0d15-0410-975c-d299462d15a1 --- src/client/PluginUI.cpp | 2 +- src/engine/ConnectionImpl.cpp | 2 +- src/engine/JackDriver.cpp | 2 +- src/engine/LV2BlobFeature.hpp | 2 +- src/engine/LV2EventFeature.hpp | 2 +- src/engine/LV2Info.cpp | 17 ++++++-- src/engine/LV2Node.cpp | 9 ++-- src/engine/LV2RequestRunFeature.hpp | 82 +++++++++++++++++++++++++++++++++++++ src/engine/LV2ResizeFeature.hpp | 2 +- src/engine/MessageContext.cpp | 28 ++++++------- src/engine/MessageContext.hpp | 10 ++--- src/engine/events/SetPortValue.cpp | 2 +- src/shared/LV2Features.cpp | 4 +- src/shared/LV2Features.hpp | 6 ++- src/shared/LV2URIMap.hpp | 4 +- 15 files changed, 132 insertions(+), 42 deletions(-) create mode 100644 src/engine/LV2RequestRunFeature.hpp (limited to 'src') diff --git a/src/client/PluginUI.cpp b/src/client/PluginUI.cpp index cae67156..693976fb 100644 --- a/src/client/PluginUI.cpp +++ b/src/client/PluginUI.cpp @@ -151,7 +151,7 @@ PluginUI::create(Ingen::Shared::World* world, if (ui) { info << "Found GTK Plugin UI: " << slv2_ui_get_uri(ui) << endl; ret = SharedPtr(new PluginUI(world, node)); - ret->_features = world->lv2_features()->lv2_features(node.get()); + ret->_features = world->lv2_features()->lv2_features(world, node.get()); SLV2UIInstance inst = slv2_ui_instantiate( plugin, ui, lv2_ui_write, ret.get(), ret->_features->array()); 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 feature(Shared::Node*) { + SharedPtr feature(Shared::World*, Shared::Node*) { return SharedPtr(&_feature, NullDeleter); } 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 feature(Shared::Node*) { + SharedPtr feature(Shared::World*, Shared::Node*) { return SharedPtr(&_feature, NullDeleter); } 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 + #include + +#include + #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(new BlobFeature())); world->lv2_features()->add_feature(LV2_RESIZE_PORT_URI, SharedPtr(new ResizeFeature())); + world->lv2_features()->add_feature(LV2_CONTEXTS_URI "#RequestRunFeature", + SharedPtr(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(num_ports, NULL); _instances = new Instances(_polyphony, SharedPtr()); - _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( @@ -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 + * + * 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_ptr); + if (!data->world->local_engine()) + return; + + data->world->local_engine()->message_context()->run( + dynamic_cast(data->node), + data->world->local_engine()->driver()->frame_time()); + } + + static void delete_feature(LV2_Feature* feature) { + delete (Data*)feature->data; + free(feature); + } + + SharedPtr feature(Shared::World* world, Shared::Node* n) { + info << "REQUEST RUN FEATURE FOR NODE " << n->path() << endl; + NodeImpl* node = dynamic_cast(n); + if (!node) + return SharedPtr(); + + 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(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 feature(Shared::Node* n) { + SharedPtr feature(Shared::World* w, Shared::Node* n) { NodeImpl* node = dynamic_cast(n); if (!node) return SharedPtr(); 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()); } diff --git a/src/shared/LV2Features.cpp b/src/shared/LV2Features.cpp index 21e6ce35..4b8fa1c5 100644 --- a/src/shared/LV2Features.cpp +++ b/src/shared/LV2Features.cpp @@ -50,11 +50,11 @@ LV2Features::add_feature(const std::string& uri, SharedPtr feature) SharedPtr -LV2Features::lv2_features(Node* node) const +LV2Features::lv2_features(Shared::World* world, Node* node) const { FeatureArray::FeatureVector vec; for (Features::const_iterator f = _features.begin(); f != _features.end(); ++f) { - SharedPtr fptr = f->second->feature(node); + SharedPtr fptr = f->second->feature(world, node); if (fptr) vec.push_back(fptr); } diff --git a/src/shared/LV2Features.hpp b/src/shared/LV2Features.hpp index 20b17628..386e4ea8 100644 --- a/src/shared/LV2Features.hpp +++ b/src/shared/LV2Features.hpp @@ -26,9 +26,11 @@ #include "ingen-config.h" namespace Ingen { + namespace Shared { class Node; +class World; /** Stuff that may need to be passed to an LV2 plugin (i.e. LV2 features). */ @@ -39,7 +41,7 @@ public: class Feature { public: virtual ~Feature() {} - virtual SharedPtr feature(Node* node) = 0; + virtual SharedPtr feature(Shared::World* world, Node* node) = 0; }; class FeatureArray { @@ -70,7 +72,7 @@ public: void add_feature(const std::string& uri, SharedPtr feature); - SharedPtr lv2_features(Node* node) const; + SharedPtr lv2_features(Shared::World* world, Node* node) const; private: typedef std::map< std::string, SharedPtr > Features; diff --git a/src/shared/LV2URIMap.hpp b/src/shared/LV2URIMap.hpp index a4bdb2d8..c8607426 100644 --- a/src/shared/LV2URIMap.hpp +++ b/src/shared/LV2URIMap.hpp @@ -40,14 +40,14 @@ class LV2URIMap : public boost::noncopyable, public LV2Features::Feature { public: LV2URIMap(); - SharedPtr feature(Node*) { + SharedPtr feature(Shared::World*, Node*) { return SharedPtr(&uri_map_feature, NullDeleter); } struct UnmapFeature : public LV2Features::Feature { UnmapFeature(const LV2URIMap& map) : _feature(map.uri_unmap_feature) {} - SharedPtr feature(Node*) { + SharedPtr feature(Shared::World*, Node*) { return SharedPtr(&_feature, NullDeleter); } -- cgit v1.2.1