1 /*
2  * Copyright (C) 2019-2021 Alexandros Theodotou <alex at zrythm dot org>
3  *
4  * This file is part of Zrythm
5  *
6  * Zrythm is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Affero General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * Zrythm is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Affero General Public License for more details.
15  *
16  * You should have received a copy of the GNU Affero General Public License
17  * along with Zrythm.  If not, see <https://www.gnu.org/licenses/>.
18  *
19  * This file incorporates work covered by the following copyright and
20  * permission notice:
21  *
22  * Copyright (C) 2017, 2019 Robin Gareus <robin@gareus.org>
23  *
24  * This program is free software: you can redistribute it and/or modify
25  * it under the terms of the GNU General Public License as published by
26  * the Free Software Foundation, either version 2 of the License, or
27  * (at your option) any later version.
28  *
29  * This program is distributed in the hope that it will be useful,
30  * but WITHOUT ANY WARRANTY; without even the implied warranty of
31  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
32  * GNU General Public License for more details.
33  *
34  * You should have received a copy of the GNU General Public License
35  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
36  */
37 
38 /**
39  * \file
40  *
41  * Routing graph.
42  */
43 
44 #ifndef __AUDIO_GRAPH_H__
45 #define __AUDIO_GRAPH_H__
46 
47 #include <pthread.h>
48 
49 #include "audio/graph_node.h"
50 #include "utils/types.h"
51 
52 #include "zix/sem.h"
53 
54 typedef struct GraphNode GraphNode;
55 typedef struct Graph Graph;
56 typedef struct MPMCQueue MPMCQueue;
57 typedef struct Port Port;
58 typedef struct Fader Fader;
59 typedef struct Track Track;
60 typedef struct SampleProcessor SampleProcessor;
61 typedef struct Plugin Plugin;
62 typedef struct Position Position;
63 typedef struct GraphThread GraphThread;
64 typedef struct Router Router;
65 typedef struct ModulatorMacroProcessor
66   ModulatorMacroProcessor;
67 
68 /**
69  * @addtogroup audio
70  *
71  * @{
72  */
73 
74 #define mpmc_queue_push_back_node(q,x) \
75   mpmc_queue_push_back (q, (void *) x)
76 
77 #define mpmc_queue_dequeue_node(q,x) \
78   mpmc_queue_dequeue (q, (void *) x)
79 
80 #define MAX_GRAPH_THREADS 128
81 
82 /**
83  * Graph.
84  */
85 typedef struct Graph
86 {
87   /** Pointer back to router for convenience. */
88   Router *     router;
89 
90   /** Flag to indicate if graph is currently getting
91    * destroyed. */
92   int          destroying;
93 
94   /** List of all graph nodes (only used for memory
95    * management) */
96   /** key = internal pointer, value = graph node. */
97   GHashTable * graph_nodes;
98 
99   /* --- caches for current graph --- */
100   GraphNode *  bpm_node;
101   GraphNode *  beats_per_bar_node;
102   GraphNode *  beat_unit_node;
103 
104   /** Nodes without incoming edges.
105    * These run concurrently at the start of each
106    * cycle to kick off processing */
107   GraphNode ** init_trigger_list;
108   size_t       n_init_triggers;
109 
110   /* Terminal node reference count. */
111   /** Number of graph nodes without an outgoing
112    * edge. */
113   gint          n_terminal_nodes;
114   GraphNode **  terminal_nodes;
115 
116   /** Remaining unprocessed terminal nodes in this
117    * cycle. */
118   volatile gint terminal_refcnt;
119 
120   /** Synchronization with main process callback. */
121   ZixSem          callback_start;
122   ZixSem          callback_done;
123 
124   /** Wake up graph node process threads. */
125   ZixSem          trigger;
126 
127   /** Queue containing nodes that can be
128    * processed. */
129   MPMCQueue *     trigger_queue;
130 
131   /** Number of entries in trigger queue. */
132   volatile guint  trigger_queue_size;
133 
134   /** flag to exit, terminate all process-threads */
135   volatile gint     terminate;
136 
137   /** Number of threads waiting for work. */
138   volatile guint      idle_thread_cnt;
139 
140   /** Chain used to setup in the background.
141    * This is applied and cleared by graph_rechain()
142    */
143   /** key = internal pointer, value = graph node. */
144   GHashTable *         setup_graph_nodes;
145 
146   GraphNode **         setup_init_trigger_list;
147   size_t               num_setup_init_triggers;
148 
149   /** Used only when constructing the graph so we
150    * can traverse the graph backwards to calculate
151    * the playback latencies. */
152   GraphNode **         setup_terminal_nodes;
153   size_t               num_setup_terminal_nodes;
154 
155   /** Dummy member to make lookups work. */
156   int                  initial_processor;
157 
158   /* ------------------------------------ */
159 
160   GraphThread *        threads[MAX_GRAPH_THREADS];
161   GraphThread *        main_thread;
162   gint                 num_threads;
163 
164   /**
165    * An array of pointers to ports that are exposed
166    * to the backend and are outputs.
167    *
168    * Used to clear their buffers when returning
169    * early from the processing cycle.
170    */
171   GPtrArray *          external_out_ports;
172 
173 } Graph;
174 
175 void
176 graph_print (
177   Graph * graph);
178 
179 void
180 graph_destroy (
181   Graph * graph);
182 
183 GraphNode *
184 graph_find_node_from_port (
185   const Graph * self,
186   const Port *  port);
187 
188 GraphNode *
189 graph_find_node_from_plugin (
190   const Graph *  self,
191   const Plugin * pl);
192 
193 GraphNode *
194 graph_find_node_from_track (
195   const Graph * self,
196   const Track * track,
197   bool          use_setup_nodes);
198 
199 GraphNode *
200 graph_find_node_from_fader (
201   const Graph * self,
202   const Fader * fader);
203 
204 GraphNode *
205 graph_find_node_from_prefader (
206   const Graph * self,
207   const Fader * prefader);
208 
209 GraphNode *
210 graph_find_node_from_sample_processor (
211   const Graph *           self,
212   const SampleProcessor * sample_processor);
213 
214 GraphNode *
215 graph_find_node_from_monitor_fader (
216   const Graph * self,
217   const Fader * fader);
218 
219 GraphNode *
220 graph_find_node_from_modulator_macro_processor (
221   const Graph *                   self,
222   const ModulatorMacroProcessor * processor);
223 
224 GraphNode *
225 graph_find_node_from_channel_send (
226   const Graph *       self,
227   const ChannelSend * send);
228 
229 GraphNode *
230 graph_find_initial_processor_node (
231   const Graph * self);
232 
233 GraphNode *
234 graph_find_hw_processor_node (
235   const Graph *             self,
236   const HardwareProcessor * processor);
237 
238 /**
239  * Creates a new node, adds it to the graph and
240  * returns it.
241  */
242 NONNULL
243 GraphNode *
244 graph_create_node (
245   Graph *       self,
246   GraphNodeType type,
247   void *        data);
248 
249 /**
250  * Returns the max playback latency of the trigger
251  * nodes.
252  */
253 nframes_t
254 graph_get_max_route_playback_latency (
255   Graph * graph,
256   bool    use_setup_nodes);
257 
258 /* called from a terminal node (from the Graph
259  * worked-thread) to indicate it has completed
260  * processing.
261  *
262  * The thread of the last terminal node that
263  * reaches here will inform the main-thread, wait,
264  * and kick off the next process cycle.
265  */
266 HOT
267 void
268 graph_on_reached_terminal_node (
269   Graph *  self);
270 
271 void
272 graph_update_latencies (
273   Graph * self,
274   bool    use_setup_nodes);
275 
276 /*
277  * Adds the graph nodes and connections, then
278  * rechains.
279  *
280  * @param drop_unnecessary_ports Drops any ports
281  *   that don't connect anywhere.
282  * @param rechain Whether to rechain or not. If
283  *   we are just validating this should be 0.
284  */
285 void
286 graph_setup (
287   Graph *   self,
288   const int drop_unnecessary_ports,
289   const int rechain);
290 
291 /**
292  * Adds a new connection for the given
293  * src and dest ports and validates the graph.
294  *
295  * This is a low level function. Better used via
296  * ports_can_be_connected().
297  *
298  * @note The graph should be created before this
299  *   call with graph_new() and free'd after this
300  *   call with graph_free().
301  *
302  * @return True if ok, false if invalid.
303  */
304 bool
305 graph_validate_with_connection (
306   Graph *      self,
307   const Port * src,
308   const Port * dest);
309 
310 /**
311  * Starts as many threads as there are cores.
312  *
313  * @return 1 if graph started, 0 otherwise.
314  */
315 int
316 graph_start (
317   Graph * graph);
318 
319 /**
320  * Returns a new graph.
321  */
322 Graph *
323 graph_new (
324   Router * router);
325 
326 /**
327  * Tell all threads to terminate.
328  */
329 void
330 graph_terminate (
331   Graph * self);
332 
333 /**
334  * Frees the graph and its members.
335  */
336 void
337 graph_free (
338   Graph * self);
339 
340 /**
341  * @}
342  */
343 
344 #endif
345