Zrythm v2.0.0-DEV
a highly automated and intuitive digital audio workstation
Loading...
Searching...
No Matches
arranger_selections_action.h
1// SPDX-FileCopyrightText: © 2019-2025 Alexandros Theodotou <alex@zrythm.org>
2// SPDX-License-Identifier: LicenseRef-ZrythmLicense
3
4#pragma once
5
6#include "gui/backend/backend/actions/undoable_action.h"
7#include "gui/dsp/quantize_options.h"
8#include "structure/arrangement/arranger_object_span.h"
9#include "structure/arrangement/audio_function.h"
10#include "structure/arrangement/automation_function.h"
11#include "structure/arrangement/midi_function.h"
12
13namespace zrythm::gui::actions
14{
15
29class ArrangerSelectionsAction : public QObject, public UndoableAction
30{
31 Q_OBJECT
32 QML_ELEMENT
33 DEFINE_UNDOABLE_ACTION_QML_PROPERTIES (ArrangerSelectionsAction)
34
35 using ArrangerObjectRegistry = structure::arrangement::ArrangerObjectRegistry;
36 using ArrangerObjectPtrVariant =
37 structure::arrangement::ArrangerObjectPtrVariant;
38 using ArrangerObjectSpan = structure::arrangement::ArrangerObjectSpan;
39 using ArrangerObject = structure::arrangement::ArrangerObject;
40 using MidiFunction = structure::arrangement::MidiFunction;
41 using AutomationFunction = structure::arrangement::AutomationFunction;
42
43public:
44 enum class Type
45 {
46 AutomationFill,
47 Create,
48 Delete,
49 Duplicate,
50 Edit,
51 Link,
52 Merge,
53 Move,
54 Quantize,
55 Record,
56 Resize,
57 Split,
58 };
59
63 enum class ResizeType
64 {
65 L, //< Resize the left side of the `ArrangerObject`s in the selection.
66 R, //< Resize the right side of the `ArrangerObject`s in the selection.
67 LLoop,
68 RLoop,
69 LFade,
70 RFade,
71 LStretch,
72 RStretch,
73 };
74
78 enum class EditType
79 {
82
88 Position,
89
97
100
103
106
109 // ARRANGER_SELECTIONS_ACTION_EDIT_RAMP,
110
113 };
114
115 using Position = zrythm::dsp::Position;
116
117public:
119 ~ArrangerSelectionsAction () override = default;
120
121 class RecordAction;
122 class MoveOrDuplicateAction;
123 class MoveOrDuplicateTimelineAction;
124 class MoveOrDuplicateMidiAction;
125 class MoveOrDuplicateAutomationAction;
126 class MoveOrDuplicateChordAction;
127 // class MoveByTicksAction;
128 class MoveMidiAction;
129 class MoveChordAction;
130 class LinkAction;
131 class AutomationFillAction;
132 class SplitAction;
133 class MergeAction;
134 class ResizeAction;
135 class QuantizeAction;
136
137 ArrangerObjectRegistry &get_arranger_object_registry () const;
138
139 friend void init_from (
141 const ArrangerSelectionsAction &other,
142 utils::ObjectCloneType clone_type);
143
144 bool needs_transport_total_bar_update (bool perform) const override;
145
146 bool needs_pause () const override
147 {
148 /* always needs a pause to update the track playback snapshots */
149 return true;
150 }
151
152 [[nodiscard]] QString to_string () const final;
153
154protected:
162 ArrangerSelectionsAction (ArrangerObjectSpan before_sel, Type type)
163 : UndoableAction (UndoableAction::Type::ArrangerSelections), type_ (type),
164 first_run_ (true)
165 {
166 set_before_selections (before_sel);
167 }
168
174 void set_before_selections (ArrangerObjectSpan src_var);
175
181 void set_after_selections (ArrangerObjectSpan src_var);
182
183private:
185 void do_or_undo (bool do_it);
186
187 void do_or_undo_duplicate_or_link (bool link, bool do_it);
188 void do_or_undo_move (bool do_it);
189 void do_or_undo_create_or_delete (bool do_it, bool create);
190 void do_or_undo_record (bool do_it);
191 void do_or_undo_edit (bool do_it);
192 void do_or_undo_automation_fill (bool do_it);
193 void do_or_undo_split (bool do_it);
194 void do_or_undo_merge (bool do_it);
195 void do_or_undo_resize (bool do_it);
196 void do_or_undo_quantize (bool do_it);
197
202 void update_region_link_groups (const auto &objects);
203
213 void move_obj_by_tracks_and_lanes (
214 ArrangerObjectPtrVariant obj_var,
215 int tracks_diff,
216 int lanes_diff,
217 bool use_index_in_prev_lane,
218 int index_in_prev_lane);
219
220 std::vector<ArrangerObjectPtrVariant> get_project_arranger_objects () const;
221
222 void init_loaded_impl () final;
223 void perform_impl () final;
224 void undo_impl () final;
225
226public:
228 Type type_{};
229
231 std::optional<std::vector<ArrangerObjectPtrVariant>> sel_;
232
237 std::optional<std::vector<ArrangerObjectPtrVariant>> sel_after_;
238
241
243 double ticks_{};
253 int delta_vel_ = 0;
259
260 std::optional<std::pair<Position, Position>>
261 selected_positions_in_audio_editor_;
262
264 std::optional<ArrangerObject::Uuid> clip_editor_region_id_;
265
269 std::optional<dsp::PortUuid> target_port_;
270
273
275 Position pos_;
276
278 std::vector<ArrangerObject::Uuid> r1_;
279 std::vector<ArrangerObject::Uuid> r2_;
280
282 // size_t num_split_objs_ = 0;
283
289 bool first_run_ = false;
290
292 std::unique_ptr<gui::old_dsp::QuantizeOptions> opts_{};
293
297 std::optional<ArrangerObjectPtrVariant> region_before_;
298 std::optional<ArrangerObjectPtrVariant> region_after_;
299
302};
303
304class CreateOrDeleteArrangerSelectionsAction : public ArrangerSelectionsAction
305{
306public:
307 ~CreateOrDeleteArrangerSelectionsAction () override = default;
308
309protected:
317 ArrangerObjectSpan sel_var,
318 bool create);
319};
320
321class CreateArrangerSelectionsAction final
323{
324public:
325 CreateArrangerSelectionsAction (ArrangerObjectSpan sel)
327};
328
329class DeleteArrangerSelectionsAction final
331{
332public:
333 DeleteArrangerSelectionsAction (ArrangerObjectSpan sel)
335};
336
337class ArrangerSelectionsAction::RecordAction : public ArrangerSelectionsAction
338{
339public:
348 ArrangerObjectSpan sel_before,
349 ArrangerObjectSpan sel_after,
350 bool already_recorded);
351};
352
354 : public ArrangerSelectionsAction
355{
356public:
365 ArrangerObjectSpan sel_var,
366 bool move,
367 double ticks,
368 int delta_chords,
369 int delta_pitch,
370 int delta_tracks,
371 int delta_lanes,
372 double delta_normalized_amount,
373 std::optional<dsp::PortUuid> tgt_port_id,
374 bool already_moved);
375};
376
379{
380public:
381 MoveOrDuplicateTimelineAction (
382 ArrangerObjectSpan sel,
383 bool move,
384 double ticks,
385 int delta_tracks,
386 int delta_lanes,
387 std::optional<dsp::PortUuid> tgt_port_id,
388 bool already_moved)
390 sel,
391 move,
392 ticks,
393 0,
394 0,
395 delta_tracks,
396 delta_lanes,
397 0,
398 tgt_port_id,
399 already_moved) { };
400};
401
404{
405public:
406 MoveOrDuplicateMidiAction (
407 ArrangerObjectSpan sel,
408 bool move,
409 double ticks,
410 int delta_pitch,
411 bool already_moved)
413 sel,
414 move,
415 ticks,
416 0,
417 delta_pitch,
418 0,
419 0,
420 0,
421 std::nullopt,
422 already_moved) { };
423};
424
427{
428public:
429 MoveOrDuplicateChordAction (
430 ArrangerObjectSpan sel,
431 bool move,
432 double ticks,
433 int delta_chords,
434 bool already_moved)
436 sel,
437 move,
438 ticks,
439 delta_chords,
440 0,
441 0,
442 0,
443 0,
444 std::nullopt,
445 already_moved) { };
446};
447
450{
451public:
452 MoveOrDuplicateAutomationAction (
453 ArrangerObjectSpan sel,
454 bool move,
455 double ticks,
456 int delta_normalized_amount,
457 bool already_moved)
459 sel,
460 move,
461 ticks,
462 0,
463 0,
464 0,
465 0,
466 delta_normalized_amount,
467 std::nullopt,
468 already_moved) { };
469};
470
471#if 0
472class ArrangerSelectionsAction::MoveByTicksAction
474{
475public:
476 template <FinalArrangerSelectionsSubclass T>
477 MoveByTicksAction (const T &sel, double ticks, bool already_moved)
478 : MoveOrDuplicateAction (sel, true, ticks, 0, 0, 0, 0, 0, nullptr, already_moved)
479 {
480 }
481};
482#endif
483
486{
487public:
488 MoveMidiAction (
489 ArrangerObjectSpan sel,
490 double ticks,
491 int delta_pitch,
492 bool already_moved)
493 : MoveOrDuplicateAction (sel, true, ticks, 0, delta_pitch, 0, 0, 0, std::nullopt, already_moved)
494 {
495 }
496};
497
500{
501public:
502 MoveChordAction (
503 ArrangerObjectSpan sel,
504 double ticks,
505 int delta_chords,
506 bool already_moved)
507 : MoveOrDuplicateAction (sel, true, ticks, delta_chords, 0, 0, 0, 0, std::nullopt, already_moved)
508 {
509 }
510};
511
512class ArrangerSelectionsAction::LinkAction : public ArrangerSelectionsAction
513{
514public:
523 ArrangerObjectSpan sel_before,
524 ArrangerObjectSpan sel_after,
525 double ticks,
526 int delta_tracks,
527 int delta_lanes,
528 bool already_moved);
529};
530
531class EditArrangerSelectionsAction : public ArrangerSelectionsAction
532{
533public:
542 ArrangerObjectSpan sel_before,
543 std::optional<ArrangerObjectSpan> sel_after,
544 EditType type,
545 bool already_edited);
546
550 static std::unique_ptr<EditArrangerSelectionsAction> create (
551 ArrangerObjectSpan sel_before,
552 ArrangerObjectSpan sel_after,
553 EditType type,
554 bool already_edited);
555
560 ArrangerObjectSpan sel_before,
561 MidiFunction::Type midi_func_type,
563
568 ArrangerObjectSpan sel_before,
569 AutomationFunction::Type automation_func_type);
570
575 ArrangerObject::Uuid region_id,
576 const dsp::Position &sel_start,
577 const dsp::Position &sel_end,
578 structure::arrangement::AudioFunctionType audio_func_type,
580 std::optional<utils::Utf8String> uri);
581};
582
584 : public ArrangerSelectionsAction
585{
586public:
594 template <structure::arrangement::RegionObject RegionT>
596 const RegionT &region_before,
597 const RegionT &region_after,
598 bool already_changed);
599};
600
601class ArrangerSelectionsAction::SplitAction : public ArrangerSelectionsAction
602{
603public:
609 SplitAction (ArrangerObjectSpan sel, Position pos);
610};
611
612class ArrangerSelectionsAction::MergeAction : public ArrangerSelectionsAction
613{
614public:
618 MergeAction (ArrangerObjectSpan sel)
619 : ArrangerSelectionsAction (sel, Type::Merge)
620 {
621 }
622};
623
624class ArrangerSelectionsAction::ResizeAction : public ArrangerSelectionsAction
625{
626public:
634 ArrangerObjectSpan sel_before,
635 std::optional<ArrangerObjectSpan> sel_after,
636 ResizeType type,
637 double ticks);
638};
639
640class ArrangerSelectionsAction::QuantizeAction : public ArrangerSelectionsAction
641{
642public:
648 QuantizeAction (ArrangerObjectSpan sel, const old_dsp::QuantizeOptions &opts)
649 : ArrangerSelectionsAction (sel, Type::Quantize)
650 {
651 opts_ = std::make_unique<old_dsp::QuantizeOptions> (opts);
652 }
653};
654
655}; // namespace zrythm::gui::actions
656
657DEFINE_ENUM_FORMATTER (
659 ArrangerSelectionsAction_ResizeType,
660 "Resize L",
661 "Resize R",
662 "Resize L (loop)",
663 "Resize R (loop)",
664 "Resize L (fade)",
665 "Resize R (fade)",
666 "Stretch L",
667 "Stretch R");
Represents the position of an object.
Definition position.h:72
AutomationFillAction(const RegionT &region_before, const RegionT &region_after, bool already_changed)
Creates a new action for automation autofill.
LinkAction(ArrangerObjectSpan sel_before, ArrangerObjectSpan sel_after, double ticks, int delta_tracks, int delta_lanes, bool already_moved)
Creates a new action for linking regions.
MergeAction(ArrangerObjectSpan sel)
Creates a new action for merging objects.
MoveOrDuplicateAction(ArrangerObjectSpan sel_var, bool move, double ticks, int delta_chords, int delta_pitch, int delta_tracks, int delta_lanes, double delta_normalized_amount, std::optional< dsp::PortUuid > tgt_port_id, bool already_moved)
Creates a new action for moving or duplicating objects.
QuantizeAction(ArrangerObjectSpan sel, const old_dsp::QuantizeOptions &opts)
Creates a new action for quantizing ArrangerObject's.
RecordAction(ArrangerObjectSpan sel_before, ArrangerObjectSpan sel_after, bool already_recorded)
Construct a new action for recording.
ResizeAction(ArrangerObjectSpan sel_before, std::optional< ArrangerObjectSpan > sel_after, ResizeType type, double ticks)
Creates a new action for resizing ArrangerObject's.
SplitAction(ArrangerObjectSpan sel, Position pos)
Creates a new action for splitting regions.
An action that performs changes to the arranger selections.
QString to_string() const final
Stringizes the action to be used in Undo/Redo buttons.
EditType edit_type_
Type of edit action, if an Edit action.
std::optional< std::vector< ArrangerObjectPtrVariant > > sel_
A clone of the ArrangerSelections before the change.
std::optional< std::vector< ArrangerObjectPtrVariant > > sel_after_
A clone of the ArrangerSelections after the change (used in the EDIT action and quantize).
std::unique_ptr< gui::old_dsp::QuantizeOptions > opts_
QuantizeOptions clone, if quantizing.
ResizeType
Type used when the action is a RESIZE action.
Position pos_
Position, when changing a Position.
void set_before_selections(ArrangerObjectSpan src_var)
Sets sel_ to a clone of src.
std::optional< ArrangerObjectPtrVariant > region_before_
Used for automation autofill action.
utils::Utf8String str_
String, when changing a string.
double delta_normalized_amount_
Difference in a normalized amount, such as automation point normalized value.
void set_after_selections(ArrangerObjectSpan src_var)
Sets sel_after_ to a clone of src.
std::optional< dsp::PortUuid > target_port_
Target port (used to find corresponding automation track when moving/copying automation regions to an...
int delta_chords_
Chords moved (up/down in the Chord editor).
EditType
Type used when the action is an EDIT action.
@ Primitive
Edit a primitive (int, etc) member of objects in the selection.
@ Scale
For editing the MusicalScale inside ScaleObjects.
@ EditorFunction
For ramping MidiNote velocities or AutomationPoint values.
std::optional< ArrangerObject::Uuid > clip_editor_region_id_
Clip editor region ID (for non-timeline actions).
std::vector< ArrangerObject::Uuid > r1_
Used when splitting - these are the split BoundedObject's.
bool needs_transport_total_bar_update(bool perform) const override
Returns whether the total transport bars need to be recalculated.
bool needs_pause() const override
Returns whether the action requires pausing the engine.
CreateOrDeleteArrangerSelectionsAction(ArrangerObjectSpan sel_var, bool create)
Creates a new action for creating/deleting objects.
static std::unique_ptr< EditArrangerSelectionsAction > create(ArrangerObjectSpan sel_before, ArrangerObjectSpan sel_after, EditType type, bool already_edited)
Wrapper for a single object.
EditArrangerSelectionsAction(ArrangerObjectSpan sel_before, AutomationFunction::Type automation_func_type)
Wrapper for automation functions.
EditArrangerSelectionsAction(ArrangerObject::Uuid region_id, const dsp::Position &sel_start, const dsp::Position &sel_end, structure::arrangement::AudioFunctionType audio_func_type, structure::arrangement::AudioFunctionOpts opts, std::optional< utils::Utf8String > uri)
Wrapper for audio functions.
EditArrangerSelectionsAction(ArrangerObjectSpan sel_before, MidiFunction::Type midi_func_type, MidiFunction::Options opts)
Wrapper for MIDI functions.
EditArrangerSelectionsAction(ArrangerObjectSpan sel_before, std::optional< ArrangerObjectSpan > sel_after, EditType type, bool already_edited)
Creates a new action for editing properties of an object.
void perform()
Performs the action.
Track span that offers helper methods on a range of tracks.
Base class for all objects in the arranger.
Lightweight UTF-8 string wrapper with safe conversions.
Definition utf8_string.h:38