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