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