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