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 
20 #include "zrythm-config.h"
21 
22 #include <math.h>
23 
24 #include "audio/audio_region.h"
25 #include "audio/automation_region.h"
26 #include "audio/automation_track.h"
27 #include "audio/automation_tracklist.h"
28 #include "audio/channel.h"
29 #include "audio/clip.h"
30 #include "audio/modulator_track.h"
31 #include "audio/pool.h"
32 #include "audio/router.h"
33 #include "audio/stretcher.h"
34 #include "audio/track.h"
35 #include "gui/backend/event.h"
36 #include "gui/backend/event_manager.h"
37 #include "gui/backend/clip_editor.h"
38 #include "gui/backend/piano_roll.h"
39 #include "gui/widgets/audio_arranger.h"
40 #include "gui/widgets/audio_editor_space.h"
41 #include "gui/widgets/automation_arranger.h"
42 #include "gui/widgets/automation_editor_space.h"
43 #include "gui/widgets/bot_bar.h"
44 #include "gui/widgets/bot_dock_edge.h"
45 #include "gui/widgets/center_dock.h"
46 #include "gui/widgets/clip_editor.h"
47 #include "gui/widgets/clip_editor_inner.h"
48 #include "gui/widgets/channel.h"
49 #include "gui/widgets/channel_sends_expander.h"
50 #include "gui/widgets/chord_arranger.h"
51 #include "gui/widgets/chord_editor_space.h"
52 #include "gui/widgets/chord_key.h"
53 #include "gui/widgets/chord_pad.h"
54 #include "gui/widgets/color_area.h"
55 #include "gui/widgets/editor_ruler.h"
56 #include "gui/widgets/editor_selection_info.h"
57 #include "gui/widgets/editor_toolbar.h"
58 #include "gui/widgets/event_viewer.h"
59 #include "gui/widgets/foldable_notebook.h"
60 #include "gui/widgets/header.h"
61 #include "gui/widgets/home_toolbar.h"
62 #include "gui/widgets/inspector_track.h"
63 #include "gui/widgets/left_dock_edge.h"
64 #include "gui/widgets/main_notebook.h"
65 #include "gui/widgets/main_window.h"
66 #include "gui/widgets/midi_arranger.h"
67 #include "gui/widgets/midi_modifier_arranger.h"
68 #include "gui/widgets/modulator.h"
69 #include "gui/widgets/modulator_view.h"
70 #include "gui/widgets/monitor_section.h"
71 #include "gui/widgets/midi_editor_space.h"
72 #include "gui/widgets/mixer.h"
73 #include "gui/widgets/piano_roll_keys.h"
74 #include "gui/widgets/plugin_browser.h"
75 #include "gui/widgets/plugin_strip_expander.h"
76 #include "gui/widgets/right_dock_edge.h"
77 #include "gui/widgets/route_target_selector.h"
78 #include "gui/widgets/ruler_marker.h"
79 #include "gui/widgets/snap_box.h"
80 #include "gui/widgets/timeline_arranger.h"
81 #include "gui/widgets/timeline_bot_box.h"
82 #include "gui/widgets/timeline_minimap.h"
83 #include "gui/widgets/timeline_panel.h"
84 #include "gui/widgets/timeline_ruler.h"
85 #include "gui/widgets/timeline_toolbar.h"
86 #include "gui/widgets/timeline_selection_info.h"
87 #include "gui/widgets/toolbox.h"
88 #include "gui/widgets/top_bar.h"
89 #include "gui/widgets/track.h"
90 #include "gui/widgets/track_properties_expander.h"
91 #include "gui/widgets/track_visibility_tree.h"
92 #include "gui/widgets/tracklist.h"
93 #include "gui/widgets/tracklist_header.h"
94 #include "gui/widgets/transport_controls.h"
95 #include "gui/widgets/visibility.h"
96 #include "plugins/plugin_gtk.h"
97 #include "project.h"
98 #include "settings/settings.h"
99 #include "utils/arrays.h"
100 #include "utils/flags.h"
101 #include "utils/gtk.h"
102 #include "utils/log.h"
103 #include "utils/mpmc_queue.h"
104 #include "utils/object_pool.h"
105 #include "utils/objects.h"
106 #include "utils/stack.h"
107 #include "utils/string.h"
108 #include "zrythm.h"
109 #include "zrythm_app.h"
110 
111 #include <glib/gi18n.h>
112 
113 static void
on_project_selection_type_changed(void)114 on_project_selection_type_changed (void)
115 {
116   const char * class = "selected-element";
117   const char * selectable_class =
118     "selectable-element";
119 
120   z_gtk_widget_remove_style_class (
121     GTK_WIDGET (MW_TRACKLIST), class);
122   z_gtk_widget_remove_style_class (
123     GTK_WIDGET (
124       MW_TIMELINE_PANEL->timelines_plus_ruler),
125     class);
126   z_gtk_widget_add_style_class (
127     GTK_WIDGET (
128       MW_TIMELINE_PANEL->timelines_plus_ruler),
129     selectable_class);
130   z_gtk_widget_remove_style_class (
131     GTK_WIDGET (MW_TIMELINE_PANEL->tracklist_top),
132     class);
133   z_gtk_widget_add_style_class (
134     GTK_WIDGET (MW_TIMELINE_PANEL->tracklist_top),
135     selectable_class);
136   z_gtk_widget_remove_style_class (
137     GTK_WIDGET (MW_CLIP_EDITOR_INNER), class);
138   z_gtk_widget_add_style_class (
139     GTK_WIDGET (MW_CLIP_EDITOR_INNER),
140     selectable_class);
141   z_gtk_widget_remove_style_class (
142     GTK_WIDGET (MW_MIXER), class);
143   z_gtk_widget_add_style_class (
144     GTK_WIDGET (MW_MIXER), selectable_class);
145 
146   switch (PROJECT->last_selection)
147     {
148     case SELECTION_TYPE_TRACKLIST:
149       z_gtk_widget_add_style_class (
150         GTK_WIDGET (
151           MW_TIMELINE_PANEL->tracklist_top),
152         class);
153       z_gtk_widget_remove_style_class (
154         GTK_WIDGET (
155           MW_TIMELINE_PANEL->tracklist_top),
156         selectable_class);
157       z_gtk_widget_add_style_class (
158         GTK_WIDGET (MW_MIXER), class);
159       z_gtk_widget_remove_style_class (
160         GTK_WIDGET (MW_MIXER),
161         selectable_class);
162       break;
163     case SELECTION_TYPE_TIMELINE:
164       z_gtk_widget_add_style_class (
165         GTK_WIDGET (
166           MW_TIMELINE_PANEL->timelines_plus_ruler),
167         class);
168       z_gtk_widget_remove_style_class (
169         GTK_WIDGET (
170           MW_TIMELINE_PANEL->timelines_plus_ruler),
171         selectable_class);
172       break;
173     case SELECTION_TYPE_INSERT:
174     case SELECTION_TYPE_MIDI_FX:
175     case SELECTION_TYPE_INSTRUMENT:
176     case SELECTION_TYPE_MODULATOR:
177       break;
178     case SELECTION_TYPE_EDITOR:
179       z_gtk_widget_add_style_class (
180         GTK_WIDGET (MW_CLIP_EDITOR_INNER), class);
181       z_gtk_widget_remove_style_class (
182         GTK_WIDGET (MW_CLIP_EDITOR_INNER),
183         selectable_class);
184       break;
185     }
186 }
187 
188 static void
redraw_arranger_for_selections(ArrangerSelections * sel)189 redraw_arranger_for_selections (
190   ArrangerSelections * sel)
191 {
192   switch (sel->type)
193     {
194     case ARRANGER_SELECTIONS_TYPE_TIMELINE:
195       arranger_widget_redraw_whole (MW_TIMELINE);
196       arranger_widget_redraw_whole (
197         MW_PINNED_TIMELINE);
198       break;
199     case ARRANGER_SELECTIONS_TYPE_AUTOMATION:
200       arranger_widget_redraw_whole (
201         MW_AUTOMATION_ARRANGER);
202       break;
203     case ARRANGER_SELECTIONS_TYPE_MIDI:
204       arranger_widget_redraw_whole (
205         MW_MIDI_ARRANGER);
206       arranger_widget_redraw_whole (
207         MW_MIDI_MODIFIER_ARRANGER);
208       break;
209     case ARRANGER_SELECTIONS_TYPE_CHORD:
210       arranger_widget_redraw_whole (
211         MW_CHORD_ARRANGER);
212       break;
213     default:
214       break;
215     }
216 }
217 
218 static void
redraw_all_arranger_bgs()219 redraw_all_arranger_bgs ()
220 {
221   arranger_widget_redraw_whole (MW_TIMELINE);
222   arranger_widget_redraw_whole (MW_PINNED_TIMELINE);
223   arranger_widget_redraw_whole (MW_MIDI_ARRANGER);
224   arranger_widget_redraw_whole (
225     MW_MIDI_MODIFIER_ARRANGER);
226   arranger_widget_redraw_whole (
227     MW_AUTOMATION_ARRANGER);
228   arranger_widget_redraw_whole (MW_CHORD_ARRANGER);
229   arranger_widget_redraw_whole (MW_AUDIO_ARRANGER);
230 }
231 
232 static void
redraw_regions_for_midi_selections(MidiArrangerSelections * sel)233 redraw_regions_for_midi_selections (
234   MidiArrangerSelections * sel)
235 {
236   for (int i = 0; i < sel->num_midi_notes;
237        i++)
238     {
239       MidiNote * mn = sel->midi_notes[i];
240       ZRegion * region =
241         midi_note_get_region (mn);
242       arranger_object_queue_redraw (
243         (ArrangerObject *) region);
244     }
245 }
246 
247 static void
redraw_velocities_for_midi_selections(MidiArrangerSelections * sel)248 redraw_velocities_for_midi_selections (
249   MidiArrangerSelections * sel)
250 {
251   for (int i = 0; i < sel->num_midi_notes;
252        i++)
253     {
254       MidiNote * mn = sel->midi_notes[i];
255       arranger_object_queue_redraw (
256         (ArrangerObject *) mn->vel);
257     }
258 }
259 
260 static void
on_arranger_selections_in_transit(ArrangerSelections * sel)261 on_arranger_selections_in_transit (
262   ArrangerSelections * sel)
263 {
264   g_return_if_fail (sel);
265 
266   arranger_selections_redraw (sel);
267 
268   event_viewer_widget_refresh_for_selections (sel);
269 
270   switch (sel->type)
271   {
272   case ARRANGER_SELECTIONS_TYPE_TIMELINE:
273     if (TL_SELECTIONS->num_regions > 0)
274       {
275         ZRegion * r = TL_SELECTIONS->regions[0];
276         switch (r->id.type)
277           {
278           case REGION_TYPE_MIDI:
279             arranger_widget_redraw_whole (
280               MW_MIDI_ARRANGER);
281             arranger_widget_redraw_whole (
282               MW_MIDI_MODIFIER_ARRANGER);
283             break;
284           case REGION_TYPE_AUTOMATION:
285             arranger_widget_redraw_whole (
286               MW_AUTOMATION_ARRANGER);
287             break;
288           case REGION_TYPE_CHORD:
289             arranger_widget_redraw_whole (
290               MW_CHORD_ARRANGER);
291             break;
292           case REGION_TYPE_AUDIO:
293             arranger_widget_redraw_whole (
294               MW_AUDIO_ARRANGER);
295             break;
296           }
297         ruler_widget_redraw_whole (EDITOR_RULER);
298       }
299     break;
300   case ARRANGER_SELECTIONS_TYPE_AUTOMATION:
301     clip_editor_redraw_region (CLIP_EDITOR);
302     break;
303   case ARRANGER_SELECTIONS_TYPE_MIDI:
304     redraw_regions_for_midi_selections (
305       (MidiArrangerSelections *) sel);
306     redraw_velocities_for_midi_selections (
307       (MidiArrangerSelections *) sel);
308     break;
309   default:
310     break;
311   }
312 }
313 
314 /**
315  * @param manually Whether the position was changed
316  *   by the user.
317  */
318 static void
on_playhead_changed(bool manually)319 on_playhead_changed (
320   bool manually)
321 {
322   if (MAIN_WINDOW)
323     {
324       if (MW_DIGITAL_TRANSPORT)
325         {
326           gtk_widget_queue_draw (
327             GTK_WIDGET (MW_DIGITAL_TRANSPORT));
328         }
329       if (MW_RULER)
330         {
331           if (manually)
332             ruler_widget_redraw_whole (MW_RULER);
333           else
334             ruler_widget_redraw_playhead (MW_RULER);
335         }
336       if (EDITOR_RULER)
337         {
338           if (manually)
339             ruler_widget_redraw_whole (
340               EDITOR_RULER);
341           else
342             ruler_widget_redraw_playhead (
343               EDITOR_RULER);
344         }
345       if (MW_MIDI_EDITOR_SPACE)
346         {
347           if (MW_MIDI_ARRANGER)
348             {
349               if (manually)
350                 arranger_widget_redraw_whole (
351                   MW_MIDI_ARRANGER);
352               else
353                 arranger_widget_redraw_playhead (
354                   MW_MIDI_ARRANGER);
355             }
356           if (MW_MIDI_MODIFIER_ARRANGER)
357             {
358               if (manually)
359                 arranger_widget_redraw_whole (
360                   MW_MIDI_MODIFIER_ARRANGER);
361               else
362                 arranger_widget_redraw_playhead (
363                   MW_MIDI_MODIFIER_ARRANGER);
364             }
365           piano_roll_keys_widget_refresh (
366             MW_PIANO_ROLL_KEYS);
367         }
368       if (MW_TIMELINE)
369         {
370           if (manually)
371             arranger_widget_redraw_whole (
372               MW_TIMELINE);
373           else
374             arranger_widget_redraw_playhead (
375               MW_TIMELINE);
376         }
377       if (MW_PINNED_TIMELINE)
378         {
379           if (manually)
380             arranger_widget_redraw_whole (
381               MW_PINNED_TIMELINE);
382           else
383             arranger_widget_redraw_playhead (
384               MW_PINNED_TIMELINE);
385         }
386       if (MW_AUTOMATION_ARRANGER)
387         {
388           if (manually)
389             arranger_widget_redraw_whole (
390               MW_AUTOMATION_ARRANGER);
391           else
392             arranger_widget_redraw_playhead (
393               MW_AUTOMATION_ARRANGER);
394         }
395       if (MW_AUDIO_ARRANGER)
396         {
397           if (manually)
398             arranger_widget_redraw_whole (
399               MW_AUDIO_ARRANGER);
400           else
401             arranger_widget_redraw_playhead (
402               MW_AUDIO_ARRANGER);
403         }
404       if (MW_CHORD_ARRANGER)
405         {
406           if (manually)
407             arranger_widget_redraw_whole (
408               MW_CHORD_ARRANGER);
409           else
410             arranger_widget_redraw_playhead (
411               MW_CHORD_ARRANGER);
412         }
413     }
414 }
415 
416 static void
on_channel_output_changed(Channel * ch)417 on_channel_output_changed (
418   Channel * ch)
419 {
420   if (ch->widget)
421     {
422       route_target_selector_widget_refresh (
423         ch->widget->output, ch);
424     }
425 }
426 
427 static void
on_track_state_changed(Track * track)428 on_track_state_changed (Track * track)
429 {
430   if (track->widget)
431     {
432       /*track_widget_block_all_signal_handlers (*/
433         /*track->widget);*/
434       track_widget_force_redraw (track->widget);
435       /*track_widget_unblock_all_signal_handlers (*/
436         /*track->widget);*/
437     }
438 
439   Channel * chan = track_get_channel (track);
440   if (chan && chan->widget)
441     {
442       channel_widget_refresh (chan->widget);
443     }
444 
445   if (TRACKLIST_SELECTIONS->tracks[0] == track)
446     {
447       inspector_track_widget_show_tracks (
448         MW_TRACK_INSPECTOR, TRACKLIST_SELECTIONS,
449         true);
450     }
451 }
452 
453 static void
on_range_selection_changed()454 on_range_selection_changed ()
455 {
456   redraw_all_arranger_bgs ();
457   /*gtk_widget_set_visible (*/
458     /*GTK_WIDGET (MW_RULER->range),*/
459     /*PROJECT->has_range);*/
460   gtk_widget_queue_allocate (
461     GTK_WIDGET (MW_RULER));
462   ruler_widget_redraw_whole (
463     (RulerWidget *) MW_RULER);
464   ruler_widget_redraw_whole (
465     (RulerWidget *) EDITOR_RULER);
466 }
467 
468 static void
on_automation_track_added(AutomationTrack * at)469 on_automation_track_added (
470   AutomationTrack * at)
471 {
472   /*AutomationTracklist * atl =*/
473     /*track_get_automation_tracklist (at->track);*/
474   /*if (atl && atl->widget)*/
475     /*automation_tracklist_widget_refresh (*/
476       /*atl->widget);*/
477 
478   Track * track =
479     automation_track_get_track (at);
480   g_return_if_fail (track);
481   if (Z_IS_TRACK_WIDGET (track->widget))
482     {
483       TrackWidget * tw =
484         (TrackWidget *) track->widget;
485       track_widget_update_size (tw);
486     }
487 
488   arranger_widget_redraw_whole (
489     MW_TIMELINE);
490   arranger_widget_redraw_whole (
491     MW_PINNED_TIMELINE);
492 
493   visibility_widget_refresh (MW_VISIBILITY);
494 }
495 
496 static void
on_track_added(Track * track)497 on_track_added (Track * track)
498 {
499   if (!MAIN_WINDOW || !MW_CENTER_DOCK)
500     return;
501 
502   if (MW_MIXER)
503     mixer_widget_hard_refresh (MW_MIXER);
504   if (MW_TRACKLIST)
505     tracklist_widget_hard_refresh (MW_TRACKLIST);
506 
507   /* needs to be called later because tracks need
508    * time to get allocated */
509   EVENTS_PUSH (ET_REFRESH_ARRANGER, NULL);
510 }
511 
512 static void
on_automation_value_changed(Port * port)513 on_automation_value_changed (
514   Port * port)
515 {
516   PortIdentifier * id = &port->id;
517 
518   if (id->flags2 & PORT_FLAG2_CHANNEL_SEND_AMOUNT)
519     {
520       Track * tr = port_get_track (port, true);
521       if (track_is_selected (tr))
522         {
523           gtk_widget_queue_draw (
524             GTK_WIDGET (
525               MW_TRACK_INSPECTOR->sends->
526                 slots[id->port_index]));
527         }
528     }
529 }
530 
531 static void
on_plugin_added(Plugin * plugin)532 on_plugin_added (Plugin * plugin)
533 {
534   Track * track =
535     plugin_get_track (plugin);
536   /*AutomationTracklist * automation_tracklist =*/
537     /*track_get_automation_tracklist (track);*/
538   if (track && track->widget)
539     track_widget_force_redraw (track->widget);
540 }
541 
542 static void
on_plugin_crashed(Plugin * plugin)543 on_plugin_crashed (Plugin * plugin)
544 {
545   char * str =
546     g_strdup_printf (
547       _("Plugin '%s' has crashed and has been "
548       "disabled."),
549       plugin->setting->descr->name);
550   ui_show_error_message (MAIN_WINDOW, str);
551   g_free (str);
552 }
553 
554 static void
on_plugin_state_changed(Plugin * pl)555 on_plugin_state_changed (Plugin * pl)
556 {
557   Track * track = plugin_get_track (pl);
558   if (track && track->channel &&
559       track->channel->widget)
560     {
561       /* redraw slot */
562       switch (pl->id.slot_type)
563         {
564         case PLUGIN_SLOT_MIDI_FX:
565           plugin_strip_expander_widget_redraw_slot (
566             MW_TRACK_INSPECTOR->midi_fx,
567             pl->id.slot);
568           break;
569         case PLUGIN_SLOT_INSERT:
570           plugin_strip_expander_widget_redraw_slot (
571             MW_TRACK_INSPECTOR->inserts,
572             pl->id.slot);
573           plugin_strip_expander_widget_redraw_slot (
574             track->channel->widget->inserts,
575             pl->id.slot);
576           break;
577         default:
578           break;
579         }
580     }
581 }
582 
583 static void
on_modulator_added(Plugin * modulator)584 on_modulator_added (Plugin * modulator)
585 {
586   on_plugin_added (modulator);
587 
588   Track * track = plugin_get_track (modulator);
589   modulator_view_widget_refresh (
590     MW_MODULATOR_VIEW, track);
591 }
592 
593 static void
on_plugins_removed(Track * tr)594 on_plugins_removed (Track * tr)
595 {
596   /* redraw slots */
597   if (tr && tr->channel)
598     {
599       plugin_strip_expander_widget_set_state_flags (
600         tr->channel->widget->inserts, -1,
601         GTK_STATE_FLAG_SELECTED, false);
602     }
603 
604   /* change inspector page */
605   left_dock_edge_widget_refresh (
606     MW_LEFT_DOCK_EDGE);
607 
608   /* refresh modulator view */
609   modulator_view_widget_refresh (
610     MW_MODULATOR_VIEW, P_MODULATOR_TRACK);
611 }
612 
613 static void
refresh_for_selections_type(ArrangerSelectionsType type)614 refresh_for_selections_type (
615   ArrangerSelectionsType type)
616 {
617   switch (type)
618     {
619     case ARRANGER_SELECTIONS_TYPE_TIMELINE:
620       event_viewer_widget_refresh (
621         MW_TIMELINE_EVENT_VIEWER);
622       break;
623     case ARRANGER_SELECTIONS_TYPE_MIDI:
624       clip_editor_redraw_region (CLIP_EDITOR);
625       event_viewer_widget_refresh (
626         MW_EDITOR_EVENT_VIEWER);
627       break;
628     case ARRANGER_SELECTIONS_TYPE_CHORD:
629       clip_editor_redraw_region (CLIP_EDITOR);
630       event_viewer_widget_refresh (
631         MW_EDITOR_EVENT_VIEWER);
632       break;
633     case ARRANGER_SELECTIONS_TYPE_AUTOMATION:
634       clip_editor_redraw_region (CLIP_EDITOR);
635       event_viewer_widget_refresh (
636         MW_EDITOR_EVENT_VIEWER);
637       break;
638     default:
639       g_return_if_reached ();
640     }
641 }
642 
643 static void
on_arranger_selections_changed(ArrangerSelections * sel)644 on_arranger_selections_changed (
645   ArrangerSelections * sel)
646 {
647   int size = 0;
648   ArrangerObject ** objs =
649     arranger_selections_get_all_objects (
650       sel, &size);
651   bool redraw_editor_ruler = false;
652   bool redraw_midi_modifier = false;
653   for (int i = 0; i < size; i++)
654     {
655       ArrangerObject * obj = objs[i];
656       g_return_if_fail (IS_ARRANGER_OBJECT (obj));
657 
658       if (obj->type == ARRANGER_OBJECT_TYPE_REGION)
659         redraw_editor_ruler = true;
660 
661       arranger_object_queue_redraw (obj);
662 
663       if (obj->type ==
664             ARRANGER_OBJECT_TYPE_MIDI_NOTE)
665         {
666           redraw_midi_modifier = true;
667 
668           /* FIXME doesn't work for some reason */
669 #if 0
670           MidiNote * mn = (MidiNote *) obj;
671           arranger_object_queue_redraw (
672             (ArrangerObject *) mn->vel);
673 #endif
674         }
675     }
676 
677   if (redraw_editor_ruler)
678     {
679       ruler_widget_redraw_whole (EDITOR_RULER);
680     }
681   if (redraw_midi_modifier)
682     {
683       arranger_widget_redraw_whole (
684         MW_MIDI_MODIFIER_ARRANGER);
685     }
686 
687   refresh_for_selections_type (sel->type);
688   left_dock_edge_widget_refresh (
689     MW_LEFT_DOCK_EDGE);
690 
691   timeline_toolbar_widget_refresh (
692     MW_TIMELINE_TOOLBAR);
693 }
694 
695 static void
arranger_selections_change_redraw_everything(ArrangerSelections * sel)696 arranger_selections_change_redraw_everything (
697   ArrangerSelections * sel)
698 {
699   switch (sel->type)
700     {
701     case ARRANGER_SELECTIONS_TYPE_TIMELINE:
702       arranger_widget_redraw_whole (
703         MW_TIMELINE);
704       arranger_widget_redraw_whole (
705         MW_PINNED_TIMELINE);
706       event_viewer_widget_refresh (
707         MW_TIMELINE_EVENT_VIEWER);
708       arranger_widget_redraw_whole (
709         MW_MIDI_ARRANGER);
710       arranger_widget_redraw_whole (
711         MW_MIDI_MODIFIER_ARRANGER);
712       arranger_widget_redraw_whole (
713         MW_CHORD_ARRANGER);
714       arranger_widget_redraw_whole (
715         MW_AUTOMATION_ARRANGER);
716       ruler_widget_redraw_whole (
717         EDITOR_RULER);
718       break;
719     case ARRANGER_SELECTIONS_TYPE_MIDI:
720       clip_editor_redraw_region (CLIP_EDITOR);
721       arranger_widget_redraw_whole (
722         MW_MIDI_ARRANGER);
723       arranger_widget_redraw_whole (
724         MW_MIDI_MODIFIER_ARRANGER);
725       {
726         MidiArrangerSelections * ma_sel =
727           (MidiArrangerSelections *) sel;
728         redraw_regions_for_midi_selections (
729           ma_sel);
730       }
731       event_viewer_widget_refresh (
732         MW_EDITOR_EVENT_VIEWER);
733       break;
734     case ARRANGER_SELECTIONS_TYPE_CHORD:
735       clip_editor_redraw_region (CLIP_EDITOR);
736       arranger_widget_redraw_whole (
737         MW_CHORD_ARRANGER);
738       event_viewer_widget_refresh (
739         MW_EDITOR_EVENT_VIEWER);
740       break;
741     case ARRANGER_SELECTIONS_TYPE_AUTOMATION:
742       clip_editor_redraw_region (CLIP_EDITOR);
743       arranger_widget_redraw_whole (
744         MW_AUTOMATION_ARRANGER);
745       event_viewer_widget_refresh (
746         MW_EDITOR_EVENT_VIEWER);
747       break;
748     case ARRANGER_SELECTIONS_TYPE_AUDIO:
749       clip_editor_redraw_region (CLIP_EDITOR);
750       arranger_widget_redraw_whole (
751         MW_AUDIO_ARRANGER);
752       event_viewer_widget_refresh (
753         MW_EDITOR_EVENT_VIEWER);
754       break;
755     default:
756       g_return_if_reached ();
757     }
758 }
759 
760 static void
on_arranger_selections_created(ArrangerSelections * sel)761 on_arranger_selections_created (
762   ArrangerSelections * sel)
763 {
764   arranger_selections_change_redraw_everything (
765     sel);
766 }
767 
768 static void
on_arranger_selections_moved(ArrangerSelections * sel)769 on_arranger_selections_moved (
770   ArrangerSelections * sel)
771 {
772   arranger_selections_change_redraw_everything (
773     sel);
774 }
775 
776 static void
on_arranger_selections_removed(ArrangerSelections * sel)777 on_arranger_selections_removed (
778   ArrangerSelections * sel)
779 {
780   MW_TIMELINE->hovered_object = NULL;
781   MW_MIDI_ARRANGER->hovered_object = NULL;
782   MW_MIDI_MODIFIER_ARRANGER->hovered_object = NULL;
783   MW_AUTOMATION_ARRANGER->hovered_object = NULL;
784   MW_AUDIO_ARRANGER->hovered_object = NULL;
785   MW_CHORD_ARRANGER->hovered_object = NULL;
786 
787   arranger_selections_change_redraw_everything (
788     sel);
789 
790 #if 0
791   switch (type)
792     {
793     case ARRANGER_SELECTIONS_TYPE_TIMELINE:
794       arranger_widget_redraw_whole (
795         MW_TIMELINE);
796       arranger_widget_redraw_whole (
797         MW_PINNED_TIMELINE);
798       event_viewer_widget_refresh (
799         MW_TIMELINE_EVENT_VIEWER);
800       break;
801     case ARRANGER_SELECTIONS_TYPE_MIDI:
802       clip_editor_redraw_region (CLIP_EDITOR);
803       arranger_widget_redraw_whole (
804         MW_MIDI_ARRANGER);
805       arranger_widget_redraw_whole (
806         MW_MIDI_MODIFIER_ARRANGER);
807       event_viewer_widget_refresh (
808         MW_EDITOR_EVENT_VIEWER);
809       break;
810     case ARRANGER_SELECTIONS_TYPE_CHORD:
811       clip_editor_redraw_region (CLIP_EDITOR);
812       arranger_widget_redraw_whole (
813         MW_CHORD_ARRANGER);
814       event_viewer_widget_refresh (
815         MW_EDITOR_EVENT_VIEWER);
816       break;
817     case ARRANGER_SELECTIONS_TYPE_AUTOMATION:
818       clip_editor_redraw_region (CLIP_EDITOR);
819       arranger_widget_redraw_whole (
820         MW_AUTOMATION_ARRANGER);
821       event_viewer_widget_refresh (
822         MW_EDITOR_EVENT_VIEWER);
823       break;
824     default:
825       g_return_if_reached ();
826     }
827 #endif
828   timeline_toolbar_widget_refresh (
829     MW_TIMELINE_TOOLBAR);
830 }
831 
832 static void
on_mixer_selections_changed()833 on_mixer_selections_changed ()
834 {
835   for (int i = 0; i < TRACKLIST->num_tracks; i++)
836     {
837       Track * track = TRACKLIST->tracks[i];
838       if (!track_type_has_channel (track->type))
839         continue;
840 
841       Channel * ch = track->channel;
842       if (ch->widget)
843         {
844           plugin_strip_expander_widget_refresh (
845             ch->widget->inserts);
846         }
847     }
848   left_dock_edge_widget_refresh (
849     MW_LEFT_DOCK_EDGE);
850 }
851 
852 static void
on_track_color_changed(Track * track)853 on_track_color_changed (Track * track)
854 {
855   if (track_type_has_channel (track->type))
856     {
857       channel_widget_refresh (
858         track->channel->widget);
859     }
860   track_widget_force_redraw (track->widget);
861   left_dock_edge_widget_refresh (
862     MW_LEFT_DOCK_EDGE);
863 }
864 
865 static void
on_track_name_changed(Track * track)866 on_track_name_changed (Track * track)
867 {
868   /* refresh all because tracks routed to/from are
869    * also affected */
870   mixer_widget_soft_refresh (MW_MIXER);
871   track_widget_force_redraw (track->widget);
872   left_dock_edge_widget_refresh (
873     MW_LEFT_DOCK_EDGE);
874   visibility_widget_refresh (MW_VISIBILITY);
875 }
876 
877 static void
on_arranger_object_changed(ArrangerObject * obj)878 on_arranger_object_changed (
879   ArrangerObject * obj)
880 {
881   g_return_if_fail (IS_ARRANGER_OBJECT (obj));
882 
883   /* parent region, if any */
884   ArrangerObject * parent_r_obj =
885     (ArrangerObject *)
886     arranger_object_get_region (obj);
887 
888   bool is_timeline = !parent_r_obj;
889   if (is_timeline)
890     event_viewer_widget_refresh (
891       MW_TIMELINE_EVENT_VIEWER);
892   else
893     event_viewer_widget_refresh (
894       MW_EDITOR_EVENT_VIEWER);
895 
896   switch (obj->type)
897     {
898     case ARRANGER_OBJECT_TYPE_AUTOMATION_POINT:
899       {
900         /*ArrangerObject * prev_ap_obj =*/
901           /*(ArrangerObject *)*/
902           /*automation_region_get_prev_ap (*/
903             /*((AutomationPoint *) obj)->region,*/
904             /*(AutomationPoint *) obj);*/
905 
906         /* redraw this ap and also the previous one
907          * if any */
908         for (int i = 0; i < 2; i++)
909           {
910             /*ArrangerObject * _obj = NULL;*/
911             /*if (i == 0)*/
912               /*_obj = obj;*/
913             /*else if (prev_ap_obj)*/
914               /*_obj = prev_ap_obj;*/
915             /*else*/
916               /*break;*/
917 
918             /*if (_obj &&*/
919                 /*Z_IS_ARRANGER_OBJECT_WIDGET (*/
920                   /*_obj->widget))*/
921               /*{*/
922                 /*arranger_object_widget_force_redraw (*/
923                   /*(ArrangerObjectWidget *)*/
924                   /*_obj->widget);*/
925               /*}*/
926           }
927       }
928       break;
929     case ARRANGER_OBJECT_TYPE_MIDI_NOTE:
930       {
931         /*MidiNote * mn =*/
932           /*(MidiNote *)*/
933           /*arranger_object_get_main (obj);*/
934         /*ArrangerObject * vel_obj =*/
935           /*(ArrangerObject *) mn->vel;*/
936         /*if (vel_obj->widget)*/
937           /*{*/
938             /*arranger_object_set_widget_visibility_and_state (*/
939               /*vel_obj, 1);*/
940           /*}*/
941         arranger_object_queue_redraw (
942           (ArrangerObject *) parent_r_obj);
943       }
944       break;
945     case ARRANGER_OBJECT_TYPE_REGION:
946       /* redraw editor ruler if region
947        * positions were changed */
948       ruler_widget_redraw_whole (
949         EDITOR_RULER);
950       timeline_toolbar_widget_refresh (
951         MW_TIMELINE_TOOLBAR);
952       break;
953     case ARRANGER_OBJECT_TYPE_MARKER:
954       {
955         /*MarkerWidget * mw =*/
956           /*(MarkerWidget *) obj->widget;*/
957         /*if (Z_IS_MARKER_WIDGET (mw))*/
958           /*{*/
959             /*marker_widget_recreate_pango_layouts (*/
960               /*mw);*/
961           /*}*/
962       }
963       break;
964     default:
965       break;
966     }
967 
968   /* redraw parent region */
969   if (parent_r_obj)
970     {
971       /*ArrangerObjectWidget * obj_w =*/
972         /*(ArrangerObjectWidget *)*/
973         /*parent_r_obj->widget;*/
974       /*if (obj_w)*/
975         /*arranger_object_widget_force_redraw (*/
976           /*obj_w);*/
977     }
978 
979   /* redraw this */
980   /*ArrangerObjectWidget * obj_w =*/
981     /*(ArrangerObjectWidget *) obj->widget;*/
982   /*if (obj_w)*/
983     /*arranger_object_widget_force_redraw (obj_w);*/
984 
985   /* refresh arranger */
986   arranger_object_queue_redraw (obj);
987   /*ArrangerWidget * arranger =*/
988     /*arranger_object_get_arranger (obj);*/
989   /*arranger_widget_redraw_whole (arranger);*/
990 }
991 
992 static void
on_arranger_object_created(ArrangerObject * obj)993 on_arranger_object_created (
994   ArrangerObject * obj)
995 {
996   /* refresh arranger */
997   /*ArrangerWidget * arranger =*/
998     /*arranger_object_get_arranger (obj);*/
999   /*arranger_widget_redraw_whole (arranger);*/
1000   arranger_object_queue_redraw (obj);
1001 
1002   if (obj->type == ARRANGER_OBJECT_TYPE_MIDI_NOTE)
1003     {
1004       arranger_widget_redraw_whole (
1005         (ArrangerWidget *)
1006         MW_MIDI_MODIFIER_ARRANGER);
1007     }
1008 }
1009 
1010 static void
on_arranger_object_removed(ArrangerObjectType type)1011 on_arranger_object_removed (
1012   ArrangerObjectType type)
1013 {
1014   switch (type)
1015     {
1016     case ARRANGER_OBJECT_TYPE_MIDI_NOTE:
1017     case ARRANGER_OBJECT_TYPE_VELOCITY:
1018       arranger_widget_redraw_whole (
1019         MW_MIDI_ARRANGER);
1020       arranger_widget_redraw_whole (
1021         MW_MIDI_MODIFIER_ARRANGER);
1022       break;
1023     case ARRANGER_OBJECT_TYPE_REGION:
1024     case ARRANGER_OBJECT_TYPE_SCALE_OBJECT:
1025     case ARRANGER_OBJECT_TYPE_MARKER:
1026       arranger_widget_redraw_whole (
1027         MW_TIMELINE);
1028       arranger_widget_redraw_whole (
1029         MW_PINNED_TIMELINE);
1030       break;
1031     case ARRANGER_OBJECT_TYPE_CHORD_OBJECT:
1032       arranger_widget_redraw_whole (
1033         MW_CHORD_ARRANGER);
1034       break;
1035     case ARRANGER_OBJECT_TYPE_AUTOMATION_POINT:
1036       arranger_widget_redraw_whole (
1037         MW_AUTOMATION_ARRANGER);
1038       break;
1039     default:
1040       g_return_if_reached ();
1041     }
1042 }
1043 
1044 static void
on_track_changed(Track * track)1045 on_track_changed (
1046   Track * track)
1047 {
1048   g_return_if_fail (IS_TRACK_AND_NONNULL (track));
1049   if (GTK_IS_WIDGET (track->widget))
1050     {
1051       gtk_widget_set_visible (
1052         GTK_WIDGET (track->widget),
1053         track->visible);
1054       track_widget_force_redraw (track->widget);
1055     }
1056 }
1057 
1058 static void
on_plugin_window_visibility_changed(Plugin * pl)1059 on_plugin_window_visibility_changed (
1060   Plugin * pl)
1061 {
1062   g_message ("start");
1063   if (!IS_PLUGIN (pl) || pl->deleting)
1064     {
1065       return;
1066     }
1067 
1068   Track * track = plugin_get_track (pl);
1069   if (track && track->type == TRACK_TYPE_INSTRUMENT
1070       && track->widget
1071       && Z_IS_TRACK_WIDGET (track->widget))
1072     track_widget_force_redraw (track->widget);
1073 
1074   if (track && track->channel
1075       && track->channel->widget
1076       &&
1077       Z_IS_CHANNEL_WIDGET (track->channel->widget))
1078     {
1079       /* redraw slot */
1080       switch (pl->id.slot_type)
1081         {
1082         case PLUGIN_SLOT_MIDI_FX:
1083           plugin_strip_expander_widget_redraw_slot (
1084             MW_TRACK_INSPECTOR->midi_fx,
1085             pl->id.slot);
1086           break;
1087         case PLUGIN_SLOT_INSERT:
1088           plugin_strip_expander_widget_redraw_slot (
1089             MW_TRACK_INSPECTOR->inserts,
1090             pl->id.slot);
1091           plugin_strip_expander_widget_redraw_slot (
1092             track->channel->widget->inserts,
1093             pl->id.slot);
1094           break;
1095         case PLUGIN_SLOT_INSTRUMENT:
1096           track_properties_expander_widget_refresh (
1097             MW_TRACK_INSPECTOR->track_info, track);
1098           break;
1099         default:
1100           break;
1101         }
1102     }
1103 
1104   if (pl->modulator_widget)
1105     {
1106       modulator_widget_refresh (
1107         pl->modulator_widget);
1108     }
1109   g_message ("done");
1110 }
1111 
1112 static void
on_plugin_visibility_changed(Plugin * pl)1113 on_plugin_visibility_changed (Plugin * pl)
1114 {
1115   g_debug (
1116     "start - visible: %d", pl->visible);
1117   if (pl->visible)
1118     {
1119       plugin_open_ui (pl);
1120     }
1121   else if (!pl->visible)
1122     {
1123       plugin_close_ui (pl);
1124     }
1125 
1126   on_plugin_window_visibility_changed (pl);
1127   g_debug ("done");
1128 }
1129 
1130 /*static int*/
1131 /*update_adj ()*/
1132 /*{*/
1133   /*GtkAdjustment * adj =*/
1134     /*gtk_scrolled_window_get_hadjustment (*/
1135       /*MW_CENTER_DOCK->timeline_scroll);*/
1136   /*gtk_adjustment_set_value (*/
1137     /*adj,*/
1138     /*gtk_adjustment_get_value (adj) + gtk_adjustment_get_step_increment (adj));*/
1139   /*gtk_scrolled_window_set_hadjustment(*/
1140     /*MW_CENTER_DOCK->timeline_scroll,*/
1141     /*adj);*/
1142 
1143   /*return FALSE;*/
1144 /*}*/
1145 
1146 static inline void
clean_duplicates_and_copy(EventManager * self,GPtrArray * events_arr)1147 clean_duplicates_and_copy (
1148   EventManager * self,
1149   GPtrArray *    events_arr)
1150 {
1151   MPMCQueue * q = self->mqueue;
1152   ZEvent * event;
1153 
1154   g_ptr_array_remove_range (
1155     events_arr, 0, events_arr->len);
1156 
1157   /* only add events once to new array while
1158    * popping */
1159   while (event_queue_dequeue_event (
1160            q, &event))
1161     {
1162       bool already_exists = false;
1163 
1164       for (guint i = 0; i < events_arr->len; i++)
1165         {
1166           ZEvent * cur_event =
1167             (ZEvent *)
1168             g_ptr_array_index (events_arr, i);
1169           if (event->type == cur_event->type &&
1170               event->arg == cur_event->arg)
1171             already_exists = true;
1172         }
1173 
1174       if (already_exists)
1175         {
1176           object_pool_return (
1177             self->obj_pool, event);
1178         }
1179       else
1180         {
1181           g_ptr_array_add (events_arr, event);
1182         }
1183     }
1184 }
1185 
1186 static int
soft_recalc_graph_when_paused(void * data)1187 soft_recalc_graph_when_paused (
1188   void * data)
1189 {
1190   EventManager * self = (EventManager *) data;
1191   if (TRANSPORT->play_state == PLAYSTATE_PAUSED)
1192     {
1193       router_recalc_graph (ROUTER, F_SOFT);
1194       self->pending_soft_recalc = false;
1195       return G_SOURCE_REMOVE;
1196     }
1197   return G_SOURCE_CONTINUE;
1198 }
1199 
1200 /**
1201  * Processes the given event.
1202  *
1203  * The caller is responsible for putting the event
1204  * back in the object pool if needed.
1205  */
1206 void
event_manager_process_event(EventManager * self,ZEvent * ev)1207 event_manager_process_event (
1208   EventManager * self,
1209   ZEvent *       ev)
1210 {
1211   switch (ev->type)
1212     {
1213     case ET_PLUGIN_LATENCY_CHANGED:
1214       if (!self->pending_soft_recalc)
1215         {
1216           self->pending_soft_recalc = true;
1217           g_idle_add (
1218             soft_recalc_graph_when_paused,
1219             self);
1220         }
1221       break;
1222     case ET_TRACKS_REMOVED:
1223       if (MW_MIXER)
1224         mixer_widget_hard_refresh (MW_MIXER);
1225       if (MW_TRACKLIST)
1226         tracklist_widget_hard_refresh (
1227           MW_TRACKLIST);
1228       visibility_widget_refresh (
1229         MW_VISIBILITY);
1230       tracklist_header_widget_refresh_track_count (
1231         MW_TRACKLIST_HEADER);
1232       left_dock_edge_widget_refresh (
1233         MW_LEFT_DOCK_EDGE);
1234       break;
1235     case ET_CHANNEL_REMOVED:
1236       mixer_widget_hard_refresh (
1237         MW_MIXER);
1238       break;
1239     case ET_ARRANGER_OBJECT_CREATED:
1240       on_arranger_object_created (
1241         (ArrangerObject *) ev->arg);
1242       break;
1243     case ET_ARRANGER_OBJECT_CHANGED:
1244       on_arranger_object_changed (
1245         (ArrangerObject *) ev->arg);
1246       break;
1247     case ET_ARRANGER_OBJECT_REMOVED:
1248       on_arranger_object_removed (
1249         (ArrangerObjectType) ev->arg);
1250       break;
1251     case ET_ARRANGER_SELECTIONS_CHANGED:
1252       on_arranger_selections_changed (
1253         ARRANGER_SELECTIONS (ev->arg));
1254       break;
1255     case ET_ARRANGER_SELECTIONS_CREATED:
1256       on_arranger_selections_created (
1257         ARRANGER_SELECTIONS (ev->arg));
1258       break;
1259     case ET_ARRANGER_SELECTIONS_REMOVED:
1260       on_arranger_selections_removed (
1261         ARRANGER_SELECTIONS (ev->arg));
1262       break;
1263     case ET_ARRANGER_SELECTIONS_MOVED:
1264       on_arranger_selections_moved (
1265         ARRANGER_SELECTIONS (ev->arg));
1266       break;
1267     case ET_ARRANGER_SELECTIONS_QUANTIZED:
1268       redraw_arranger_for_selections (
1269         ARRANGER_SELECTIONS (ev->arg));
1270       break;
1271     case ET_ARRANGER_SELECTIONS_ACTION_FINISHED:
1272       redraw_all_arranger_bgs ();
1273       ruler_widget_redraw_whole (
1274         (RulerWidget *) MW_RULER);
1275       ruler_widget_redraw_whole (
1276         (RulerWidget *) EDITOR_RULER);
1277       break;
1278     case ET_TRACKLIST_SELECTIONS_CHANGED:
1279       /* only refresh the inspector if the
1280        * tracklist selection changed by
1281        * clicking on a track */
1282       if (PROJECT->last_selection ==
1283             SELECTION_TYPE_TRACKLIST ||
1284           PROJECT->last_selection ==
1285             SELECTION_TYPE_INSERT ||
1286           PROJECT->last_selection ==
1287             SELECTION_TYPE_MIDI_FX)
1288         {
1289           left_dock_edge_widget_refresh (
1290             MW_LEFT_DOCK_EDGE);
1291         }
1292       mixer_widget_soft_refresh (MW_MIXER);
1293       /* TODO implement soft refresh */
1294       tracklist_widget_hard_refresh (
1295         MW_TRACKLIST);
1296       break;
1297     case ET_RULER_SIZE_CHANGED:
1298       {
1299         RulerWidget * ruler =
1300           Z_RULER_WIDGET (ev->arg);
1301         gtk_widget_queue_allocate (
1302           GTK_WIDGET (ruler));
1303         ruler_widget_redraw_whole (ruler);
1304         if (ev->arg == MW_RULER)
1305           {
1306             arranger_widget_redraw_whole (
1307               Z_ARRANGER_WIDGET (
1308                 MW_TIMELINE));
1309             arranger_widget_redraw_whole (
1310               Z_ARRANGER_WIDGET (
1311                 MW_PINNED_TIMELINE));
1312           }
1313         else if (ev->arg == EDITOR_RULER)
1314           {
1315             if (gtk_widget_get_visible (
1316                   GTK_WIDGET (MW_MIDI_ARRANGER)))
1317               {
1318                 arranger_widget_redraw_whole (
1319                   Z_ARRANGER_WIDGET (
1320                     MW_MIDI_ARRANGER));
1321                 arranger_widget_redraw_whole (
1322                   Z_ARRANGER_WIDGET (
1323                     MW_MIDI_MODIFIER_ARRANGER));
1324               }
1325             if (gtk_widget_get_visible (
1326                   GTK_WIDGET (MW_AUDIO_ARRANGER)))
1327               {
1328                 arranger_widget_redraw_whole (
1329                   Z_ARRANGER_WIDGET (
1330                     MW_AUDIO_ARRANGER));
1331               }
1332           }
1333       }
1334       break;
1335     case ET_CLIP_MARKER_POS_CHANGED:
1336       ruler_widget_redraw_whole (
1337         EDITOR_RULER);
1338       clip_editor_redraw_region (CLIP_EDITOR);
1339       break;
1340     case ET_TIMELINE_LOOP_MARKER_POS_CHANGED:
1341     case ET_TIMELINE_PUNCH_MARKER_POS_CHANGED:
1342       ruler_widget_redraw_whole (
1343         (RulerWidget *) MW_RULER);
1344       ruler_widget_redraw_whole (
1345         (RulerWidget *) EDITOR_RULER);
1346       redraw_all_arranger_bgs ();
1347       break;
1348     case ET_TIMELINE_SONG_MARKER_POS_CHANGED:
1349       gtk_widget_queue_allocate (
1350         GTK_WIDGET (MW_RULER));
1351       ruler_widget_redraw_whole (
1352         (RulerWidget *) MW_RULER);
1353       break;
1354     case ET_PLUGIN_VISIBILITY_CHANGED:
1355       on_plugin_visibility_changed (
1356         (Plugin *) ev->arg);
1357       break;
1358     case ET_PLUGIN_WINDOW_VISIBILITY_CHANGED:
1359       on_plugin_window_visibility_changed (
1360         (Plugin *) ev->arg);
1361       break;
1362     case ET_PLUGIN_STATE_CHANGED:
1363       {
1364         Plugin * pl = (Plugin *) ev->arg;
1365         if (IS_PLUGIN (pl))
1366           {
1367             on_plugin_state_changed (pl);
1368             g_atomic_int_set (
1369               &pl->state_changed_event_sent, 0);
1370           }
1371       }
1372       break;
1373     case ET_TRANSPORT_TOTAL_BARS_CHANGED:
1374       snap_grid_update_snap_points_default (
1375         SNAP_GRID_TIMELINE);
1376 
1377       ruler_widget_refresh (
1378         (RulerWidget *) MW_RULER);
1379       ruler_widget_refresh (
1380         (RulerWidget *) EDITOR_RULER);
1381       timeline_minimap_widget_refresh (
1382         MW_TIMELINE_MINIMAP);
1383       break;
1384     case ET_AUTOMATION_VALUE_CHANGED:
1385       on_automation_value_changed (
1386         (Port *) ev->arg);
1387       break;
1388     case ET_RANGE_SELECTION_CHANGED:
1389       on_range_selection_changed ();
1390       timeline_toolbar_widget_refresh (
1391         MW_TIMELINE_TOOLBAR);
1392       break;
1393     case ET_TOOL_CHANGED:
1394       toolbox_widget_refresh (MW_TOOLBOX);
1395       arranger_widget_refresh_cursor (
1396         Z_ARRANGER_WIDGET (MW_TIMELINE));
1397       if (MW_MIDI_ARRANGER &&
1398           gtk_widget_get_realized (
1399             GTK_WIDGET (MW_MIDI_ARRANGER)))
1400         arranger_widget_refresh_cursor (
1401           Z_ARRANGER_WIDGET (MW_MIDI_ARRANGER));
1402       if (MW_MIDI_MODIFIER_ARRANGER &&
1403           gtk_widget_get_realized (
1404             GTK_WIDGET (MW_MIDI_MODIFIER_ARRANGER)))
1405         arranger_widget_refresh_cursor (
1406           Z_ARRANGER_WIDGET (
1407             MW_MIDI_MODIFIER_ARRANGER));
1408       break;
1409     case ET_TIME_SIGNATURE_CHANGED:
1410       ruler_widget_refresh (
1411         Z_RULER_WIDGET (MW_RULER));
1412       ruler_widget_refresh (
1413         Z_RULER_WIDGET (EDITOR_RULER));
1414       gtk_widget_queue_draw (
1415         GTK_WIDGET (MW_DIGITAL_TIME_SIG));
1416       break;
1417     case ET_PLAYHEAD_POS_CHANGED:
1418       on_playhead_changed (false);
1419       break;
1420     case ET_PLAYHEAD_POS_CHANGED_MANUALLY:
1421       on_playhead_changed (true);
1422       break;
1423     case ET_CLIP_EDITOR_REGION_CHANGED:
1424       /*on_clip_editor_region_changed ();*/
1425       clip_editor_widget_on_region_changed (
1426         MW_CLIP_EDITOR);
1427       PIANO_ROLL->num_current_notes = 0;
1428       piano_roll_keys_widget_redraw_full (
1429         MW_PIANO_ROLL_KEYS);
1430       break;
1431     case ET_TRACK_AUTOMATION_VISIBILITY_CHANGED:
1432       tracklist_widget_update_track_visibility (
1433         MW_TRACKLIST);
1434       break;
1435     case ET_TRACK_LANES_VISIBILITY_CHANGED:
1436       tracklist_widget_update_track_visibility (
1437         MW_TRACKLIST);
1438       /*arranger_widget_update_visibility (*/
1439         /*(ArrangerWidget *) MW_TIMELINE);*/
1440       /*arranger_widget_update_visibility (*/
1441         /*(ArrangerWidget *) MW_PINNED_TIMELINE);*/
1442       break;
1443     case ET_TRACK_ADDED:
1444       on_track_added ((Track *) ev->arg);
1445       tracklist_header_widget_refresh_track_count (
1446         MW_TRACKLIST_HEADER);
1447       break;
1448     case ET_TRACK_CHANGED:
1449       on_track_changed ((Track *) ev->arg);
1450       break;
1451     case ET_TRACKS_ADDED:
1452       if (MW_MIXER)
1453         mixer_widget_hard_refresh (MW_MIXER);
1454       if (MW_TRACKLIST)
1455         tracklist_widget_hard_refresh (
1456           MW_TRACKLIST);
1457       visibility_widget_refresh (
1458         MW_VISIBILITY);
1459       tracklist_header_widget_refresh_track_count (
1460         MW_TRACKLIST_HEADER);
1461       break;
1462     case ET_TRACK_COLOR_CHANGED:
1463       on_track_color_changed ((Track *) ev->arg);
1464       break;
1465     case ET_TRACK_NAME_CHANGED:
1466       on_track_name_changed ((Track *) ev->arg);
1467       break;
1468     case ET_REFRESH_ARRANGER:
1469       /* remove the children of the pinned
1470        * timeline first because one of them
1471        * will be added to the unpinned
1472        * tracklist when unpinning */
1473       arranger_widget_redraw_whole (
1474         MW_PINNED_TIMELINE);
1475 
1476       if (MW_TIMELINE)
1477         arranger_widget_redraw_whole (
1478           MW_TIMELINE);
1479       break;
1480     case ET_RULER_VIEWPORT_CHANGED:
1481       timeline_minimap_widget_refresh (
1482         MW_TIMELINE_MINIMAP);
1483       ruler_widget_refresh (
1484         Z_RULER_WIDGET (ev->arg));
1485       break;
1486     case ET_TRACK_STATE_CHANGED:
1487       /*on_track_state_changed (*/
1488         /*(Track *) ev->arg);*/
1489       for (int j = 0; j < TRACKLIST->num_tracks;
1490            j++)
1491         {
1492           on_track_state_changed (
1493             TRACKLIST->tracks[j]);
1494         }
1495       monitor_section_widget_refresh (
1496         MW_MONITOR_SECTION);
1497       break;
1498     case ET_TRACK_VISIBILITY_CHANGED:
1499       tracklist_widget_update_track_visibility (
1500         MW_TRACKLIST);
1501       arranger_widget_redraw_whole (
1502         MW_TIMELINE);
1503       arranger_widget_redraw_whole (
1504         MW_PINNED_TIMELINE);
1505       track_visibility_tree_widget_refresh (
1506         MW_TRACK_VISIBILITY_TREE);
1507       tracklist_header_widget_refresh_track_count (
1508         MW_TRACKLIST_HEADER);
1509       mixer_widget_hard_refresh (MW_MIXER);
1510       break;
1511     case ET_UNDO_REDO_ACTION_DONE:
1512       home_toolbar_widget_refresh_undo_redo_buttons (
1513         MW_HOME_TOOLBAR);
1514       break;
1515     case ET_PIANO_ROLL_HIGHLIGHTING_CHANGED:
1516       if (MW_MIDI_EDITOR_SPACE)
1517         piano_roll_keys_widget_refresh (
1518           MW_PIANO_ROLL_KEYS);
1519       break;
1520     case ET_PIANO_ROLL_KEY_ON_OFF:
1521       piano_roll_keys_widget_redraw_full (
1522         MW_PIANO_ROLL_KEYS);
1523       break;
1524     case ET_RULER_STATE_CHANGED:
1525       ruler_widget_refresh (
1526         (RulerWidget *) MW_RULER);
1527       break;
1528     case ET_AUTOMATION_TRACK_ADDED:
1529     case ET_AUTOMATION_TRACK_REMOVED:
1530     case ET_AUTOMATION_TRACK_CHANGED:
1531       on_automation_track_added (
1532         (AutomationTrack *) ev->arg);
1533       break;
1534     case ET_PLUGINS_ADDED:
1535       on_plugins_removed ((Track *)ev->arg);
1536       break;
1537     case ET_PLUGIN_ADDED:
1538       on_plugin_added (
1539         (Plugin *) ev->arg);
1540       break;
1541     case ET_PLUGIN_CRASHED:
1542       on_plugin_crashed (
1543         (Plugin *) ev->arg);
1544       break;
1545     case ET_PLUGINS_REMOVED:
1546       on_plugins_removed ((Track *)ev->arg);
1547       break;
1548     case ET_MIXER_SELECTIONS_CHANGED:
1549       on_mixer_selections_changed ();
1550       break;
1551     case ET_CHANNEL_OUTPUT_CHANGED:
1552       on_channel_output_changed (
1553         (Channel *)ev->arg);
1554       break;
1555     case ET_TRACKS_MOVED:
1556       if (MW_MIXER)
1557         mixer_widget_hard_refresh (MW_MIXER);
1558 
1559       /* remove the children of the pinned
1560        * tracklist first because one of them
1561        * will be added to the unpinned
1562        * tracklist when unpinning */
1563       /*z_gtk_container_remove_all_children (*/
1564         /*GTK_CONTAINER (MW_PINNED_TRACKLIST));*/
1565 
1566       if (MW_TRACKLIST)
1567         tracklist_widget_hard_refresh (
1568           MW_TRACKLIST);
1569       /*if (MW_PINNED_TRACKLIST)*/
1570         /*pinned_tracklist_widget_hard_refresh (*/
1571           /*MW_PINNED_TRACKLIST);*/
1572 
1573       visibility_widget_refresh (
1574         MW_VISIBILITY);
1575 
1576       /* needs to be called later because tracks
1577        * need time to get allocated */
1578       EVENTS_PUSH (ET_REFRESH_ARRANGER, NULL);
1579       break;
1580     case ET_CHANNEL_SLOTS_CHANGED:
1581       {
1582         Channel * ch = (Channel *) ev->arg;
1583         ChannelWidget * cw =
1584           ch ? ch->widget : NULL;
1585         if (cw)
1586           {
1587             channel_widget_update_midi_fx_and_inserts (
1588               cw);
1589           }
1590       }
1591       break;
1592     case ET_DRUM_MODE_CHANGED:
1593       midi_editor_space_widget_refresh (
1594         MW_MIDI_EDITOR_SPACE);
1595       arranger_widget_redraw_whole (
1596         MW_MIDI_ARRANGER);
1597       break;
1598     case ET_MODULATOR_ADDED:
1599       on_modulator_added ((Plugin *)ev->arg);
1600       break;
1601     case ET_PINNED_TRACKLIST_SIZE_CHANGED:
1602       /*gtk_widget_set_size_request (*/
1603         /*GTK_WIDGET (*/
1604           /*MW_CENTER_DOCK->*/
1605             /*pinned_timeline_scroll),*/
1606         /*-1,*/
1607         /*gtk_widget_get_allocated_height (*/
1608           /*GTK_WIDGET (MW_PINNED_TRACKLIST)));*/
1609       break;
1610     case ET_TRACK_LANE_ADDED:
1611     case ET_TRACK_LANE_REMOVED:
1612       tracklist_widget_update_track_visibility (
1613         MW_TRACKLIST);
1614       /*arranger_widget_update_visibility (*/
1615         /*(ArrangerWidget *) MW_TIMELINE);*/
1616       break;
1617     case ET_LOOP_TOGGLED:
1618       redraw_all_arranger_bgs ();
1619       ruler_widget_redraw_whole (
1620         (RulerWidget *) EDITOR_RULER);
1621       ruler_widget_redraw_whole (
1622         (RulerWidget *) MW_RULER);
1623       transport_controls_widget_refresh (
1624         MW_TRANSPORT_CONTROLS);
1625       break;
1626     case ET_ARRANGER_SELECTIONS_IN_TRANSIT:
1627       on_arranger_selections_in_transit (
1628         (ArrangerSelections *) ev->arg);
1629       break;
1630     case ET_CHORD_KEY_CHANGED:
1631       for (int j = 0;
1632            j < CHORD_EDITOR->num_chords; j++)
1633         {
1634           if (CHORD_EDITOR->chords[j] ==
1635                (ChordDescriptor *) ev->arg)
1636             {
1637               chord_key_widget_refresh (
1638                 MW_CHORD_EDITOR_SPACE->
1639                   chord_keys[j]);
1640             }
1641         }
1642       chord_pad_widget_refresh (MW_CHORD_PAD);
1643       break;
1644     case ET_JACK_TRANSPORT_TYPE_CHANGED:
1645       g_message ("doing");
1646       top_bar_widget_refresh (
1647         TOP_BAR);
1648       break;
1649     case ET_SELECTING_IN_ARRANGER:
1650       {
1651         ArrangerWidget * arranger =
1652           Z_ARRANGER_WIDGET (ev->arg);
1653         ArrangerSelections * sel =
1654           arranger_widget_get_selections (arranger);
1655         arranger_selections_redraw (sel);
1656         event_viewer_widget_refresh_for_arranger (
1657           arranger);
1658         timeline_toolbar_widget_refresh (
1659           MW_TIMELINE_TOOLBAR);
1660       }
1661       break;
1662     case ET_TRACKS_RESIZED:
1663       g_warn_if_fail (ev->arg);
1664       arranger_widget_redraw_whole (
1665         MW_TIMELINE);
1666       arranger_widget_redraw_whole (
1667         MW_PINNED_TIMELINE);
1668       break;
1669     case ET_CLIP_EDITOR_FIRST_TIME_REGION_SELECTED:
1670       gtk_widget_set_visible (
1671         GTK_WIDGET (MW_EDITOR_EVENT_VIEWER),
1672         g_settings_get_boolean (
1673           S_UI, "editor-event-viewer-visible"));
1674       break;
1675     case ET_PIANO_ROLL_MIDI_MODIFIER_CHANGED:
1676       arranger_widget_redraw_whole (
1677         (ArrangerWidget *)
1678         MW_MIDI_MODIFIER_ARRANGER);
1679       break;
1680     case ET_BPM_CHANGED:
1681       ruler_widget_refresh (MW_RULER);
1682       ruler_widget_refresh (EDITOR_RULER);
1683       gtk_widget_queue_draw (
1684         GTK_WIDGET (MW_DIGITAL_BPM));
1685 
1686       /* these are only used in the UI so
1687        * no need to update them during DSP */
1688       snap_grid_update_snap_points_default (
1689         SNAP_GRID_TIMELINE);
1690       snap_grid_update_snap_points_default (
1691         SNAP_GRID_EDITOR);
1692       quantize_options_update_quantize_points (
1693         QUANTIZE_OPTIONS_TIMELINE);
1694       quantize_options_update_quantize_points (
1695         QUANTIZE_OPTIONS_EDITOR);
1696       redraw_all_arranger_bgs ();
1697       break;
1698     case ET_CHANNEL_FADER_VAL_CHANGED:
1699       channel_widget_redraw_fader (
1700         ((Channel *)ev->arg)->widget);
1701 #if 0
1702       inspector_track_widget_show_tracks (
1703         MW_TRACK_INSPECTOR, TRACKLIST_SELECTIONS);
1704 #endif
1705       break;
1706     case ET_PIANO_ROLL_KEY_HEIGHT_CHANGED:
1707       midi_editor_space_widget_refresh (
1708         MW_MIDI_EDITOR_SPACE);
1709       break;
1710     case ET_MAIN_WINDOW_LOADED:
1711       /* show all visible plugins */
1712       for (int j = 0; j < TRACKLIST->num_tracks;
1713            j++)
1714         {
1715           Channel * ch =
1716             TRACKLIST->tracks[j]->channel;
1717           if (!ch)
1718             continue;
1719 
1720           for (int k = 0;
1721                k < STRIP_SIZE * 2 + 1; k++)
1722             {
1723               Plugin * pl = NULL;
1724               if (k < STRIP_SIZE)
1725                 pl = ch->midi_fx[k];
1726               else if (k == STRIP_SIZE)
1727                 pl = ch->instrument;
1728               else
1729                 pl =
1730                   ch->inserts[
1731                     k - (STRIP_SIZE + 1)];
1732 
1733               if (!pl)
1734                 continue;
1735               if (pl->visible)
1736                 plugin_open_ui (pl);
1737             }
1738         }
1739       /* refresh modulator view */
1740       if (MW_MODULATOR_VIEW)
1741         {
1742           modulator_view_widget_refresh (
1743             MW_MODULATOR_VIEW,
1744             P_MODULATOR_TRACK);
1745         }
1746 
1747       /* show clip editor if clip selected */
1748       if (MW_CLIP_EDITOR &&
1749           CLIP_EDITOR->has_region)
1750         {
1751           clip_editor_widget_on_region_changed (
1752             MW_CLIP_EDITOR);
1753         }
1754 
1755       /* refresh inspector */
1756       left_dock_edge_widget_refresh (
1757         MW_LEFT_DOCK_EDGE);
1758       on_project_selection_type_changed ();
1759       main_notebook_widget_refresh (
1760         MW_MAIN_NOTEBOOK);
1761 
1762 #ifdef CHECK_UPDATES
1763       zrythm_app_check_for_updates (zrythm_app);
1764 #endif /* CHECK_UPDATES */
1765       break;
1766     case ET_SPLASH_CLOSED:
1767       break;
1768     case ET_PROJECT_SAVED:
1769       header_widget_set_subtitle (
1770         MW_HEADER,
1771         ((Project *) ev->arg)->title);
1772       break;
1773     case ET_PROJECT_LOADED:
1774       header_widget_set_subtitle (
1775         MW_HEADER,
1776         ((Project *) ev->arg)->title);
1777       home_toolbar_widget_refresh_undo_redo_buttons (
1778         MW_HOME_TOOLBAR);
1779       ruler_widget_set_zoom_level (
1780         MW_RULER,
1781         ruler_widget_get_zoom_level (
1782           MW_RULER));
1783       ruler_widget_set_zoom_level (
1784         EDITOR_RULER,
1785         ruler_widget_get_zoom_level (
1786           EDITOR_RULER));
1787       break;
1788     case ET_AUTOMATION_TRACKLIST_AT_REMOVED:
1789       /* TODO */
1790       break;
1791     case ET_TRIAL_LIMIT_REACHED:
1792       {
1793         char msg[500];
1794         sprintf (
1795           msg,
1796           _("Trial limit has been reached. "
1797           "%s will now go silent"),
1798           PROGRAM_NAME);
1799         ui_show_message_full (
1800           GTK_WINDOW (MAIN_WINDOW),
1801           GTK_MESSAGE_INFO, "%s", msg);
1802       }
1803       break;
1804     case ET_CHANNEL_SEND_CHANGED:
1805       {
1806         ChannelSend * send =
1807           (ChannelSend *) ev->arg;
1808         ChannelSendWidget * widget =
1809           channel_send_find_widget (send);
1810         if (widget)
1811           {
1812             gtk_widget_queue_draw (
1813               GTK_WIDGET (widget));
1814           }
1815         Track * tr =
1816           channel_send_get_track (send);
1817         ChannelWidget * ch_w =
1818           tr->channel->widget;
1819         if (ch_w)
1820           {
1821             gtk_widget_queue_draw (
1822               GTK_WIDGET (
1823                 ch_w->sends->slots[
1824                   send->slot]));
1825           }
1826       }
1827       break;
1828     case ET_RULER_DISPLAY_TYPE_CHANGED:
1829       redraw_all_arranger_bgs ();
1830       if (EDITOR_RULER)
1831         {
1832           ruler_widget_redraw_whole (
1833             EDITOR_RULER);
1834         }
1835       if (MW_RULER)
1836         {
1837           ruler_widget_redraw_whole (MW_RULER);
1838         }
1839       break;
1840     case ET_ARRANGER_HIGHLIGHT_CHANGED:
1841       {
1842         ArrangerWidget * arranger =
1843           Z_ARRANGER_WIDGET (ev->arg);
1844         arranger_widget_redraw_whole (
1845           arranger);
1846        }
1847       break;
1848     case ET_ENGINE_ACTIVATE_CHANGED:
1849     case ET_ENGINE_BUFFER_SIZE_CHANGED:
1850     case ET_ENGINE_SAMPLE_RATE_CHANGED:
1851       if (!gtk_widget_in_destruction (
1852              GTK_WIDGET (MAIN_WINDOW)))
1853         {
1854           bot_bar_widget_refresh (MW_BOT_BAR);
1855           ruler_widget_redraw_whole (EDITOR_RULER);
1856           ruler_widget_redraw_whole (MW_RULER);
1857           inspector_track_widget_show_tracks (
1858             MW_TRACK_INSPECTOR,
1859             TRACKLIST_SELECTIONS, false);
1860         }
1861       break;
1862     case ET_MIDI_BINDINGS_CHANGED:
1863       main_notebook_widget_refresh (
1864         MW_MAIN_NOTEBOOK);
1865       break;
1866     case ET_PORT_CONNECTION_CHANGED:
1867       main_notebook_widget_refresh (
1868         MW_MAIN_NOTEBOOK);
1869       break;
1870     case ET_EDITOR_FUNCTION_APPLIED:
1871       editor_toolbar_widget_refresh (
1872         MW_EDITOR_TOOLBAR);
1873       break;
1874     case ET_ARRANGER_SELECTIONS_CHANGED_REDRAW_EVERYTHING:
1875       arranger_selections_change_redraw_everything (
1876         ARRANGER_SELECTIONS (ev->arg));
1877       break;
1878     case ET_AUTOMATION_VALUE_VISIBILITY_CHANGED:
1879       arranger_widget_redraw_whole (
1880         MW_AUTOMATION_ARRANGER);
1881       break;
1882     case ET_PROJECT_SELECTION_TYPE_CHANGED:
1883       on_project_selection_type_changed ();
1884       break;
1885     case ET_AUDIO_SELECTIONS_RANGE_CHANGED:
1886       arranger_widget_redraw_whole (
1887         MW_AUDIO_ARRANGER);
1888       break;
1889     case ET_PLUGIN_COLLETIONS_CHANGED:
1890       plugin_browser_widget_refresh_collections (
1891         MW_PLUGIN_BROWSER);
1892       break;
1893     case ET_SNAP_GRID_OPTIONS_CHANGED:
1894       {
1895         SnapGrid * sg = (SnapGrid *) ev->arg;
1896         if (sg == SNAP_GRID_TIMELINE)
1897           {
1898             snap_box_widget_refresh (
1899               MW_TIMELINE_TOOLBAR->snap_box);
1900           }
1901         else if (sg == SNAP_GRID_EDITOR)
1902           {
1903             snap_box_widget_refresh (
1904               MW_EDITOR_TOOLBAR->snap_box);
1905           }
1906       }
1907       break;
1908     case ET_TRANSPORT_RECORDING_ON_OFF_CHANGED:
1909       gtk_toggle_button_set_active (
1910         MW_TRANSPORT_CONTROLS->trans_record_btn,
1911         TRANSPORT->recording);
1912       break;
1913     case ET_TRACK_FREEZE_CHANGED:
1914       arranger_selections_change_redraw_everything (
1915         (ArrangerSelections *) TL_SELECTIONS);
1916       break;
1917     case ET_LOG_WARNING_STATE_CHANGED:
1918       header_widget_refresh (MW_HEADER);
1919       break;
1920     case ET_PLAYHEAD_SCROLL_MODE_CHANGED:
1921       break;
1922     case ET_TRACK_FADER_BUTTON_CHANGED:
1923       on_track_state_changed (
1924         (Track *) ev->arg);
1925       break;
1926     case ET_PLUGIN_PRESET_SAVED:
1927     case ET_PLUGIN_PRESET_LOADED:
1928       {
1929         Plugin * pl = (Plugin *) ev->arg;
1930         if (pl->window)
1931           {
1932             plugin_gtk_set_window_title (
1933               pl, pl->window);
1934           }
1935       }
1936       break;
1937     case ET_TRACK_FOLD_CHANGED:
1938       on_track_added ((Track *) ev->arg);
1939       break;
1940     case ET_MIXER_CHANNEL_INSERTS_EXPANDED_CHANGED:
1941     case ET_MIXER_CHANNEL_MIDI_FX_EXPANDED_CHANGED:
1942     case ET_MIXER_CHANNEL_SENDS_EXPANDED_CHANGED:
1943       mixer_widget_soft_refresh (MW_MIXER);
1944       break;
1945     case ET_REGION_ACTIVATED:
1946       bot_dock_edge_widget_show_clip_editor (
1947         MW_BOT_DOCK_EDGE, true);
1948       break;
1949     case ET_VELOCITIES_RAMPED:
1950       arranger_widget_redraw_whole (
1951         MW_MIDI_MODIFIER_ARRANGER);
1952       break;
1953     case ET_AUDIO_REGION_FADE_IN_CHANGED:
1954       audio_arranger_widget_redraw_fade (
1955         MW_AUDIO_ARRANGER, true);
1956       break;
1957     case ET_AUDIO_REGION_FADE_OUT_CHANGED:
1958       audio_arranger_widget_redraw_fade (
1959         MW_AUDIO_ARRANGER, false);
1960       break;
1961     case ET_AUDIO_REGION_GAIN_CHANGED:
1962       audio_arranger_widget_redraw_gain (
1963         MW_AUDIO_ARRANGER);
1964       break;
1965     default:
1966       g_warning (
1967         "event %d not implemented yet",
1968         ev->type);
1969       break;
1970     }
1971 }
1972 
1973 /**
1974  * GSourceFunc to be added using idle add.
1975  *
1976  * This will loop indefinintely.
1977  */
1978 static int
process_events(void * data)1979 process_events (void * data)
1980 {
1981   EventManager * self = (EventManager *) data;
1982 
1983   ZEvent * ev;
1984   clean_duplicates_and_copy (
1985     self, self->events_arr);
1986 
1987   /*g_message ("starting processing");*/
1988   for (guint i = 0; i < self->events_arr->len; i++)
1989     {
1990       if (i > 30)
1991         {
1992           g_message (
1993             "more than 30 UI events processed "
1994             "(%d)!", i);
1995         }
1996 
1997       ev =
1998         (ZEvent *)
1999         g_ptr_array_index (self->events_arr, i);
2000 
2001       if (!ZRYTHM_HAVE_UI)
2002         {
2003           g_message (
2004             "%s: (%d) No UI, skipping",
2005             __func__, i);
2006           goto return_to_pool;
2007         }
2008 
2009       /*g_message ("event type %d", ev->type);*/
2010 
2011       event_manager_process_event (self, ev);
2012 
2013 return_to_pool:
2014       object_pool_return (
2015         self->obj_pool, ev);
2016     }
2017   /*g_message ("processed %d events", i);*/
2018 
2019   if (self->events_arr->len > 6)
2020     g_message ("More than 6 events processed. "
2021                "Optimization needed.");
2022 
2023   /*g_usleep (8000);*/
2024   /*project_validate (PROJECT);*/
2025 
2026   return G_SOURCE_CONTINUE;
2027 }
2028 
2029 /**
2030  * Starts accepting events.
2031  */
2032 void
event_manager_start_events(EventManager * self)2033 event_manager_start_events (
2034   EventManager * self)
2035 {
2036   g_message ("%s: starting...", __func__);
2037 
2038   if (self->process_source_id)
2039     {
2040       g_message (
2041         "%s: already processing events", __func__);
2042       return;
2043     }
2044 
2045   g_message (
2046     "%s: starting processing events...", __func__);
2047 
2048   self->process_source_id =
2049     g_timeout_add (12, process_events, self);
2050 
2051   g_message ("%s: done...", __func__);
2052 }
2053 
2054 /**
2055  * Creates the event queue and starts the event loop.
2056  *
2057  * Must be called from a GTK thread.
2058  */
2059 EventManager *
event_manager_new(void)2060 event_manager_new (void)
2061 {
2062   EventManager * self = object_new (EventManager);
2063 
2064   self->obj_pool =
2065     object_pool_new (
2066       (ObjectCreatorFunc) event_new,
2067       (ObjectFreeFunc) event_free,
2068       EVENT_MANAGER_MAX_EVENTS);
2069   self->mqueue = mpmc_queue_new ();
2070   mpmc_queue_reserve (
2071     self->mqueue,
2072     (size_t)
2073     EVENT_MANAGER_MAX_EVENTS * sizeof (ZEvent *));
2074 
2075   self->events_arr =
2076     g_ptr_array_sized_new (200);
2077 
2078   return self;
2079 }
2080 
2081 /**
2082  * Stops events from getting fired.
2083  */
2084 void
event_manager_stop_events(EventManager * self)2085 event_manager_stop_events (
2086   EventManager * self)
2087 {
2088   if (self->process_source_id)
2089     {
2090       /* remove the source func */
2091       g_source_remove_and_zero (
2092         self->process_source_id);
2093     }
2094 
2095   /* process any remaining events - clear the
2096    * queue. */
2097   process_events (self);
2098 }
2099 
2100 /**
2101  * Processes the events now.
2102  *
2103  * Must only be called from the GTK thread.
2104  */
2105 void
event_manager_process_now(EventManager * self)2106 event_manager_process_now (
2107   EventManager * self)
2108 {
2109   g_return_if_fail (self);
2110 
2111   g_message ("processing events now...");
2112 
2113   /* process events now */
2114   process_events (self);
2115 
2116   g_message ("done");
2117 }
2118 
2119 /**
2120  * Removes events where the arg matches the
2121  * given object.
2122  *
2123  * FIXME doesn't work - infinite loop.
2124  */
2125 void
event_manager_remove_events_for_obj(EventManager * self,void * obj)2126 event_manager_remove_events_for_obj (
2127   EventManager * self,
2128   void *         obj)
2129 {
2130   MPMCQueue * q = self->mqueue;
2131   ZEvent * event;
2132   while (event_queue_dequeue_event (q, &event))
2133     {
2134       if (event->arg == obj)
2135         {
2136           object_pool_return (
2137             self->obj_pool, event);
2138         }
2139       else
2140         {
2141           event_queue_push_back_event (q, event);
2142         }
2143     }
2144 }
2145 
2146 void
event_manager_free(EventManager * self)2147 event_manager_free (
2148   EventManager * self)
2149 {
2150   g_message ("%s: Freeing...", __func__);
2151 
2152   event_manager_stop_events (self);
2153 
2154   object_free_w_func_and_null (
2155     object_pool_free, self->obj_pool);
2156   object_free_w_func_and_null (
2157     mpmc_queue_free, self->mqueue);
2158   object_free_w_func_and_null (
2159     g_ptr_array_unref, self->events_arr);
2160 
2161   object_zero_and_free (self);
2162 
2163   g_message ("%s: done", __func__);
2164 }
2165