From ba2e3fac36f4db4ec4c27775f1a2246c111ce403 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Wed, 9 May 2012 03:58:59 +0000 Subject: Factor audio thread execution stuff out of JackDriver into Engine::run(). Towards an Ingen library interface usable on user-provided buffers. git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@4326 a436a847-0d15-0410-975c-d299462d15a1 --- src/server/Context.hpp | 5 ++- src/server/Driver.hpp | 5 --- src/server/Engine.cpp | 61 ++++++++++++++++++++++--------- src/server/Engine.hpp | 9 +++++ src/server/InputPort.cpp | 1 + src/server/JackDriver.cpp | 71 +++++++++---------------------------- src/server/JackDriver.hpp | 8 ----- src/server/LV2Node.cpp | 1 + src/server/MessageContext.cpp | 10 ++++++ src/server/MessageContext.hpp | 10 +----- src/server/Notification.cpp | 1 + src/server/PostProcessor.cpp | 15 ++++---- src/server/ProcessContext.cpp | 4 +++ src/server/ProcessContext.hpp | 2 +- src/server/ProcessSlave.cpp | 2 +- src/server/ProcessSlave.hpp | 7 +--- src/server/events/CreatePatch.cpp | 15 +++----- src/server/events/SetMetadata.cpp | 2 +- src/server/internals/Controller.cpp | 1 + 19 files changed, 105 insertions(+), 125 deletions(-) (limited to 'src/server') diff --git a/src/server/Context.hpp b/src/server/Context.hpp index 23547059..fa2a2c7e 100644 --- a/src/server/Context.hpp +++ b/src/server/Context.hpp @@ -21,7 +21,6 @@ #include "ingen/shared/World.hpp" -#include "Engine.hpp" #include "types.hpp" namespace Ingen { @@ -49,10 +48,10 @@ public: MESSAGE }; - Context(Engine& engine, ID id) + Context(Engine& engine, size_t event_sink_size, ID id) : _engine(engine) , _id(id) - , _event_sink(engine.event_queue_size()) + , _event_sink(event_sink_size) , _start(0) , _end(0) , _nframes(0) diff --git a/src/server/Driver.hpp b/src/server/Driver.hpp index bd2202ad..cce1be7e 100644 --- a/src/server/Driver.hpp +++ b/src/server/Driver.hpp @@ -96,9 +96,6 @@ public: virtual Raul::Deletable* remove_port(const Raul::Path& path, DriverPort** port=NULL) = 0; - virtual void set_root_patch(PatchImpl* patch) = 0; - virtual PatchImpl* root_patch() = 0; - /** Return the audio buffer size in frames */ virtual SampleCount block_length() const = 0; @@ -109,8 +106,6 @@ public: virtual SampleCount frame_time() const = 0; virtual bool is_realtime() const = 0; - - virtual ProcessContext& context() = 0; }; } // namespace Server diff --git a/src/server/Engine.cpp b/src/server/Engine.cpp index c2cc7cab..f2f088f5 100644 --- a/src/server/Engine.cpp +++ b/src/server/Engine.cpp @@ -21,7 +21,6 @@ #include "raul/Deletable.hpp" #include "raul/Maid.hpp" #include "raul/SharedPtr.hpp" -#include "events/CreatePatch.hpp" #include "events/CreatePort.hpp" #include "ingen/shared/World.hpp" #include "ingen/shared/LV2Features.hpp" @@ -63,6 +62,7 @@ Engine::Engine(Ingen::Shared::World* a_world) , _pre_processor(new PreProcessor()) , _post_processor(new PostProcessor(*this)) , _event_writer(new EventWriter(*this)) + , _process_context(*this) , _quit_flag(false) { if (a_world->store()) { @@ -101,7 +101,7 @@ Engine::~Engine() SharedPtr Engine::engine_store() const { - return PtrCast(_world->store()); + return PtrCast(_world->store()); } size_t @@ -153,18 +153,19 @@ Engine::activate() Ingen::Forge& forge = world()->forge(); // Create root patch - PatchImpl* root_patch = _driver->root_patch(); - if (!root_patch) { - root_patch = new PatchImpl(*this, "root", 1, NULL, _driver->sample_rate(), 1); - root_patch->set_property(uris.rdf_type, - Resource::Property(uris.ingen_Patch, Resource::INTERNAL)); - root_patch->set_property(uris.ingen_polyphony, - Resource::Property(_world->forge().make(int32_t(1)), - Resource::INTERNAL)); - root_patch->activate(*_buffer_factory); - _world->store()->add(root_patch); - root_patch->compiled_patch(root_patch->compile()); - _driver->set_root_patch(root_patch); + if (!_root_patch) { + _root_patch = new PatchImpl( + *this, "root", 1, NULL, _driver->sample_rate(), 1); + _root_patch->set_property( + uris.rdf_type, + Resource::Property(uris.ingen_Patch, Resource::INTERNAL)); + _root_patch->set_property( + uris.ingen_polyphony, + Resource::Property(_world->forge().make(int32_t(1)), + Resource::INTERNAL)); + _root_patch->activate(*_buffer_factory); + _world->store()->add(_root_patch); + _root_patch->compiled_patch(_root_patch->compile()); ProcessContext context(*this); @@ -212,7 +213,7 @@ Engine::activate() } _driver->activate(); - root_patch->enable(); + _root_patch->enable(); ThreadManager::single_threaded = false; @@ -223,11 +224,39 @@ void Engine::deactivate() { _driver->deactivate(); - _driver->root_patch()->deactivate(); + _root_patch->deactivate(); ThreadManager::single_threaded = true; } +void +Engine::run(uint32_t sample_count) +{ + // Apply control bindings to input + control_bindings()->pre_process( + _process_context, _root_patch->port_impl(0)->buffer(0).get()); + + post_processor()->set_end_time(_process_context.end()); + + // Process events that came in during the last cycle + // (Aiming for jitter-free 1 block event latency, ideally) + process_events(_process_context); + + // Run root patch + if (_root_patch) { + _root_patch->process(_process_context); + } + + // Emit control binding feedback + control_bindings()->post_process( + _process_context, _root_patch->port_impl(1)->buffer(0).get()); + + // Signal message context to run if necessary + if (message_context()->has_requests()) { + message_context()->signal(_process_context); + } +} + bool Engine::pending_events() { diff --git a/src/server/Engine.hpp b/src/server/Engine.hpp index 042264e4..5111f52c 100644 --- a/src/server/Engine.hpp +++ b/src/server/Engine.hpp @@ -23,6 +23,8 @@ #include "ingen/Interface.hpp" #include "raul/SharedPtr.hpp" +#include "ProcessContext.hpp" + namespace Raul { class Maid; } namespace Ingen { @@ -43,6 +45,7 @@ class NodeFactory; class PostProcessor; class PreProcessor; class ProcessContext; +class PatchImpl; /** The engine which executes the process graph. @@ -63,6 +66,7 @@ public: // EngineBase methods virtual bool activate(); virtual void deactivate(); + virtual void run(uint32_t sample_count); virtual void quit(); virtual bool main_iteration(); virtual void register_client(const Raul::URI& uri, Interface* client); @@ -85,6 +89,8 @@ public: MessageContext* message_context() const { return _message_context; } NodeFactory* node_factory() const { return _node_factory; } PostProcessor* post_processor() const { return _post_processor; } + PatchImpl* root_patch() const { return _root_patch; } + ProcessContext& process_context() { return _process_context; } SharedPtr engine_store() const; @@ -104,6 +110,9 @@ private: PostProcessor* _post_processor; EventWriter* _event_writer; + PatchImpl* _root_patch; + ProcessContext _process_context; + bool _quit_flag; }; diff --git a/src/server/InputPort.cpp b/src/server/InputPort.cpp index fa76c9b0..a6b377c7 100644 --- a/src/server/InputPort.cpp +++ b/src/server/InputPort.cpp @@ -22,6 +22,7 @@ #include "AudioBuffer.hpp" #include "BufferFactory.hpp" #include "ConnectionImpl.hpp" +#include "Engine.hpp" #include "InputPort.hpp" #include "NodeImpl.hpp" #include "Notification.hpp" diff --git a/src/server/JackDriver.cpp b/src/server/JackDriver.cpp index cccaadf1..46b80a40 100644 --- a/src/server/JackDriver.cpp +++ b/src/server/JackDriver.cpp @@ -184,8 +184,6 @@ JackDriver::JackDriver(Engine& engine) , _block_length(0) , _sample_rate(0) , _is_activated(false) - , _process_context(engine) - , _root_patch(NULL) { _midi_event_type = _engine.world()->uris()->midi_MidiEvent; } @@ -277,8 +275,9 @@ JackDriver::activate() _is_activated = true; - _process_context.activate(world->conf()->option("parallelism").get_int(), - is_realtime()); + _engine.process_context().activate( + world->conf()->option("parallelism").get_int(), + is_realtime()); if (jack_activate(_client)) { LOG(error) << "Could not activate Jack client, aborting" << endl; @@ -400,68 +399,29 @@ int JackDriver::_process_cb(jack_nframes_t nframes) { if (nframes == 0 || ! _is_activated) { - if (_flag == 1) + if (_flag == 1) { _sem.post(); + } return 0; } - // FIXME: all of this time stuff is screwy - - // FIXME: support nframes != buffer_size, even though that never damn well happens - //assert(nframes == _block_length); - - // Note that Jack can not call this function for a cycle, if overloaded + /* Note that Jack can not call this function for a cycle, if overloaded, + so a rolling counter here would not always be correct. */ const jack_nframes_t start_of_current_cycle = jack_last_frame_time(_client); _transport_state = jack_transport_query(_client, &_position); - _process_context.locate(start_of_current_cycle, nframes, 0); - - for (ProcessContext::Slaves::iterator i = _process_context.slaves().begin(); - i != _process_context.slaves().end(); ++i) { - (*i)->context().locate(start_of_current_cycle, nframes, 0); - } + _engine.process_context().locate(start_of_current_cycle, nframes, 0); // Read input for (Raul::List::iterator i = _ports.begin(); i != _ports.end(); ++i) - (*i)->pre_process(_process_context); - - // Apply control bindings to input - _engine.control_bindings()->pre_process( - _process_context, _root_patch->port_impl(0)->buffer(0).get()); - - _engine.post_processor()->set_end_time(_process_context.end()); - - // Process events that came in during the last cycle - // (Aiming for jitter-free 1 block event latency, ideally) - _engine.process_events(_process_context); - - // Run root patch - if (_root_patch) { - _root_patch->process(_process_context); -#if 0 - static const SampleCount control_block_size = nframes / 2; - for (jack_nframes_t i = 0; i < nframes; i += control_block_size) { - const SampleCount block_size = (i + control_block_size < nframes) - ? control_block_size - : nframes - i; - _process_context.locate(start_of_current_cycle + i, block_size, i); - _root_patch->process(_process_context); - } -#endif - } - - // Emit control binding feedback - _engine.control_bindings()->post_process( - _process_context, _root_patch->port_impl(1)->buffer(0).get()); + (*i)->pre_process(_engine.process_context()); - // Signal message context to run if necessary - if (_engine.message_context()->has_requests()) - _engine.message_context()->signal(_process_context); + _engine.run(nframes); // Write output for (Raul::List::iterator i = _ports.begin(); i != _ports.end(); ++i) - (*i)->post_process(_process_context); + (*i)->post_process(_engine.process_context()); return 0; } @@ -499,10 +459,11 @@ JackDriver::_sample_rate_cb(jack_nframes_t nframes) int JackDriver::_block_length_cb(jack_nframes_t nframes) { - if (_root_patch) { + if (_engine.root_patch()) { _block_length = nframes; - _root_patch->set_buffer_size(context(), *_engine.buffer_factory(), PortType::AUDIO, - _engine.buffer_factory()->audio_buffer_size(nframes)); + _engine.root_patch()->set_buffer_size( + _engine.process_context(), *_engine.buffer_factory(), PortType::AUDIO, + _engine.buffer_factory()->audio_buffer_size(nframes)); } return 0; } @@ -519,7 +480,7 @@ JackDriver::_session_cb(jack_session_event_t* event) SharedPtr serialiser = _engine.world()->serialiser(); if (serialiser) { - SharedPtr root(_engine.driver()->root_patch(), NullDeleter); + SharedPtr root(_engine.root_patch(), NullDeleter); serialiser->write_bundle(root, string("file://") + event->session_dir); } diff --git a/src/server/JackDriver.hpp b/src/server/JackDriver.hpp index 1e6202f9..24a2dab8 100644 --- a/src/server/JackDriver.hpp +++ b/src/server/JackDriver.hpp @@ -35,7 +35,6 @@ #include "Buffer.hpp" #include "Driver.hpp" -#include "ProcessContext.hpp" namespace Raul { class Path; } @@ -104,11 +103,6 @@ public: Raul::Deletable* remove_port(const Raul::Path& path, DriverPort** port=NULL); - PatchImpl* root_patch() { return _root_patch; } - void set_root_patch(PatchImpl* patch) { _root_patch = patch; } - - ProcessContext& context() { return _process_context; } - /** Transport state for this frame. * Intended to only be called from the audio thread. */ inline const jack_position_t* position() { return &_position; } @@ -171,8 +165,6 @@ private: jack_position_t _position; jack_transport_state_t _transport_state; Raul::List _ports; - ProcessContext _process_context; - PatchImpl* _root_patch; }; } // namespace Server diff --git a/src/server/LV2Node.cpp b/src/server/LV2Node.cpp index bdbb858c..dfba7177 100644 --- a/src/server/LV2Node.cpp +++ b/src/server/LV2Node.cpp @@ -31,6 +31,7 @@ #include "ingen/shared/URIs.hpp" #include "AudioBuffer.hpp" +#include "Engine.hpp" #include "InputPort.hpp" #include "LV2Node.hpp" #include "LV2Plugin.hpp" diff --git a/src/server/MessageContext.cpp b/src/server/MessageContext.cpp index 1d42576c..ed2c8543 100644 --- a/src/server/MessageContext.cpp +++ b/src/server/MessageContext.cpp @@ -32,6 +32,16 @@ using namespace Raul; namespace Ingen { namespace Server { +MessageContext::MessageContext(Engine& engine) + : Context(engine, engine.event_queue_size(), MESSAGE) + , Raul::Thread("MessageContext") + , _sem(0) + , _requests(engine.event_queue_size()) + , _end_time(0) +{ + Thread::set_context(THREAD_MESSAGE); +} + void MessageContext::run(NodeImpl* node, FrameTime time) { diff --git a/src/server/MessageContext.hpp b/src/server/MessageContext.hpp index 604810bd..0bc8ecf5 100644 --- a/src/server/MessageContext.hpp +++ b/src/server/MessageContext.hpp @@ -43,15 +43,7 @@ class NodeImpl; class MessageContext : public Context, public Raul::Thread { public: - explicit MessageContext(Engine& engine) - : Context(engine, MESSAGE) - , Raul::Thread("MessageContext") - , _sem(0) - , _requests(engine.event_queue_size()) - , _end_time(0) - { - Thread::set_context(THREAD_MESSAGE); - } + explicit MessageContext(Engine& engine); /** Schedule a message context run at a certain time. * Safe to call from either process thread or pre-process thread. diff --git a/src/server/Notification.cpp b/src/server/Notification.cpp index 7cbea267..3d7efe23 100644 --- a/src/server/Notification.cpp +++ b/src/server/Notification.cpp @@ -18,6 +18,7 @@ #include "ingen/shared/URIs.hpp" #include "ClientBroadcaster.hpp" +#include "Engine.hpp" #include "Notification.hpp" #include "PortImpl.hpp" diff --git a/src/server/PostProcessor.cpp b/src/server/PostProcessor.cpp index 3a8ee612..2ad23254 100644 --- a/src/server/PostProcessor.cpp +++ b/src/server/PostProcessor.cpp @@ -72,15 +72,12 @@ PostProcessor::process() /* FIXME: process events from all threads if parallel */ /* Process audio thread generated events */ - Driver* driver = _engine.driver(); - if (driver) { - Raul::RingBuffer& event_sink = driver->context().event_sink(); - const uint32_t read_space = event_sink.read_space(); - Notification note; - for (uint32_t i = 0; i < read_space; i += sizeof(note)) { - if (event_sink.read(sizeof(note), ¬e) == sizeof(note)) { - Notification::post_process(note, _engine); - } + Raul::RingBuffer& event_sink = _engine.process_context().event_sink(); + const uint32_t read_space = event_sink.read_space(); + Notification note; + for (uint32_t i = 0; i < read_space; i += sizeof(note)) { + if (event_sink.read(sizeof(note), ¬e) == sizeof(note)) { + Notification::post_process(note, _engine); } } diff --git a/src/server/ProcessContext.cpp b/src/server/ProcessContext.cpp index c13d53eb..78f6d50e 100644 --- a/src/server/ProcessContext.cpp +++ b/src/server/ProcessContext.cpp @@ -20,6 +20,10 @@ namespace Ingen { namespace Server { +ProcessContext::ProcessContext(Engine& engine) + : Context(engine, engine.event_queue_size(), AUDIO) +{} + void ProcessContext::activate(uint32_t parallelism, bool sched_rt) { diff --git a/src/server/ProcessContext.hpp b/src/server/ProcessContext.hpp index 43b6f8b9..1af480be 100644 --- a/src/server/ProcessContext.hpp +++ b/src/server/ProcessContext.hpp @@ -33,7 +33,7 @@ class ProcessSlave; class ProcessContext : public Context { public: - explicit ProcessContext(Engine& engine) : Context(engine, AUDIO) {} + explicit ProcessContext(Engine& engine); typedef std::vector Slaves; diff --git a/src/server/ProcessSlave.cpp b/src/server/ProcessSlave.cpp index 8d74224a..6960b5e4 100644 --- a/src/server/ProcessSlave.cpp +++ b/src/server/ProcessSlave.cpp @@ -46,7 +46,7 @@ ProcessSlave::_whipped() n.node()->wait_for_input(n.n_providers()); - n.node()->process(*_context); + n.node()->process(_engine.process_context()); /* Signal dependants their input is ready */ for (size_t i=0; i < n.dependants().size(); ++i) diff --git a/src/server/ProcessSlave.hpp b/src/server/ProcessSlave.hpp index 99ff116f..4bafb1c7 100644 --- a/src/server/ProcessSlave.hpp +++ b/src/server/ProcessSlave.hpp @@ -42,7 +42,6 @@ public: , _index(0) , _state(STATE_FINISHED) , _compiled_patch(NULL) - , _context(NULL) { std::stringstream ss; ss << "Process Slave "; @@ -69,7 +68,6 @@ public: _index = start_index; _state = STATE_RUNNING; _compiled_patch = compiled_patch; - _context = &context; Raul::Slave::whip(); } @@ -79,9 +77,7 @@ public: _state.compare_and_exchange(STATE_RUNNING, STATE_FINISH_SIGNALLED); } - inline uint32_t id() const { return _id; } - inline const ProcessContext& context() const { return _engine.driver()->context(); } - inline ProcessContext& context() { return _engine.driver()->context(); } + inline uint32_t id() const { return _id; } private: void _whipped(); @@ -97,7 +93,6 @@ private: uint32_t _index; Raul::AtomicInt _state; CompiledPatch* _compiled_patch; - ProcessContext* _context; }; } // namespace Server diff --git a/src/server/events/CreatePatch.cpp b/src/server/events/CreatePatch.cpp index 5463cb99..794ff7d6 100644 --- a/src/server/events/CreatePatch.cpp +++ b/src/server/events/CreatePatch.cpp @@ -99,7 +99,6 @@ CreatePatch::pre_process() _patch->activate(*_engine.buffer_factory()); // Insert into EngineStore - //_patch->add_to_store(_engine.engine_store()); _engine.engine_store()->add(_patch); Event::pre_process(); @@ -111,16 +110,10 @@ CreatePatch::execute(ProcessContext& context) Event::execute(context); if (_patch) { - if (!_parent) { - assert(_path.is_root()); - assert(_patch->parent_patch() == NULL); - _engine.driver()->set_root_patch(_patch); - } else { - assert(_parent); - assert(!_path.is_root()); - _engine.maid()->push(_parent->compiled_patch()); - _parent->compiled_patch(_compiled_patch); - } + assert(_parent); + assert(!_path.is_root()); + _engine.maid()->push(_parent->compiled_patch()); + _parent->compiled_patch(_compiled_patch); } } diff --git a/src/server/events/SetMetadata.cpp b/src/server/events/SetMetadata.cpp index 7d88c83c..68cdbbbd 100644 --- a/src/server/events/SetMetadata.cpp +++ b/src/server/events/SetMetadata.cpp @@ -319,7 +319,7 @@ SetMetadata::execute(ProcessContext& context) break; case POLYPHONY: if (_patch->internal_poly() != static_cast(value.get_int32()) && - !_patch->apply_internal_poly(_engine.driver()->context(), + !_patch->apply_internal_poly(_engine.process_context(), *_engine.buffer_factory(), *_engine.maid(), value.get_int32())) { _status = INTERNAL_ERROR; diff --git a/src/server/internals/Controller.cpp b/src/server/internals/Controller.cpp index 6a9139b5..25561535 100644 --- a/src/server/internals/Controller.cpp +++ b/src/server/internals/Controller.cpp @@ -23,6 +23,7 @@ #include "raul/midi_events.h" #include "AudioBuffer.hpp" +#include "Engine.hpp" #include "InputPort.hpp" #include "InternalPlugin.hpp" #include "Notification.hpp" -- cgit v1.2.1