From f240b08a1799b3aa6a29701c90388d51c0c1b2ce Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sat, 18 Feb 2017 18:32:02 +0100 Subject: Add experimental PortAudio driver --- src/server/Engine.cpp | 88 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 57 insertions(+), 31 deletions(-) (limited to 'src/server/Engine.cpp') diff --git a/src/server/Engine.cpp b/src/server/Engine.cpp index a460ac48..647fa6e6 100644 --- a/src/server/Engine.cpp +++ b/src/server/Engine.cpp @@ -1,6 +1,6 @@ /* This file is part of Ingen. - Copyright 2007-2016 David Robillard + Copyright 2007-2017 David Robillard Ingen is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free @@ -19,6 +19,7 @@ #include #include +#include #include "lv2/lv2plug.in/ns/ext/buf-size/buf-size.h" #include "lv2/lv2plug.in/ns/ext/state/state.h" @@ -91,6 +92,7 @@ Engine::Engine(Ingen::World* world) , _reset_load_flag(false) , _direct_driver(true) , _atomic_bundles(world->conf().option("atomic-bundles").get()) + , _activated(false) { if (!world->store()) { world->set_store(SPtr(new Store())); @@ -205,6 +207,14 @@ Engine::listen() #endif } +void +Engine::advance(SampleCount nframes) +{ + for (RunContext* ctx : _run_contexts) { + ctx->locate(ctx->start() + nframes, block_length()); + } +} + void Engine::locate(FrameTime s, SampleCount nframes) { @@ -213,6 +223,25 @@ Engine::locate(FrameTime s, SampleCount nframes) } } +void +Engine::flush_events(const std::chrono::milliseconds& sleep_ms) +{ + bool finished = !pending_events(); + while (!finished) { + // Run one audio block to execute prepared events + run(block_length()); + advance(block_length()); + + // Run one main iteration to post-process events + main_iteration(); + + // Sleep before continuing if there are still events to process + if (!(finished = !pending_events())) { + std::this_thread::sleep_for(sleep_ms); + } + } +} + void Engine::emit_notifications(FrameTime end) { @@ -338,6 +367,11 @@ Engine::set_driver(SPtr driver) ctx->set_priority(driver->real_time_priority()); ctx->set_rate(driver->sample_rate()); } + + _buffer_factory->set_block_length(driver->block_length()); + _options->set(sample_rate(), + block_length(), + buffer_factory()->default_size(_world->uris().atom_Sequence)); } SampleCount @@ -383,41 +417,31 @@ Engine::activate() ThreadManager::single_threaded = true; - _buffer_factory->set_block_length(_driver->block_length()); - _options->set(sample_rate(), - block_length(), - buffer_factory()->default_size(_world->uris().atom_Sequence)); - const Ingen::URIs& uris = world()->uris(); if (!_root_graph) { - // Create root graph - Properties graph_properties; - graph_properties.insert( - make_pair(uris.rdf_type, - Property(uris.ingen_Graph))); - graph_properties.insert( - make_pair(uris.ingen_polyphony, - Property(_world->forge().make(1), - Resource::Graph::INTERNAL))); - - Events::CreateGraph ev( - *this, SPtr(), -1, 0, Raul::Path("/"), graph_properties); - - // Execute in "fake" process context (we are single threaded) - PreProcessContext pctx; - RunContext rctx(run_context()); - ev.pre_process(pctx); - ev.execute(rctx); - ev.post_process(); - - _root_graph = ev.graph(); + // No root graph has been loaded, create an empty one + const Properties properties = { + {uris.rdf_type, uris.ingen_Graph}, + {uris.ingen_polyphony, + Property(_world->forge().make(1), + Resource::Graph::INTERNAL)}}; + + enqueue_event( + new Events::CreateGraph( + *this, SPtr(), -1, 0, Raul::Path("/"), properties)); + + flush_events(std::chrono::milliseconds(10)); + if (!_root_graph) { + return false; + } } _driver->activate(); _root_graph->enable(); ThreadManager::single_threaded = false; + _activated = true; return true; } @@ -434,6 +458,7 @@ Engine::deactivate() } ThreadManager::single_threaded = true; + _activated = false; } unsigned @@ -442,10 +467,6 @@ Engine::run(uint32_t sample_count) RunContext& ctx = run_context(); _cycle_start_time = current_time(ctx); - // Apply control bindings to input - control_bindings()->pre_process( - ctx, _root_graph->port_impl(0)->buffer(0).get()); - post_processor()->set_end_time(ctx.end()); // Process events that came in during the last cycle @@ -455,6 +476,11 @@ Engine::run(uint32_t sample_count) // Run root graph if (_root_graph) { + // Apply control bindings to input + control_bindings()->pre_process( + ctx, _root_graph->port_impl(0)->buffer(0).get()); + + // Run root graph for this cycle _root_graph->process(ctx); // Emit control binding feedback -- cgit v1.2.1