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 /**
21  * \file
22  *
23  * Common data structures and functions for
24  * *ArrangerSelections.
25  */
26 
27 #ifndef __GUI_BACKEND_ARRANGER_SELECTIONS_H__
28 #define __GUI_BACKEND_ARRANGER_SELECTIONS_H__
29 
30 #include <stdbool.h>
31 
32 #include "utils/yaml.h"
33 
34 typedef struct ArrangerObject ArrangerObject;
35 typedef struct Position Position;
36 typedef struct AudioClip AudioClip;
37 typedef enum ArrangerSelectionsActionEditType
38   ArrangerSelectionsActionEditType;
39 
40 /**
41  * @addtogroup gui_backend
42  *
43  * @{
44  */
45 
46 #define ARRANGER_SELECTIONS_SCHEMA_VERSION 1
47 
48 #define ARRANGER_SELECTIONS_MAGIC 35867752
49 #define IS_ARRANGER_SELECTIONS(x) \
50   (((ArrangerSelections *) x)->magic == \
51    ARRANGER_SELECTIONS_MAGIC)
52 #define IS_ARRANGER_SELECTIONS_AND_NONNULL(x) \
53   (x && IS_ARRANGER_SELECTIONS (x))
54 #define ARRANGER_SELECTIONS(x) \
55   arranger_selections_cast (x)
56 
57 #define ARRANGER_SELECTIONS_DEFAULT_NUDGE_TICKS 0.1
58 
59 typedef enum ArrangerSelectionsType
60 {
61   ARRANGER_SELECTIONS_TYPE_NONE,
62   ARRANGER_SELECTIONS_TYPE_CHORD,
63   ARRANGER_SELECTIONS_TYPE_TIMELINE,
64   ARRANGER_SELECTIONS_TYPE_MIDI,
65   ARRANGER_SELECTIONS_TYPE_AUTOMATION,
66   ARRANGER_SELECTIONS_TYPE_AUDIO,
67 } ArrangerSelectionsType;
68 
69 static const cyaml_strval_t
70 arranger_selections_type_strings[] =
71 {
72   { "None",
73     ARRANGER_SELECTIONS_TYPE_NONE    },
74   { "Chord",
75     ARRANGER_SELECTIONS_TYPE_CHORD    },
76   { "Timeline",
77     ARRANGER_SELECTIONS_TYPE_TIMELINE   },
78   { "MIDI",
79     ARRANGER_SELECTIONS_TYPE_MIDI },
80   { "Automation",
81     ARRANGER_SELECTIONS_TYPE_AUTOMATION   },
82   { "Audio",
83     ARRANGER_SELECTIONS_TYPE_AUDIO   },
84 };
85 
86 typedef struct ArrangerSelections
87 {
88   int                    schema_version;
89 
90   /** Type of selections. */
91   ArrangerSelectionsType type;
92 
93   int                    magic;
94 } ArrangerSelections;
95 
96 static const cyaml_schema_field_t
97 arranger_selections_fields_schema[] =
98 {
99   YAML_FIELD_INT (
100     ArrangerSelections, schema_version),
101   YAML_FIELD_ENUM (
102     ArrangerSelections, type,
103     arranger_selections_type_strings),
104 
105   CYAML_FIELD_END
106 };
107 
108 static const cyaml_schema_value_t
109 arranger_selections_schema = {
110   YAML_VALUE_PTR (
111     ArrangerSelections,
112     arranger_selections_fields_schema),
113 };
114 
115 typedef enum ArrangerSelectionsProperty
116 {
117   ARRANGER_SELECTIONS_PROPERTY_HAS_LENGTH,
118   ARRANGER_SELECTIONS_PROPERTY_CAN_LOOP,
119   ARRANGER_SELECTIONS_PROPERTY_HAS_LOOPED,
120   ARRANGER_SELECTIONS_PROPERTY_CAN_FADE,
121 } ArrangerSelectionsProperty;
122 
123 static inline ArrangerSelections *
arranger_selections_cast(void * sel)124 arranger_selections_cast (void * sel)
125 {
126   if (!IS_ARRANGER_SELECTIONS (
127         (ArrangerSelections *) sel))
128     {
129       g_warning ("%s", __func__);
130     }
131   return (ArrangerSelections *) sel;
132 }
133 
134 /**
135  * Inits the selections after loading a project.
136  *
137  * @param project Whether these are project
138  *   selections (as opposed to clones).
139  */
140 NONNULL
141 void
142 arranger_selections_init_loaded (
143   ArrangerSelections * self,
144   bool                 project);
145 
146 /**
147  * Initializes the selections.
148  */
149 NONNULL
150 void
151 arranger_selections_init (
152   ArrangerSelections *   self,
153   ArrangerSelectionsType type);
154 
155 /**
156  * Creates new arranger selections.
157  */
158 ArrangerSelections *
159 arranger_selections_new (
160   ArrangerSelectionsType type);
161 
162 /**
163  * Verify that the objects are not invalid.
164  */
165 NONNULL
166 bool
167 arranger_selections_verify (
168   ArrangerSelections * self);
169 
170 /**
171  * Appends the given object to the selections.
172  */
173 NONNULL
174 void
175 arranger_selections_add_object (
176   ArrangerSelections * self,
177   ArrangerObject *     obj);
178 
179 /**
180  * Sets the values of each object in the dest
181  * selections to the values in the src selections.
182  */
183 NONNULL
184 void
185 arranger_selections_set_from_selections (
186   ArrangerSelections * dest,
187   ArrangerSelections * src);
188 
189 /**
190  * Sorts the selections by their indices (eg, for
191  * regions, their track indices, then the lane
192  * indices, then the index in the lane).
193  *
194  * @note Only works for objects whose tracks exist.
195  *
196  * @param desc Descending or not.
197  */
198 NONNULL
199 void
200 arranger_selections_sort_by_indices (
201   ArrangerSelections * sel,
202   int                  desc);
203 
204 /**
205  * Clone the struct for copying, undoing, etc.
206  */
207 NONNULL
208 ArrangerSelections *
209 arranger_selections_clone (
210   ArrangerSelections * self);
211 
212 /**
213  * Returns if there are any selections.
214  */
215 NONNULL
216 bool
217 arranger_selections_has_any (
218   ArrangerSelections * self);
219 
220 /**
221  * Returns the position of the leftmost object.
222  *
223  * @param pos[out] The return value will be stored
224  *   here.
225  * @param global Return global (timeline) Position,
226  *   otherwise returns the local (from the start
227  *   of the Region) Position.
228  */
229 NONNULL
230 void
231 arranger_selections_get_start_pos (
232   ArrangerSelections * self,
233   Position *           pos,
234   bool                 global);
235 
236 /**
237  * Returns the end position of the rightmost object.
238  *
239  * @param pos The return value will be stored here.
240  * @param global Return global (timeline) Position,
241  *   otherwise returns the local (from the start
242  *   of the Region) Position.
243  */
244 NONNULL
245 void
246 arranger_selections_get_end_pos (
247   ArrangerSelections * self,
248   Position *           pos,
249   int                  global);
250 
251 /**
252  * Returns the number of selected objects.
253  */
254 NONNULL
255 int
256 arranger_selections_get_num_objects (
257   const ArrangerSelections * self);
258 
259 /**
260  * Gets first object.
261  */
262 NONNULL
263 ArrangerObject *
264 arranger_selections_get_first_object (
265   ArrangerSelections * self);
266 
267 /**
268  * Gets last object.
269  */
270 NONNULL
271 ArrangerObject *
272 arranger_selections_get_last_object (
273   ArrangerSelections * self);
274 
275 /**
276  * Pastes the given selections to the given
277  * Position.
278  */
279 NONNULL
280 void
281 arranger_selections_paste_to_pos (
282   ArrangerSelections * self,
283   Position *           pos,
284   bool                 undoable);
285 
286 /**
287  * Returns all objects in the selections in a
288  * newly allocated array that should be free'd.
289  *
290  * @param size A pointer to save the size into.
291  */
292 NONNULL
293 ArrangerObject **
294 arranger_selections_get_all_objects (
295   ArrangerSelections * self,
296   int *                size);
297 
298 /**
299  * Redraws each object in the arranger selections.
300  */
301 NONNULL
302 void
303 arranger_selections_redraw (
304   ArrangerSelections * self);
305 
306 /**
307  * Adds each object in the selection to the given
308  * region (if applicable).
309  */
310 NONNULL
311 void
312 arranger_selections_add_to_region (
313   ArrangerSelections * self,
314   ZRegion *            region);
315 
316 /**
317  * Moves the selections by the given
318  * amount of ticks.
319  *
320  * @param ticks Ticks to add.
321  */
322 NONNULL
323 void
324 arranger_selections_add_ticks (
325   ArrangerSelections *     self,
326   const double             ticks);
327 
328 /**
329  * Returns whether all the selections are on the
330  * same lane (track lane or automation lane).
331  */
332 NONNULL
333 bool
334 arranger_selections_all_on_same_lane (
335   ArrangerSelections * self);
336 
337 /**
338  * Selects all possible objects from the project.
339  */
340 NONNULL
341 void
342 arranger_selections_select_all (
343   ArrangerSelections * self,
344   bool                 fire_events);
345 
346 /**
347  * Clears selections.
348  */
349 NONNULL
350 void
351 arranger_selections_clear (
352   ArrangerSelections * self,
353   bool                 free,
354   bool                 fire_events);
355 
356 /**
357  * Code to run after deserializing.
358  */
359 NONNULL
360 void
361 arranger_selections_post_deserialize (
362   ArrangerSelections * self);
363 
364 NONNULL
365 bool
366 arranger_selections_validate (
367   ArrangerSelections * self);
368 
369 /**
370  * Frees anything allocated by the selections
371  * but not the objects or @ref self itself.
372  */
373 NONNULL
374 void
375 arranger_selections_free_members (
376   ArrangerSelections * self);
377 
378 /**
379  * Frees the selections but not the objects.
380  */
381 NONNULL
382 void
383 arranger_selections_free (
384   ArrangerSelections * self);
385 
386 /**
387  * Frees all the objects as well.
388  *
389  * To be used in actions where the selections are
390  * all clones.
391  */
392 NONNULL
393 void
394 arranger_selections_free_full (
395   ArrangerSelections * self);
396 
397 /**
398  * Returns if the arranger object is in the
399  * selections or  not.
400  *
401  * The object must be the main object (see
402  * ArrangerObjectInfo).
403  */
404 NONNULL
405 int
406 arranger_selections_contains_object (
407   ArrangerSelections * self,
408   ArrangerObject *     obj);
409 
410 /**
411  * Returns if the selections contain an undeletable
412  * object (such as the start marker).
413  */
414 NONNULL
415 bool
416 arranger_selections_contains_undeletable_object (
417   ArrangerSelections * self);
418 
419 /**
420  * Checks whether an object matches the given
421  * parameters.
422  *
423  * If a parameter should be checked, the has_*
424  * argument must be true and the corresponding
425  * argument must have the value to be checked
426  * against.
427  */
428 NONNULL
429 bool
430 arranger_selections_contains_object_with_property (
431   ArrangerSelections *       self,
432   ArrangerSelectionsProperty property,
433   bool                       value);
434 
435 /**
436  * Removes the arranger object from the selections.
437  */
438 NONNULL
439 void
440 arranger_selections_remove_object (
441   ArrangerSelections * self,
442   ArrangerObject *     obj);
443 
444 /**
445  * Merges the given selections into one region.
446  *
447  * @note All selections must be on the same lane.
448  */
449 NONNULL
450 void
451 arranger_selections_merge (
452   ArrangerSelections * self);
453 
454 /**
455  * Returns if the selections can be pasted.
456  */
457 NONNULL
458 bool
459 arranger_selections_can_be_pasted (
460   ArrangerSelections * self);
461 
462 NONNULL
463 bool
464 arranger_selections_contains_looped (
465   ArrangerSelections * self);
466 
467 NONNULL
468 bool
469 arranger_selections_can_be_merged (
470   ArrangerSelections * self);
471 
472 NONNULL
473 double
474 arranger_selections_get_length_in_ticks (
475   ArrangerSelections * self);
476 
477 NONNULL
478 bool
479 arranger_selections_contains_clip (
480   ArrangerSelections * self,
481   AudioClip *          clip);
482 
483 NONNULL
484 bool
485 arranger_selections_can_split_at_pos (
486   const ArrangerSelections * self,
487   const Position *           pos);
488 
489 NONNULL
490 ArrangerSelections *
491 arranger_selections_get_for_type (
492   ArrangerSelectionsType type);
493 
494 /**
495 * @}
496 */
497 
498 #endif
499