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 /**
21  * \file
22  *
23  * Macros for arranger object backends.
24  */
25 
26 #ifndef __GUI_BACKEND_ARRANGER_OBJECT_H__
27 #define __GUI_BACKEND_ARRANGER_OBJECT_H__
28 
29 #include <stdbool.h>
30 
31 #include "audio/curve.h"
32 #include "audio/position.h"
33 #include "audio/region_identifier.h"
34 #include "utils/yaml.h"
35 
36 typedef struct ArrangerObject ArrangerObject;
37 typedef struct ArrangerSelections ArrangerSelections;
38 typedef struct _ArrangerWidget ArrangerWidget;
39 typedef struct _ArrangerObjectWidget
40   ArrangerObjectWidget;
41 
42 /**
43  * @addtogroup gui_backend
44  *
45  * @{
46  */
47 
48 #define ARRANGER_OBJECT_SCHEMA_VERSION 1
49 
50 #define ARRANGER_OBJECT_MAGIC 347616554
51 #define IS_ARRANGER_OBJECT(tr) \
52   (((ArrangerObject *) tr)->magic == \
53      ARRANGER_OBJECT_MAGIC && \
54    ((ArrangerObject *) tr)->type >= ARRANGER_OBJECT_TYPE_REGION && \
55    ((ArrangerObject *) tr)->type <= ARRANGER_OBJECT_TYPE_VELOCITY)
56 #define IS_ARRANGER_OBJECT_AND_NONNULL(x) \
57   (x && IS_ARRANGER_OBJECT (x))
58 
59 /**
60  * Flag used in some functions.
61  */
62 typedef enum ArrangerObjectResizeType
63 {
64   ARRANGER_OBJECT_RESIZE_NORMAL,
65   ARRANGER_OBJECT_RESIZE_LOOP,
66   ARRANGER_OBJECT_RESIZE_FADE,
67   ARRANGER_OBJECT_RESIZE_STRETCH,
68 
69   /**
70    * Used when we want to resize to contents
71    * when BPM changes.
72    *
73    * Only applies to audio.
74    */
75   ARRANGER_OBJECT_RESIZE_STRETCH_BPM_CHANGE,
76 } ArrangerObjectResizeType;
77 
78 /**
79  * The type of the object.
80  */
81 typedef enum ArrangerObjectType
82 {
83   /* These two are not actual object types. */
84   ARRANGER_OBJECT_TYPE_NONE,
85   ARRANGER_OBJECT_TYPE_ALL,
86 
87   ARRANGER_OBJECT_TYPE_REGION,
88   ARRANGER_OBJECT_TYPE_MIDI_NOTE,
89   ARRANGER_OBJECT_TYPE_CHORD_OBJECT,
90   ARRANGER_OBJECT_TYPE_SCALE_OBJECT,
91   ARRANGER_OBJECT_TYPE_MARKER,
92   ARRANGER_OBJECT_TYPE_AUTOMATION_POINT,
93   ARRANGER_OBJECT_TYPE_VELOCITY,
94 } ArrangerObjectType;
95 
96 static const cyaml_strval_t
97 arranger_object_type_strings[] =
98 {
99   { __("None"),
100     ARRANGER_OBJECT_TYPE_NONE },
101   { __("All"),
102     ARRANGER_OBJECT_TYPE_ALL },
103   { __("Region"),
104     ARRANGER_OBJECT_TYPE_REGION },
105   { __("Midi Note"),
106     ARRANGER_OBJECT_TYPE_MIDI_NOTE },
107   { __("Chord Object"),
108     ARRANGER_OBJECT_TYPE_CHORD_OBJECT },
109   { __("Scale Object"),
110     ARRANGER_OBJECT_TYPE_SCALE_OBJECT },
111   { __("Marker"),
112     ARRANGER_OBJECT_TYPE_MARKER },
113   { __("Automation Point"),
114     ARRANGER_OBJECT_TYPE_AUTOMATION_POINT },
115   { __("Velocity"),
116     ARRANGER_OBJECT_TYPE_VELOCITY },
117 };
118 
119 /**
120  * ArrangerObject flags.
121  */
122 typedef enum ArrangerObjectFlags
123 {
124   /** This object is not a project object, but an
125    * object used temporarily eg. when undoing/
126    * redoing. */
127   ARRANGER_OBJECT_FLAG_NON_PROJECT = 1 << 0,
128 
129 } ArrangerObjectFlags;
130 
131 static const cyaml_bitdef_t
132 arranger_object_flags_bitvals[] =
133 {
134   { .name = "non_project", .offset =  0, .bits =  1 },
135 };
136 
137 typedef enum ArrangerObjectPositionType
138 {
139   ARRANGER_OBJECT_POSITION_TYPE_START,
140   ARRANGER_OBJECT_POSITION_TYPE_END,
141   ARRANGER_OBJECT_POSITION_TYPE_CLIP_START,
142   ARRANGER_OBJECT_POSITION_TYPE_LOOP_START,
143   ARRANGER_OBJECT_POSITION_TYPE_LOOP_END,
144   ARRANGER_OBJECT_POSITION_TYPE_FADE_IN,
145   ARRANGER_OBJECT_POSITION_TYPE_FADE_OUT,
146 } ArrangerObjectPositionType;
147 
148 /**
149  * Base struct for arranger objects.
150  */
151 typedef struct ArrangerObject
152 {
153   int                schema_version;
154 
155   ArrangerObjectType type;
156 
157   /** Flags. */
158   ArrangerObjectFlags flags;
159 
160   /**
161    * Position (or start Position if the object
162    * has length).
163    *
164    * For audio/MIDI, the material starts at this
165    * frame.
166    *
167    * Midway Position between previous and next
168    * AutomationPoint's, if AutomationCurve.
169    */
170   Position           pos;
171 
172   /**
173    * End Position, if the object has one.
174    *
175    * This is exclusive of the material, i.e., the
176    * data at this position is not counted (for
177    * audio regions at least, TODO check for
178    * others).
179    */
180   Position           end_pos;
181 
182   /**
183    * Start position of the clip loop, relative
184    * to the object's start.
185    *
186    * The first time the region plays it will start
187    * playing from the clip_start_pos and then loop
188    * to this position.
189    */
190   Position           clip_start_pos;
191 
192   /** Loop start Position, if the object has one,
193    * relative to the object's start. */
194   Position           loop_start_pos;
195 
196   /**
197    * End position of the clip loop, relative to the
198    * object's start.
199    *
200    * Once this is reached, the clip will go back to
201    * the clip  loop start position.
202    */
203   Position           loop_end_pos;
204 
205   /** Fade in position, relative to the object's
206    * start. */
207   Position           fade_in_pos;
208 
209   /** Fade out position, relative to the object's
210    * start. */
211   Position           fade_out_pos;
212 
213   /** Fade in curve options. */
214   CurveOptions       fade_in_opts;
215 
216   /** Fade out curve options. */
217   CurveOptions       fade_out_opts;
218 
219   /** The full rectangle this object covers
220    * including off-screen parts, in absolute
221    * coordinates. */
222   GdkRectangle       full_rect;
223 
224   /** The rectangle this object was last drawn in
225    * (ie, after any necessary clipping),
226    * in absolute coordinates. */
227   //GdkRectangle       draw_rect;
228 
229   /** Cache text H extents and W extents for
230    * the text, if the object has any. */
231   int                textw;
232   int                texth;
233 
234   /**
235    * A copy ArrangerObject corresponding to this,
236    * such as when ctrl+dragging.
237    *
238    * This will be the clone object saved in the
239    * cloned arranger selections in each arranger
240    * during actions, and would get drawn separately.
241    */
242   ArrangerObject *   transient;
243 
244   /**
245    * The opposite of the above. This will be set on
246    * the transient objects.
247    */
248   ArrangerObject *   main;
249 
250   /** Whether muted or not (if applicable). */
251   bool               muted;
252 
253   int                magic;
254 
255   /** Parent region identifier for objects that are
256    * part of a region. */
257   RegionIdentifier   region_id;
258 
259   /**
260    * Object's index in the previous lane (before
261    * being moved to a new lane/track).
262    *
263    * Used at runtime when duplicating objects
264    * in new lanes/tracks so we can put the
265    * object back to its place before creating
266    * new copies.
267    *
268    * @seealso arranger_selections_action_do().
269    */
270   int                index_in_prev_lane;
271 
272   /**
273    * Whether deleted with delete tool.
274    *
275    * This is used to simply hide these objects
276    * until the action finishes so that they can
277    * be cloned for the actions.
278    */
279   bool               deleted_temporarily;
280 
281   /** 1 when hovering over the object. */
282   //int                hover;
283 
284   /* ---- The following should only be used for
285    * objects that really need caching, such as
286    * audio regions ---- */
287 
288   /**
289    * Set to true to blit the cached surface, false
290    * to redraw.
291    *
292    * @note This is only used if \ref
293    *   ArrangerObject.can_cache_drawing is true.
294    */
295   bool               use_cache;
296 
297   /**
298    * Cached cairo_t.
299    *
300    * Has 2 elements in case the object needs to
301    * draw more than 1 copy (such as lane/track
302    * regions).
303    *
304    * @note This is only used if \ref
305    *   ArrangerObject.can_cache_drawing is true.
306    */
307   cairo_t *          cached_cr[2];
308 
309   /**
310    * Cached surface containing drawing.
311    *
312    * Has 2 elements in case the object needs to
313    * draw more than 1 copy (such as lane/track
314    * regions).
315    *
316    * @note This is only used if \ref
317    *   ArrangerObject.can_cache_drawing is true.
318    */
319   cairo_surface_t *  cached_surface[2];
320 
321   /** Last drawn name rectangle, if object has a
322    * name. */
323   GdkRectangle       last_name_rect;
324 
325   /**
326    * Whether part of an auditioner track. */
327   bool               is_auditioner;
328 } ArrangerObject;
329 
330 static const cyaml_schema_field_t
331   arranger_object_fields_schema[] =
332 {
333   YAML_FIELD_INT (ArrangerObject, schema_version),
334   YAML_FIELD_ENUM (
335     ArrangerObject, type,
336     arranger_object_type_strings),
337   CYAML_FIELD_BITFIELD (
338     "flags", CYAML_FLAG_DEFAULT,
339     ArrangerObject, flags,
340     arranger_object_flags_bitvals,
341     CYAML_ARRAY_LEN (
342       arranger_object_flags_bitvals)),
343   YAML_FIELD_INT (
344     ArrangerObject, muted),
345   YAML_FIELD_MAPPING_EMBEDDED (
346     ArrangerObject, pos,
347     position_fields_schema),
348   YAML_FIELD_MAPPING_EMBEDDED (
349     ArrangerObject, end_pos,
350     position_fields_schema),
351   YAML_FIELD_MAPPING_EMBEDDED (
352     ArrangerObject, clip_start_pos,
353     position_fields_schema),
354   YAML_FIELD_MAPPING_EMBEDDED (
355     ArrangerObject, loop_start_pos,
356     position_fields_schema),
357   YAML_FIELD_MAPPING_EMBEDDED (
358     ArrangerObject, loop_end_pos,
359     position_fields_schema),
360   YAML_FIELD_MAPPING_EMBEDDED (
361     ArrangerObject, fade_in_pos,
362     position_fields_schema),
363   YAML_FIELD_MAPPING_EMBEDDED (
364     ArrangerObject, fade_out_pos,
365     position_fields_schema),
366   YAML_FIELD_MAPPING_EMBEDDED (
367     ArrangerObject, fade_in_opts,
368     curve_options_fields_schema),
369   YAML_FIELD_MAPPING_EMBEDDED (
370     ArrangerObject, fade_out_opts,
371     curve_options_fields_schema),
372   YAML_FIELD_MAPPING_EMBEDDED (
373     ArrangerObject, region_id,
374     region_identifier_fields_schema),
375 
376   CYAML_FIELD_END
377 };
378 
379 static const cyaml_schema_value_t
380   arranger_object_schema =
381 {
382   CYAML_VALUE_MAPPING (CYAML_FLAG_POINTER,
383     ArrangerObject, arranger_object_fields_schema),
384 };
385 
386 /**
387  * Returns if the object type has a length.
388  */
389 #define arranger_object_type_has_length(type) \
390   (type == ARRANGER_OBJECT_TYPE_REGION || \
391    type == ARRANGER_OBJECT_TYPE_MIDI_NOTE)
392 
393 /**
394  * Returns if the object type has a global position.
395  */
396 #define arranger_object_type_has_global_pos(type) \
397   (type == ARRANGER_OBJECT_TYPE_REGION || \
398    type == ARRANGER_OBJECT_TYPE_SCALE_OBJECT || \
399    type == ARRANGER_OBJECT_TYPE_MARKER)
400 
401 #define arranger_object_type_has_name(type) \
402   (type == ARRANGER_OBJECT_TYPE_REGION \
403    || type == ARRANGER_OBJECT_TYPE_MARKER)
404 
405 /**
406  * Returns if the object is allowed to have lanes.
407  */
408 #define arranger_object_can_have_lanes(_obj) \
409   ((_obj)->type == ARRANGER_OBJECT_TYPE_REGION && \
410     region_type_has_lane ( \
411       ((ZRegion *) _obj)->id.type))
412 
413 /** Returns if the object can loop. */
414 #define arranger_object_type_can_loop(type) \
415   (type == ARRANGER_OBJECT_TYPE_REGION)
416 
417 #define arranger_object_can_fade(_obj) \
418   ((_obj)->type == ARRANGER_OBJECT_TYPE_REGION && \
419     region_type_can_fade ( \
420       ((ZRegion *) _obj)->id.type))
421 
422 #define arranger_object_can_mute(_obj) \
423   ((_obj)->type == ARRANGER_OBJECT_TYPE_REGION || \
424    (_obj)->type == ARRANGER_OBJECT_TYPE_MIDI_NOTE)
425 
426 #define arranger_object_owned_by_region(_obj) \
427   ((_obj)->type == ARRANGER_OBJECT_TYPE_VELOCITY || \
428    (_obj)->type == ARRANGER_OBJECT_TYPE_MIDI_NOTE || \
429    (_obj)->type == ARRANGER_OBJECT_TYPE_CHORD_OBJECT || \
430    (_obj)->type == ARRANGER_OBJECT_TYPE_AUTOMATION_POINT)
431 
432 /** Whether or not this object supports cached
433  * drawing.
434  * FIXME off for now. */
435 #define arranger_object_can_cache_drawing(_obj) \
436   (false)
437 
438 #if 0
439   ((_obj)->type == ARRANGER_OBJECT_TYPE_REGION && \
440     region_type_can_fade ( \
441       ((ZRegion *) _obj)->id.type))
442 #endif
443 
444 /**
445  * Gets the arranger for this arranger object.
446  */
447 ArrangerWidget *
448 arranger_object_get_arranger (
449   ArrangerObject * self);
450 
451 /**
452  * Sets the magic on the arranger object.
453  */
454 void
455 arranger_object_set_magic (
456   ArrangerObject * self);
457 
458 /**
459  * If the object is part of a ZRegion, returns it,
460  * otherwise returns NULL.
461  */
462 HOT
463 ZRegion *
464 arranger_object_get_region (
465   const ArrangerObject * const self);
466 
467 /**
468  * Returns a pointer to the name of the object,
469  * if the object can have names.
470  */
471 const char *
472 arranger_object_get_name (
473   ArrangerObject * self);
474 
475 /**
476  * Generates the escaped name for the object,
477  * where applicable.
478  */
479 void
480 arranger_object_gen_escaped_name (
481   ArrangerObject * self);
482 
483 /**
484  * Sets the dest object's values to the main
485  * src object's values.
486  */
487 void
488 arranger_object_set_to_object (
489   ArrangerObject * dest,
490   ArrangerObject * src);
491 
492 /**
493  * Returns if the cached object should be visible,
494  * ie, while copy- moving (ctrl+drag) we want to
495  * show both the object at its original position
496  * and the current object.
497  *
498  * This refers to the object at its original
499  * position (called "transient").
500  */
501 bool
502 arranger_object_should_orig_be_visible (
503   ArrangerObject * self);
504 
505 /**
506  * Gets the object the ArrangerObjectInfo
507  * represents.
508  */
509 ArrangerObject *
510 arranger_object_get_object (
511   ArrangerObject * self);
512 
513 void
514 arranger_object_init (
515   ArrangerObject * self);
516 
517 /**
518  * Initializes the object after loading a Project.
519  */
520 void
521 arranger_object_init_loaded (
522   ArrangerObject * self);
523 
524 /**
525  * Returns the ArrangerSelections corresponding
526  * to the given object type.
527  */
528 ArrangerSelections *
529 arranger_object_get_selections_for_type (
530   ArrangerObjectType type);
531 
532 /**
533  * Selects the object by adding it to its
534  * corresponding selections or making it the
535  * only selection.
536  *
537  * @param select 1 to select, 0 to deselect.
538  * @param append 1 to append, 0 to make it the only
539  *   selection.
540  */
541 void
542 arranger_object_select (
543   ArrangerObject * self,
544   const bool       select,
545   const bool       append,
546   bool             fire_events);
547 
548 /**
549  * Returns whether the given object is hit by the
550  * given position or range.
551  *
552  * @param start Start position.
553  * @param end End position, or NULL to only check
554  *   for intersection with \ref start.
555  */
556 bool
557 arranger_object_is_hit (
558   ArrangerObject * self,
559   Position *       start,
560   Position *       end);
561 
562 /**
563  * Returns the number of loops in the ArrangerObject,
564  * optionally including incomplete ones.
565  */
566 int
567 arranger_object_get_num_loops (
568   ArrangerObject * self,
569   const int        count_incomplete);
570 
571 /**
572  * Returns if the object is in the selections.
573  */
574 bool
575 arranger_object_is_selected (
576   ArrangerObject * self);
577 
578 /**
579  * Prints debug information about the given
580  * object.
581  */
582 void
583 arranger_object_print (
584   ArrangerObject * self);
585 
586 /**
587  * Gets the mute status of the object.
588  */
589 static inline bool
arranger_object_get_muted(ArrangerObject * self)590 arranger_object_get_muted (
591   ArrangerObject * self)
592 {
593   return self->muted;
594 }
595 
596 /**
597  * Sets the mute status of the object.
598  */
599 void
600 arranger_object_set_muted (
601   ArrangerObject * self,
602   bool             muted,
603   bool             fire_events);
604 
605 /**
606  * Getter.
607  */
608 void
609 arranger_object_get_pos (
610   const ArrangerObject * self,
611   Position *             pos);
612 
613 /**
614  * Getter.
615  */
616 void
617 arranger_object_get_end_pos (
618   const ArrangerObject * self,
619   Position *             pos);
620 
621 /**
622  * Getter.
623  */
624 void
625 arranger_object_get_clip_start_pos (
626   const ArrangerObject * self,
627   Position *             pos);
628 
629 /**
630  * Getter.
631  */
632 void
633 arranger_object_get_loop_start_pos (
634   const ArrangerObject * self,
635   Position *             pos);
636 
637 /**
638  * Getter.
639  */
640 void
641 arranger_object_get_loop_end_pos (
642   const ArrangerObject * self,
643   Position *             pos);
644 
645 /**
646  * The setter is for use in e.g. the digital meters
647  * whereas the set_pos func is used during
648  * arranger actions.
649  */
650 void
651 arranger_object_pos_setter (
652   ArrangerObject * self,
653   const Position * pos);
654 
655 /**
656  * The setter is for use in e.g. the digital meters
657  * whereas the set_pos func is used during
658  * arranger actions.
659  */
660 void
661 arranger_object_end_pos_setter (
662   ArrangerObject * self,
663   const Position * pos);
664 
665 /**
666  * The setter is for use in e.g. the digital meters
667  * whereas the set_pos func is used during
668  * arranger actions.
669  */
670 void
671 arranger_object_clip_start_pos_setter (
672   ArrangerObject * self,
673   const Position * pos);
674 
675 /**
676  * The setter is for use in e.g. the digital meters
677  * whereas the set_pos func is used during
678  * arranger actions.
679  */
680 void
681 arranger_object_loop_start_pos_setter (
682   ArrangerObject * self,
683   const Position * pos);
684 
685 /**
686  * The setter is for use in e.g. the digital meters
687  * whereas the set_pos func is used during
688  * arranger actions.
689  */
690 void
691 arranger_object_loop_end_pos_setter (
692   ArrangerObject * self,
693   const Position * pos);
694 
695 /**
696  * Returns if the given Position is valid.
697  *
698  * @param pos The position to set to.
699  * @param pos_type The type of Position to set in the
700  *   ArrangerObject.
701  */
702 HOT
703 NONNULL
704 WARN_UNUSED_RESULT
705 bool
706 arranger_object_is_position_valid (
707   ArrangerObject *           self,
708   const Position *           pos,
709   ArrangerObjectPositionType pos_type);
710 
711 /**
712  * Sets the Position  all of the object's linked
713  * objects (see ArrangerObjectInfo)
714  *
715  * @param pos The position to set to.
716  * @param pos_type The type of Position to set in the
717  *   ArrangerObject.
718  * @param validate Validate the Position before
719  *   setting it.
720  */
721 void
722 arranger_object_set_position (
723   ArrangerObject *           self,
724   const Position *           pos,
725   ArrangerObjectPositionType pos_type,
726   const int                  validate);
727 
728 /**
729  * Returns the type as a string.
730  */
731 const char *
732 arranger_object_stringize_type (
733   ArrangerObjectType type);
734 
735 /**
736  * Copies the identifier from src to dest.
737  */
738 void
739 arranger_object_copy_identifier (
740   ArrangerObject * dest,
741   ArrangerObject * src);
742 
743 void
744 arranger_object_add_linked_region (
745   ArrangerObject * self,
746   ZRegion *        region);
747 
748 void
749 arranger_object_remove_linked_region (
750   ArrangerObject * self,
751   ZRegion *        region);
752 
753 /**
754  * Moves the object by the given amount of
755  * ticks.
756  */
757 void
758 arranger_object_move (
759   ArrangerObject * self,
760   const double     ticks);
761 
762 /**
763  * Returns the length of the ArrangerObject (if
764  * it has length) in ticks.
765  *
766  * (End Position - start Position).
767  */
768 NONNULL
769 WARN_UNUSED_RESULT
770 static inline double
arranger_object_get_length_in_ticks(const ArrangerObject * const self)771 arranger_object_get_length_in_ticks (
772   const ArrangerObject * const self)
773 {
774   g_return_val_if_fail (
775     arranger_object_type_has_length (self->type),
776     0);
777 
778   return self->end_pos.ticks - self->pos.ticks;
779 }
780 
781 /**
782  * Returns the length of the ArrangerObject (if
783  * it has length) in frames.
784  *
785  * (End Position - start Position).
786  */
787 NONNULL
788 WARN_UNUSED_RESULT
789 static inline long
arranger_object_get_length_in_frames(const ArrangerObject * const self)790 arranger_object_get_length_in_frames (
791   const ArrangerObject * const self)
792 {
793   g_return_val_if_fail (
794     arranger_object_type_has_length (self->type),
795     0);
796 
797   return self->end_pos.frames - self->pos.frames;
798 }
799 
800 /**
801  * Returns the length of the loop in ticks.
802  */
803 NONNULL
804 static inline double
arranger_object_get_loop_length_in_ticks(const ArrangerObject * const self)805 arranger_object_get_loop_length_in_ticks (
806   const ArrangerObject * const self)
807 {
808   g_return_val_if_fail (
809     arranger_object_type_has_length (self->type),
810     0);
811 
812   return
813     self->loop_end_pos.ticks -
814     self->loop_start_pos.ticks;
815 }
816 
817 /**
818  * Returns the length of the loop in frames.
819  */
820 NONNULL
821 HOT
822 static inline long
arranger_object_get_loop_length_in_frames(const ArrangerObject * const self)823 arranger_object_get_loop_length_in_frames (
824   const ArrangerObject * const self)
825 {
826   g_return_val_if_fail (
827     arranger_object_type_has_length (self->type),
828     0);
829 
830   return
831     self->loop_end_pos.frames -
832     self->loop_start_pos.frames;
833 }
834 
835 /**
836  * Updates the positions in each child recursively.
837  *
838  * @param from_ticks Whether to update the
839  *   positions based on ticks (true) or frames
840  *   (false).
841  */
842 void
843 arranger_object_update_positions (
844   ArrangerObject * self,
845   bool             from_ticks);
846 
847 /**
848  * Frees only this object.
849  */
850 void
851 arranger_object_free (
852   ArrangerObject * self);
853 
854 /**
855  * Resizes the object on the left side or right
856  * side by given amount of ticks, for objects that
857  * do not have loops (currently none? keep it as
858  * reference).
859  *
860  * @param left 1 to resize left side, 0 to resize
861  *   right side.
862  * @param ticks Number of ticks to resize.
863  * @param during_ui_action Whether this is called
864  *   during a UI action (not at the end).
865  */
866 void
867 arranger_object_resize (
868   ArrangerObject *         self,
869   const bool               left,
870   ArrangerObjectResizeType type,
871   const double             ticks,
872   bool                     during_ui_action);
873 
874 void
875 arranger_object_append_children (
876   ArrangerObject * self,
877   GPtrArray *      children);
878 
879 /**
880  * Adds the given ticks to each included object.
881  */
882 void
883 arranger_object_add_ticks_to_children (
884   ArrangerObject * self,
885   const double     ticks);
886 
887 /**
888  * Not to be used anywhere besides below.
889  */
890 #define _ARRANGER_OBJECT_FREE_AND_SET_STRING( \
891   _obj,_val_name,_val_value) \
892   g_free_and_null (_obj->_val_name); \
893   _obj->_val_name = g_strdup (_val_value)
894 
895 /**
896  * Updates an arranger object's string value.
897  *
898  * @param cc CamelCase (eg, Region).
899  * @param obj The object.
900  * @param val_name The struct member name to set
901  *   the primitive value to.
902  * @param val_value The value to store.
903  */
904 #define arranger_object_set_string( \
905   cc,obj,val_name,val_value) \
906   { \
907     cc * _obj = (cc *) obj; \
908     _ARRANGER_OBJECT_FREE_AND_SET_STRING( \
909       _obj,val_name,val_value); \
910   }
911 
912 /**
913  * Returns the Track this ArrangerObject is in.
914  */
915 HOT
916 Track *
917 arranger_object_get_track (
918   const ArrangerObject * const self);
919 
920 static inline const char *
arranger_object_get_type_as_string(ArrangerObjectType type)921 arranger_object_get_type_as_string (
922   ArrangerObjectType type)
923 {
924   return arranger_object_type_strings[type].str;
925 }
926 
927 void
928 arranger_object_post_deserialize (
929   ArrangerObject * self);
930 
931 /**
932  * Validates the given Position.
933  *
934  * @return 1 if valid, 0 otherwise.
935  */
936 int
937 arranger_object_validate_pos (
938   const ArrangerObject * const self,
939   const Position *             pos,
940   ArrangerObjectPositionType   type);
941 
942 /**
943  * Validates the arranger object.
944  *
945  * @return True if valid.
946  */
947 bool
948 arranger_object_validate (
949   const ArrangerObject * const self);
950 
951 /**
952  * Validates the given name.
953  *
954  * @return True if valid, false otherwise.
955  */
956 bool
957 arranger_object_validate_name (
958   ArrangerObject * self,
959   const char *     name);
960 
961 /**
962  * Returns the ArrangerObject matching the
963  * given one.
964  *
965  * This should be called when we have a copy or a
966  * clone, to get the actual region in the project.
967  */
968 ArrangerObject *
969 arranger_object_find (
970   ArrangerObject * obj);
971 
972 /**
973  * Clones the ArrangerObject.
974  */
975 ArrangerObject *
976 arranger_object_clone (
977   ArrangerObject * self);
978 
979 /**
980  * Splits the given object at the given Position.
981  *
982  * if \ref is_project is true, it
983  * deletes the original object and adds 2 new
984  * objects in the same parent (Track or
985  * AutomationTrack or Region).
986  *
987  * @param region The ArrangerObject to split. This
988  *   ArrangerObject will be deleted.
989  * @param pos The Position to split at.
990  * @param pos_is_local If the position is local (1)
991  *   or global (0).
992  * @param r1 Address to hold the pointer to the
993  *   newly created ArrangerObject 1.
994  * @param r2 Address to hold the pointer to the
995  *   newly created ArrangerObject 2.
996  * @param is_project Whether the object being
997  *   passed is a project object. If true, it will
998  *   be removed from the project and the child
999  *   objects will be added to the project,
1000  *   otherwise it will be untouched and the
1001  *   children will be mere clones.
1002  */
1003 void
1004 arranger_object_split (
1005   ArrangerObject *  self,
1006   const Position *  pos,
1007   const bool        pos_is_local,
1008   ArrangerObject ** r1,
1009   ArrangerObject ** r2,
1010   bool              is_project);
1011 
1012 
1013 /**
1014  * Undoes what arranger_object_split() did.
1015  */
1016 void
1017 arranger_object_unsplit (
1018   ArrangerObject *  r1,
1019   ArrangerObject *  r2,
1020   ArrangerObject ** obj,
1021   bool              fire_events);
1022 
1023 /**
1024  * Sets the name of the object, if the object can
1025  * have a name.
1026  */
1027 void
1028 arranger_object_set_name (
1029   ArrangerObject * self,
1030   const char *     name,
1031   int              fire_events);
1032 
1033 /**
1034  * Changes the name and adds an action to the
1035  * undo stack.
1036  *
1037  * Calls arranger_object_set_name() internally.
1038  */
1039 void
1040 arranger_object_set_name_with_action (
1041   ArrangerObject * self,
1042   const char *     name);
1043 
1044 /**
1045  * Sets the end position of the ArrangerObject and
1046  * also sets the loop end and fade out so that
1047  * they are at the end.
1048  */
1049 void
1050 arranger_object_set_start_pos_full_size (
1051   ArrangerObject * obj,
1052   Position *       pos);
1053 
1054 /**
1055  * Sets the end position of the ArrangerObject and
1056  * also sets the loop end and fade out to that
1057  * position.
1058  */
1059 void
1060 arranger_object_set_end_pos_full_size (
1061   ArrangerObject * obj,
1062   Position *       pos);
1063 
1064 /**
1065  * Appends the ArrangerObject to where it belongs
1066  * in the project (eg, a Track), without taking
1067  * into account its previous index (eg, before
1068  * deletion if undoing).
1069  */
1070 void
1071 arranger_object_add_to_project (
1072   ArrangerObject * obj,
1073   bool             fire_events);
1074 
1075 /**
1076  * Inserts the ArrangerObject where it belongs in
1077  * the project (eg, a Track).
1078  *
1079  * This function assumes that the object already
1080  * knows the index where it should be inserted
1081  * in its parent.
1082  *
1083  * This is mostly used when undoing.
1084  */
1085 void
1086 arranger_object_insert_to_project (
1087   ArrangerObject * obj);
1088 
1089 /**
1090  * Removes the object from its parent in the
1091  * project.
1092  */
1093 void
1094 arranger_object_remove_from_project (
1095   ArrangerObject * obj);
1096 
1097 /**
1098  * Returns whether the arranger object is part of
1099  * a frozen track.
1100  */
1101 bool
1102 arranger_object_is_frozen (
1103   ArrangerObject * obj);
1104 
1105 /**
1106  * Returns whether the given object is deletable
1107  * or not (eg, start marker).
1108  */
1109 bool
1110 arranger_object_is_deletable (
1111   ArrangerObject * obj);
1112 
1113 /**
1114  * Removes the child from the given object.
1115  */
1116 void
1117 arranger_object_remove_child (
1118   ArrangerObject * self,
1119   ArrangerObject * child);
1120 
1121 /**
1122  * @}
1123  */
1124 
1125 #endif
1126