/* This file is part of Ingen. Copyright 2007-2012 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 Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. You should have received a copy of the GNU Affero General Public License along with Ingen. If not, see . */ #include #include "Engine.hpp" #include "Event.hpp" #include "PostProcessor.hpp" #include "ProcessContext.hpp" using namespace std; namespace Ingen { namespace Server { PostProcessor::PostProcessor(Engine& engine) : _engine(engine) , _head(NULL) , _tail(NULL) , _max_time(0) { } PostProcessor::~PostProcessor() { } void PostProcessor::append(ProcessContext& context, Event* first, Event* last) { assert(first); assert(last); assert(!last->next()); /* Note that tail is only used here, not in process(). The head must be checked first here, since if it is NULL the tail pointer is junk. */ if (!_head) { _tail = last; _head = first; } else { _tail.load()->next(first); _tail = last; } } bool PostProcessor::pending() const { return _head.load() || _engine.process_context().pending_notifications(); } void PostProcessor::process() { const FrameTime end_time = _max_time; Event* ev = _head.load(); if (!ev) { // Process audio thread notifications until end _engine.process_context().emit_notifications(end_time); return; } while (ev && ev->time() < end_time) { Event* const next = (Event*)ev->next(); // Process audio thread notifications up until this event's time _engine.process_context().emit_notifications(ev->time()); // Process and delete this event ev->post_process(); delete ev; ev = next; } // Since _head was not NULL, we know it hasn't been changed since _head = ev; /* If next is NULL, then _tail may now be invalid. However, it would cause a race to reset _tail here. Instead, append() checks only _head for emptiness, and resets the tail appropriately. */ // Process remaining audio thread notifications until end _engine.process_context().emit_notifications(end_time); } } // namespace Server } // namespace Ingen