/* * Copyright (C) 2008-2017 Paul Davis * Copyright (C) 2009-2014 David Robillard * Copyright (C) 2010-2012 Carl Hetherington * Copyright (C) 2013 Tim Mayberry * Copyright (C) 2015-2019 Robin Gareus * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef __ardour_graph_h__ #define __ardour_graph_h__ #include #include #include #include #include #include "pbd/mpmc_queue.h" #include "pbd/semutils.h" #include "ardour/audio_backend.h" #include "ardour/libardour_visibility.h" #include "ardour/session_handle.h" #include "ardour/types.h" namespace ARDOUR { class GraphNode; class Graph; class Route; class Session; class GraphEdges; typedef boost::shared_ptr node_ptr_t; typedef std::list node_list_t; typedef std::set node_set_t; class LIBARDOUR_API Graph : public SessionHandleRef { public: Graph (Session& session); void trigger (GraphNode* n); void rechain (boost::shared_ptr, GraphEdges const&); bool plot (std::string const& file_name) const; void plot (int chain); void reached_terminal_node (); void helper_thread (); int process_routes (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample, bool& need_butler); int routes_no_roll (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample, bool non_rt_pending); void process_one_route (Route* route); void clear_other_chain (); bool in_process_thread () const; protected: virtual void session_going_away (); private: void reset_thread_list (); void drop_threads (); void run_one (); void main_thread (); void prep (); void dump (int chain) const; node_list_t _nodes_rt[2]; node_list_t _init_trigger_list[2]; PBD::MPMCQueue _trigger_queue; ///< nodes that can be processed volatile guint _trigger_queue_size; ///< number of entries in trigger-queue /** Start worker threads */ PBD::Semaphore _execution_sem; /** The number of processing threads that are asleep */ volatile guint _idle_thread_cnt; /** Signalled to start a run of the graph for a process callback */ PBD::Semaphore _callback_start_sem; PBD::Semaphore _callback_done_sem; /** The number of unprocessed nodes that do not feed any other node; updated during processing */ volatile guint _terminal_refcnt; /** The initial number of nodes that do not feed any other node (for each chain) */ guint _n_terminal_nodes[2]; bool _graph_empty; /* number of background worker threads >= 0 */ volatile guint _n_workers; /* flag to terminate background threads */ volatile gint _terminate; /* chain swapping */ Glib::Threads::Cond _cleanup_cond; mutable Glib::Threads::Mutex _swap_mutex; volatile int _current_chain; volatile int _pending_chain; volatile int _setup_chain; /* parameter caches */ pframes_t _process_nframes; samplepos_t _process_start_sample; samplepos_t _process_end_sample; bool _process_can_record; bool _process_non_rt_pending; bool _process_noroll; int _process_retval; bool _process_need_butler; /* engine / thread connection */ PBD::ScopedConnectionList engine_connections; void engine_stopped (); }; } // namespace #endif /* __ardour_graph_h__ */