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 this program.  If not, see <https://www.gnu.org/licenses/>.
18  */
19 
20 #include <limits.h>
21 #include <math.h>
22 #include <stdlib.h>
23 
24 #include "audio/audio_region.h"
25 #include "audio/automation_region.h"
26 #include "audio/chord_object.h"
27 #include "audio/chord_region.h"
28 #include "audio/chord_track.h"
29 #include "audio/engine.h"
30 #include "audio/marker.h"
31 #include "audio/marker_track.h"
32 #include "audio/scale_object.h"
33 #include "audio/transport.h"
34 #include "gui/backend/arranger_selections.h"
35 #include "gui/backend/automation_selections.h"
36 #include "gui/backend/chord_selections.h"
37 #include "gui/backend/event.h"
38 #include "gui/backend/event_manager.h"
39 #include "gui/backend/midi_arranger_selections.h"
40 #include "gui/backend/timeline_selections.h"
41 #include "gui/widgets/arranger_object.h"
42 #include "project.h"
43 #include "utils/arrays.h"
44 #include "utils/dsp.h"
45 #include "utils/error.h"
46 #include "utils/flags.h"
47 #include "utils/mem.h"
48 #include "utils/objects.h"
49 #include "zrythm_app.h"
50 
51 #include <glib/gi18n.h>
52 
53 #define TYPE(x) \
54   (ARRANGER_SELECTIONS_TYPE_##x)
55 
56 /**
57  * Inits the selections after loading a project.
58  *
59  * @param project Whether these are project
60  *   selections (as opposed to clones).
61  */
62 void
arranger_selections_init_loaded(ArrangerSelections * self,bool project)63 arranger_selections_init_loaded (
64   ArrangerSelections * self,
65   bool                 project)
66 {
67   int i;
68   TimelineSelections * ts;
69   ChordSelections * cs;
70   MidiArrangerSelections * mas;
71   AutomationSelections * as;
72   self->magic = ARRANGER_SELECTIONS_MAGIC;
73 
74 #define SET_OBJ(sel,cc,sc) \
75   for (i = 0; i < sel->num_##sc##s; i++) \
76     { \
77       ArrangerObject * obj = \
78         (ArrangerObject *) sel->sc##s[i]; \
79       arranger_object_set_magic (obj); \
80       if (project) \
81         { \
82           /* throws an error otherwise */ \
83           if (obj->type == \
84                 ARRANGER_OBJECT_TYPE_REGION) \
85             { \
86               ZRegion * r = (ZRegion *) obj; \
87               if (r->id.type == \
88                     REGION_TYPE_AUDIO) \
89                 { \
90                   r->read_from_pool = true; \
91                   AudioClip * clip = \
92                     audio_region_get_clip (r); \
93                   g_return_if_fail (clip); \
94                   r->last_clip_change = \
95                     g_get_monotonic_time (); \
96                 } \
97             } \
98           arranger_object_update_positions ( \
99             obj, true); \
100           sel->sc##s[i] = \
101             (cc *) \
102             arranger_object_find (obj); \
103         } \
104       else \
105         { \
106           arranger_object_init_loaded ( \
107             (ArrangerObject *) sel->sc##s[i]); \
108           arranger_object_update_positions ( \
109             obj, true); \
110         } \
111     }
112 
113   switch (self->type)
114     {
115     case TYPE (TIMELINE):
116       ts = (TimelineSelections *) self;
117       SET_OBJ (ts, ZRegion, region);
118       SET_OBJ (ts, ScaleObject, scale_object);
119       SET_OBJ (ts, Marker, marker);
120       break;
121     case TYPE (MIDI):
122       mas = (MidiArrangerSelections *) self;
123       for (i = 0; i < mas->num_midi_notes; i++)
124         {
125           MidiNote * mn = mas->midi_notes[i];
126           ArrangerObject * mn_obj =
127             (ArrangerObject *) mn;
128           arranger_object_update_positions (
129             mn_obj, true);
130           if (project)
131             {
132               mas->midi_notes[i] =
133                 (MidiNote *)
134                 arranger_object_find (mn_obj);
135             }
136           else
137             {
138               arranger_object_init_loaded (
139                 (ArrangerObject *)
140                 mas->midi_notes[i]);
141             }
142           g_warn_if_fail (mas->midi_notes[i]);
143         }
144       break;
145     case TYPE (AUTOMATION):
146       as = (AutomationSelections *) self;
147       SET_OBJ (as, AutomationPoint, automation_point);
148       break;
149     case TYPE (CHORD):
150       cs = (ChordSelections *) self;
151       SET_OBJ (cs, ChordObject, chord_object);
152       break;
153     case TYPE (AUDIO):
154       break;
155     default:
156       g_return_if_reached ();
157     }
158 
159 #undef SET_OBJ
160 }
161 
162 /**
163  * Initializes the selections.
164  */
165 void
arranger_selections_init(ArrangerSelections * self,ArrangerSelectionsType type)166 arranger_selections_init (
167   ArrangerSelections *   self,
168   ArrangerSelectionsType type)
169 {
170   self->type = type;
171   self->magic = ARRANGER_SELECTIONS_MAGIC;
172   self->schema_version =
173     ARRANGER_SELECTIONS_SCHEMA_VERSION;
174 
175   TimelineSelections * ts;
176   ChordSelections * cs;
177   MidiArrangerSelections * mas;
178   AutomationSelections * as;
179 
180 #define SET_OBJ(sel,cc,sc) \
181   sel->sc##s_size = 1; \
182   sel->sc##s = \
183     object_new_n (1, cc *)
184 
185   switch (self->type)
186     {
187     case TYPE (TIMELINE):
188       ts = (TimelineSelections *) self;
189       ts->schema_version =
190         TL_SELECTIONS_SCHEMA_VERSION;
191       SET_OBJ (ts, ZRegion, region);
192       SET_OBJ (ts, ScaleObject, scale_object);
193       SET_OBJ (ts, Marker, marker);
194       break;
195     case TYPE (MIDI):
196       mas = (MidiArrangerSelections *) self;
197       mas->schema_version =
198         MA_SELECTIONS_SCHEMA_VERSION;
199       SET_OBJ (mas, MidiNote, midi_note);
200       break;
201     case TYPE (AUTOMATION):
202       as = (AutomationSelections *) self;
203       as->schema_version =
204         AUTOMATION_SELECTIONS_SCHEMA_VERSION;
205       SET_OBJ (
206         as, AutomationPoint, automation_point);
207       break;
208     case TYPE (CHORD):
209       cs = (ChordSelections *) self;
210       cs->schema_version =
211         CHORD_SELECTIONS_SCHEMA_VERSION;
212       SET_OBJ (cs, ChordObject, chord_object);
213       break;
214     case TYPE (AUDIO):
215       {
216         AudioSelections * sel =
217           (AudioSelections *) self;
218         sel->schema_version =
219           AUDIO_SELECTIONS_SCHEMA_VERSION;
220         position_init (&sel->sel_start);
221         position_init (&sel->sel_end);
222         region_identifier_init (&sel->region_id);
223         sel->pool_id = -1;
224       }
225       break;
226     default:
227       g_return_if_reached ();
228     }
229 
230 #undef SET_OBJ
231 }
232 
233 /**
234  * Creates new arranger selections.
235  */
236 ArrangerSelections *
arranger_selections_new(ArrangerSelectionsType type)237 arranger_selections_new (
238   ArrangerSelectionsType type)
239 {
240   ArrangerSelections * self = NULL;
241 
242   switch (type)
243     {
244     case TYPE (TIMELINE):
245       self =
246         (ArrangerSelections *)
247         object_new (TimelineSelections);
248       break;
249     case TYPE (MIDI):
250       self =
251         (ArrangerSelections *)
252         object_new (MidiArrangerSelections);
253       break;
254     case TYPE (AUTOMATION):
255       self =
256         (ArrangerSelections *)
257         object_new (AutomationSelections);
258       break;
259     case TYPE (CHORD):
260       self =
261         (ArrangerSelections *)
262         object_new (ChordSelections);
263       break;
264     case TYPE (AUDIO):
265       self =
266         (ArrangerSelections *)
267         object_new (AudioSelections);
268       break;
269     default:
270       g_return_val_if_reached (NULL);
271     }
272 
273   arranger_selections_init (self, type);
274 
275   return self;
276 }
277 
278 /**
279  * Verify that the objects are not invalid.
280  */
281 bool
arranger_selections_verify(ArrangerSelections * self)282 arranger_selections_verify (
283   ArrangerSelections * self)
284 {
285   /* verify that all objects are arranger
286    * objects */
287   int size = 0;
288   ArrangerObject ** objs =
289     arranger_selections_get_all_objects (
290       self, &size);
291   for (int i = 0; i < size; i++)
292     {
293       g_return_val_if_fail (
294         IS_ARRANGER_OBJECT (objs[i]), false);
295     }
296   free (objs);
297 
298   return true;
299 }
300 
301 /**
302  * Appends the given object to the selections.
303  */
304 void
arranger_selections_add_object(ArrangerSelections * self,ArrangerObject * obj)305 arranger_selections_add_object (
306   ArrangerSelections * self,
307   ArrangerObject *     obj)
308 {
309   g_return_if_fail (
310     IS_ARRANGER_SELECTIONS (self) &&
311     IS_ARRANGER_OBJECT (obj));
312 
313   /* check if object is allowed */
314   switch (self->type)
315     {
316     case TYPE (CHORD):
317       g_return_if_fail (
318         obj->type ==
319           ARRANGER_OBJECT_TYPE_CHORD_OBJECT);
320       break;
321     case TYPE (TIMELINE):
322       g_return_if_fail (
323         obj->type == ARRANGER_OBJECT_TYPE_REGION ||
324         obj->type == ARRANGER_OBJECT_TYPE_SCALE_OBJECT ||
325         obj->type == ARRANGER_OBJECT_TYPE_MARKER);
326       break;
327     case TYPE (MIDI):
328       g_return_if_fail (
329         obj->type == ARRANGER_OBJECT_TYPE_MIDI_NOTE ||
330         obj->type == ARRANGER_OBJECT_TYPE_VELOCITY);
331       break;
332     case TYPE (AUTOMATION):
333       g_return_if_fail (
334         obj->type == ARRANGER_OBJECT_TYPE_AUTOMATION_POINT);
335       break;
336     default:
337       g_return_if_reached();
338     }
339 
340 #define ADD_OBJ(sel,caps,cc,sc) \
341   if (obj->type == ARRANGER_OBJECT_TYPE_##caps) \
342     { \
343       cc * sc = (cc *) obj; \
344       if (!array_contains ( \
345              sel->sc##s, sel->num_##sc##s, \
346              sc)) \
347         { \
348           array_double_size_if_full ( \
349             sel->sc##s, sel->num_##sc##s, \
350             sel->sc##s_size, cc *); \
351           array_append ( \
352             sel->sc##s, \
353             sel->num_##sc##s, \
354             sc); \
355         } \
356     }
357 
358   /* add the object to the child selections */
359   switch (self->type)
360     {
361     case TYPE (CHORD):
362       {
363         ChordSelections * sel =
364           (ChordSelections *) self;
365         ADD_OBJ (
366           sel, CHORD_OBJECT,
367           ChordObject, chord_object);
368         }
369       break;
370     case TYPE (TIMELINE):
371       {
372         TimelineSelections * sel =
373           (TimelineSelections *) self;
374         ADD_OBJ (
375           sel, REGION,
376           ZRegion, region);
377         ADD_OBJ (
378           sel, SCALE_OBJECT,
379           ScaleObject, scale_object);
380         ADD_OBJ (
381           sel, MARKER,
382           Marker, marker);
383         }
384       break;
385     case TYPE (MIDI):
386       {
387         MidiArrangerSelections * sel =
388           (MidiArrangerSelections *) self;
389         if (obj->type ==
390               ARRANGER_OBJECT_TYPE_VELOCITY)
391           {
392             Velocity * vel = (Velocity *) obj;
393             obj =
394               (ArrangerObject *)
395               velocity_get_midi_note (vel);
396           }
397         ADD_OBJ (
398           sel, MIDI_NOTE,
399           MidiNote, midi_note);
400         }
401       break;
402     case TYPE (AUTOMATION):
403       {
404         AutomationSelections * sel =
405           (AutomationSelections *) self;
406         ADD_OBJ (
407           sel, AUTOMATION_POINT,
408           AutomationPoint, automation_point);
409         }
410       break;
411     default:
412       g_return_if_reached ();
413     }
414 #undef ADD_OBJ
415 }
416 
417 /**
418  * Sets the values of each object in the dest selections
419  * to the values in the src selections.
420  */
421 void
arranger_selections_set_from_selections(ArrangerSelections * dest,ArrangerSelections * src)422 arranger_selections_set_from_selections (
423   ArrangerSelections * dest,
424   ArrangerSelections * src)
425 {
426   int i;
427   TimelineSelections * ts;
428   ChordSelections * cs;
429   MidiArrangerSelections * mas;
430   AutomationSelections * as;
431 
432   /* TODO */
433 #define RESET_COUNTERPART(sel,cc,sc) \
434   for (i = 0; i < sel->num_##sc##s; i++) \
435     break;
436 
437   switch (dest->type)
438     {
439     case TYPE (TIMELINE):
440       ts = (TimelineSelections *) dest;
441       RESET_COUNTERPART (ts, ZRegion, region);
442       RESET_COUNTERPART (
443         ts, ScaleObject, scale_object);
444       RESET_COUNTERPART (ts, Marker, marker);
445       break;
446     case TYPE (MIDI):
447       mas = (MidiArrangerSelections *) dest;
448       RESET_COUNTERPART (mas, MidiNote, midi_note);
449       break;
450     case TYPE (AUTOMATION):
451       as = (AutomationSelections *) dest;
452       RESET_COUNTERPART (
453         as, AutomationPoint, automation_point);
454       break;
455     case TYPE (CHORD):
456       cs = (ChordSelections *) dest;
457       RESET_COUNTERPART (
458         cs, ChordObject, chord_object);
459       break;
460     default:
461       g_return_if_reached ();
462     }
463 
464 #undef RESET_COUNTERPART
465 }
466 
467 /**
468  * Clone the struct for copying, undoing, etc.
469  */
470 ArrangerSelections *
arranger_selections_clone(ArrangerSelections * self)471 arranger_selections_clone (
472   ArrangerSelections * self)
473 {
474   g_return_val_if_fail (
475     IS_ARRANGER_SELECTIONS (self), NULL);
476 
477   TimelineSelections * src_ts, * new_ts;
478   ChordSelections * src_cs, * new_cs;
479   MidiArrangerSelections * src_mas, * new_mas;
480   AutomationSelections * src_as, * new_as;
481   AudioSelections * src_aus, * new_aus;
482 
483 #define CLONE_OBJS(src_sel,new_sel,cc,sc) \
484   cc * sc, * new_##sc; \
485     for (int i = 0; i < src_sel->num_##sc##s; i++) \
486     { \
487       sc = src_sel->sc##s[i]; \
488       ArrangerObject * sc_obj = \
489         (ArrangerObject *) sc; \
490       new_##sc = \
491         (cc *) \
492         arranger_object_clone ( \
493           (ArrangerObject *) sc); \
494       ArrangerObject * new_sc_obj = \
495         (ArrangerObject *) new_##sc; \
496       sc_obj->transient = new_sc_obj; \
497       arranger_selections_add_object ( \
498         (ArrangerSelections *) new_sel, \
499         new_sc_obj); \
500     }
501 
502   switch (self->type)
503     {
504     case TYPE (TIMELINE):
505       src_ts = (TimelineSelections *) self;
506       new_ts = object_new (TimelineSelections);
507       new_ts->base = src_ts->base;
508       arranger_selections_init (
509         (ArrangerSelections *) new_ts,
510         ARRANGER_SELECTIONS_TYPE_TIMELINE);
511       CLONE_OBJS (
512         src_ts, new_ts, ZRegion, region);
513       CLONE_OBJS (
514         src_ts, new_ts, ScaleObject, scale_object);
515       CLONE_OBJS (
516         src_ts, new_ts, Marker, marker);
517       return ((ArrangerSelections *) new_ts);
518     case TYPE (MIDI):
519       src_mas = (MidiArrangerSelections *) self;
520       new_mas =
521         object_new (MidiArrangerSelections);
522       arranger_selections_init (
523         (ArrangerSelections *) new_mas,
524         ARRANGER_SELECTIONS_TYPE_MIDI);
525       new_mas->base = src_mas->base;
526       CLONE_OBJS (
527         src_mas, new_mas, MidiNote, midi_note);
528       return ((ArrangerSelections *) new_mas);
529     case TYPE (AUTOMATION):
530       src_as = (AutomationSelections *) self;
531       new_as =
532         object_new (AutomationSelections);
533       arranger_selections_init (
534         (ArrangerSelections *) new_as,
535         ARRANGER_SELECTIONS_TYPE_AUTOMATION);
536       new_as->base = src_as->base;
537       CLONE_OBJS (
538         src_as, new_as, AutomationPoint,
539         automation_point);
540       return ((ArrangerSelections *) new_as);
541     case TYPE (CHORD):
542       src_cs = (ChordSelections *) self;
543       new_cs =
544         object_new (ChordSelections);
545       arranger_selections_init (
546         (ArrangerSelections *) new_cs,
547         ARRANGER_SELECTIONS_TYPE_CHORD);
548       new_cs->base = src_cs->base;
549       CLONE_OBJS (
550         src_cs, new_cs, ChordObject, chord_object);
551       return ((ArrangerSelections *) new_cs);
552     case TYPE (AUDIO):
553       src_aus = (AudioSelections *) self;
554       new_aus =
555         object_new (AudioSelections);
556       arranger_selections_init (
557         (ArrangerSelections *) new_aus,
558         ARRANGER_SELECTIONS_TYPE_CHORD);
559       new_aus->base = src_aus->base;
560       new_aus->sel_start = src_aus->sel_start;
561       new_aus->sel_end = src_aus->sel_end;
562       new_aus->has_selection =
563         src_aus->has_selection;
564       new_aus->pool_id = src_aus->pool_id;
565       new_aus->region_id = src_aus->region_id;
566       return ((ArrangerSelections *) new_aus);
567     default:
568       g_return_val_if_reached (NULL);
569     }
570 
571   g_return_val_if_reached (NULL);
572 
573 #undef CLONE_OBJS
574 }
575 
576 static int
sort_midi_notes_func(const void * _a,const void * _b)577 sort_midi_notes_func (
578   const void * _a,
579   const void * _b)
580 {
581   MidiNote * a =
582     *(MidiNote * const *) _a;
583   MidiNote * b =
584     *(MidiNote * const *)_b;
585 
586   /* region index doesn't really matter */
587   return a->pos - b->pos;
588 }
589 
590 static int
sort_midi_notes_desc(const void * a,const void * b)591 sort_midi_notes_desc (
592   const void * a,
593   const void * b)
594 {
595   return - sort_midi_notes_func (a, b);
596 }
597 
598 static int
sort_aps(const void * _a,const void * _b)599 sort_aps (
600   const void * _a,
601   const void * _b)
602 {
603   AutomationPoint * a =
604     *(AutomationPoint * const *) _a;
605   AutomationPoint * b =
606     *(AutomationPoint * const *)_b;
607 
608   return a->index - b->index;
609 }
610 
611 static int
sort_aps_desc(const void * a,const void * b)612 sort_aps_desc (
613   const void * a,
614   const void * b)
615 {
616   return - sort_aps (a, b);
617 }
618 
619 static int
sort_chords(const void * _a,const void * _b)620 sort_chords (
621   const void * _a,
622   const void * _b)
623 {
624   ChordObject * a =
625     *(ChordObject * const *) _a;
626   ChordObject * b =
627     *(ChordObject * const *)_b;
628 
629   return a->index - b->index;
630 }
631 
632 static int
sort_chords_desc(const void * a,const void * b)633 sort_chords_desc (
634   const void * a,
635   const void * b)
636 {
637   return - sort_chords (a, b);
638 }
639 
640 static int
sort_regions_func(const void * _a,const void * _b)641 sort_regions_func (
642   const void * _a,
643   const void * _b)
644 {
645   ZRegion * a =
646     *(ZRegion * const *) _a;
647   ZRegion * b =
648     *(ZRegion * const *)_b;
649 
650   Track * at =
651     tracklist_find_track_by_name_hash (
652       TRACKLIST, a->id.track_name_hash);
653   g_return_val_if_fail (
654     IS_TRACK_AND_NONNULL (at), -1);
655   Track * bt =
656     tracklist_find_track_by_name_hash (
657       TRACKLIST, b->id.track_name_hash);
658   g_return_val_if_fail (
659     IS_TRACK_AND_NONNULL (bt), -1);
660   if (at->pos < bt->pos)
661     return -1;
662   else if (at->pos > bt->pos)
663     return 1;
664 
665   int have_lane =
666     region_type_has_lane (a->id.type);
667   /* order doesn't matter in this case */
668   if (have_lane !=
669         region_type_has_lane (b->id.type))
670     return -1;
671 
672   if (have_lane)
673     {
674       if (a->id.lane_pos < b->id.lane_pos)
675         {
676           return -1;
677         }
678       else if (a->id.lane_pos > b->id.lane_pos)
679         {
680           return 1;
681         }
682     }
683   else if (a->id.type == REGION_TYPE_AUTOMATION &&
684            b->id.type == REGION_TYPE_AUTOMATION)
685     {
686       if (a->id.at_idx < b->id.at_idx)
687         {
688           return -1;
689         }
690       else if (a->id.at_idx > b->id.at_idx)
691         {
692           return 1;
693         }
694     }
695 
696   return a->id.idx - b->id.idx;
697 }
698 
699 static int
sort_scales_func(const void * _a,const void * _b)700 sort_scales_func (
701   const void * _a,
702   const void * _b)
703 {
704   ScaleObject * a =
705     *(ScaleObject * const *) _a;
706   ScaleObject * b =
707     *(ScaleObject * const *)_b;
708   return a->index - b->index;
709 }
710 
711 static int
sort_markers_func(const void * _a,const void * _b)712 sort_markers_func (
713   const void * _a,
714   const void * _b)
715 {
716   Marker * a =
717     *(Marker * const *) _a;
718   Marker * b =
719     *(Marker * const *)_b;
720   return a->index - b->index;
721 }
722 
723 static int
sort_regions_desc(const void * a,const void * b)724 sort_regions_desc (
725   const void * a,
726   const void * b)
727 {
728   return - sort_regions_func (a, b);
729 }
730 
731 static int
sort_scales_desc(const void * a,const void * b)732 sort_scales_desc (
733   const void * a,
734   const void * b)
735 {
736   return - sort_scales_func (a, b);
737 }
738 
739 static int
sort_markers_desc(const void * a,const void * b)740 sort_markers_desc (
741   const void * a,
742   const void * b)
743 {
744   return - sort_markers_func (a, b);
745 }
746 
747 /**
748  * Sorts the selections by their indices (eg, for
749  * regions, their track indices, then the lane
750  * indices, then the index in the lane).
751  *
752  * @note Only works for objects whose tracks exist.
753  *
754  * @param desc Descending or not.
755  */
756 void
arranger_selections_sort_by_indices(ArrangerSelections * self,int desc)757 arranger_selections_sort_by_indices (
758   ArrangerSelections * self,
759   int                  desc)
760 {
761   TimelineSelections * ts;
762   ChordSelections * cs;
763   MidiArrangerSelections * mas;
764   AutomationSelections * as;
765   switch (self->type)
766     {
767     case TYPE (TIMELINE):
768       ts = (TimelineSelections *) self;
769       qsort (
770         ts->regions, (size_t) ts->num_regions,
771         sizeof (ZRegion *),
772         desc ?
773           sort_regions_desc : sort_regions_func);
774       qsort (
775         ts->scale_objects,
776         (size_t) ts->num_scale_objects,
777         sizeof (ScaleObject *),
778         desc ?
779           sort_scales_desc : sort_scales_func);
780       qsort (
781         ts->markers,
782         (size_t) ts->num_markers,
783         sizeof (Marker *),
784         desc ?
785           sort_markers_desc : sort_markers_func);
786       break;
787     case TYPE (MIDI):
788       mas = (MidiArrangerSelections *) self;
789       qsort (
790         mas->midi_notes,
791         (size_t) mas->num_midi_notes,
792         sizeof (MidiNote *),
793         desc ? sort_midi_notes_desc :
794           sort_midi_notes_func);
795       break;
796     case TYPE (AUTOMATION):
797       as = (AutomationSelections *) self;
798       qsort (
799         as->automation_points,
800         (size_t) as->num_automation_points,
801         sizeof (AutomationPoint *),
802         desc ? sort_aps_desc : sort_aps);
803       break;
804     case TYPE (CHORD):
805       cs = (ChordSelections *) self;
806       qsort (
807         cs->chord_objects,
808         (size_t) cs->num_chord_objects,
809         sizeof (ChordObject *),
810         desc ? sort_chords_desc : sort_chords);
811       break;
812     default:
813       g_warn_if_reached ();
814       break;
815     }
816 }
817 
818 /**
819  * Returns if there are any selections.
820  */
821 bool
arranger_selections_has_any(ArrangerSelections * self)822 arranger_selections_has_any (
823   ArrangerSelections * self)
824 {
825   TimelineSelections * ts;
826   ChordSelections * cs;
827   MidiArrangerSelections * mas;
828   AutomationSelections * as;
829 
830   switch (self->type)
831     {
832     case TYPE (TIMELINE):
833       ts = (TimelineSelections *) self;
834       return
835         ts->num_regions > 0 ||
836         ts->num_scale_objects > 0 ||
837         ts->num_markers > 0;
838     case TYPE (MIDI):
839       mas = (MidiArrangerSelections *) self;
840       return
841         mas->num_midi_notes > 0;
842     case TYPE (AUTOMATION):
843       as = (AutomationSelections *) self;
844       return
845         as->num_automation_points > 0;
846     case TYPE (CHORD):
847       cs = (ChordSelections *) self;
848       return
849         cs->num_chord_objects > 0;
850     case TYPE (AUDIO):
851       {
852         AudioSelections * sel =
853           (AudioSelections *) self;
854         return sel->has_selection;
855       }
856     default:
857       g_return_val_if_reached (-1);
858     }
859 
860   g_return_val_if_reached (-1);
861 }
862 
863 /**
864  * Add owner region's ticks to the given position.
865  */
866 static void
add_region_ticks(ArrangerSelections * self,Position * pos)867 add_region_ticks (
868   ArrangerSelections * self,
869   Position *           pos)
870 {
871   ArrangerObject * obj =
872     arranger_selections_get_first_object (self);
873   g_return_if_fail (obj);
874   ArrangerObject * region =
875     (ArrangerObject *)
876     arranger_object_get_region (obj);
877   g_return_if_fail (region);
878   position_add_ticks (
879     pos, region->pos.ticks);
880 }
881 
882 /**
883  * Returns the position of the leftmost object.
884  *
885  * @param pos The return value will be stored here.
886  * @param global Return global (timeline) Position,
887  *   otherwise returns the local (from the start
888  *   of the ZRegion) Position.
889  */
890 void
arranger_selections_get_start_pos(ArrangerSelections * self,Position * pos,bool global)891 arranger_selections_get_start_pos (
892   ArrangerSelections * self,
893   Position *           pos,
894   bool                 global)
895 {
896   int i;
897   TimelineSelections * ts;
898   ChordSelections * cs;
899   MidiArrangerSelections * mas;
900   AutomationSelections * as;
901 
902   position_set_to_bar (pos, 80000);
903   g_return_if_fail (pos->ticks > 0);
904     /*&pos, TRANSPORT->total_bars);*/
905 
906 #define GET_START_POS(sel,cc,sc) \
907   for (i = 0; i < (sel)->num_##sc##s; i++) \
908     { \
909       cc * sc = (sel)->sc##s[i]; \
910       ArrangerObject * obj = (ArrangerObject *) sc; \
911       g_warn_if_fail (obj); \
912       if (position_is_before ( \
913             &obj->pos, pos)) \
914         { \
915           position_set_to_pos ( \
916             pos, &obj->pos); \
917         } \
918     }
919 
920   switch (self->type)
921     {
922     case TYPE (TIMELINE):
923       ts = (TimelineSelections *) self;
924       GET_START_POS (
925         ts, ZRegion, region);
926       GET_START_POS (
927         ts, ScaleObject, scale_object);
928       GET_START_POS (
929         ts, Marker, marker);
930       break;
931     case TYPE (MIDI):
932       mas = (MidiArrangerSelections *) self;
933       GET_START_POS (
934         mas, MidiNote, midi_note);
935       if (global)
936         {
937           add_region_ticks (self, pos);
938         }
939       break;
940     case TYPE (AUTOMATION):
941       as = (AutomationSelections *) self;
942       GET_START_POS (
943         as, AutomationPoint, automation_point);
944       if (global)
945         {
946           add_region_ticks (self, pos);
947         }
948       break;
949     case TYPE (CHORD):
950       cs = (ChordSelections *) self;
951       GET_START_POS (
952         cs, ChordObject, chord_object);
953       if (global)
954         {
955           add_region_ticks (self, pos);
956         }
957       break;
958     default:
959       g_return_if_reached ();
960     }
961 
962 #undef GET_START_POS
963 }
964 
965 /**
966  * Returns the end position of the rightmost object.
967  *
968  * @param pos The return value will be stored here.
969  * @param global Return global (timeline) Position,
970  *   otherwise returns the local (from the start
971  *   of the ZRegion) Position.
972  */
973 void
arranger_selections_get_end_pos(ArrangerSelections * self,Position * pos,int global)974 arranger_selections_get_end_pos (
975   ArrangerSelections * self,
976   Position *           pos,
977   int                  global)
978 {
979   int i;
980   TimelineSelections * ts;
981   ChordSelections * cs;
982   MidiArrangerSelections * mas;
983   AutomationSelections * as;
984 
985   position_init (pos);
986 
987 #define GET_END_POS(sel,cc,sc) \
988   for (i = 0; i < (sel)->num_##sc##s; i++) \
989     { \
990       cc * sc = (sel)->sc##s[i]; \
991       ArrangerObject * obj = (ArrangerObject *) sc; \
992       g_warn_if_fail (obj); \
993       if (arranger_object_type_has_length ( \
994             obj->type)) \
995         { \
996           if (position_is_after ( \
997                 &obj->end_pos, pos)) \
998             { \
999               position_set_to_pos ( \
1000                 pos, &obj->end_pos); \
1001             } \
1002         } \
1003       else \
1004         { \
1005           if (position_is_after ( \
1006                 &obj->pos, pos)) \
1007             { \
1008               position_set_to_pos ( \
1009                 pos, &obj->pos); \
1010             } \
1011         } \
1012     }
1013 
1014   switch (self->type)
1015     {
1016     case TYPE (TIMELINE):
1017       ts = (TimelineSelections *) self;
1018       GET_END_POS (
1019         ts, ZRegion, region);
1020       GET_END_POS (
1021         ts, ScaleObject, scale_object);
1022       GET_END_POS (
1023         ts, Marker, marker);
1024       break;
1025     case TYPE (MIDI):
1026       mas = (MidiArrangerSelections *) self;
1027       GET_END_POS (
1028         mas, MidiNote, midi_note);
1029       if (global)
1030         {
1031           add_region_ticks (self, pos);
1032         }
1033       break;
1034     case TYPE (AUTOMATION):
1035       as = (AutomationSelections *) self;
1036       GET_END_POS (
1037         as, AutomationPoint, automation_point);
1038       if (global)
1039         {
1040           add_region_ticks (self, pos);
1041         }
1042       break;
1043     case TYPE (CHORD):
1044       cs = (ChordSelections *) self;
1045       GET_END_POS (
1046         cs, ChordObject, chord_object);
1047       if (global)
1048         {
1049           add_region_ticks (self, pos);
1050         }
1051       break;
1052     default:
1053       g_return_if_reached ();
1054     }
1055 
1056 #undef GET_END_POS
1057 }
1058 
1059 /**
1060  * Adds each object in the selection to the given
1061  * region (if applicable).
1062  */
1063 void
arranger_selections_add_to_region(ArrangerSelections * self,ZRegion * region)1064 arranger_selections_add_to_region (
1065   ArrangerSelections * self,
1066   ZRegion *            region)
1067 {
1068   switch (self->type)
1069     {
1070     case TYPE (MIDI):
1071       {
1072         MidiArrangerSelections * mas =
1073           (MidiArrangerSelections *) self;
1074         for (int i = 0; i < mas->num_midi_notes;
1075              i++)
1076           {
1077             ArrangerObject * obj =
1078               (ArrangerObject *) mas->midi_notes[i];
1079             region_add_arranger_object (
1080               region, obj, F_NO_PUBLISH_EVENTS);
1081           }
1082       }
1083       break;
1084     case TYPE (AUTOMATION):
1085       {
1086         AutomationSelections * as =
1087           (AutomationSelections *) self;
1088         for (int i = 0;
1089              i < as->num_automation_points; i++)
1090           {
1091             ArrangerObject * obj =
1092               (ArrangerObject *)
1093               as->automation_points[i];
1094             region_add_arranger_object (
1095               region, obj, F_NO_PUBLISH_EVENTS);
1096           }
1097       }
1098       break;
1099     case TYPE (CHORD):
1100       {
1101         ChordSelections * cs =
1102           (ChordSelections *) self;
1103         for (int i = 0;
1104              i < cs->num_chord_objects; i++)
1105           {
1106             ArrangerObject * obj =
1107               (ArrangerObject *)
1108               cs->chord_objects[i];
1109             region_add_arranger_object (
1110               region, obj, F_NO_PUBLISH_EVENTS);
1111           }
1112       }
1113       break;
1114     default:
1115       g_return_if_reached ();
1116     }
1117 }
1118 
1119 /**
1120  * Gets first object.
1121  */
1122 ArrangerObject *
arranger_selections_get_first_object(ArrangerSelections * self)1123 arranger_selections_get_first_object (
1124   ArrangerSelections * self)
1125 {
1126   int i;
1127   TimelineSelections * ts;
1128   ChordSelections * cs;
1129   MidiArrangerSelections * mas;
1130   AutomationSelections * as;
1131 
1132   Position pos;
1133   position_set_to_bar (&pos, 80000);
1134   ArrangerObject * ret_obj = NULL;
1135 
1136 #define GET_FIRST_OBJ(sel,cc,sc) \
1137   for (i = 0; i < (sel)->num_##sc##s; i++) \
1138     { \
1139       cc * sc = (sel)->sc##s[i]; \
1140       ArrangerObject * obj = (ArrangerObject *) sc; \
1141       g_warn_if_fail (obj); \
1142       if (position_is_before ( \
1143             &obj->pos, &pos)) \
1144         { \
1145           position_set_to_pos ( \
1146             &pos, &obj->pos); \
1147           ret_obj = obj; \
1148         } \
1149     }
1150 
1151   switch (self->type)
1152     {
1153     case TYPE (TIMELINE):
1154       ts = (TimelineSelections *) self;
1155       GET_FIRST_OBJ (
1156         ts, ZRegion, region);
1157       GET_FIRST_OBJ (
1158         ts, ScaleObject, scale_object);
1159       GET_FIRST_OBJ (
1160         ts, Marker, marker);
1161       break;
1162     case TYPE (MIDI):
1163       mas = (MidiArrangerSelections *) self;
1164       GET_FIRST_OBJ (
1165         mas, MidiNote, midi_note);
1166       break;
1167     case TYPE (AUTOMATION):
1168       as = (AutomationSelections *) self;
1169       GET_FIRST_OBJ (
1170         as, AutomationPoint, automation_point);
1171       break;
1172     case TYPE (CHORD):
1173       cs = (ChordSelections *) self;
1174       GET_FIRST_OBJ (
1175         cs, ChordObject, chord_object);
1176       break;
1177     default:
1178       g_return_val_if_reached (NULL);
1179     }
1180 
1181   return ret_obj;
1182 
1183 #undef GET_FIRST_OBJ
1184 }
1185 
1186 /**
1187  * Gets last object.
1188  */
1189 ArrangerObject *
arranger_selections_get_last_object(ArrangerSelections * self)1190 arranger_selections_get_last_object (
1191   ArrangerSelections * self)
1192 {
1193   int i;
1194   TimelineSelections * ts;
1195   ChordSelections * cs;
1196   MidiArrangerSelections * mas;
1197   AutomationSelections * as;
1198 
1199   Position pos;
1200   position_set_to_bar (&pos, - POSITION_MAX_BAR);
1201   ArrangerObject * ret_obj = NULL;
1202 
1203 #define GET_LAST_OBJ(sel,cc,sc) \
1204   for (i = 0; i < (sel)->num_##sc##s; i++) \
1205     { \
1206       cc * sc = (sel)->sc##s[i]; \
1207       ArrangerObject * obj = (ArrangerObject *) sc; \
1208       g_warn_if_fail (obj); \
1209       if (arranger_object_type_has_length ( \
1210             obj->type)) \
1211         { \
1212           if (position_is_after ( \
1213                 &obj->end_pos, &pos)) \
1214             { \
1215               position_set_to_pos ( \
1216                 &pos, &obj->end_pos); \
1217               ret_obj = obj; \
1218             } \
1219         } \
1220       else \
1221         { \
1222           if (position_is_after ( \
1223                 &obj->pos, &pos)) \
1224             { \
1225               position_set_to_pos ( \
1226                 &pos, &obj->pos); \
1227               ret_obj = obj; \
1228             } \
1229         } \
1230     }
1231 
1232   switch (self->type)
1233     {
1234     case TYPE (TIMELINE):
1235       ts = (TimelineSelections *) self;
1236       GET_LAST_OBJ (
1237         ts, ZRegion, region);
1238       GET_LAST_OBJ (
1239         ts, ScaleObject, scale_object);
1240       GET_LAST_OBJ (
1241         ts, Marker, marker);
1242       break;
1243     case TYPE (MIDI):
1244       mas = (MidiArrangerSelections *) self;
1245       GET_LAST_OBJ (
1246         mas, MidiNote, midi_note);
1247       break;
1248     case TYPE (AUTOMATION):
1249       as = (AutomationSelections *) self;
1250       GET_LAST_OBJ (
1251         as, AutomationPoint, automation_point);
1252       break;
1253     case TYPE (CHORD):
1254       cs = (ChordSelections *) self;
1255       GET_LAST_OBJ (
1256         cs, ChordObject, chord_object);
1257       break;
1258     default:
1259       g_return_val_if_reached (NULL);
1260     }
1261 
1262   return ret_obj;
1263 
1264 #undef GET_LAST_OBJ
1265 }
1266 
1267 /**
1268  * Moves the selections by the given
1269  * amount of ticks.
1270  *
1271  * @param ticks Ticks to add.
1272  */
1273 void
arranger_selections_add_ticks(ArrangerSelections * self,const double ticks)1274 arranger_selections_add_ticks (
1275   ArrangerSelections *     self,
1276   const double             ticks)
1277 {
1278   int i;
1279   TimelineSelections * ts;
1280   ChordSelections * cs;
1281   MidiArrangerSelections * mas;
1282   AutomationSelections * as;
1283 
1284 #define ADD_TICKS(sel,sc) \
1285   for (i = 0; i < sel->num_##sc##s; i++) \
1286     { \
1287       ArrangerObject * sc = \
1288         (ArrangerObject *) sel->sc##s[i]; \
1289       arranger_object_move (sc, ticks); \
1290     }
1291 
1292   switch (self->type)
1293     {
1294     case TYPE (TIMELINE):
1295       ts = (TimelineSelections *) self;
1296       ADD_TICKS (
1297         ts, region);
1298       ADD_TICKS (
1299         ts, scale_object);
1300       ADD_TICKS (
1301         ts, marker);
1302       break;
1303     case TYPE (MIDI):
1304       mas = (MidiArrangerSelections *) self;
1305       ADD_TICKS (
1306         mas, midi_note);
1307       break;
1308     case TYPE (AUTOMATION):
1309       as = (AutomationSelections *) self;
1310       ADD_TICKS (
1311         as, automation_point);
1312       break;
1313     case TYPE (CHORD):
1314       cs = (ChordSelections *) self;
1315       ADD_TICKS (
1316         cs, chord_object);
1317       break;
1318     default:
1319       g_return_if_reached ();
1320     }
1321 
1322 #undef ADD_TICKS
1323 }
1324 
1325 /**
1326  * Selects all possible objects from the project.
1327  */
1328 void
arranger_selections_select_all(ArrangerSelections * self,bool fire_events)1329 arranger_selections_select_all (
1330   ArrangerSelections * self,
1331   bool                 fire_events)
1332 {
1333   arranger_selections_clear (
1334     self, F_NO_FREE, F_NO_PUBLISH_EVENTS);
1335 
1336   ZRegion * r =
1337     clip_editor_get_region (CLIP_EDITOR);
1338 
1339   ArrangerObject * obj = NULL;
1340   switch (self->type)
1341     {
1342     case ARRANGER_SELECTIONS_TYPE_TIMELINE:
1343       /* midi/audio regions */
1344       for (int i = 0;
1345            i < TRACKLIST->num_tracks;
1346            i++)
1347         {
1348           Track * track = TRACKLIST->tracks[i];
1349           for (int j = 0;
1350                j < track->num_lanes; j++)
1351             {
1352               TrackLane * lane =
1353                 track->lanes[j];
1354               for (int k = 0;
1355                    k < lane->num_regions;
1356                    k++)
1357                 {
1358                   obj =
1359                     (ArrangerObject *)
1360                     lane->regions[k];
1361                   arranger_object_select (
1362                     obj, F_SELECT, F_APPEND,
1363                     F_NO_PUBLISH_EVENTS);
1364                 }
1365             }
1366 
1367           /* automation regions */
1368           AutomationTracklist * atl =
1369             track_get_automation_tracklist (
1370               track);
1371           if (atl &&
1372               track->automation_visible)
1373             {
1374               for (int j = 0;
1375                    j < atl->num_ats;
1376                    j++)
1377                 {
1378                   AutomationTrack * at =
1379                     atl->ats[j];
1380 
1381                   if (!at->visible)
1382                     continue;
1383 
1384                   for (int k = 0;
1385                        k < at->num_regions;
1386                        k++)
1387                     {
1388                       obj =
1389                         (ArrangerObject *)
1390                         at->regions[k];
1391                       arranger_object_select (
1392                         obj, F_SELECT, F_APPEND,
1393                         F_NO_PUBLISH_EVENTS);
1394                     }
1395                 }
1396             }
1397         }
1398 
1399       /* chord regions */
1400       for (int j = 0;
1401            j < P_CHORD_TRACK->num_chord_regions;
1402            j++)
1403         {
1404           ZRegion * cr =
1405             P_CHORD_TRACK->chord_regions[j];
1406           obj = (ArrangerObject *) cr;
1407           arranger_object_select (
1408             obj, F_SELECT, F_APPEND,
1409             F_NO_PUBLISH_EVENTS);
1410         }
1411 
1412       /* scales */
1413       for (int i = 0;
1414            i < P_CHORD_TRACK->num_scales; i++)
1415         {
1416           obj =
1417             (ArrangerObject *)
1418             P_CHORD_TRACK->scales[i];
1419           arranger_object_select (
1420             obj, F_SELECT, F_APPEND,
1421             F_NO_PUBLISH_EVENTS);
1422         }
1423 
1424       /* markers */
1425       for (int j = 0;
1426            j < P_MARKER_TRACK->num_markers;
1427            j++)
1428         {
1429           Marker * marker =
1430             P_MARKER_TRACK->markers[j];
1431           obj =
1432             (ArrangerObject *) marker;
1433           arranger_object_select (
1434             obj, F_SELECT, F_APPEND,
1435             F_NO_PUBLISH_EVENTS);
1436         }
1437       break;
1438     case ARRANGER_SELECTIONS_TYPE_CHORD:
1439       if (!r || r->id.type != REGION_TYPE_CHORD)
1440         break;
1441 
1442       for (int i = 0; i < r->num_chord_objects;
1443            i++)
1444         {
1445           ChordObject * co =
1446             r->chord_objects[i];
1447           obj =
1448             (ArrangerObject *) co;
1449           g_return_if_fail (
1450             co->chord_index <
1451             CHORD_EDITOR->num_chords);
1452           arranger_object_select (
1453             obj, F_SELECT, F_APPEND,
1454             F_NO_PUBLISH_EVENTS);
1455         }
1456       break;
1457     case ARRANGER_SELECTIONS_TYPE_MIDI:
1458       if (!r || r->id.type != REGION_TYPE_MIDI)
1459         break;
1460 
1461       for (int i = 0; i < r->num_midi_notes;
1462            i++)
1463         {
1464           MidiNote * mn = r->midi_notes[i];
1465           obj =
1466             (ArrangerObject *)
1467             mn;
1468           arranger_object_select (
1469             obj, F_SELECT, F_APPEND,
1470             F_NO_PUBLISH_EVENTS);
1471         }
1472       break;
1473       break;
1474     case ARRANGER_SELECTIONS_TYPE_AUDIO:
1475       /* no objects in audio arranger yet */
1476       break;
1477     case ARRANGER_SELECTIONS_TYPE_AUTOMATION:
1478       if (!r ||
1479           r->id.type != REGION_TYPE_AUTOMATION)
1480         break;
1481 
1482       for (int i = 0; i < r->num_aps; i++)
1483         {
1484           AutomationPoint * ap =  r->aps[i];
1485           obj = (ArrangerObject *) ap;
1486           arranger_object_select (
1487             obj, F_SELECT, F_APPEND,
1488             F_NO_PUBLISH_EVENTS);
1489         }
1490       break;
1491     default:
1492       g_return_if_reached ();
1493       break;
1494     }
1495 
1496   if (fire_events)
1497     {
1498       EVENTS_PUSH (
1499         ET_ARRANGER_SELECTIONS_CHANGED, self);
1500     }
1501 }
1502 
1503 /**
1504  * Clears selections.
1505  */
1506 void
arranger_selections_clear(ArrangerSelections * self,bool _free,bool fire_events)1507 arranger_selections_clear (
1508   ArrangerSelections * self,
1509   bool                 _free,
1510   bool                 fire_events)
1511 {
1512   if (!arranger_selections_has_any (self))
1513     {
1514       return;
1515     }
1516 
1517   int i;
1518   TimelineSelections * ts;
1519   ChordSelections * cs;
1520   MidiArrangerSelections * mas;
1521   AutomationSelections * as;
1522 
1523 /* use caches because ts->* will be operated on. */
1524 #define REMOVE_OBJS(sel,sc) \
1525   { \
1526     g_message ( \
1527       "%s", "clearing " #sc " selections"); \
1528     int num_##sc##s = sel->num_##sc##s; \
1529     ArrangerObject * sc##s[num_##sc##s]; \
1530     for (i = 0; i < num_##sc##s; i++) \
1531       { \
1532         sc##s[i] = \
1533           (ArrangerObject *) sel->sc##s[i]; \
1534       } \
1535     for (i = 0; i < num_##sc##s; i++) \
1536       { \
1537         ArrangerObject * sc = sc##s[i]; \
1538         arranger_selections_remove_object ( \
1539           self, sc); \
1540         if (_free) \
1541           { \
1542             arranger_object_free (sc); \
1543           } \
1544         else if (fire_events) \
1545           { \
1546             EVENTS_PUSH ( \
1547               ET_ARRANGER_OBJECT_CHANGED, sc); \
1548           } \
1549       } \
1550   }
1551 
1552   switch (self->type)
1553     {
1554     case TYPE (TIMELINE):
1555       ts = (TimelineSelections *) self;
1556       REMOVE_OBJS (
1557         ts, region);
1558       REMOVE_OBJS (
1559         ts, scale_object);
1560       REMOVE_OBJS (
1561         ts, marker);
1562       break;
1563     case TYPE (MIDI):
1564       mas = (MidiArrangerSelections *) self;
1565       REMOVE_OBJS (
1566         mas, midi_note);
1567       break;
1568     case TYPE (AUTOMATION):
1569       as = (AutomationSelections *) self;
1570       REMOVE_OBJS (
1571         as, automation_point);
1572       break;
1573     case TYPE (CHORD):
1574       cs = (ChordSelections *) self;
1575       REMOVE_OBJS (
1576         cs, chord_object);
1577       break;
1578     default:
1579       g_return_if_reached ();
1580     }
1581 
1582 #undef REMOVE_OBJS
1583 }
1584 
1585 /**
1586  * Returns the number of selected objects.
1587  */
1588 int
arranger_selections_get_num_objects(const ArrangerSelections * self)1589 arranger_selections_get_num_objects (
1590   const ArrangerSelections * self)
1591 {
1592   TimelineSelections * ts;
1593   ChordSelections * cs;
1594   MidiArrangerSelections * mas;
1595   AutomationSelections * as;
1596 
1597   int size = 0;
1598 
1599 #define ADD_OBJ(sel,sc) \
1600   for (int i = 0; i < sel->num_##sc##s; i++) \
1601     { \
1602       size++; \
1603     }
1604 
1605   switch (self->type)
1606     {
1607     case TYPE (TIMELINE):
1608       ts = (TimelineSelections *) self;
1609       ADD_OBJ (
1610         ts, region);
1611       ADD_OBJ (
1612         ts, scale_object);
1613       ADD_OBJ (
1614         ts, marker);
1615       break;
1616     case TYPE (MIDI):
1617       mas = (MidiArrangerSelections *) self;
1618       ADD_OBJ (
1619         mas, midi_note);
1620       break;
1621     case TYPE (AUTOMATION):
1622       as = (AutomationSelections *) self;
1623       ADD_OBJ (
1624         as, automation_point);
1625       break;
1626     case TYPE (CHORD):
1627       cs = (ChordSelections *) self;
1628       ADD_OBJ (
1629         cs, chord_object);
1630       break;
1631     default:
1632       g_return_val_if_reached (-1);
1633     }
1634 #undef ADD_OBJ
1635 
1636   return size;
1637 }
1638 
1639 /**
1640  * Code to run after deserializing.
1641  */
1642 void
arranger_selections_post_deserialize(ArrangerSelections * self)1643 arranger_selections_post_deserialize (
1644   ArrangerSelections * self)
1645 {
1646   int i;
1647   TimelineSelections * ts;
1648   ChordSelections * cs;
1649   MidiArrangerSelections * mas;
1650   AutomationSelections * as;
1651 
1652   self->magic = ARRANGER_SELECTIONS_MAGIC;
1653 
1654 /* use caches because ts->* will be operated on. */
1655 #define POST_DESERIALIZE(sel,sc) \
1656   for (i = 0; i < sel->num_##sc##s; i++) \
1657     { \
1658       arranger_object_post_deserialize ( \
1659         (ArrangerObject *) \
1660         sel->sc##s[i]); \
1661     } \
1662 
1663   switch (self->type)
1664     {
1665     case TYPE (TIMELINE):
1666       ts = (TimelineSelections *) self;
1667       POST_DESERIALIZE (
1668         ts, region);
1669       POST_DESERIALIZE (
1670         ts, scale_object);
1671       POST_DESERIALIZE (
1672         ts, marker);
1673       break;
1674     case TYPE (MIDI):
1675       mas = (MidiArrangerSelections *) self;
1676       POST_DESERIALIZE (
1677         mas, midi_note);
1678       break;
1679     case TYPE (AUTOMATION):
1680       as = (AutomationSelections *) self;
1681       POST_DESERIALIZE (
1682         as, automation_point);
1683       break;
1684     case TYPE (CHORD):
1685       cs = (ChordSelections *) self;
1686       POST_DESERIALIZE (
1687         cs, chord_object);
1688       break;
1689     default:
1690       g_return_if_reached ();
1691     }
1692 
1693 #undef POST_DESERIALIZE
1694 }
1695 
1696 bool
arranger_selections_validate(ArrangerSelections * self)1697 arranger_selections_validate (
1698   ArrangerSelections * self)
1699 {
1700   TimelineSelections * ts;
1701   ChordSelections * cs;
1702   MidiArrangerSelections * mas;
1703   AutomationSelections * as;
1704   AudioSelections * aus;
1705 
1706   switch (self->type)
1707     {
1708     case TYPE (TIMELINE):
1709       ts = (TimelineSelections *) self;
1710       (void) ts;
1711       break;
1712     case TYPE (MIDI):
1713       mas = (MidiArrangerSelections *) self;
1714       (void) mas;
1715       break;
1716     case TYPE (AUTOMATION):
1717       as = (AutomationSelections *) self;
1718       (void) as;
1719       break;
1720     case TYPE (CHORD):
1721       cs = (ChordSelections *) self;
1722       (void) cs;
1723       break;
1724     case TYPE (AUDIO):
1725       {
1726         aus = (AudioSelections *) self;
1727         ZRegion * r = region_find (&aus->region_id);
1728         g_return_val_if_fail (
1729           IS_REGION_AND_NONNULL (r), false);
1730         if (position_is_before (
1731               &aus->sel_start, &r->base.pos)
1732             ||
1733             position_is_after_or_equal (
1734               &aus->sel_end, &r->base.end_pos))
1735           return false;
1736       }
1737       break;
1738     default:
1739       g_return_val_if_reached (false);
1740     }
1741 
1742   return true;
1743 }
1744 
1745 /**
1746  * Frees anything allocated by the selections
1747  * but not the objects or @ref self itself.
1748  */
1749 void
arranger_selections_free_members(ArrangerSelections * self)1750 arranger_selections_free_members (
1751   ArrangerSelections * self)
1752 {
1753   TimelineSelections * ts;
1754   ChordSelections * cs;
1755   MidiArrangerSelections * mas;
1756   AutomationSelections * as;
1757 
1758   switch (self->type)
1759     {
1760     case TYPE (TIMELINE):
1761       ts = (TimelineSelections *) self;
1762       free (ts->regions);
1763       free (ts->scale_objects);
1764       free (ts->markers);
1765       break;
1766     case TYPE (MIDI):
1767       mas = (MidiArrangerSelections *) self;
1768       free (mas->midi_notes);
1769       break;
1770     case TYPE (AUTOMATION):
1771       as = (AutomationSelections *) self;
1772       free (as->automation_points);
1773       break;
1774     case TYPE (CHORD):
1775       cs = (ChordSelections *) self;
1776       free (cs->chord_objects);
1777       break;
1778     case TYPE (AUDIO):
1779       /* nothing to free */
1780       break;
1781     default:
1782       g_return_if_reached ();
1783     }
1784 }
1785 
1786 /**
1787  * Frees the selections but not the objects.
1788  */
1789 void
arranger_selections_free(ArrangerSelections * self)1790 arranger_selections_free (
1791   ArrangerSelections * self)
1792 {
1793   arranger_selections_free_members (self);
1794   object_zero_and_free (self);
1795 }
1796 
1797 /**
1798  * Frees all the objects as well.
1799  *
1800  * To be used in actions where the selections are
1801  * all clones.
1802  */
1803 void
arranger_selections_free_full(ArrangerSelections * self)1804 arranger_selections_free_full (
1805   ArrangerSelections * self)
1806 {
1807   g_return_if_fail (IS_ARRANGER_SELECTIONS (self));
1808 
1809   g_debug (
1810     "freeing arranger selections %p...", self);
1811 
1812   int i;
1813   TimelineSelections * ts;
1814   ChordSelections * cs;
1815   MidiArrangerSelections * mas;
1816   AutomationSelections * as;
1817 
1818 /* use caches because ts->* will be operated on. */
1819 #define FREE_OBJS(sel,sc) \
1820   for (i = 0; i < sel->num_##sc##s; i++) \
1821     { \
1822       object_free_w_func_and_null_cast ( \
1823         arranger_object_free, \
1824         ArrangerObject *, sel->sc##s[i]); \
1825     } \
1826   object_zero_and_free (sel->sc##s); \
1827   sel->num_##sc##s = 0
1828 
1829   switch (self->type)
1830     {
1831     case TYPE (TIMELINE):
1832       ts = (TimelineSelections *) self;
1833       FREE_OBJS (
1834         ts, region);
1835       FREE_OBJS (
1836         ts, scale_object);
1837       FREE_OBJS (
1838         ts, marker);
1839       break;
1840     case TYPE (MIDI):
1841       mas = (MidiArrangerSelections *) self;
1842       FREE_OBJS (
1843         mas, midi_note);
1844       break;
1845     case TYPE (AUTOMATION):
1846       as = (AutomationSelections *) self;
1847       FREE_OBJS (
1848         as, automation_point);
1849       break;
1850     case TYPE (CHORD):
1851       cs = (ChordSelections *) self;
1852       FREE_OBJS (
1853         cs, chord_object);
1854       break;
1855     case TYPE (AUDIO):
1856       /* nothing to free */
1857       break;
1858     default:
1859       g_return_if_reached ();
1860     }
1861 
1862 #undef FREE_OBJS
1863 
1864   object_zero_and_free (self);
1865 }
1866 
1867 /**
1868  * Returns if the arranger object is in the
1869  * selections or  not.
1870  *
1871  * The object must be the main object (see
1872  * ArrangerObjectInfo).
1873  */
1874 int
arranger_selections_contains_object(ArrangerSelections * self,ArrangerObject * obj)1875 arranger_selections_contains_object (
1876   ArrangerSelections * self,
1877   ArrangerObject *     obj)
1878 {
1879   TimelineSelections * ts;
1880   ChordSelections * cs;
1881   MidiArrangerSelections * mas;
1882   AutomationSelections * as;
1883 
1884   g_return_val_if_fail (
1885     IS_ARRANGER_SELECTIONS (self), 0);
1886 
1887   switch (self->type)
1888     {
1889     case TYPE (TIMELINE):
1890       ts = (TimelineSelections *) self;
1891       switch (obj->type)
1892         {
1893         case ARRANGER_OBJECT_TYPE_REGION:
1894           return
1895             array_contains (
1896               ts->regions, ts->num_regions, obj);
1897           break;
1898         case ARRANGER_OBJECT_TYPE_SCALE_OBJECT:
1899           return
1900             array_contains (
1901               ts->scale_objects,
1902               ts->num_scale_objects, obj);
1903           break;
1904         case ARRANGER_OBJECT_TYPE_MARKER:
1905           return
1906             array_contains (
1907               ts->markers,
1908               ts->num_markers, obj);
1909           break;
1910         default:
1911           break;
1912         }
1913       break;
1914     case TYPE (MIDI):
1915       {
1916         mas = (MidiArrangerSelections *) self;
1917         switch (obj->type)
1918           {
1919           case ARRANGER_OBJECT_TYPE_VELOCITY:
1920             {
1921               Velocity * vel =
1922                 (Velocity *) obj;
1923               MidiNote * mn =
1924                 velocity_get_midi_note (vel);
1925               return
1926                 array_contains (
1927                   mas->midi_notes,
1928                   mas->num_midi_notes,
1929                   mn);
1930             }
1931             break;
1932           case ARRANGER_OBJECT_TYPE_MIDI_NOTE:
1933             {
1934               return
1935                 array_contains (
1936                   mas->midi_notes,
1937                   mas->num_midi_notes, obj);
1938             }
1939             break;
1940           default:
1941             g_return_val_if_reached (-1);
1942           }
1943       }
1944       break;
1945     case TYPE (AUTOMATION):
1946       as = (AutomationSelections *) self;
1947       switch (obj->type)
1948         {
1949         case ARRANGER_OBJECT_TYPE_AUTOMATION_POINT:
1950           {
1951             return
1952               array_contains (
1953                 as->automation_points,
1954                 as->num_automation_points, obj);
1955           }
1956           break;
1957         default:
1958           g_return_val_if_reached (-1);
1959         }
1960       break;
1961     case TYPE (CHORD):
1962       cs = (ChordSelections *) self;
1963       if (obj->type ==
1964             ARRANGER_OBJECT_TYPE_CHORD_OBJECT)
1965         {
1966           return
1967             array_contains (
1968               cs->chord_objects,
1969               cs->num_chord_objects, obj);
1970         }
1971       break;
1972     default:
1973       g_return_val_if_reached (0);
1974     }
1975 
1976   g_return_val_if_reached (0);
1977 }
1978 
1979 /**
1980  * Returns if the selections contain an undeletable
1981  * object (such as the start marker).
1982  */
1983 bool
arranger_selections_contains_undeletable_object(ArrangerSelections * self)1984 arranger_selections_contains_undeletable_object (
1985   ArrangerSelections * self)
1986 {
1987   switch (self->type)
1988     {
1989     case ARRANGER_SELECTIONS_TYPE_TIMELINE:
1990       {
1991         TimelineSelections * tl_sel =
1992           (TimelineSelections *) self;
1993         for (int i = 0; i < tl_sel->num_markers;
1994              i++)
1995           {
1996             Marker * m = tl_sel->markers[i];
1997             if (!marker_is_deletable (m))
1998               {
1999                 return true;
2000               }
2001           }
2002       }
2003       break;
2004     default:
2005       return false;
2006     }
2007   return false;
2008 }
2009 
2010 /**
2011  * Checks whether an object matches the given
2012  * parameters.
2013  *
2014  * If a parameter should be checked, the has_*
2015  * argument must be true and the corresponding
2016  * argument must have the value to be checked
2017  * against.
2018  */
2019 bool
arranger_selections_contains_object_with_property(ArrangerSelections * self,ArrangerSelectionsProperty property,bool value)2020 arranger_selections_contains_object_with_property (
2021   ArrangerSelections *       self,
2022   ArrangerSelectionsProperty property,
2023   bool                       value)
2024 {
2025   int num_objs;
2026   ArrangerObject ** objs =
2027     arranger_selections_get_all_objects (
2028       self, &num_objs);
2029 
2030 #define CHECK_PROP(x) \
2031   (property == ARRANGER_SELECTIONS_PROPERTY_##x)
2032 
2033   bool ret = false;
2034   for (int i = 0; i < num_objs; i++)
2035     {
2036       ArrangerObject * cur_obj = objs[i];
2037 
2038       if (CHECK_PROP (HAS_LENGTH)
2039           &&
2040           arranger_object_type_has_length (
2041             cur_obj->type) == value)
2042         {
2043           ret = true;
2044           break;
2045         }
2046 
2047       if (CHECK_PROP (HAS_LOOPED))
2048         {
2049           int num_loops =
2050             arranger_object_type_can_loop (
2051               cur_obj->type)
2052             ?
2053             arranger_object_get_num_loops (
2054               cur_obj, false)
2055             : 0;
2056           if ((num_loops > 0) == value)
2057             {
2058               ret = true;
2059               break;
2060             }
2061         }
2062 
2063       if (CHECK_PROP (CAN_LOOP)
2064           &&
2065           arranger_object_type_can_loop (
2066             cur_obj->type) == value)
2067         {
2068           ret = true;
2069           break;
2070         }
2071 
2072       if (CHECK_PROP (CAN_FADE)
2073           &&
2074           arranger_object_can_fade (cur_obj)
2075             == value)
2076         {
2077           ret = true;
2078           break;
2079         }
2080     }
2081 
2082 #undef CHECK_PROP
2083 
2084   free (objs);
2085   return ret;
2086 }
2087 
2088 /**
2089  * Removes the arranger object from the selections.
2090  */
2091 void
arranger_selections_remove_object(ArrangerSelections * self,ArrangerObject * obj)2092 arranger_selections_remove_object (
2093   ArrangerSelections * self,
2094   ArrangerObject *     obj)
2095 {
2096   g_return_if_fail (
2097     IS_ARRANGER_SELECTIONS (self) &&
2098     IS_ARRANGER_OBJECT (obj));
2099 
2100   TimelineSelections * ts;
2101   ChordSelections * cs;
2102   MidiArrangerSelections * mas;
2103   AutomationSelections * as;
2104 
2105 #define REMOVE_OBJ(sel,caps,sc) \
2106   if (obj->type == ARRANGER_OBJECT_TYPE_##caps && \
2107       array_contains ( \
2108         sel->sc##s, sel->num_##sc##s, obj)) \
2109     { \
2110       array_delete ( \
2111         sel->sc##s, sel->num_##sc##s, obj); \
2112     }
2113 
2114   switch (self->type)
2115     {
2116     case TYPE (TIMELINE):
2117       ts = (TimelineSelections *) self;
2118       REMOVE_OBJ (
2119         ts, REGION, region);
2120       REMOVE_OBJ (
2121         ts, SCALE_OBJECT, scale_object);
2122       REMOVE_OBJ (
2123         ts, MARKER, marker);
2124       break;
2125     case TYPE (MIDI):
2126       mas = (MidiArrangerSelections *) self;
2127       if (obj->type ==
2128             ARRANGER_OBJECT_TYPE_VELOCITY)
2129         {
2130           Velocity * vel = (Velocity *) obj;
2131           obj =
2132             (ArrangerObject *)
2133             velocity_get_midi_note (vel);
2134         }
2135       REMOVE_OBJ (
2136         mas, MIDI_NOTE, midi_note);
2137       break;
2138     case TYPE (AUTOMATION):
2139       as = (AutomationSelections *) self;
2140       REMOVE_OBJ (
2141         as, AUTOMATION_POINT, automation_point);
2142       break;
2143     case TYPE (CHORD):
2144       cs = (ChordSelections *) self;
2145       REMOVE_OBJ (
2146         cs, CHORD_OBJECT, chord_object);
2147       break;
2148     default:
2149       g_return_if_reached ();
2150     }
2151 #undef REMOVE_OBJ
2152 }
2153 
2154 double
arranger_selections_get_length_in_ticks(ArrangerSelections * self)2155 arranger_selections_get_length_in_ticks (
2156   ArrangerSelections * self)
2157 {
2158   g_return_val_if_fail (
2159     IS_ARRANGER_SELECTIONS (self), 0);
2160 
2161   Position p1, p2;
2162   arranger_selections_get_start_pos (
2163     self, &p1, F_GLOBAL);
2164   arranger_selections_get_end_pos (
2165     self, &p2, F_GLOBAL);
2166 
2167   return p2.ticks - p1.ticks;
2168 }
2169 
2170 /**
2171  * Returns whether all the selections are on the
2172  * same lane (track lane or automation lane).
2173  */
2174 bool
arranger_selections_all_on_same_lane(ArrangerSelections * self)2175 arranger_selections_all_on_same_lane (
2176   ArrangerSelections * self)
2177 {
2178   bool ret = true;
2179   int size = 0;
2180   ArrangerObject ** objs =
2181     arranger_selections_get_all_objects (
2182       self, &size);
2183 
2184   /* return if not all regions on the same lane or
2185    * automation track */
2186   RegionIdentifier id;
2187   memset (&id, 0, sizeof (RegionIdentifier));
2188   id.type = -1;
2189   for (int i = 0; i < size; i++)
2190     {
2191       ArrangerObject * obj = objs[i];
2192       if (obj->type != ARRANGER_OBJECT_TYPE_REGION)
2193         {
2194           ret = false;
2195           goto free_objs_and_return;
2196         }
2197 
2198       /* verify that region is of same type as
2199        * first */
2200       ZRegion * r = (ZRegion *) obj;
2201       if (i == 0)
2202         {
2203           id = r->id;
2204         }
2205       else
2206         {
2207           if (id.type != r->id.type)
2208             {
2209               ret = false;
2210               goto free_objs_and_return;
2211             }
2212         }
2213 
2214       switch (id.type)
2215         {
2216         case REGION_TYPE_MIDI:
2217         case REGION_TYPE_AUDIO:
2218           if (r->id.track_name_hash !=
2219                 id.track_name_hash
2220               || r->id.lane_pos != id.lane_pos)
2221             {
2222               ret = false;
2223               goto free_objs_and_return;
2224             }
2225           break;
2226         case REGION_TYPE_CHORD:
2227           break;
2228         case REGION_TYPE_AUTOMATION:
2229           if (r->id.track_name_hash !=
2230                 id.track_name_hash
2231               || r->id.at_idx != id.at_idx)
2232             {
2233               ret = false;
2234               goto free_objs_and_return;
2235             }
2236           break;
2237         }
2238     }
2239 
2240 free_objs_and_return:
2241   free (objs);
2242 
2243   return ret;
2244 }
2245 
2246 /**
2247  * Merges the given selections into one region.
2248  *
2249  * @note All selections must be on the same lane.
2250  */
2251 void
arranger_selections_merge(ArrangerSelections * self)2252 arranger_selections_merge (
2253   ArrangerSelections * self)
2254 {
2255   /* return if not all regions on the same lane or
2256    * automation track */
2257   bool same_lane =
2258     arranger_selections_all_on_same_lane (self);
2259   if (!same_lane)
2260     {
2261       g_warning ("selections not on same lane");
2262       return;
2263     }
2264 
2265   int size = 0;
2266   ArrangerObject ** objs =
2267     arranger_selections_get_all_objects (
2268       self, &size);
2269 
2270   double ticks_length =
2271     arranger_selections_get_length_in_ticks (self);
2272   long num_frames =
2273     (long)
2274     ceil (
2275       (double) AUDIO_ENGINE->frames_per_tick *
2276       ticks_length);
2277   Position pos, end_pos;
2278   arranger_selections_get_start_pos (
2279     self, &pos, F_GLOBAL);
2280   position_from_ticks (
2281     &end_pos, pos.ticks + ticks_length);
2282 
2283   ArrangerObject * first_obj =
2284     arranger_selections_get_first_object (self);
2285   g_return_if_fail (
2286     IS_ARRANGER_OBJECT_AND_NONNULL (first_obj) &&
2287     first_obj->type == ARRANGER_OBJECT_TYPE_REGION);
2288   ZRegion * first_r = (ZRegion *) first_obj;
2289 
2290   ZRegion * new_r = NULL;
2291   switch (first_r->id.type)
2292     {
2293     case REGION_TYPE_MIDI:
2294       new_r =
2295         midi_region_new (
2296           &pos, &end_pos,
2297           first_r->id.track_name_hash,
2298           first_r->id.lane_pos, first_r->id.idx);
2299       for (int i = 0; i < size; i++)
2300         {
2301           ArrangerObject * r_obj = objs[i];
2302           ZRegion * r = (ZRegion *) r_obj;
2303           double ticks_diff =
2304             r_obj->pos.ticks -
2305               first_obj->pos.ticks;
2306 
2307           /* copy all midi notes */
2308           for (int j = 0; j < r->num_midi_notes;
2309                j++)
2310             {
2311               MidiNote * mn = r->midi_notes[j];
2312               ArrangerObject * new_obj =
2313                 arranger_object_clone (
2314                   (ArrangerObject *) mn);
2315               MidiNote * new_mn =
2316                 (MidiNote *) new_obj;
2317 
2318               /* move by diff from first object */
2319               arranger_object_move (
2320                 new_obj, ticks_diff);
2321 
2322               midi_region_add_midi_note (
2323                 new_r, new_mn, F_NO_PUBLISH_EVENTS);
2324             }
2325         }
2326       break;
2327     case REGION_TYPE_AUDIO:
2328       {
2329         float lframes[num_frames];
2330         float rframes[num_frames];
2331         float frames[num_frames * 2];
2332         dsp_fill (lframes, 0, (size_t) num_frames);
2333         dsp_fill (rframes, 0, (size_t) num_frames);
2334         AudioClip * first_r_clip =
2335           audio_region_get_clip (first_r);
2336         BitDepth max_depth =
2337           first_r_clip->bit_depth;
2338         g_warn_if_fail (first_r_clip->name);
2339         for (int i = 0; i < size; i++)
2340           {
2341             ArrangerObject * r_obj = objs[i];
2342             ZRegion * r = (ZRegion *) r_obj;
2343             long frames_diff =
2344               r_obj->pos.frames -
2345                 first_obj->pos.frames;
2346             long r_frames_length =
2347               arranger_object_get_length_in_frames (
2348                 r_obj);
2349 
2350             /* add all audio data */
2351             AudioClip * clip =
2352               audio_region_get_clip (r);
2353             dsp_add2 (
2354               &lframes[frames_diff],
2355               clip->ch_frames[0],
2356               (size_t) r_frames_length);
2357 
2358             if (clip->bit_depth > max_depth)
2359               {
2360                 max_depth = clip->bit_depth;
2361               }
2362           }
2363 
2364         /* interleave */
2365         for (long i = 0; i < num_frames; i++)
2366           {
2367             frames[i * 2] = lframes[i];
2368             frames[i * 2 + 1] = rframes[i];
2369           }
2370 
2371         /* create new region using frames */
2372         new_r =
2373           audio_region_new (
2374             -1, NULL, true, frames, num_frames,
2375             first_r_clip->name, 2, max_depth,
2376             &pos, first_r->id.track_name_hash,
2377             first_r->id.lane_pos, first_r->id.idx);
2378       }
2379       break;
2380     case REGION_TYPE_CHORD:
2381       new_r =
2382         chord_region_new (
2383           &pos, &end_pos, first_r->id.idx);
2384       for (int i = 0; i < size; i++)
2385         {
2386           ArrangerObject * r_obj = objs[i];
2387           ZRegion * r = (ZRegion *) r_obj;
2388           double ticks_diff =
2389             r_obj->pos.ticks -
2390               first_obj->pos.ticks;
2391 
2392           /* copy all chord objects */
2393           for (int j = 0; j < r->num_chord_objects;
2394                j++)
2395             {
2396               ChordObject * co =
2397                 r->chord_objects[j];
2398               ArrangerObject * new_obj =
2399                 arranger_object_clone (
2400                   (ArrangerObject *) co);
2401               ChordObject * new_co =
2402                 (ChordObject *) new_obj;
2403 
2404               /* move by diff from first object */
2405               arranger_object_move (
2406                 new_obj, ticks_diff);
2407 
2408               chord_region_add_chord_object (
2409                 new_r, new_co, F_NO_PUBLISH_EVENTS);
2410             }
2411         }
2412       break;
2413     case REGION_TYPE_AUTOMATION:
2414       new_r =
2415         automation_region_new (
2416           &pos, &end_pos,
2417           first_r->id.track_name_hash,
2418           first_r->id.at_idx, first_r->id.idx);
2419       for (int i = 0; i < size; i++)
2420         {
2421           ArrangerObject * r_obj = objs[i];
2422           ZRegion * r = (ZRegion *) r_obj;
2423           double ticks_diff =
2424             r_obj->pos.ticks -
2425               first_obj->pos.ticks;
2426 
2427           /* copy all chord objects */
2428           for (int j = 0; j < r->num_aps;
2429                j++)
2430             {
2431               AutomationPoint * ap = r->aps[j];
2432               ArrangerObject * new_obj =
2433                 arranger_object_clone (
2434                   (ArrangerObject *) ap);
2435               AutomationPoint * new_ap =
2436                 (AutomationPoint *) new_obj;
2437 
2438               /* move by diff from first object */
2439               arranger_object_move (
2440                 new_obj, ticks_diff);
2441 
2442               automation_region_add_ap (
2443                 new_r, new_ap, F_NO_PUBLISH_EVENTS);
2444             }
2445         }
2446       break;
2447     }
2448 
2449   region_gen_name (
2450     new_r, first_r->name, NULL, NULL);
2451 
2452   /* clear/free previous selections and add the
2453    * new region */
2454   arranger_selections_clear (
2455     self, F_FREE, F_NO_PUBLISH_EVENTS);
2456   arranger_selections_add_object (
2457     self, (ArrangerObject *) new_r);
2458 
2459   free (objs);
2460 }
2461 
2462 bool
arranger_selections_contains_looped(ArrangerSelections * self)2463 arranger_selections_contains_looped (
2464   ArrangerSelections * self)
2465 {
2466   if (self->type !=
2467         ARRANGER_SELECTIONS_TYPE_TIMELINE)
2468     return false;
2469 
2470   TimelineSelections * tl =
2471     (TimelineSelections *) self;
2472   for (int i = 0; i < tl->num_regions; i++)
2473     {
2474       ZRegion * r = tl->regions[i];
2475       if (region_is_looped (r))
2476         return true;
2477     }
2478 
2479   return false;
2480 }
2481 
2482 bool
arranger_selections_can_be_merged(ArrangerSelections * self)2483 arranger_selections_can_be_merged (
2484   ArrangerSelections * self)
2485 {
2486   if (self->type !=
2487         ARRANGER_SELECTIONS_TYPE_TIMELINE)
2488     return false;
2489 
2490   TimelineSelections * tl =
2491     (TimelineSelections *) self;
2492 
2493   return
2494     tl->num_regions > 1
2495     && arranger_selections_all_on_same_lane (self)
2496     && !arranger_selections_contains_looped (self);
2497 }
2498 
2499 /**
2500  * Returns if the selections can be pasted.
2501  */
2502 bool
arranger_selections_can_be_pasted(ArrangerSelections * self)2503 arranger_selections_can_be_pasted (
2504   ArrangerSelections * self)
2505 {
2506   ZRegion * r =
2507     clip_editor_get_region (CLIP_EDITOR);
2508   Position * pos = PLAYHEAD;
2509 
2510   switch (self->type)
2511     {
2512     case ARRANGER_SELECTIONS_TYPE_TIMELINE:
2513       return
2514         timeline_selections_can_be_pasted (
2515           (TimelineSelections *) self, pos,
2516           TRACKLIST_SELECTIONS->tracks[0]->pos);
2517     case ARRANGER_SELECTIONS_TYPE_CHORD:
2518       return
2519         chord_selections_can_be_pasted (
2520           (ChordSelections *) self, pos, r);
2521     case ARRANGER_SELECTIONS_TYPE_MIDI:
2522       return
2523         midi_arranger_selections_can_be_pasted (
2524           (MidiArrangerSelections *) self, pos, r);
2525     case ARRANGER_SELECTIONS_TYPE_AUTOMATION:
2526       return
2527         automation_selections_can_be_pasted (
2528           (AutomationSelections *) self, pos, r);
2529     default:
2530       g_return_val_if_reached (false);
2531       break;
2532     }
2533 
2534   return true;
2535 }
2536 
2537 /**
2538  * Pastes the given selections to the given
2539  * Position.
2540  */
2541 void
arranger_selections_paste_to_pos(ArrangerSelections * self,Position * pos,bool undoable)2542 arranger_selections_paste_to_pos (
2543   ArrangerSelections * self,
2544   Position *           pos,
2545   bool                 undoable)
2546 {
2547   g_return_if_fail (IS_ARRANGER_SELECTIONS (self));
2548 
2549   ArrangerSelections * clone_sel =
2550     arranger_selections_clone (self);
2551 
2552   /* clear current project selections */
2553   ArrangerSelections * project_sel =
2554     arranger_selections_get_for_type (self->type);
2555   arranger_selections_clear (
2556     project_sel, F_NO_FREE, F_NO_PUBLISH_EVENTS);
2557 
2558   Position first_obj_pos;
2559   arranger_selections_get_start_pos (
2560     clone_sel, &first_obj_pos, F_NOT_GLOBAL);
2561 
2562   /* if timeline selecctions */
2563   if (self->type ==
2564         ARRANGER_SELECTIONS_TYPE_TIMELINE)
2565     {
2566       TimelineSelections * ts =
2567         (TimelineSelections *) clone_sel;
2568       Track * track =
2569         TRACKLIST_SELECTIONS->tracks[0];
2570 
2571       arranger_selections_add_ticks (
2572         clone_sel,
2573         pos->ticks -
2574           first_obj_pos.ticks);
2575 
2576       /* add selections to track */
2577       for (int i = 0; i < ts->num_regions; i++)
2578         {
2579           ZRegion * r = ts->regions[i];
2580           g_critical ("FIXME get proper delta");
2581           Track * region_track =
2582             tracklist_get_visible_track_after_delta (
2583               TRACKLIST, track,
2584               /* used to be track pos stored in
2585                * region identifier */
2586               0);
2587           g_return_if_fail (region_track);
2588           AutomationTrack * at = NULL;
2589           if (r->id.type == REGION_TYPE_AUTOMATION)
2590             {
2591                 at =
2592                   region_track->
2593                     automation_tracklist.
2594                       ats[r->id.at_idx];
2595             }
2596           /* FIXME need to save visible automation
2597            * track offsets */
2598           track_add_region (
2599             track, r, at, at ? -1 : r->id.lane_pos,
2600             F_NO_GEN_NAME, F_NO_PUBLISH_EVENTS);
2601         }
2602 
2603       for (int i = 0; i < ts->num_scale_objects;
2604            i++)
2605         {
2606           ScaleObject * scale =
2607             ts->scale_objects[i];
2608           chord_track_add_scale (
2609             P_CHORD_TRACK, scale);
2610         }
2611       for (int i = 0; i < ts->num_markers; i++)
2612         {
2613           Marker * m = ts->markers[i];
2614           marker_track_add_marker (
2615             P_MARKER_TRACK, m);
2616         }
2617     }
2618   /* else if selections inside region */
2619   else
2620     {
2621       ZRegion * region =
2622         clip_editor_get_region (CLIP_EDITOR);
2623       ArrangerObject * r_obj =
2624         (ArrangerObject *) region;
2625 
2626       /* add selections to region */
2627       arranger_selections_add_to_region (
2628         clone_sel, region);
2629       arranger_selections_add_ticks (
2630         clone_sel,
2631         (pos->ticks -
2632           r_obj->pos.ticks) -
2633           first_obj_pos.ticks);
2634     }
2635 
2636   if (undoable)
2637     {
2638       GError * err = NULL;
2639       bool ret =
2640         arranger_selections_action_perform_create (
2641           clone_sel, &err);
2642       if (!ret)
2643         {
2644           HANDLE_ERROR (
2645             err, "%s",
2646             _("Failed to paste selections"));
2647         }
2648     }
2649 }
2650 
2651 /**
2652  * Returns all objects in the selections in a
2653  * newly allocated array that should be free'd.
2654  *
2655  * @param size A pointer to save the size into.
2656  */
2657 ArrangerObject **
arranger_selections_get_all_objects(ArrangerSelections * self,int * size)2658 arranger_selections_get_all_objects (
2659   ArrangerSelections * self,
2660   int *                size)
2661 {
2662   TimelineSelections * ts;
2663   ChordSelections * cs;
2664   MidiArrangerSelections * mas;
2665   AutomationSelections * as;
2666 
2667   ArrangerObject ** objs =
2668     object_new_n (1, ArrangerObject *);
2669   *size = 0;
2670 
2671 #define ADD_OBJ(sel,sc) \
2672   for (int i = 0; i < sel->num_##sc##s; i++) \
2673     { \
2674       ArrangerObject ** new_objs = \
2675         g_realloc ( \
2676           objs, \
2677           (size_t) (*size + 1) * \
2678             sizeof (ArrangerObject *)); \
2679       objs = new_objs; \
2680       objs[*size] = \
2681         (ArrangerObject *) sel->sc##s[i]; \
2682       (*size)++; \
2683     }
2684 
2685   switch (self->type)
2686     {
2687     case TYPE (TIMELINE):
2688       ts = (TimelineSelections *) self;
2689       ADD_OBJ (
2690         ts, region);
2691       ADD_OBJ (
2692         ts, scale_object);
2693       ADD_OBJ (
2694         ts, marker);
2695       break;
2696     case TYPE (MIDI):
2697       mas = (MidiArrangerSelections *) self;
2698       ADD_OBJ (
2699         mas, midi_note);
2700       break;
2701     case TYPE (AUTOMATION):
2702       as = (AutomationSelections *) self;
2703       ADD_OBJ (
2704         as, automation_point);
2705       break;
2706     case TYPE (CHORD):
2707       cs = (ChordSelections *) self;
2708       ADD_OBJ (
2709         cs, chord_object);
2710       break;
2711     case TYPE (AUDIO):
2712       return NULL;
2713     default:
2714       g_return_val_if_reached (NULL);
2715     }
2716 #undef ADD_OBJ
2717 
2718   return objs;
2719 }
2720 
2721 ArrangerSelections *
arranger_selections_get_for_type(ArrangerSelectionsType type)2722 arranger_selections_get_for_type (
2723   ArrangerSelectionsType type)
2724 {
2725   switch (type)
2726     {
2727     case ARRANGER_SELECTIONS_TYPE_TIMELINE:
2728       return (ArrangerSelections *) TL_SELECTIONS;
2729     case ARRANGER_SELECTIONS_TYPE_MIDI:
2730       return (ArrangerSelections *) MA_SELECTIONS;
2731     case ARRANGER_SELECTIONS_TYPE_CHORD:
2732       return (ArrangerSelections *) CHORD_SELECTIONS;
2733     case ARRANGER_SELECTIONS_TYPE_AUTOMATION:
2734       return (ArrangerSelections *) AUTOMATION_SELECTIONS;
2735     default:
2736       g_return_val_if_reached (NULL);
2737     }
2738   g_return_val_if_reached (NULL);
2739 }
2740 
2741 bool
arranger_selections_contains_clip(ArrangerSelections * self,AudioClip * clip)2742 arranger_selections_contains_clip (
2743   ArrangerSelections * self,
2744   AudioClip *          clip)
2745 {
2746   if (self->type ==
2747         ARRANGER_SELECTIONS_TYPE_TIMELINE)
2748     {
2749       TimelineSelections * sel =
2750         (TimelineSelections *) self;
2751       for (int i = 0; i < sel->num_regions; i++)
2752         {
2753           ZRegion * r = sel->regions[i];
2754           if (r->id.type == REGION_TYPE_AUDIO &&
2755               r->pool_id == clip->pool_id)
2756             {
2757               return true;
2758             }
2759         }
2760     }
2761   else if (self->type ==
2762              ARRANGER_SELECTIONS_TYPE_AUDIO)
2763     {
2764       AudioSelections * sel =
2765         (AudioSelections *) self;
2766       if (sel->pool_id == clip->pool_id)
2767         {
2768           return true;
2769         }
2770     }
2771 
2772   return false;
2773 }
2774 
2775 bool
arranger_selections_can_split_at_pos(const ArrangerSelections * self,const Position * pos)2776 arranger_selections_can_split_at_pos (
2777   const ArrangerSelections * self,
2778   const Position *           pos)
2779 {
2780   int num_objs =
2781     arranger_selections_get_num_objects (self);
2782   TimelineSelections * ts;
2783   MidiArrangerSelections * mas;
2784   bool can_split = true;
2785   switch (self->type)
2786     {
2787     case TYPE (TIMELINE):
2788       ts = (TimelineSelections *) self;
2789       if (num_objs != ts->num_regions)
2790         {
2791           can_split = false;
2792           goto return_can_split;
2793         }
2794       for (int i = 0; i < ts->num_regions; i++)
2795         {
2796           ZRegion * r = ts->regions[i];
2797           ArrangerObject * r_obj =
2798             (ArrangerObject *) r;
2799 
2800           /* don't allow splitting at edges */
2801           if (position_is_before_or_equal (
2802                 pos, &r_obj->pos) ||
2803               position_is_after_or_equal (
2804                 pos, &r_obj->end_pos))
2805             {
2806               can_split = false;
2807               goto return_can_split;
2808             }
2809         }
2810       break;
2811     case TYPE (MIDI):
2812       mas = (MidiArrangerSelections *) self;
2813       for (int i = 0; i < mas->num_midi_notes; i++)
2814         {
2815           MidiNote * mn = mas->midi_notes[i];
2816           ArrangerObject * mn_obj =
2817             (ArrangerObject *) mn;
2818 
2819           /* don't allow splitting at edges */
2820           if (position_is_before_or_equal (
2821                 pos, &mn_obj->pos) ||
2822               position_is_after_or_equal (
2823                 pos, &mn_obj->end_pos))
2824             {
2825               can_split = false;
2826               goto return_can_split;
2827             }
2828         }
2829       break;
2830     default:
2831       can_split = false;
2832       break;
2833     }
2834 
2835 return_can_split:
2836   if (!can_split)
2837     {
2838       char pos_str[400];
2839       position_to_string (pos, pos_str);
2840       g_message (
2841         "cannot split %s selections at %s",
2842         arranger_selections_type_strings[
2843           self->type].str,
2844         pos_str);
2845     }
2846 
2847   return can_split;
2848 }
2849 
2850 /**
2851  * Redraws each object in the arranger selections.
2852  */
2853 void
arranger_selections_redraw(ArrangerSelections * self)2854 arranger_selections_redraw (
2855   ArrangerSelections * self)
2856 {
2857   int size;
2858   ArrangerObject ** objs =
2859     arranger_selections_get_all_objects (
2860       self, &size);
2861 
2862   for (int i = 0; i < size; i++)
2863     {
2864       ArrangerObject * obj = objs[i];
2865       arranger_object_queue_redraw (obj);
2866     }
2867 
2868   free (objs);
2869 }
2870