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 Zrythm.  If not, see <https://www.gnu.org/licenses/>.
18  */
19 
20 /**
21  * \file
22  *
23  * A region in the timeline.
24  */
25 #ifndef __AUDIO_REGION_H__
26 #define __AUDIO_REGION_H__
27 
28 #include "audio/automation_point.h"
29 #include "audio/chord_object.h"
30 #include "audio/midi_note.h"
31 #include "audio/midi_region.h"
32 #include "audio/position.h"
33 #include "audio/region_identifier.h"
34 #include "gui/backend/arranger_object.h"
35 #include "utils/yaml.h"
36 
37 #include <gtk/gtk.h>
38 
39 typedef struct _RegionWidget RegionWidget;
40 typedef struct Channel Channel;
41 typedef struct Track Track;
42 typedef struct MidiNote MidiNote;
43 typedef struct TrackLane TrackLane;
44 typedef struct _AudioClipWidget AudioClipWidget;
45 typedef struct RegionLinkGroup RegionLinkGroup;
46 typedef struct Stretcher Stretcher;
47 typedef struct AudioClip AudioClip;
48 
49 /**
50  * @addtogroup audio
51  *
52  * @{
53  */
54 
55 #define REGION_SCHEMA_VERSION 1
56 
57 #define REGION_MAGIC 93075327
58 #define IS_REGION(x) \
59   (((ZRegion *) x)->magic == REGION_MAGIC)
60 #define IS_REGION_AND_NONNULL(x) \
61   (x && IS_REGION (x))
62 
63 #define REGION_PRINTF_FILENAME "%s_%s.mid"
64 
65 #define region_is_selected(r) \
66   arranger_object_is_selected ( \
67     (ArrangerObject *) r)
68 
69 /**
70  * Musical mode setting for audio regions.
71  */
72 typedef enum RegionMusicalMode
73 {
74   /** Inherit from global musical mode setting. */
75   REGION_MUSICAL_MODE_INHERIT,
76   /** Musical mode off - don't auto-stretch when
77    * BPM changes. */
78   REGION_MUSICAL_MODE_OFF,
79   /** Musical mode on - auto-stretch when BPM
80    * changes. */
81   REGION_MUSICAL_MODE_ON,
82 } RegionMusicalMode;
83 
84 static const cyaml_strval_t
85 region_musical_mode_strings[] =
86 {
87   { __("Inherit"),
88     REGION_MUSICAL_MODE_INHERIT },
89   { __("Off"),
90     REGION_MUSICAL_MODE_OFF },
91   { __("On"),
92     REGION_MUSICAL_MODE_ON },
93 };
94 
95 /**
96  * A region (clip) is an object on the timeline that
97  * contains either MidiNote's or AudioClip's.
98  *
99  * It is uniquely identified using its name, so it
100  * must be unique throughout the Project.
101  */
102 typedef struct ZRegion
103 {
104   /** Base struct. */
105   ArrangerObject base;
106 
107   int            schema_version;
108 
109   /** Unique ID. */
110   RegionIdentifier id;
111 
112   /** Name to be shown on the widget. */
113   char *          name;
114 
115   /** Escaped name for drawing. */
116   char *          escaped_name;
117 
118   /**
119    * TODO region color independent of track.
120    *
121    * If null, the track color is used.
122    */
123   GdkRGBA         color;
124 
125   /* ==== MIDI REGION ==== */
126 
127   /** MIDI notes. */
128   MidiNote **     midi_notes;
129   int             num_midi_notes;
130   size_t          midi_notes_size;
131 
132   /**
133    * Unended notes started in recording with
134    * MIDI NOTE ON
135    * signal but haven't received a NOTE OFF yet.
136    *
137    * This is also used temporarily when reading
138    * from MIDI files.
139    *
140    * FIXME allocate.
141    *
142    * @note These are present in
143    *   \ref ZRegion.midi_notes and must not be
144    *   free'd separately.
145    */
146   MidiNote *      unended_notes[12000];
147   int             num_unended_notes;
148 
149   /* ==== MIDI REGION END ==== */
150 
151   /* ==== AUDIO REGION ==== */
152 
153   /** Audio pool ID of the associated audio file,
154    * mostly used during serialization. */
155   int               pool_id;
156 
157   /**
158    * Whether currently running the stretching
159    * algorithm.
160    *
161    * If this is true, region drawing will be
162    * deferred.
163    */
164   bool              stretching;
165 
166   /**
167    * The length before stretching, in ticks.
168    */
169   double            before_length;
170 
171   /** Used during arranger UI overlay actions. */
172   double            stretch_ratio;
173 
174   /**
175    * Whether to read the clip from the pool (used
176    * in most cases).
177    */
178   bool              read_from_pool;
179 
180   /** Gain to apply to the audio (amplitude
181    * 0.0-2.0). */
182   float             gain;
183 
184   /**
185    * Clip to read frames from, if not from the pool.
186    */
187   AudioClip *       clip;
188 
189 #if 0
190   /**
191    * Frames to actually use, interleaved.
192    *
193    * Properties such as \ref AudioClip.channels can
194    * be fetched from the AudioClip.
195    */
196   sample_t *        frames;
197   size_t            num_frames;
198 
199   /**
200    * Per-channel frames for convenience.
201    */
202   sample_t *        ch_frames[16];
203 #endif
204 
205   /** Musical mode setting. */
206   RegionMusicalMode musical_mode;
207 
208   /** Array of split points. */
209   Position *        split_points;
210   int               num_split_points;
211   size_t            split_points_size;
212 
213   /* ==== AUDIO REGION END ==== */
214 
215   /* ==== AUTOMATION REGION ==== */
216 
217   /**
218    * The automation points this region contains.
219    *
220    * Could also be used in audio regions for volume
221    * automation.
222    *
223    * Must always stay sorted by position.
224    */
225   AutomationPoint ** aps;
226   int                num_aps;
227   size_t             aps_size;
228 
229   /** Last recorded automation point. */
230   AutomationPoint *  last_recorded_ap;
231 
232   /* ==== AUTOMATION REGION END ==== */
233 
234   /* ==== CHORD REGION ==== */
235 
236   /** ChordObject's in this Region. */
237   ChordObject **     chord_objects;
238   int                num_chord_objects;
239   size_t             chord_objects_size;
240 
241   /* ==== CHORD REGION END ==== */
242 
243   /**
244    * Set to ON during bouncing if this
245    * region should be included.
246    *
247    * Only relevant for audio and midi regions.
248    */
249   int                bounce;
250 
251   /* --- drawing caches --- */
252 
253   /* New region drawing needs to be cached in the
254    * following situations:
255    *
256    * 1. when hidden part of the region is revealed
257    *   (on x axis).
258    *   TODO max 140% of the region should be
259    *   cached (20% before and 20% after if before/
260    *   after is not fully visible)
261    * 2. when full rect (x/width) changes
262    * 3. when a region marker is moved
263    * 4. when the clip actually changes (use
264    *   last-change timestamp on the clip or region)
265    * 5. when fades change
266    * 6. when region height changes (track/lane)
267    */
268 
269   /** Cache layout for drawing the name. */
270   PangoLayout *      layout;
271 
272   /** Cache layout for drawing the chord names
273    * inside the region. */
274   PangoLayout *      chords_layout;
275 
276   /* these are used for caching */
277   GdkRectangle       last_main_full_rect;
278 
279   /** Last main draw rect. */
280   GdkRectangle       last_main_draw_rect;
281 
282   /* these are used for caching */
283   GdkRectangle       last_lane_full_rect;
284 
285   /** Last lane draw rect. */
286   GdkRectangle       last_lane_draw_rect;
287 
288   /** Last timestamp the audio clip or its contents
289    * changed. */
290   gint64             last_clip_change;
291 
292   /** Last timestamp the region was cached. */
293   gint64             last_cache_time;
294 
295   /** Last known marker positions (only positions
296    * are used). */
297   ArrangerObject     last_positions_obj;
298 
299   /* --- drawing caches end --- */
300 
301   int                magic;
302 } ZRegion;
303 
304 static const cyaml_schema_field_t
305   region_fields_schema[] =
306 {
307   YAML_FIELD_INT (ZRegion, schema_version),
308   YAML_FIELD_MAPPING_EMBEDDED (
309     ZRegion, base, arranger_object_fields_schema),
310   YAML_FIELD_MAPPING_EMBEDDED (
311     ZRegion, id, region_identifier_fields_schema),
312   YAML_FIELD_STRING_PTR (ZRegion, name),
313   YAML_FIELD_INT (ZRegion, pool_id),
314   YAML_FIELD_FLOAT (ZRegion, gain),
315   CYAML_FIELD_SEQUENCE_COUNT (
316     "midi_notes",
317     CYAML_FLAG_POINTER | CYAML_FLAG_OPTIONAL,
318     ZRegion, midi_notes, num_midi_notes,
319     &midi_note_schema, 0, CYAML_UNLIMITED),
320   CYAML_FIELD_SEQUENCE_COUNT (
321     "aps", CYAML_FLAG_POINTER | CYAML_FLAG_OPTIONAL,
322     ZRegion, aps, num_aps,
323     &automation_point_schema, 0, CYAML_UNLIMITED),
324   CYAML_FIELD_SEQUENCE_COUNT (
325     "chord_objects",
326     CYAML_FLAG_POINTER | CYAML_FLAG_OPTIONAL,
327     ZRegion, chord_objects, num_chord_objects,
328     &chord_object_schema, 0, CYAML_UNLIMITED),
329   YAML_FIELD_ENUM (
330     ZRegion, musical_mode,
331     region_musical_mode_strings),
332 
333   CYAML_FIELD_END
334 };
335 
336 static const cyaml_schema_value_t
337   region_schema =
338 {
339   YAML_VALUE_PTR_NULLABLE (
340     ZRegion, region_fields_schema),
341 };
342 
343 /**
344  * Returns if the given ZRegion type can have fades.
345  */
346 #define region_type_can_fade(rtype) \
347   (rtype == REGION_TYPE_AUDIO)
348 
349 /**
350  * Only to be used by implementing structs.
351  */
352 void
353 region_init (
354   ZRegion *   region,
355   const Position * start_pos,
356   const Position * end_pos,
357   unsigned int     track_name_hash,
358   int              lane_pos,
359   int              idx_inside_lane);
360 
361 /**
362  * Looks for the ZRegion matching the identifier.
363  */
364 HOT
365 NONNULL
366 ZRegion *
367 region_find (
368   const RegionIdentifier * const id);
369 
370 #if 0
371 static inline void
372 region_set_track_name_hash (
373   ZRegion *    self,
374   unsigned int name_hash)
375 {
376   self->id.track_name_hash = name_hash;
377 }
378 #endif
379 
380 NONNULL
381 void
382 region_print_to_str (
383   const ZRegion * self,
384   char *          buf,
385   const size_t    buf_size);
386 
387 /**
388  * Print region info for debugging.
389  */
390 NONNULL
391 void
392 region_print (
393   const ZRegion * region);
394 
395 TrackLane *
396 region_get_lane (
397   const ZRegion * region);
398 
399 /**
400  * Returns the region's link group.
401  */
402 RegionLinkGroup *
403 region_get_link_group (
404   ZRegion * self);
405 
406 /**
407  * Sets the link group to the region.
408  *
409  * @param group_idx If -1, the region will be
410  *   removed from its current link group, if any.
411  */
412 void
413 region_set_link_group (
414   ZRegion * region,
415   int       group_idx,
416   bool      update_identifier);
417 
418 NONNULL
419 bool
420 region_has_link_group (
421   ZRegion * region);
422 
423 /**
424  * Returns the MidiNote matching the properties of
425  * the given MidiNote.
426  *
427  * Used to find the actual MidiNote in the region
428  * from a cloned MidiNote (e.g. when doing/undoing).
429  */
430 MidiNote *
431 region_find_midi_note (
432   ZRegion * r,
433   MidiNote * _mn);
434 
435 /**
436  * Converts frames on the timeline (global)
437  * to local frames (in the clip).
438  *
439  * If normalize is 1 it will only return a position
440  * from 0 to loop_end (it will traverse the
441  * loops to find the appropriate position),
442  * otherwise it may exceed loop_end.
443  *
444  * @param timeline_frames Timeline position in
445  *   frames.
446  *
447  * @return The local frames.
448  */
449 NONNULL
450 HOT
451 long
452 region_timeline_frames_to_local (
453   const ZRegion * const self,
454   const long            timeline_frames,
455   const bool            normalize);
456 
457 /**
458  * Returns the number of frames until the next
459  * loop end point or the end of the region.
460  *
461  * @param[in] timeline_frames Global frames at
462  *   start.
463  * @param[out] ret_frames Return frames.
464  * @param[out] is_loop Whether the return frames
465  *   are for a loop (if false, the return frames
466  *   are for the region's end).
467  */
468 NONNULL
469 void
470 region_get_frames_till_next_loop_or_end (
471   const ZRegion * const self,
472   const long            timeline_frames,
473   long *                ret_frames,
474   bool *                is_loop);
475 
476 /**
477  * Sets the track lane.
478  */
479 NONNULL
480 void
481 region_set_lane (
482   ZRegion *               self,
483   const TrackLane * const lane);
484 
485 /**
486  * Generates a name for the ZRegion, either using
487  * the given AutomationTrack or Track, or appending
488  * to the given base name.
489  */
490 void
491 region_gen_name (
492   ZRegion *         region,
493   const char *      base_name,
494   AutomationTrack * at,
495   Track *           track);
496 
497 /**
498  * Stretch the region's contents.
499  *
500  * This should be called right after changing the
501  * region's size.
502  *
503  * @param ratio The ratio to stretch by.
504  */
505 NONNULL
506 void
507 region_stretch (
508   ZRegion * self,
509   double    ratio);
510 
511 /**
512  * To be called every time the identifier changes
513  * to update the region's children.
514  */
515 NONNULL
516 void
517 region_update_identifier (
518   ZRegion * self);
519 
520 /**
521  * Updates all other regions in the region link
522  * group, if any.
523  */
524 NONNULL
525 void
526 region_update_link_group (
527   ZRegion * self);
528 
529 /**
530  * Moves the given ZRegion to the given TrackLane.
531  *
532  * Works with TrackLane's of other Track's as well.
533  *
534  * Maintains the selection status of the
535  * Region.
536  *
537  * Assumes that the ZRegion is already in a
538  * TrackLane.
539  *
540  * @param index_in_lane Index in lane in the
541  *   new track to insert the region to, or -1 to
542  *   append.
543  */
544 void
545 region_move_to_lane (
546   ZRegion *    region,
547   TrackLane * lane,
548   int          index_in_lane);
549 
550 /**
551  * Moves the ZRegion to the given Track, maintaining
552  * the selection status of the ZRegion and the
553  * TrackLane position.
554  *
555  * Assumes that the ZRegion is already in a
556  * TrackLane.
557  *
558  * @param index_in_lane Index in lane in the
559  *   new track to insert the region to, or -1 to
560  *   append.
561  */
562 void
563 region_move_to_track (
564   ZRegion *  region,
565   Track *    track,
566   int        index_in_lane);
567 
568 /**
569  * Returns if the given ZRegion type can exist
570  * in TrackLane's.
571  */
572 CONST
573 static inline int
region_type_has_lane(const RegionType type)574 region_type_has_lane (
575   const RegionType type)
576 {
577   return
578     type == REGION_TYPE_MIDI ||
579     type == REGION_TYPE_AUDIO;
580 }
581 
582 /**
583  * Sets the automation track.
584  */
585 void
586 region_set_automation_track (
587   ZRegion * region,
588   AutomationTrack * at);
589 
590 /**
591  * Gets the AutomationTrack using the saved index.
592  */
593 AutomationTrack *
594 region_get_automation_track (
595   const ZRegion * const region);
596 
597 /**
598  * Copies the data from src to dest.
599  *
600  * Used when doing/undoing changes in name,
601  * clip start point, loop start point, etc.
602  */
603 void
604 region_copy (
605   ZRegion * src,
606   ZRegion * dest);
607 
608 /**
609  * Returns if the position is inside the region
610  * or not.
611  *
612  * FIXME move to arranger object
613  *
614  * @param gframes Global position in frames.
615  * @param inclusive Whether the last frame should
616  *   be counted as part of the region.
617  */
618 int
619 region_is_hit (
620   const ZRegion * region,
621   const long     gframes,
622   const int      inclusive);
623 
624 /**
625  * Returns if any part of the ZRegion is inside the
626  * given range, inclusive.
627  *
628  * FIXME move to arranger object
629  */
630 int
631 region_is_hit_by_range (
632   const ZRegion * region,
633   const long      gframes_start,
634   const long      gframes_end,
635   const bool      end_inclusive);
636 
637 /**
638  * Returns the region at the given position in the
639  * given Track.
640  *
641  * @param at The automation track to look in.
642  * @param track The track to look in, if at is
643  *   NULL.
644  * @param pos The position.
645  */
646 ZRegion *
647 region_at_position (
648   Track    *        track,
649   AutomationTrack * at,
650   Position *        pos);
651 
652 /**
653  * Generates the filename for this region.
654  *
655  * MUST be free'd.
656  */
657 char *
658 region_generate_filename (ZRegion * region);
659 
660 void
661 region_get_type_as_string (
662   RegionType type,
663   char *     buf);
664 
665 /**
666  * Returns if this region is currently being
667  * recorded onto.
668  */
669 bool
670 region_is_recording (
671   ZRegion * self);
672 
673 /**
674  * Returns whether the region is effectively in
675  * musical mode.
676  *
677  * @note Only applicable to audio regions.
678  */
679 bool
680 region_get_musical_mode (
681   ZRegion * self);
682 
683 /**
684  * Wrapper for adding an arranger object.
685  */
686 void
687 region_add_arranger_object (
688   ZRegion *        self,
689   ArrangerObject * obj,
690   bool             fire_events);
691 
692 void
693 region_create_link_group_if_none (
694   ZRegion * region);
695 
696 /**
697  * Removes the link group from the region, if any.
698  */
699 void
700 region_unlink (
701   ZRegion * region);
702 
703 /**
704  * Removes all children objects from the region.
705  */
706 void
707 region_remove_all_children (
708   ZRegion * region);
709 
710 /**
711  * Clones and copies all children from \ref src to
712  * \ref dest.
713  */
714 void
715 region_copy_children (
716   ZRegion * dest,
717   ZRegion * src);
718 
719 NONNULL
720 static inline bool
region_is_looped(const ZRegion * const self)721 region_is_looped (
722   const ZRegion * const self)
723 {
724   ArrangerObject * obj = (ArrangerObject *) self;
725   return
726     obj->loop_start_pos.ticks > 0
727     ||
728     (obj->end_pos.ticks - obj->pos.ticks) >
729        (obj->loop_end_pos.ticks +
730          /* add some buffer because these are not
731           * accurate */
732           0.1);
733 }
734 
735 /**
736  * Returns the ArrangerSelections based on the
737  * given region type.
738  */
739 ArrangerSelections *
740 region_get_arranger_selections (
741   ZRegion * self);
742 
743 /**
744  * Sanity checking.
745  */
746 bool
747 region_validate (
748   ZRegion * self,
749   bool      is_project);
750 
751 /**
752  * Disconnects the region and anything using it.
753  *
754  * Does not free the ZRegion or its children's
755  * resources.
756  */
757 void
758 region_disconnect (
759   ZRegion * self);
760 
761 /**
762  * @}
763  */
764 
765 #endif // __AUDIO_REGION_H__
766