1 /*
2  * Copyright (C) 2018-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 this program.  If not, see <https://www.gnu.org/licenses/>.
18  */
19 
20 /**
21  * \file
22  *
23  * Arranger base widget.
24  */
25 
26 #ifndef __GUI_WIDGETS_ARRANGER_H__
27 #define __GUI_WIDGETS_ARRANGER_H__
28 
29 #include "gui/widgets/main_window.h"
30 #include "audio/position.h"
31 #include "audio/transport.h"
32 #include "utils/ui.h"
33 
34 #include <gtk/gtk.h>
35 
36 #define ARRANGER_WIDGET_TYPE ( \
37   arranger_widget_get_type ())
38 G_DECLARE_FINAL_TYPE (
39   ArrangerWidget,
40   arranger_widget,
41   Z, ARRANGER_WIDGET,
42   GtkDrawingArea)
43 
44 typedef struct _ArrangerBgWidget ArrangerBgWidget;
45 typedef struct MidiNote MidiNote;
46 typedef struct SnapGrid SnapGrid;
47 typedef struct AutomationPoint AutomationPoint;
48 
49 typedef struct _GtkEventControllerMotion
50   GtkEventControllerMotion;
51 typedef struct ArrangerObject ArrangerObject;
52 typedef struct ArrangerSelections ArrangerSelections;
53 typedef struct EditorSettings EditorSettings;
54 typedef struct ObjectPool ObjectPool;
55 typedef struct _RulerWidget RulerWidget;
56 typedef enum ArrangerObjectType ArrangerObjectType;
57 typedef enum TransportDisplay TransportDisplay;
58 
59 /**
60  * @addtogroup widgets
61  *
62  * @{
63  */
64 
65 #define ARRANGER_WIDGET_GET_ACTION(arr,actn) \
66   (arr->action == UI_OVERLAY_ACTION_##actn)
67 
68 typedef enum ArrangerCursor
69 {
70   /** Invalid cursor. */
71   ARRANGER_CURSOR_NONE,
72   ARRANGER_CURSOR_SELECT,
73   ARRANGER_CURSOR_EDIT,
74   ARRANGER_CURSOR_AUTOFILL,
75   ARRANGER_CURSOR_CUT,
76   ARRANGER_CURSOR_ERASER,
77   ARRANGER_CURSOR_AUDITION,
78   ARRANGER_CURSOR_RAMP,
79   ARRANGER_CURSOR_GRAB,
80   ARRANGER_CURSOR_GRABBING,
81   ARRANGER_CURSOR_RESIZING_L,
82   ARRANGER_CURSOR_RESIZING_L_FADE,
83   ARRANGER_CURSOR_STRETCHING_L,
84   ARRANGER_CURSOR_RESIZING_L_LOOP,
85   ARRANGER_CURSOR_RESIZING_R,
86   ARRANGER_CURSOR_RESIZING_R_FADE,
87   ARRANGER_CURSOR_STRETCHING_R,
88   ARRANGER_CURSOR_RESIZING_R_LOOP,
89   ARRANGER_CURSOR_RESIZING_UP,
90   ARRANGER_CURSOR_RESIZING_UP_FADE_IN,
91   ARRANGER_CURSOR_RESIZING_UP_FADE_OUT,
92   ARRANGER_CURSOR_GRABBING_COPY,
93   ARRANGER_CURSOR_GRABBING_LINK,
94   ARRANGER_CURSOR_RANGE,
95   ARRANGER_CURSOR_FADE_IN,
96   ARRANGER_CURSOR_FADE_OUT,
97   ARRANGER_CURSOR_RENAME,
98 } ArrangerCursor;
99 
100 /**
101  * Type of arranger.
102  */
103 typedef enum ArrangerWidgetType
104 {
105   ARRANGER_WIDGET_TYPE_TIMELINE,
106   ARRANGER_WIDGET_TYPE_MIDI,
107   ARRANGER_WIDGET_TYPE_MIDI_MODIFIER,
108   ARRANGER_WIDGET_TYPE_AUDIO,
109   ARRANGER_WIDGET_TYPE_CHORD,
110   ARRANGER_WIDGET_TYPE_AUTOMATION,
111 } ArrangerWidgetType;
112 
113 #if 0
114 typedef enum ArrangerWidgetHoverType
115 {
116   ARRANGER_WIDGET_HOVER_TYPE_NONE,
117   ARRANGER_WIDGET_HOVER_TYPE_TRACK,
118   ARRANGER_WIDGET_HOVER_TYPE_TRACK_LANE,
119   ARRANGER_WIDGET_HOVER_TYPE_AUTOMATION_TRACK,
120 } ArrangerWidgetHoverType;
121 #endif
122 
123 /**
124  * The arranger widget is a canvas that draws all
125  * the arranger objects it contains.
126  */
127 typedef struct _ArrangerWidget
128 {
129   GtkDrawingArea parent_instance;
130 
131   /** Type of arranger this is. */
132   ArrangerWidgetType type;
133 
134   GtkGestureDrag * drag;
135   GtkGestureMultiPress * multipress;
136   GtkGestureMultiPress * right_mouse_mp;
137   GtkEventControllerMotion * motion_controller;
138 
139   /** Used when dragging. */
140   double         last_offset_x;
141   double         last_offset_y;
142 
143   UiOverlayAction action;
144 
145   /** X-axis coordinate at start of drag. */
146   double         start_x;
147 
148   /** Y-axis coordinate at start of drag. */
149   double         start_y;
150 
151   /** X-axis coordinate at the start of the drag,
152    * in pixels. */
153   double         start_pos_px;
154 
155   /**
156    * Whether a drag update operation started.
157    *
158    * drag_update will be skipped unless this is
159    * true or gtk_drag_check_threshold() returns
160    * true.
161    */
162   bool           drag_update_started;
163 
164   /** Whether an object exists, so we can use the
165    * earliest_obj_start_pos. */
166   int            earliest_obj_exists;
167 
168   /** Start Position of the earliest object
169    * at the start of the drag. */
170   Position       earliest_obj_start_pos;
171 
172   /**
173    * Fade in/out position at start.
174    *
175    * Used when moving fade in/out points.
176    */
177   Position       fade_pos_at_start;
178 
179   /**
180    * The object that was clicked in this drag
181    * cycle, if any.
182    *
183    * This is the ArrangerObject that was clicked,
184    * even though there could be more selected.
185    */
186   ArrangerObject * start_object;
187 
188   /** Object currently hovered. */
189   ArrangerObject * hovered_object;
190 
191   /** Whether the start object was selected before
192    * drag_begin. */
193   int            start_object_was_selected;
194 
195   /**
196    * A clone of the ArrangerSelections on drag
197    * begin.
198    *
199    * When autofilling velocities, this is used to
200    * store the affected objects before editing.
201    *
202    * This must contain clones only.
203    */
204   ArrangerSelections * sel_at_start;
205 
206   /**
207    * Region on drag begin, if editing automation.
208    */
209   ZRegion *            region_at_start;
210 
211   /** Selections to delete, used with the eraser
212    * tool. */
213   ArrangerSelections * sel_to_delete;
214 
215   /** Start Position of the earliest object
216    * currently. */
217   //Position             earliest_obj_pos;
218 
219   /** The absolute (not snapped) Position at the
220    * start of a drag, translated from start_x. */
221   Position       start_pos;
222 
223   /** The absolute (not snapped) current diff in
224    * ticks from the curr_pos to the start_pos. */
225   double         curr_ticks_diff_from_start;
226 
227   /** The adjusted diff in ticks to use for moving
228    * objects starting from their cached start
229    * positions. */
230   double         adj_ticks_diff;
231 
232   /** adj_ticks_diff in last cycle. */
233   double         last_adj_ticks_diff;
234 
235   /** The absolute (not snapped) Position as of the
236    * current action. */
237   Position       curr_pos;
238 
239   Position       end_pos; ///< for moving regions
240   gboolean       key_is_pressed;
241 
242   /** Current hovering positions. */
243   double         hover_x;
244   double         hover_y;
245 
246   /** Number of clicks in current action. */
247   int            n_press;
248 
249   /** Associated SnapGrid. */
250   SnapGrid *     snap_grid;
251 
252   /** Whether shift button is held down. */
253   int            shift_held;
254 
255   /** Whether Ctrl button is held down. */
256   int            ctrl_held;
257 
258   /** Whether Alt is currently held down. */
259   int            alt_held;
260 
261   gint64         last_frame_time;
262 
263   /* ----- TIMELINE ------ */
264 
265   /** The number of visible tracks moved during a
266    * moving operation between tracks up to the last
267    * cycle. */
268   int            visible_track_diff;
269 
270   /** The number of lanes moved during a
271    * moving operation between lanes, up to the last
272    * cycle. */
273   int            lane_diff;
274 
275   /** Whether this TimelineArrangerWidget is for
276    * the PinnedTracklist or not. */
277   int            is_pinned;
278 
279   /**
280    * 1 if resizing range.
281    */
282   int            resizing_range;
283 
284   /**
285    * 1 if this is the first call to resize the range,
286    * so range1 can be set.
287    */
288   int            resizing_range_start;
289 
290   /** Cache for chord object height, used during
291    * child size allocation. */
292   //int                  chord_obj_height;
293 
294   /* ----- END TIMELINE ----- */
295 
296   /* ------ MIDI (PIANO ROLL) ---- */
297 
298   /** The note currently hovering over */
299   int            hovered_note;
300 
301   /* ------ END MIDI (PIANO ROLL) ---- */
302 
303   /* ------ MIDI MODIFIER ---- */
304 
305   /** 1-127. */
306   int            start_vel_val;
307 
308   /**
309    * Maximum Velocity diff applied in this action.
310    *
311    * Used in drag_end to create an UndableAction.
312    * This can have any value, even greater than 127
313    * and it will be clamped when applying it to
314    * a Velocity.
315    */
316   int            vel_diff;
317 
318   /* ------ END MIDI MODIFIER ---- */
319 
320   /* ------- CHORD ------- */
321 
322   /** Index of the chord being hovered on. */
323   int            hovered_chord_index;
324 
325   /* ------- END CHORD ------- */
326 
327   /* --- AUDIO --- */
328 
329   /**
330    * Float value at start.
331    *
332    * Used when changing the audio region gain.
333    */
334   float          fval_at_start;
335 
336   double         dval_at_start;
337 
338   /* --- END AUDIO --- */
339 
340   /** Px the playhead was last drawn at, so we can
341    * redraw this and the new px only when the
342    * playhead changes position. */
343   int            last_playhead_px;
344 
345   /** Set to 1 to redraw. */
346   bool           redraw;
347 
348   cairo_t *      cached_cr;
349 
350   cairo_surface_t * cached_surface;
351 
352   /** Rectangle in the last call. */
353   GdkRectangle   last_rect;
354 
355   /**
356    * Whether the current selections can link
357    * (ie, only regions are selected).
358    *
359    * To be set on drag begin.
360    */
361   bool           can_link;
362 
363   /** Whether a rectangle is highlighted for DND. */
364   bool           is_highlighted;
365 
366   /** The rectangle to highlight. */
367   GdkRectangle   highlight_rect;
368   //GdkRectangle   prev_highlight_rect;
369   //
370 
371   /** Last selection rectangle, used to redraw the
372    * union of the new selection and this. */
373   GdkRectangle   last_selection_rect;
374 
375   /**
376    * Drag start button (primary, secondary, etc.).
377    *
378    * Can be tested against GDK_BUTTON_SECONDARY and
379    * GDK_BUTTON_PRIMARY.
380    */
381   guint          drag_start_btn;
382 
383   /**
384    * Whether this is the first time the widget is
385    * drawn.
386    *
387    * This is used for loading back the scroll
388    * positions saved in the project.
389    */
390   bool           first_draw;
391 
392   /** Cached setting. */
393   TransportDisplay ruler_display;
394 
395   /**
396    * Layout for drawing velocity text.
397    *
398    * TODO move to Velocity if parallel
399    * processing is needed - no need now.
400    */
401   PangoLayout *  vel_layout;
402 
403   /**
404    * Layout for drawing automation point text.
405    *
406    * TODO move to AutomationPoint if parallel
407    * processing is needed - no need now.
408    */
409   PangoLayout *  ap_layout;
410 
411   /**
412    * Layout for drawing audio editor text.
413    */
414   PangoLayout *  audio_layout;
415 
416 #if 0
417   /**
418    * Dummy cairo surface to create new surfaces from.
419    */
420   cairo_surface_t * dummy_surface;
421 
422   /**
423    * Thread pool for drawing in the background
424    * instead of in the UI thread.
425    *
426    * The result will be applied during draw in the
427    * UI thread.
428    */
429   GThreadPool *  draw_thread_pool;
430 
431   /**
432    * Object pool for ArrangerDrawTaskData.
433    *
434    * Must only be accessed from the GTK thread.
435    */
436   ObjectPool *   draw_task_obj_pool;
437 #endif
438 
439   /**
440    * Cached playhead x to draw.
441    *
442    * This is used to avoid queuing drawing at x and
443    * then drawing after it (if playhead moved). The
444    * playhead will be drawn at the location it
445    * was when the draw was queued.
446    */
447   //int            queued_playhead_px;
448 
449 } ArrangerWidget;
450 
451 const char *
452 arranger_widget_get_type_str (
453   ArrangerWidgetType type);
454 
455 /**
456  * Creates a timeline widget using the given
457  * timeline data.
458  */
459 void
460 arranger_widget_setup (
461   ArrangerWidget *   self,
462   ArrangerWidgetType type,
463   SnapGrid *         snap_grid);
464 
465 /**
466  * Sets the cursor on the arranger and all of its
467  * children.
468  */
469 void
470 arranger_widget_set_cursor (
471   ArrangerWidget * self,
472   ArrangerCursor   cursor);
473 
474 /**
475  * Wrapper of the UI functions based on the arranger
476  * type.
477  */
478 int
479 arranger_widget_pos_to_px (
480   ArrangerWidget * self,
481   Position * pos,
482   int        use_padding);
483 
484 /**
485  * Gets the cursor based on the current hover
486  * position.
487  */
488 ArrangerCursor
489 arranger_widget_get_cursor (
490   ArrangerWidget * self);
491 
492 /**
493  * Figures out which cursor should be used based
494  * on the current state and then sets it.
495  */
496 void
497 arranger_widget_refresh_cursor (
498   ArrangerWidget * self);
499 
500 /**
501  * Gets the corresponding scrolled window.
502  */
503 GtkScrolledWindow *
504 arranger_widget_get_scrolled_window (
505   ArrangerWidget * self);
506 
507 /**
508  * Get all objects currently present in the arranger.
509  *
510  * @param objs Array to fill in.
511  * @param size Array size to fill in.
512  */
513 void
514 arranger_widget_get_all_objects (
515   ArrangerWidget *  self,
516   ArrangerObject ** objs,
517   int *             size);
518 
519 /**
520  * Wrapper for ui_px_to_pos depending on the
521  * arranger type.
522  */
523 void
524 arranger_widget_px_to_pos (
525   ArrangerWidget * self,
526   double           px,
527   Position *       pos,
528   bool             has_padding);
529 
530 /**
531  * Returns the current visible rectangle.
532  *
533  * @param rect The rectangle to fill in.
534  */
535 void
536 arranger_widget_get_visible_rect (
537   ArrangerWidget * self,
538   GdkRectangle *   rect);
539 
540 /**
541  * Fills in the given array with the ArrangerObject's
542  * of the given type that appear in the given
543  * ranger.
544  *
545  * @param type The type of arranger objects to find,
546  *   or -1 to look for all objects.
547  * @param x X, or -1 to not check x.
548  * @param y Y, or -1 to not check y.
549  * @param array The array to fill.
550  * @param array_size The size of the array to fill.
551  */
552 void
553 arranger_widget_get_hit_objects_at_point (
554   ArrangerWidget *   self,
555   ArrangerObjectType type,
556   double             x,
557   double             y,
558   ArrangerObject **  array,
559   int *              array_size);
560 
561 /**
562  * Fills in the given array with the ArrangerObject's
563  * of the given type that appear in the given
564  * ranger.
565  *
566  * @param rect The rectangle to search in.
567  * @param type The type of arranger objects to find,
568  *   or -1 to look for all objects.
569  * @param array The array to fill.
570  * @param array_size The size of the array to fill.
571  */
572 void
573 arranger_widget_get_hit_objects_in_rect (
574   ArrangerWidget *   self,
575   ArrangerObjectType type,
576   GdkRectangle *     rect,
577   ArrangerObject **  array,
578   int *              array_size);
579 
580 /**
581  * Returns the ArrangerObject of the given type
582  * at (x,y).
583  *
584  * @param type The arranger object type, or -1 to
585  *   search for all types.
586  * @param x X, or -1 to not check x.
587  * @param y Y, or -1 to not check y.
588  */
589 ArrangerObject *
590 arranger_widget_get_hit_arranger_object (
591   ArrangerWidget *   self,
592   ArrangerObjectType type,
593   const double       x,
594   const double       y);
595 
596 void
597 arranger_widget_select_all (
598   ArrangerWidget *  self,
599   bool              select,
600   bool              fire_events);
601 
602 /**
603  * Returns if the arranger is in a moving-related
604  * operation or starting a moving-related operation.
605  *
606  * Useful to know if we need transient widgets or
607  * not.
608  */
609 bool
610 arranger_widget_is_in_moving_operation (
611   ArrangerWidget * self);
612 
613 /**
614  * Returns the ArrangerSelections for this
615  * ArrangerWidget.
616  */
617 ArrangerSelections *
618 arranger_widget_get_selections (
619   ArrangerWidget * self);
620 
621 /**
622  * Queues a redraw of the whole visible arranger.
623  */
624 void
625 arranger_widget_redraw_whole (
626   ArrangerWidget * self);
627 
628 /**
629  * Only redraws the playhead part.
630  */
631 void
632 arranger_widget_redraw_playhead (
633   ArrangerWidget * self);
634 
635 /**
636  * Only redraws the given rectangle.
637  */
638 void
639 arranger_widget_redraw_rectangle (
640   ArrangerWidget * self,
641   GdkRectangle *   rect);
642 
643 SnapGrid *
644 arranger_widget_get_snap_grid (
645   ArrangerWidget * self);
646 
647 /**
648  * Called from MainWindowWidget because some
649  * events don't reach here.
650  */
651 gboolean
652 arranger_widget_on_key_action (
653   GtkWidget *widget,
654   GdkEventKey *event,
655   ArrangerWidget * self);
656 
657 gboolean
658 arranger_widget_on_key_release (
659   GtkWidget *widget,
660   GdkEventKey *event,
661   ArrangerWidget * self);
662 
663 /**
664  * Scroll until the given object is visible.
665  *
666  * @param horizontal 1 for horizontal, 2 for
667  *   vertical.
668  * @param up Whether scrolling up or down.
669  * @param padding Padding pixels.
670  */
671 NONNULL
672 void
673 arranger_widget_scroll_until_obj (
674   ArrangerWidget * self,
675   ArrangerObject * obj,
676   int              horizontal,
677   int              up,
678   int              left,
679   double           padding);
680 
681 /**
682  * Toggles the mute status of the selection, based
683  * on the mute status of the selected object.
684  *
685  * This creates an undoable action and executes it.
686  */
687 void
688 arranger_widget_toggle_selections_muted (
689   ArrangerWidget * self,
690   ArrangerObject * clicked_object);
691 
692 /**
693  * Returns the earliest possible position allowed
694  * in this arranger (eg, 1.1.0.0 for timeline).
695  */
696 void
697 arranger_widget_get_min_possible_position (
698   ArrangerWidget * self,
699   Position *       pos);
700 
701 /**
702  * Sets the highlight rectangle.
703  *
704  * @param rect The rectangle, or NULL to
705  *   unset/unhighlight.
706  */
707 void
708 arranger_widget_set_highlight_rect (
709   ArrangerWidget * self,
710   GdkRectangle *   rect);
711 
712 /**
713  * Returns the EditorSettings corresponding to
714  * the given arranger.
715  */
716 EditorSettings *
717 arranger_widget_get_editor_settings (
718   ArrangerWidget * self);
719 
720 bool
721 arranger_widget_is_playhead_visible (
722   ArrangerWidget * self);
723 
724 NONNULL
725 PURE
726 RulerWidget *
727 arranger_widget_get_ruler (
728   ArrangerWidget * self);
729 
730 /**
731  * Returns whether any arranger is in the middle
732  * of an action.
733  */
734 bool
735 arranger_widget_any_doing_action (void);
736 
737 /**
738  * Returns the playhead's x coordinate in absolute
739  * coordinates.
740  */
741 int
742 arranger_widget_get_playhead_px (
743   ArrangerWidget * self);
744 
745 #define arranger_widget_print_action(self) \
746   g_debug ( \
747     "action: %s", ui_overlay_strings[self->action])
748 
749 /**
750  * Returns true if MIDI arranger and track mode
751  * is enabled.
752  */
753 bool
754 arranger_widget_get_drum_mode_enabled (
755   ArrangerWidget * self);
756 
757 /**
758  * @}
759  */
760 
761 #endif
762