From 3168e388d0a951cf665696b970eb5bb354fbb740 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Mon, 29 Sep 2008 18:19:17 +0000 Subject: More context extension work. Clicking the input port on bang in ingen while in edit mode will now send a message to the bang plugin in the message context. git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@1537 a436a847-0d15-0410-975c-d299462d15a1 --- src/libs/engine/Context.hpp | 51 ++++++++++++++++++++++++++++ src/libs/engine/Engine.cpp | 3 ++ src/libs/engine/Engine.hpp | 5 ++- src/libs/engine/LV2Node.cpp | 31 +++++++++++++++-- src/libs/engine/LV2Node.hpp | 4 +++ src/libs/engine/LV2Plugin.hpp | 2 +- src/libs/engine/Makefile.am | 1 + src/libs/engine/MessageContext.hpp | 10 ++---- src/libs/engine/OSCEngineReceiver.cpp | 2 +- src/libs/engine/PortImpl.cpp | 1 + src/libs/engine/PortImpl.hpp | 5 +++ src/libs/engine/ProcessContext.hpp | 7 ++-- src/libs/engine/events/SetPortValueEvent.cpp | 12 ++++++- src/libs/engine/lv2_contexts.h | 1 + 14 files changed, 117 insertions(+), 18 deletions(-) create mode 100644 src/libs/engine/Context.hpp create mode 120000 src/libs/engine/lv2_contexts.h (limited to 'src/libs') diff --git a/src/libs/engine/Context.hpp b/src/libs/engine/Context.hpp new file mode 100644 index 00000000..2e000fb1 --- /dev/null +++ b/src/libs/engine/Context.hpp @@ -0,0 +1,51 @@ +/* This file is part of Ingen. + * Copyright (C) 2007 Dave 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 CONTEXT_H +#define CONTEXT_H + +namespace Ingen { + +class Engine; + +class Context +{ +public: + enum ID { + AUDIO, + MESSAGE + }; + + Context(Engine& engine, ID id) + : _id(id) + , _engine(engine) + {} + + virtual ~Context() {} + + inline Engine& engine() const { return _engine; } + +protected: + ID _id; ///< Fast ID for this context + Engine& _engine; ///< Engine we're running in +}; + + +} // namespace Ingen + +#endif // CONTEXT_H + diff --git a/src/libs/engine/Engine.cpp b/src/libs/engine/Engine.cpp index ac71a820..a08a37ca 100644 --- a/src/libs/engine/Engine.cpp +++ b/src/libs/engine/Engine.cpp @@ -45,6 +45,8 @@ #endif #include "PostProcessor.hpp" #include "ProcessSlave.hpp" +#include "ProcessContext.hpp" +#include "MessageContext.hpp" #include "ThreadManager.hpp" #ifdef HAVE_JACK_MIDI #include "JackMidiDriver.hpp" @@ -62,6 +64,7 @@ Engine::Engine(Ingen::Shared::World* world) , _post_processor(new PostProcessor(*this, /**_maid, */post_processor_queue_size)) , _broadcaster(new ClientBroadcaster()) , _node_factory(new NodeFactory(world)) + , _message_context(new MessageContext(*this)) , _quit_flag(false) , _activated(false) { diff --git a/src/libs/engine/Engine.hpp b/src/libs/engine/Engine.hpp index 26884f73..fce826db 100644 --- a/src/libs/engine/Engine.hpp +++ b/src/libs/engine/Engine.hpp @@ -47,6 +47,7 @@ class QueuedEngineInterface; class Driver; class ProcessSlave; class ProcessContext; +class MessageContext; /** The main class for the Engine. @@ -91,6 +92,7 @@ public: PostProcessor* post_processor() const { return _post_processor; } ClientBroadcaster* broadcaster() const { return _broadcaster; } NodeFactory* node_factory() const { return _node_factory; } + MessageContext* message_context() const { return _message_context; } SharedPtr engine_store() const; @@ -104,7 +106,7 @@ public: inline ProcessSlaves& process_slaves() { return _process_slaves; } private: - ProcessSlaves _process_slaves; + ProcessSlaves _process_slaves; Ingen::Shared::World* _world; @@ -116,6 +118,7 @@ private: PostProcessor* _post_processor; ClientBroadcaster* _broadcaster; NodeFactory* _node_factory; + MessageContext* _message_context; bool _quit_flag; bool _activated; diff --git a/src/libs/engine/LV2Node.cpp b/src/libs/engine/LV2Node.cpp index a3c20a95..a06cc55a 100644 --- a/src/libs/engine/LV2Node.cpp +++ b/src/libs/engine/LV2Node.cpp @@ -28,6 +28,7 @@ #include "EventBuffer.hpp" #include "OutputPort.hpp" #include "ProcessContext.hpp" +#include "lv2_contexts.h" using namespace std; @@ -49,6 +50,7 @@ LV2Node::LV2Node(LV2Plugin* plugin, , _lv2_plugin(plugin) , _instances(NULL) , _prepared_instances(NULL) + , _message_run(NULL) { assert(_lv2_plugin); } @@ -140,6 +142,17 @@ LV2Node::instantiate() cerr << "Failed to instantiate plugin!" << endl; return false; } + + const void* ctx_ext = slv2_instance_get_extension_data( + (*_instances)[i], LV2_CONTEXT_MESSAGE); + + if (ctx_ext) { + cerr << "HAS CONTEXT EXTENSION" << endl; + if (_message_run == NULL) + _message_run = new MessageRunFuncs(_polyphony, NULL); + LV2MessageContext* mc = (LV2MessageContext*)ctx_ext; + (*_message_run)[i] = mc->message_run; + } } string port_name; @@ -202,8 +215,17 @@ LV2Node::instantiate() SLV2Value pred = slv2_value_new_uri(info->lv2_world(), "http://lv2plug.in/ns/dev/contexts#context"); SLV2Values contexts = slv2_port_get_value(plug, id, pred); - if (slv2_values_size(contexts) > 0) { - cout << "PORT HAS CONTEXT!" << endl; + 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("http://lv2plug.in/ns/dev/contexts#MessageContext", context)) { + cout << "MESSAGE CONTEXT!" << endl; + port->set_context(Context::MESSAGE); + } else { + cout << "UNKNOWN CONTEXT: " + << slv2_value_as_string(slv2_values_get_at(contexts, i)) + << endl; + } } _ports->at(j) = port; @@ -250,7 +272,10 @@ LV2Node::deactivate() void LV2Node::message_process(MessageContext& context, uint32_t* output) { - *output = 0; + // FIXME: voice + if (_message_run) + (*_message_run)[0]((*_instances)[0], output); + /* MESSAGE PROCESS */ } diff --git a/src/libs/engine/LV2Node.hpp b/src/libs/engine/LV2Node.hpp index dbdb6511..3187005c 100644 --- a/src/libs/engine/LV2Node.hpp +++ b/src/libs/engine/LV2Node.hpp @@ -62,6 +62,10 @@ protected: LV2Plugin* _lv2_plugin; Raul::Array* _instances; Raul::Array* _prepared_instances; + + typedef bool (*MessageRunFunc)(LV2_Handle, uint32_t*); + typedef Raul::Array MessageRunFuncs; + MessageRunFuncs* _message_run; }; diff --git a/src/libs/engine/LV2Plugin.hpp b/src/libs/engine/LV2Plugin.hpp index c1f8671d..c9bc4ff9 100644 --- a/src/libs/engine/LV2Plugin.hpp +++ b/src/libs/engine/LV2Plugin.hpp @@ -61,7 +61,7 @@ public: NodeImpl* instantiate(const string& name, bool polyphonic, Ingen::PatchImpl* parent, - Engine& engine); + Engine& engine); const string symbol() const; const string name() const; diff --git a/src/libs/engine/Makefile.am b/src/libs/engine/Makefile.am index c7c433d3..3c464de3 100644 --- a/src/libs/engine/Makefile.am +++ b/src/libs/engine/Makefile.am @@ -178,6 +178,7 @@ libingen_engine_la_SOURCES = \ events/UnregisterClientEvent.cpp \ events/UnregisterClientEvent.hpp \ jack_compat.h \ + lv2_contexts.h \ tuning.hpp \ types.hpp \ util.hpp diff --git a/src/libs/engine/MessageContext.hpp b/src/libs/engine/MessageContext.hpp index 3a53e73a..31531521 100644 --- a/src/libs/engine/MessageContext.hpp +++ b/src/libs/engine/MessageContext.hpp @@ -19,6 +19,7 @@ #define MESSAGECONTEXT_H #include "EventSink.hpp" +#include "Context.hpp" namespace Ingen { @@ -33,19 +34,14 @@ class NodeImpl; * * \ingroup engine */ -class MessageContext +class MessageContext : public Context { public: MessageContext(Engine& engine) - : _engine(engine) + : Context(engine, MESSAGE) {} void run(NodeImpl* node); - - inline Engine& engine() const { return _engine; } - -private: - Engine& _engine; ///< Engine we're running in }; diff --git a/src/libs/engine/OSCEngineReceiver.cpp b/src/libs/engine/OSCEngineReceiver.cpp index 04352c2f..e4e2fec1 100644 --- a/src/libs/engine/OSCEngineReceiver.cpp +++ b/src/libs/engine/OSCEngineReceiver.cpp @@ -70,7 +70,7 @@ OSCEngineReceiver::OSCEngineReceiver(Engine& engine, size_t queue_size, uint16_t } // For debugging, print all incoming OSC messages - lo_server_add_method(_server, NULL, NULL, generic_cb, NULL); + //lo_server_add_method(_server, NULL, NULL, generic_cb, NULL); // Set response address for this message. // It's important this is first and returns nonzero. diff --git a/src/libs/engine/PortImpl.cpp b/src/libs/engine/PortImpl.cpp index 9b609323..3eac65ca 100644 --- a/src/libs/engine/PortImpl.cpp +++ b/src/libs/engine/PortImpl.cpp @@ -48,6 +48,7 @@ PortImpl::PortImpl(NodeImpl* const node, , _broadcast(false) , _set_by_user(false) , _last_broadcasted_value(_value.type() == Atom::FLOAT ? _value.get_float() : 0.0f) // default? + , _context(Context::AUDIO) , _buffers(new Raul::Array(poly)) { assert(node != NULL); diff --git a/src/libs/engine/PortImpl.hpp b/src/libs/engine/PortImpl.hpp index ca21bb4c..be96a910 100644 --- a/src/libs/engine/PortImpl.hpp +++ b/src/libs/engine/PortImpl.hpp @@ -26,6 +26,7 @@ #include "GraphObjectImpl.hpp" #include "interface/DataType.hpp" #include "Buffer.hpp" +#include "Context.hpp" namespace Raul { class Maid; class Atom; } @@ -107,6 +108,9 @@ public: void raise_set_by_user_flag() { _set_by_user = true; } + Context::ID context() const { return _context; } + void set_context(Context::ID c) { _context = c; } + protected: PortImpl(NodeImpl* node, const std::string& name, @@ -130,6 +134,7 @@ protected: bool _set_by_user; Sample _last_broadcasted_value; + Context::ID _context; Raul::Array* _buffers; // Dynamic polyphony diff --git a/src/libs/engine/ProcessContext.hpp b/src/libs/engine/ProcessContext.hpp index 0f090b3b..57677126 100644 --- a/src/libs/engine/ProcessContext.hpp +++ b/src/libs/engine/ProcessContext.hpp @@ -19,6 +19,7 @@ #define PROCESSCONTEXT_H #include "EventSink.hpp" +#include "Context.hpp" namespace Ingen { @@ -35,11 +36,11 @@ namespace Ingen { * * \ingroup engine */ -class ProcessContext +class ProcessContext : public Context { public: ProcessContext(Engine& engine) - : _engine(engine) + : Context(engine, AUDIO) , _event_sink(engine, 1024) // FIXME: size? {} @@ -49,7 +50,6 @@ public: _end = end; } - inline Engine& engine() const { return _engine; } inline SampleCount nframes() const { return _nframes; } inline FrameTime start() const { return _start; } inline FrameTime end() const { return _end; } @@ -57,7 +57,6 @@ public: inline EventSink& event_sink() { return _event_sink; } private: - Engine& _engine; ///< Engine we're running in SampleCount _nframes; ///< Number of actual time (Jack) frames this cycle FrameTime _start; ///< Start frame of this cycle, timeline relative FrameTime _end; ///< End frame of this cycle, timeline relative diff --git a/src/libs/engine/events/SetPortValueEvent.cpp b/src/libs/engine/events/SetPortValueEvent.cpp index 90e66c1c..6d65082b 100644 --- a/src/libs/engine/events/SetPortValueEvent.cpp +++ b/src/libs/engine/events/SetPortValueEvent.cpp @@ -27,6 +27,7 @@ #include "AudioBuffer.hpp" #include "EventBuffer.hpp" #include "ProcessContext.hpp" +#include "MessageContext.hpp" using namespace std; @@ -76,7 +77,7 @@ SetPortValueEvent::~SetPortValueEvent() { } - + void SetPortValueEvent::pre_process() { @@ -91,6 +92,12 @@ SetPortValueEvent::pre_process() if (_port == NULL && _error == NO_ERROR) _error = PORT_NOT_FOUND; } + + // Port is a message context port, set its value and + // call the plugin's message run function once + if (_port && _port->context() == Context::MESSAGE) { + _engine.message_context()->run(_port->parent_node()); + } QueuedEvent::pre_process(); } @@ -101,6 +108,9 @@ SetPortValueEvent::execute(ProcessContext& context) { Event::execute(context); assert(_time >= context.start() && _time <= context.end()); + + if (_port && _port->context() == Context::MESSAGE) + return; if (_error == NO_ERROR && _port == NULL) { if (Path::is_valid(_port_path)) diff --git a/src/libs/engine/lv2_contexts.h b/src/libs/engine/lv2_contexts.h new file mode 120000 index 00000000..8556a582 --- /dev/null +++ b/src/libs/engine/lv2_contexts.h @@ -0,0 +1 @@ +../../../../lv2/lv2/contexts/lv2_contexts.h \ No newline at end of file -- cgit v1.2.1