Zrythm
a highly automated and intuitive digital audio workstation
Loading...
Searching...
No Matches
arranger_object.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: © 2019-2022 Alexandros Theodotou <alex@zrythm.org>
2// SPDX-License-Identifier: LicenseRef-ZrythmLicense
3
10#ifndef __GUI_BACKEND_ARRANGER_OBJECT_H__
11#define __GUI_BACKEND_ARRANGER_OBJECT_H__
12
13#include "dsp/curve.h"
14#include "dsp/position.h"
16#include "utils/yaml.h"
17
18#include <glib/gi18n.h>
19
20typedef struct ArrangerObject ArrangerObject;
22typedef struct _ArrangerWidget ArrangerWidget;
23typedef struct _ArrangerObjectWidget ArrangerObjectWidget;
24typedef struct UndoableAction UndoableAction;
26
33#define ARRANGER_OBJECT_MAGIC 347616554
34#define IS_ARRANGER_OBJECT(tr) \
35 (((ArrangerObject *) tr)->magic == ARRANGER_OBJECT_MAGIC \
36 && ((ArrangerObject *) tr)->type \
37 >= ArrangerObjectType::ARRANGER_OBJECT_TYPE_REGION \
38 && ((ArrangerObject *) tr)->type \
39 <= ArrangerObjectType::ARRANGER_OBJECT_TYPE_VELOCITY)
40#define IS_ARRANGER_OBJECT_AND_NONNULL(x) (x && IS_ARRANGER_OBJECT (x))
41
46{
47 ARRANGER_OBJECT_RESIZE_NORMAL,
48 ARRANGER_OBJECT_RESIZE_LOOP,
49 ARRANGER_OBJECT_RESIZE_FADE,
50 ARRANGER_OBJECT_RESIZE_STRETCH,
51
59};
60
65{
66 /* These two are not actual object types. */
67 ARRANGER_OBJECT_TYPE_NONE,
68 ARRANGER_OBJECT_TYPE_ALL,
69
70 ARRANGER_OBJECT_TYPE_REGION,
71 ARRANGER_OBJECT_TYPE_MIDI_NOTE,
72 ARRANGER_OBJECT_TYPE_CHORD_OBJECT,
73 ARRANGER_OBJECT_TYPE_SCALE_OBJECT,
74 ARRANGER_OBJECT_TYPE_MARKER,
75 ARRANGER_OBJECT_TYPE_AUTOMATION_POINT,
76 ARRANGER_OBJECT_TYPE_VELOCITY,
77};
78
79static const char * arranger_object_type_strings[] = {
80 N_ ("None"), N_ ("All"),
81 N_ ("Region"), N_ ("Midi Note"),
82 N_ ("Chord Object"), N_ ("Scale Object"),
83 N_ ("Marker"), N_ ("Automation Point"),
84 N_ ("Velocity"),
85};
86
91{
95
97 // ARRANGER_OBJECT_FLAG_SNAPSHOT = 1 << 1,
98};
99
100enum class ArrangerObjectPositionType
101{
102 ARRANGER_OBJECT_POSITION_TYPE_START,
103 ARRANGER_OBJECT_POSITION_TYPE_END,
104 ARRANGER_OBJECT_POSITION_TYPE_CLIP_START,
105 ARRANGER_OBJECT_POSITION_TYPE_LOOP_START,
106 ARRANGER_OBJECT_POSITION_TYPE_LOOP_END,
107 ARRANGER_OBJECT_POSITION_TYPE_FADE_IN,
108 ARRANGER_OBJECT_POSITION_TYPE_FADE_OUT,
109};
110
114typedef struct ArrangerObject
115{
117
120
130
138
148
152
161
168
175
178
181
185 GdkRectangle full_rect;
186
189 int textw;
190 int texth;
191
199
205
207 bool muted;
208
209 int magic;
210
213
224
232
233 /* --- The following should only be used for objects that really need caching,
234 * such as audio regions --- */
235
246 cairo_t * cached_cr[2];
247
258 cairo_surface_t * cached_surface[2];
259
261 GdkRectangle last_name_rect;
262
267
271#define arranger_object_type_has_length(type) \
272 (type == ArrangerObjectType::ARRANGER_OBJECT_TYPE_REGION \
273 || type == ArrangerObjectType::ARRANGER_OBJECT_TYPE_MIDI_NOTE)
274
278#define arranger_object_type_has_global_pos(type) \
279 (type == ArrangerObjectType::ARRANGER_OBJECT_TYPE_REGION \
280 || type == ArrangerObjectType::ARRANGER_OBJECT_TYPE_SCALE_OBJECT \
281 || type == ArrangerObjectType::ARRANGER_OBJECT_TYPE_MARKER)
282
283#define arranger_object_type_has_name(type) \
284 (type == ArrangerObjectType::ARRANGER_OBJECT_TYPE_REGION \
285 || type == ArrangerObjectType::ARRANGER_OBJECT_TYPE_MARKER)
286
290#define arranger_object_can_have_lanes(_obj) \
291 ((_obj)->type == ArrangerObjectType::ARRANGER_OBJECT_TYPE_REGION \
292 && region_type_has_lane (((Region *) _obj)->id.type))
293
295#define arranger_object_type_can_loop(type) \
296 (type == ArrangerObjectType::ARRANGER_OBJECT_TYPE_REGION)
297
298#define arranger_object_can_fade(_obj) \
299 ((_obj)->type == ArrangerObjectType::ARRANGER_OBJECT_TYPE_REGION \
300 && region_type_can_fade (((Region *) _obj)->id.type))
301
302#define arranger_object_can_mute(_obj) \
303 ((_obj)->type == ArrangerObjectType::ARRANGER_OBJECT_TYPE_REGION \
304 || (_obj)->type == ArrangerObjectType::ARRANGER_OBJECT_TYPE_MIDI_NOTE)
305
306#define arranger_object_owned_by_region(_obj) \
307 ((_obj)->type == ArrangerObjectType::ARRANGER_OBJECT_TYPE_VELOCITY \
308 || (_obj)->type == ArrangerObjectType::ARRANGER_OBJECT_TYPE_MIDI_NOTE \
309 || (_obj)->type == ArrangerObjectType::ARRANGER_OBJECT_TYPE_CHORD_OBJECT \
310 || (_obj)->type == ArrangerObjectType::ARRANGER_OBJECT_TYPE_AUTOMATION_POINT)
311
315#define arranger_object_can_cache_drawing(_obj) (false)
316
317#if 0
318 ((_obj)->type == ArrangerObjectType::ARRANGER_OBJECT_TYPE_REGION && \
320 ((Region *) _obj)->id.type))
321#endif
322
328
332void
334
339HOT Region *
341
346const char *
348
357char *
359
364void
366
371void
373
380
381void
382arranger_object_init (ArrangerObject * self);
383
387void
389
396
404void
406 ArrangerObject * self,
407 const bool select,
408 const bool append,
409 bool fire_events);
410
419NONNULL_ARGS (1)
420WARN_UNUSED_RESULT bool arranger_object_is_hit (
421 const ArrangerObject * self,
422 const Position * start,
423 const Position * end);
424
429int
430arranger_object_get_num_loops (ArrangerObject * self, const int count_incomplete);
431
435bool
437
442NONNULL void
444
455NONNULL bool
456arranger_object_get_muted (ArrangerObject * self, bool check_parent);
457
461void
462arranger_object_set_muted (ArrangerObject * self, bool muted, bool fire_events);
463
467void
469
473void
475
479void
481
485void
487
491void
493
497void
499
503void
505
506void
507arranger_object_get_position_from_type (
508 const ArrangerObject * self,
509 Position * pos,
510 ArrangerObjectPositionType type);
511
517void
519
525void
527 const ArrangerObject * self,
529
530void
531arranger_object_edit_position_finish (const ArrangerObject * self);
532
539void
541
546void
548
553void
555 ArrangerObject * self,
556 const Position * pos);
557
562void
564 ArrangerObject * self,
565 const Position * pos);
566
571void
573
580HOT NONNULL WARN_UNUSED_RESULT bool
582 const ArrangerObject * const self,
583 const Position * pos,
584 ArrangerObjectPositionType pos_type);
585
586#define arranger_object_validate_pos arranger_object_is_position_valid
587
599bool
601 ArrangerObject * self,
602 const Position * pos,
603 ArrangerObjectPositionType pos_type,
604 const bool validate);
605
609void
611
612void
613arranger_object_add_linked_region (ArrangerObject * self, Region * region);
614
615void
616arranger_object_remove_linked_region (ArrangerObject * self, Region * region);
617
623void
624arranger_object_move (ArrangerObject * self, const double ticks);
625
631NONNULL WARN_UNUSED_RESULT static inline double
632arranger_object_get_length_in_ticks (const ArrangerObject * const self)
633{
634 g_return_val_if_fail (arranger_object_type_has_length (self->type), 0);
635
636 return self->end_pos.ticks - self->pos.ticks;
637}
638
645NONNULL WARN_UNUSED_RESULT static inline signed_frame_t
646arranger_object_get_length_in_frames (const ArrangerObject * const self)
647{
648 g_return_val_if_fail (arranger_object_type_has_length (self->type), 0);
649
650 return self->end_pos.frames - self->pos.frames;
651}
652
656NONNULL static inline double
657arranger_object_get_loop_length_in_ticks (const ArrangerObject * const self)
658{
659 g_return_val_if_fail (arranger_object_type_has_length (self->type), 0);
660
661 return self->loop_end_pos.ticks - self->loop_start_pos.ticks;
662}
663
667NONNULL HOT static inline signed_frame_t
668arranger_object_get_loop_length_in_frames (const ArrangerObject * const self)
669{
670 g_return_val_if_fail (arranger_object_type_has_length (self->type), 0);
671
672 return self->loop_end_pos.frames - self->loop_start_pos.frames;
673}
674
683void
685 ArrangerObject * self,
686 bool from_ticks,
687 bool bpm_change,
688 UndoableAction * action);
689
693void
695
707WARN_UNUSED_RESULT bool
709 ArrangerObject * self,
710 const bool left,
712 const double ticks,
713 bool during_ui_action,
714 GError ** error);
715
716void
717arranger_object_append_children (ArrangerObject * self, GPtrArray * children);
718
722void
724
728#define _ARRANGER_OBJECT_FREE_AND_SET_STRING(_obj, _val_name, _val_value) \
729 g_free_and_null (_obj->_val_name); \
730 _obj->_val_name = g_strdup (_val_value)
731
740#define arranger_object_set_string(cc, obj, val_name, val_value) \
741 { \
742 cc * _obj = (cc *) obj; \
743 _ARRANGER_OBJECT_FREE_AND_SET_STRING (_obj, val_name, val_value); \
744 }
745
749HOT NONNULL Track *
751
752static inline const char *
753arranger_object_get_type_as_string (ArrangerObjectType type)
754{
755 return arranger_object_type_strings[static_cast<int> (type)];
756}
757
758void
759arranger_object_post_deserialize (ArrangerObject * self);
760
768bool
770
776bool
778
787
793
815WARN_UNUSED_RESULT bool
817 ArrangerObject * self,
818 const Position * pos,
819 const bool pos_is_local,
820 ArrangerObject ** r1,
821 ArrangerObject ** r2,
822 bool is_project,
823 GError ** error);
824
830WARN_UNUSED_RESULT NONNULL_ARGS (1, 2) bool arranger_object_unsplit (
831 ArrangerObject * r1,
832 ArrangerObject * r2,
833 ArrangerObject ** obj,
834 bool fire_events,
835 GError ** error);
836
842void
843arranger_object_set_name (
844 ArrangerObject * self,
845 const char * name,
846 int fire_events);
847
854void
856
861void
863
868void
870
878WARN_UNUSED_RESULT NONNULL_ARGS (1) bool arranger_object_add_to_project (
879 ArrangerObject * obj,
880 bool fire_events,
881 GError ** error);
882
894WARN_UNUSED_RESULT bool
896
902void
904
909bool
911
916bool
918
919bool
920arranger_object_is_renamable (const ArrangerObject * obj);
921
925void
927
932#endif
Curves.
ArrangerSelectionsActionEditType
Type used when the action is an EDIT action.
#define region_type_can_fade(rtype)
Returns if the given Region type can have fades.
Definition region.h:281
void arranger_object_set_start_pos_full_size(ArrangerObject *obj, Position *pos)
Sets the end position of the ArrangerObject and also sets the loop end and fade out so that they are ...
ArrangerObject * arranger_object_clone(const ArrangerObject *self)
Clones the ArrangerObject.
void arranger_object_loop_end_pos_setter(ArrangerObject *self, const Position *pos)
The setter is for use in e.g.
void arranger_object_get_end_pos(const ArrangerObject *self, Position *pos)
Getter.
void arranger_object_pos_setter(ArrangerObject *self, const Position *pos)
The setter is for use in e.g.
void arranger_object_free(ArrangerObject *self)
Frees only this object.
void arranger_object_select(ArrangerObject *self, const bool select, const bool append, bool fire_events)
Selects the object by adding it to its corresponding selections or making it the only selection.
HOT NONNULL WARN_UNUSED_RESULT bool arranger_object_is_position_valid(const ArrangerObject *const self, const Position *pos, ArrangerObjectPositionType pos_type)
Returns if the given Position is valid.
WARN_UNUSED_RESULT bool arranger_object_insert_to_project(ArrangerObject *obj, GError **error)
Inserts the ArrangerObject where it belongs in the project (eg, a Track).
bool arranger_object_is_deletable(const ArrangerObject *obj)
Returns whether the given object is deletable or not (eg, start marker).
void arranger_object_set_to_object(ArrangerObject *dest, ArrangerObject *src)
Sets the dest object's values to the main src object's values.
void arranger_object_get_clip_start_pos(const ArrangerObject *self, Position *pos)
Getter.
ArrangerObject * arranger_object_get_object(ArrangerObject *self)
Gets the object the ArrangerObjectInfo represents.
WARN_UNUSED_RESULT bool arranger_object_is_hit(const ArrangerObject *self, const Position *start, const Position *end)
Returns whether the given object is hit by the given position or range.
void arranger_object_remove_child(ArrangerObject *self, ArrangerObject *child)
Removes the child from the given object.
void arranger_object_set_name_with_action(ArrangerObject *self, const char *name)
Changes the name and adds an action to the undo stack.
void arranger_object_edit_finish(const ArrangerObject *self, ArrangerSelectionsActionEditType type)
Callback when finishing editing the object.
void arranger_object_get_pos(const ArrangerObject *self, Position *pos)
Getter.
WARN_UNUSED_RESULT bool arranger_object_split(ArrangerObject *self, const Position *pos, const bool pos_is_local, ArrangerObject **r1, ArrangerObject **r2, bool is_project, GError **error)
Splits the given object at the given Position.
void arranger_object_get_fade_in_pos(const ArrangerObject *self, Position *pos)
Getter.
ArrangerSelections * arranger_object_get_selections_for_type(ArrangerObjectType type)
Returns the ArrangerSelections corresponding to the given object type.
NONNULL void arranger_object_print(const ArrangerObject *self)
Prints debug information about the given object.
void arranger_object_move(ArrangerObject *self, const double ticks)
Moves the object by the given amount of ticks.
void arranger_object_get_fade_out_pos(const ArrangerObject *self, Position *pos)
Getter.
void arranger_object_set_magic(ArrangerObject *self)
Sets the magic on the arranger object.
char * arranger_object_gen_human_readable_name(const ArrangerObject *self)
Generates a human readable name for the object.
void arranger_object_get_loop_start_pos(const ArrangerObject *self, Position *pos)
Getter.
void arranger_object_update_positions(ArrangerObject *self, bool from_ticks, bool bpm_change, UndoableAction *action)
Updates the positions in each child recursively.
void arranger_object_add_ticks_to_children(ArrangerObject *self, const double ticks)
Adds the given ticks to each included object.
void arranger_object_edit_begin(const ArrangerObject *self)
Callback when beginning to edit the object.
ArrangerObjectFlags
ArrangerObject flags.
void arranger_object_set_muted(ArrangerObject *self, bool muted, bool fire_events)
Sets the mute status of the object.
bool arranger_object_validate_name(ArrangerObject *self, const char *name)
Validates the given name.
void arranger_object_get_loop_end_pos(const ArrangerObject *self, Position *pos)
Getter.
#define arranger_object_type_has_length(type)
Returns if the object type has a length.
void arranger_object_set_end_pos_full_size(ArrangerObject *obj, Position *pos)
Sets the end position of the ArrangerObject and also sets the loop end and fade out to that position.
HOT Region * arranger_object_get_region(const ArrangerObject *const self)
If the object is part of a Region, returns it, otherwise returns NULL.
bool arranger_object_is_selected(ArrangerObject *self)
Returns if the object is in the selections.
void arranger_object_init_loaded(ArrangerObject *self)
Initializes the object after loading a Project.
bool arranger_object_set_position(ArrangerObject *self, const Position *pos, ArrangerObjectPositionType pos_type, const bool validate)
Sets the given position on the object, optionally attempting to validate before.
void arranger_object_clip_start_pos_setter(ArrangerObject *self, const Position *pos)
The setter is for use in e.g.
void arranger_object_remove_from_project(ArrangerObject *obj)
Removes the object from its parent in the project.
ArrangerObjectType
The type of the object.
const char * arranger_object_get_name(const ArrangerObject *self)
Returns a pointer to the name of the object, if the object can have names.
ArrangerObjectResizeType
Flag used in some functions.
NONNULL bool arranger_object_get_muted(ArrangerObject *self, bool check_parent)
Gets the mute status of the object.
void arranger_object_copy_identifier(ArrangerObject *dest, ArrangerObject *src)
Copies the identifier from src to dest.
void arranger_object_loop_start_pos_setter(ArrangerObject *self, const Position *pos)
The setter is for use in e.g.
bool arranger_object_validate(const ArrangerObject *const self)
Validates the arranger object.
bool arranger_object_is_frozen(ArrangerObject *obj)
Returns whether the arranger object is part of a frozen track.
void arranger_object_gen_escaped_name(const ArrangerObject *self)
Generates the escaped name for the object, where applicable.
WARN_UNUSED_RESULT NONNULL_ARGS(1, 2) bool arranger_object_unsplit(ArrangerObject *r1
Undoes what arranger_object_split() did.
ArrangerObject * arranger_object_find(ArrangerObject *obj)
Returns the ArrangerObject matching the given one.
WARN_UNUSED_RESULT bool arranger_object_resize(ArrangerObject *self, const bool left, ArrangerObjectResizeType type, const double ticks, bool during_ui_action, GError **error)
Resizes the object on the left side or right side by given amount of ticks, for objects that do not h...
HOT NONNULL Track * arranger_object_get_track(const ArrangerObject *const self)
Returns the Track this ArrangerObject is in.
int arranger_object_get_num_loops(ArrangerObject *self, const int count_incomplete)
Returns the number of loops in the ArrangerObject, optionally including incomplete ones.
void arranger_object_end_pos_setter(ArrangerObject *self, const Position *pos)
The setter is for use in e.g.
ArrangerWidget * arranger_object_get_arranger(const ArrangerObject *self)
Gets the arranger for this arranger object.
@ ARRANGER_OBJECT_FLAG_NON_PROJECT
This object is not a project object, but an object used temporarily eg.
@ ARRANGER_OBJECT_RESIZE_STRETCH_BPM_CHANGE
Used when we want to resize to contents when BPM changes.
int_fast64_t signed_frame_t
Signed type for frame index.
Definition types.h:59
Position struct and API.
Region identifier.
Base struct for arranger objects.
ArrangerObjectFlags flags
Flags.
Position fade_in_pos
Fade in position, relative to the object's start.
bool deleted_temporarily
Whether deleted with delete tool.
RegionIdentifier region_id
Parent region identifier for objects that are part of a region.
bool muted
Whether muted or not (if applicable).
Position loop_start_pos
Loop start Position, if the object has one, relative to the object's start.
Position fade_out_pos
Fade out position, relative to the object's start.
int textw
Cache text H extents and W extents for the text, if the object has any.
ArrangerObject * transient
A copy ArrangerObject corresponding to this, such as when ctrl+dragging.
Position clip_start_pos
Start position of the clip loop, relative to the object's start.
GdkRectangle last_name_rect
Last drawn name rectangle, if object has a name.
bool is_auditioner
Whether part of an auditioner track.
cairo_surface_t * cached_surface[2]
Cached surface containing drawing.
Position end_pos
End Position, if the object has one.
Position loop_end_pos
End position of the clip loop, relative to the object's start.
CurveOptions fade_out_opts
Fade out curve options.
ArrangerObject * main
The opposite of the above.
GdkRectangle full_rect
The full rectangle this object covers including off-screen parts, in absolute coordinates.
CurveOptions fade_in_opts
Fade in curve options.
Position pos
Position (or start Position if the object has length).
cairo_t * cached_cr[2]
Cached cairo_t.
int index_in_prev_lane
Object's index in the previous lane (before being moved to a new lane/track).
The arranger widget is a canvas that draws all the arranger objects it contains.
Definition arranger.h:108
Curve options.
Definition curve.h:105
A Position is made up of bars.beats.sixteenths.ticks.
Definition position.h:124
double ticks
Precise total number of ticks.
Definition position.h:126
signed_frame_t frames
Position in frames (samples).
Definition position.h:133
Index/identifier for a Region, so we can get Region objects quickly with it without searching by name...
A region (clip) is an object on the timeline that contains either MidiNote's or AudioClip's.
Definition region.h:72
Track to be inserted into the Project's Tracklist.
Definition track.h:177
Base struct to be inherited by implementing undoable actions.
YAML utils.