/*
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
#include "ingen/ingen.h"
#include "BlockImpl.hpp"
#include "CompiledGraph.hpp"
#include "DuplexPort.hpp"
#include "PluginImpl.hpp"
#include "PortType.hpp"
#include "ThreadManager.hpp"
namespace Ingen {
class Arc;
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 local_poly);
virtual ~GraphImpl();
virtual GraphType graph_type() const { return GraphType::GRAPH; }
BlockImpl* duplicate(Engine& engine,
const Raul::Symbol& symbol,
GraphImpl* parent);
void activate(BufferFactory& bufs);
void deactivate();
void pre_process(RunContext& context);
void process(RunContext& context);
void run(RunContext& context);
void set_buffer_size(RunContext& context,
BufferFactory& bufs,
LV2_URID type,
uint32_t size);
/** 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
typedef boost::intrusive::slist<
BlockImpl, boost::intrusive::constant_time_size > Blocks;
/** 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;
typedef boost::intrusive::slist<
DuplexPort, boost::intrusive::constant_time_size > Ports;
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 arc);
/** Remove an arc from this graph.
* Pre-processing thread only.
*/
SPtr remove_arc(const PortImpl* tail,
const PortImpl* head);
bool has_arc(const PortImpl* tail, const PortImpl* head) const;
/** Set a new compiled graph to run, and return the old one. */
CompiledGraph* swap_compiled_graph(CompiledGraph* cp) INGEN_WARN_UNUSED_RESULT;
Raul::Array* external_ports() { return _ports; }
void external_ports(Raul::Array* pa) { _ports = pa; }
Raul::Array* build_ports_array();
/** 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
CompiledGraph* _compiled_graph; ///< Process thread only
Ports _inputs; ///< Pre-process thread only
Ports _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