/* This file is part of Ingen. Copyright 2007-2015 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 . */ #ifndef INGEN_ENGINE_GRAPHIMPL_HPP #define INGEN_ENGINE_GRAPHIMPL_HPP #include "BlockImpl.hpp" #include "DuplexPort.hpp" #include "ThreadManager.hpp" #include "ingen/types.hpp" #include #include #include #include namespace raul { class Maid; } namespace ingen { namespace server { class ArcImpl; class CompiledGraph; class Engine; class RunContext; /** A group of blocks in a graph, possibly polyphonic. * * Note that this is also a Block, just one which contains Blocks. * Therefore infinite subgraphing is possible, of polyphonic * graphs of polyphonic blocks etc. etc. * * \ingroup engine */ class GraphImpl : public BlockImpl { public: GraphImpl(Engine& engine, const Raul::Symbol& symbol, uint32_t poly, GraphImpl* parent, SampleRate srate, uint32_t internal_poly); virtual ~GraphImpl(); GraphType graph_type() const override { return GraphType::GRAPH; } BlockImpl* duplicate(Engine& engine, const Raul::Symbol& symbol, GraphImpl* parent) override; void activate(BufferFactory& bufs) override; void deactivate() override; void pre_process(RunContext& context) override; void process(RunContext& context) override; void run(RunContext& context) override; void set_buffer_size(RunContext& context, BufferFactory& bufs, LV2_URID type, uint32_t size) override; /** Prepare for a new (internal) polyphony value. * * Pre-process thread, poly is actually applied by apply_internal_poly. * \return true on success. */ bool prepare_internal_poly(BufferFactory& bufs, uint32_t poly); /** Apply a new (internal) polyphony value. * * Audio thread. * * \param context Process context * \param bufs New set of buffers * \param poly Must be < the most recent value passed to prepare_internal_poly. * \param maid Any objects no longer needed will be pushed to this */ bool apply_internal_poly(RunContext& context, BufferFactory& bufs, Raul::Maid& maid, uint32_t poly); // Graph specific stuff not inherited from Block using Blocks = boost::intrusive::slist>; /** Add a block to this graph. * Pre-process thread only. */ void add_block(BlockImpl& block); /** Remove a block from this graph. * Pre-process thread only. */ void remove_block(BlockImpl& block); Blocks& blocks() { return _blocks; } const Blocks& blocks() const { return _blocks; } uint32_t num_ports_non_rt() const; bool has_port_with_index(uint32_t index) const; using PortList = boost::intrusive::slist>; void add_input(DuplexPort& port) { ThreadManager::assert_thread(THREAD_PRE_PROCESS); assert(port.is_input()); _inputs.push_front(port); } void add_output(DuplexPort& port) { ThreadManager::assert_thread(THREAD_PRE_PROCESS); assert(port.is_output()); _outputs.push_front(port); } /** Remove port from ports list used in pre-processing thread. * * Port is not removed from ports array for process thread (which could be * simultaneously running). * * Pre-processing thread or situations that won't cause races with it only. */ void remove_port(DuplexPort& port); /** Remove all ports from ports list used in pre-processing thread. * * Ports are not removed from ports array for process thread (which could be * simultaneously running). Returned is a (inputs, outputs) pair. * * Pre-processing thread or situations that won't cause races with it only. */ void clear_ports(); /** Add an arc to this graph. * Pre-processing thread only. */ void add_arc(SPtr a); /** Remove an arc from this graph. * Pre-processing thread only. */ SPtr remove_arc(const PortImpl* tail, const PortImpl* dst_port); bool has_arc(const PortImpl* tail, const PortImpl* dst_port) const; /** Set a new compiled graph to run, and return the old one. */ void set_compiled_graph(MPtr&& cg); const MPtr& external_ports() { return _ports; } void set_external_ports(MPtr&& pa) { _ports = std::move(pa); } MPtr build_ports_array(Raul::Maid& maid); /** Whether to run this graph's DSP bits in the audio thread */ bool enabled() const { return _process; } void enable() { _process = true; } void disable(RunContext& context); uint32_t internal_poly() const { return _poly_pre; } uint32_t internal_poly_process() const { return _poly_process; } Engine& engine() { return _engine; } private: Engine& _engine; uint32_t _poly_pre; ///< Pre-process thread only uint32_t _poly_process; ///< Process thread only MPtr _compiled_graph; ///< Process thread only PortList _inputs; ///< Pre-process thread only PortList _outputs; ///< Pre-process thread only Blocks _blocks; ///< Pre-process thread only bool _process; ///< True iff graph is enabled }; } // namespace server } // namespace ingen #endif // INGEN_ENGINE_GRAPHIMPL_HPP