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 #include "zrythm-config.h"
39 
40 #include "audio/audio_track.h"
41 #include "audio/control_port.h"
42 #include "audio/engine.h"
43 #include "audio/engine_alsa.h"
44 #ifdef HAVE_JACK
45 #include "audio/engine_jack.h"
46 #endif
47 #ifdef HAVE_PORT_AUDIO
48 #include "audio/engine_pa.h"
49 #endif
50 #include "audio/graph.h"
51 #include "audio/graph_thread.h"
52 #include "audio/master_track.h"
53 #include "audio/midi.h"
54 #include "audio/midi_track.h"
55 #include "audio/pan.h"
56 #include "audio/port.h"
57 #include "audio/router.h"
58 #include "audio/stretcher.h"
59 #include "audio/tempo_track.h"
60 #include "audio/track.h"
61 #include "audio/track_processor.h"
62 #include "project.h"
63 #include "utils/arrays.h"
64 #include "utils/flags.h"
65 #include "utils/env.h"
66 #include "utils/mpmc_queue.h"
67 #include "utils/object_utils.h"
68 #include "utils/objects.h"
69 #include "utils/stoat.h"
70 #include "zrythm_app.h"
71 
72 #ifdef HAVE_JACK
73 #include "weak_libjack.h"
74 #endif
75 
76 /**
77  * Returns the max playback latency of the trigger
78  * nodes.
79  */
80 nframes_t
router_get_max_route_playback_latency(Router * router)81 router_get_max_route_playback_latency (
82   Router * router)
83 {
84   g_return_val_if_fail (
85     router && router->graph, 0);
86   router->max_route_playback_latency =
87     graph_get_max_route_playback_latency (
88       router->graph, false);
89 
90   return router->max_route_playback_latency;
91 }
92 
93 /**
94  * Starts a new cycle.
95  */
96 void
router_start_cycle(Router * self,EngineProcessTimeInfo time_nfo)97 router_start_cycle (
98   Router *              self,
99   EngineProcessTimeInfo time_nfo)
100 {
101   g_return_if_fail (self && self->graph);
102   g_return_if_fail (
103     time_nfo.local_offset + time_nfo.nframes <=
104       AUDIO_ENGINE->nframes);
105 
106   /* only set the kickoff thread when not called
107    * from the gtk thread (sometimes this is called
108    * from the gtk thread to force some
109    * processing) */
110   if (g_thread_self () != zrythm_app->gtk_thread)
111     self->process_kickoff_thread = g_thread_self ();
112 
113   if (!zix_sem_try_wait (&self->graph_access))
114     {
115       g_message (
116         "graph access is busy, returning...");
117       return;
118     }
119 
120   self->global_offset =
121     self->max_route_playback_latency -
122     AUDIO_ENGINE->remaining_latency_preroll;
123   memcpy (
124     &self->time_nfo, &time_nfo,
125     sizeof (EngineProcessTimeInfo));
126 
127   /* read control port change events */
128   while (zix_ring_read_space (
129            self->ctrl_port_change_queue)
130              >= sizeof (ControlPortChange))
131     {
132       ControlPortChange change = { 0 };
133       zix_ring_read (
134         self->ctrl_port_change_queue, &change,
135         sizeof (change));
136       if (change.flag1 & PORT_FLAG_BPM)
137         {
138           tempo_track_set_bpm (
139             P_TEMPO_TRACK, change.real_val, 0.f,
140             true, F_PUBLISH_EVENTS);
141         }
142       else if (change.flag2 &
143                  PORT_FLAG2_BEATS_PER_BAR)
144         {
145           tempo_track_set_beats_per_bar (
146             P_TEMPO_TRACK, change.ival);
147         }
148       else if (change.flag2 & PORT_FLAG2_BEAT_UNIT)
149         {
150           tempo_track_set_beat_unit_from_enum (
151             P_TEMPO_TRACK, change.beat_unit);
152         }
153     }
154 
155   /* process tempo track ports first */
156   if (self->graph->bpm_node)
157     {
158       graph_node_process (
159         self->graph->bpm_node, time_nfo);
160     }
161   if (self->graph->beats_per_bar_node)
162     {
163       graph_node_process (
164         self->graph->beats_per_bar_node, time_nfo);
165     }
166   if (self->graph->beat_unit_node)
167     {
168       graph_node_process (
169         self->graph->beat_unit_node, time_nfo);
170     }
171 
172   self->callback_in_progress = true;
173   zix_sem_post (&self->graph->callback_start);
174   zix_sem_wait (&self->graph->callback_done);
175   self->callback_in_progress = false;
176 
177   zix_sem_post (&self->graph_access);
178 }
179 
180 /**
181  * Recalculates the process acyclic directed graph.
182  *
183  * @param soft If true, only readjusts latencies.
184  */
185 void
router_recalc_graph(Router * self,bool soft)186 router_recalc_graph (
187   Router * self,
188   bool     soft)
189 {
190   g_message (
191     "Recalculating%s...", soft ? " (soft)" : "");
192 
193   g_return_if_fail (self);
194 
195   if (!self->graph && !soft)
196     {
197       self->graph = graph_new (self);
198       graph_setup (self->graph, 1, 1);
199       graph_start (self->graph);
200       return;
201     }
202 
203   if (soft)
204     {
205       zix_sem_wait (&self->graph_access);
206       graph_update_latencies (self->graph, false);
207       zix_sem_post (&self->graph_access);
208     }
209   else
210     {
211       zix_sem_wait (&self->graph_access);
212       graph_setup (self->graph, 1, 1);
213       zix_sem_post (&self->graph_access);
214     }
215 
216   g_message ("done");
217 }
218 
219 /**
220  * Queues a control port change to be applied
221  * when processing starts.
222  *
223  * Currently only applies to BPM/time signature
224  * changes.
225  */
226 void
router_queue_control_port_change(Router * self,const ControlPortChange * change)227 router_queue_control_port_change (
228   Router *                  self,
229   const ControlPortChange * change)
230 {
231   if (zix_ring_write_space (
232         self->ctrl_port_change_queue) <
233           sizeof (ControlPortChange))
234     {
235       zix_ring_skip (
236         self->ctrl_port_change_queue,
237         sizeof (ControlPortChange));
238     }
239 
240   zix_ring_write (
241     self->ctrl_port_change_queue, change,
242     sizeof (ControlPortChange));
243 }
244 
245 /**
246  * Creates a new Router.
247  *
248  * There is only 1 router needed in a project.
249  */
250 Router *
router_new(void)251 router_new (void)
252 {
253   g_message ("Creating new router...");
254 
255   Router * self = object_new (Router);
256 
257   zix_sem_init (&self->graph_access, 1);
258 
259   self->ctrl_port_change_queue =
260     zix_ring_new (
261       sizeof (ControlPortChange) * (size_t) 24);
262 
263   g_message ("done");
264 
265   return self;
266 }
267 
268 /**
269  * Returns whether this is the thread that kicks
270  * off processing (thread that calls
271  * router_start_cycle()).
272  */
273 bool
router_is_processing_kickoff_thread(const Router * const self)274 router_is_processing_kickoff_thread (
275   const Router * const self)
276 {
277   return
278     g_thread_self () ==
279       self->process_kickoff_thread;
280 }
281 
282 /**
283  * Returns if the current thread is a
284  * processing thread.
285  */
286 bool
router_is_processing_thread(const Router * const self)287 router_is_processing_thread (
288   const Router * const self)
289 {
290   if (!self->graph)
291     return false;
292 
293   for (int j = 0;
294        j < self->graph->num_threads; j++)
295     {
296 #ifdef HAVE_JACK
297       if (AUDIO_ENGINE->audio_backend ==
298             AUDIO_BACKEND_JACK)
299         {
300           if (pthread_equal (
301                 pthread_self (),
302                 self->graph->threads[j]->jthread))
303             return true;
304         }
305       else
306         {
307 #endif
308           if (pthread_equal (
309                 pthread_self (),
310                 self->graph->threads[j]->pthread))
311             return true;
312 #ifdef HAVE_JACK
313         }
314 #endif
315     }
316 
317 #ifdef HAVE_JACK
318   if (AUDIO_ENGINE->audio_backend ==
319         AUDIO_BACKEND_JACK)
320     {
321       if (self->graph->main_thread
322           &&
323           pthread_equal (
324             pthread_self (),
325             self->graph->main_thread->jthread))
326         return true;
327     }
328   else
329     {
330 #endif
331       if (self->graph->main_thread
332           &&
333           pthread_equal (
334             pthread_self (),
335             self->graph->main_thread->pthread))
336         return true;
337 #ifdef HAVE_JACK
338     }
339 #endif
340 
341   return false;
342 }
343 
344 void
router_free(Router * self)345 router_free (
346   Router * self)
347 {
348   g_debug ("%s: freeing...", __func__);
349 
350   if (self->graph)
351     graph_destroy (self->graph);
352   self->graph = NULL;
353 
354   zix_sem_destroy (&self->graph_access);
355   object_set_to_zero (&self->graph_access);
356 
357   object_free_w_func_and_null (
358     zix_ring_free, self->ctrl_port_change_queue);
359 
360   object_zero_and_free (self);
361 
362   g_debug ("%s: done", __func__);
363 }
364