Zrythm v2.0.0-DEV
a highly automated and intuitive digital audio workstation
Loading...
Searching...
No Matches
tracklist.h
1// SPDX-FileCopyrightText: © 2018-2025 Alexandros Theodotou <alex@zrythm.org>
2// SPDX-License-Identifier: LicenseRef-ZrythmLicense
3
4#pragma once
5
6#include "gui/dsp/arranger_object_span.h"
7#include "gui/dsp/track.h"
8#include "gui/dsp/track_span.h"
9
10#include <QtQmlIntegration>
11
12struct FileImportInfo;
13
14#define TRACKLIST (PROJECT->tracklist_)
15
16class ChordTrack;
17class TempoTrack;
18class ModulatorTrack;
19class MasterTrack;
20class MarkerTrack;
21class Router;
22class Project;
23
31class Tracklist final : public QAbstractListModel, public ICloneable<Tracklist>
32{
33 Q_OBJECT
34 QML_ELEMENT
35 Q_PROPERTY (TempoTrack * tempoTrack READ getTempoTrack CONSTANT FINAL)
36
37public:
38 using TrackUuid = Track::Uuid;
39
43 enum class PinOption
44 {
45 PinnedOnly,
46 UnpinnedOnly,
47 Both,
48 };
49
50 enum TrackRoles
51 {
52 TrackPtrRole = Qt::UserRole + 1,
53 TrackNameRole,
54 };
55
56public:
57 Tracklist (QObject * parent = nullptr);
58 explicit Tracklist (
59 Project &project,
60 PortRegistry &port_registry,
61 TrackRegistry &track_registry,
62 dsp::PortConnectionsManager * port_connections_manager);
63 explicit Tracklist (
64 SampleProcessor &sample_processor,
65 PortRegistry &port_registry,
66 TrackRegistry &track_registry,
67 dsp::PortConnectionsManager * port_connections_manager);
68 Z_DISABLE_COPY_MOVE (Tracklist)
69 ~Tracklist () override;
70
71 // ========================================================================
72 // QML Interface
73 // ========================================================================
74 QHash<int, QByteArray> roleNames () const override;
75 int rowCount (const QModelIndex &parent = QModelIndex ()) const override;
76 QVariant
77 data (const QModelIndex &index, int role = Qt::DisplayRole) const override;
78
79 TempoTrack * getTempoTrack () const;
80
81 Q_INVOKABLE void setExclusivelySelectedTrack (QVariant track);
82
83 // ========================================================================
84
88 static constexpr std::array<Track::Type, 4> unique_track_types_ = {
91 };
92
93 auto get_track_span () const { return TrackSpan{ tracks_ }; }
94
95 bool is_in_active_project () const;
96
97 bool is_auditioner () const
98 {
99 return sample_processor_ && is_in_active_project ();
100 }
101
102 void init_after_cloning (const Tracklist &other, ObjectCloneType clone_type)
103 override;
104
109 PortRegistry &port_registry,
110 Project * project,
111 SampleProcessor * sample_processor);
112
113 void init_loaded (PortRegistry &port_registry, Project &project)
114 {
115 init_loaded (port_registry, &project, nullptr);
116 }
117 void
118 init_loaded (PortRegistry &port_registry, SampleProcessor &sample_processor)
119 {
120 init_loaded (port_registry, nullptr, &sample_processor);
121 }
122
130 TrackPtrVariant insert_track (
131 const TrackUuidReference &track_id,
132 int pos,
133 AudioEngine &engine,
134 bool publish_events,
135 bool recalc_graph);
136
140 TrackPtrVariant append_track (
141 auto track_id,
142 AudioEngine &engine,
143 bool publish_events,
144 bool recalc_graph)
145 {
146 return insert_track (
147 track_id, tracks_.size (), engine, publish_events, recalc_graph);
148 }
149
156 void remove_track (const TrackUuid &track_id);
157
168 TrackUuid track_id,
169 int pos,
170 bool always_before_pos,
171 std::optional<std::reference_wrapper<Router>> router);
172
173 std::optional<TrackPtrVariant> get_track (const TrackUuid &id) const
174 {
175 auto span = get_track_span ();
176 auto it = std::ranges::find (span, id, TrackSpan::uuid_projection);
177 if (it == span.end ()) [[unlikely]]
178 {
179 return std::nullopt;
180 }
181 return std::make_optional (*it);
182 }
183
188 TrackUuid track_id,
189 bool pinned,
190 int publish_events,
191 int recalc_graph);
192
193 bool validate () const;
194
195 ChordTrack * get_chord_track () const;
196
203 std::optional<TrackPtrVariant> get_first_visible_track (bool pinned) const;
204
209 std::optional<TrackPtrVariant>
210 get_prev_visible_track (Track::TrackUuid track_id) const;
211
216 std::optional<TrackPtrVariant>
217 get_next_visible_track (Track::TrackUuid track_id) const;
218
226 int
227 get_last_pos (PinOption pin_opt = PinOption::Both, bool visible_only = false)
228 const;
229
236 std::optional<TrackPtrVariant>
237 get_last_track (PinOption pin_opt = PinOption::Both, bool visible_only = false)
238 const
239 {
240 return get_track_span ().get_track_by_pos (
241 get_last_pos (pin_opt, visible_only));
242 }
243
252 std::optional<TrackPtrVariant>
253 get_visible_track_after_delta (Track::TrackUuid track_id, int delta) const;
254
263 Track::TrackUuid src_track,
264 Track::TrackUuid dest_track) const;
265
272 double multiplier,
273 bool visible_only,
274 bool check_only,
275 bool fire_events);
276
280 void handle_click (TrackUuid track_id, bool ctrl, bool shift, bool dragged);
281
282 std::vector<ArrangerObjectPtrVariant> get_timeline_objects_in_range (
283 std::optional<std::pair<dsp::Position, dsp::Position>> range = std::nullopt)
284 const;
285
291 void
292 clear_selections_for_object_siblings (const ArrangerObject::Uuid &object_id);
293
303 std::vector<std::vector<std::shared_ptr<Region>>> &region_arrays,
304 const FileImportInfo * import_info,
305 TracksReadyCallback ready_cb);
306
325 ArrangerObjectPtrVariant region,
326 const Track::Uuid &to_track_id,
327 int lane_or_at_index,
328 int index);
329
334 const Plugin::Uuid &plugin_id,
335 const Track::Uuid &prev_track_id,
336 const Track::Uuid &track_id_to_move_to,
338
348 const Plugin::Uuid &plugin_id,
349 const Track::Uuid &target_track_id,
351 bool confirm_overwrite);
352
353 zrythm::gui::Channel * get_channel_for_plugin (const Plugin::Uuid &plugin_id);
354
369 std::optional<std::vector<utils::Utf8String>> uri_list,
370 const FileDescriptor * orig_file,
371 const Track * track,
372 const TrackLane * lane,
373 int index,
374 const zrythm::dsp::Position * pos,
375 TracksReadyCallback ready_cb);
376
377#if 0
385 void handle_move_or_copy (
386 Track &this_track,
387 TrackWidgetHighlight location,
388 GdkDragAction action);
389#endif
390
396 bool
397 track_name_is_unique (const utils::Utf8String &name, TrackUuid track_to_skip)
398 const;
399
403 bool is_track_pinned (size_t index) const
404 {
405 return index < pinned_tracks_cutoff_;
406 }
407
408 auto get_track_index (const Track::TrackUuid &track_id) const
409 {
410 return std::distance (
411 tracks_.begin (),
412 std::ranges::find (tracks_, track_id, &TrackUuidReference::id));
413 }
414
415 auto get_track_at_index (size_t index) const
416 {
417 if (index >= tracks_.size ())
418 throw std::out_of_range ("Track index out of range");
419 return get_track_span ().at (index);
420 }
421
422 auto get_track_ref_at_index (size_t index) const
423 {
424 if (index >= tracks_.size ())
425 throw std::out_of_range ("Track index out of range");
426 return tracks_.at (index);
427 }
428
429 bool is_track_pinned (Track::TrackUuid track_id) const
430 {
431 return is_track_pinned (get_track_index (track_id));
432 }
433
434 auto get_selection_manager ()
435 {
436 return TrackSelectionManager{ selected_tracks_, *track_registry_ };
437 }
438
444 {
445 auto selected_vec = std::ranges::to<std::vector> (selected_tracks_);
446 TrackSpan span{ *track_registry_, selected_vec };
447 std::ranges::for_each (span, [&] (auto &&track_var) {
448 std::visit (
449 [&] (auto &&track_ref) {
450 using TrackT = base_type<decltype (track_ref)>;
451 if constexpr (std::derived_from<TrackT, FoldableTrack>)
452 {
453 for (int i = 1; i < track_ref->size_; ++i)
454 {
455 const size_t child_pos =
456 get_track_index (track_ref->get_uuid ()) + i;
457 const auto &child_track_var = get_track_at_index (child_pos);
458 get_selection_manager ().append_to_selection (
459 TrackSpan::uuid_projection (child_track_var));
460 }
461 }
462 },
463 track_var);
464 });
465 }
466
467 auto get_pinned_tracks_cutoff_index () const { return pinned_tracks_cutoff_; }
468 void set_pinned_tracks_cutoff_index (size_t index)
469 {
470 pinned_tracks_cutoff_ = index;
471 }
472 auto track_count () const { return tracks_.size (); }
473
483 TrackPtrVariant track_var,
484 bool bounce,
485 bool mark_regions,
486 bool mark_children,
487 bool mark_parents);
488
489 void mark_all_tracks_for_bounce (bool bounce)
490 {
491 get_track_span ().mark_all_tracks_for_bounce (*this, bounce);
492 }
493
494private:
495 static constexpr auto kPinnedTracksCutoffKey = "pinnedTracksCutoff"sv;
496 static constexpr auto kTracksKey = "tracks"sv;
497 static constexpr auto kSelectedTracksKey = "selectedTracks"sv;
498 friend void to_json (nlohmann::json &j, const Tracklist &t)
499 {
500 j = nlohmann::json{
501 { kPinnedTracksCutoffKey, t.pinned_tracks_cutoff_ },
502 { kTracksKey, t.tracks_ },
503 { kSelectedTracksKey, t.selected_tracks_ },
504 };
505 }
506 friend void from_json (const nlohmann::json &j, Tracklist &t)
507 {
508 j.at (kPinnedTracksCutoffKey).get_to (t.pinned_tracks_cutoff_);
509 j.at (kTracksKey).get_to (t.tracks_);
510 j.at (kSelectedTracksKey).get_to (t.selected_tracks_);
511 }
512
513 void swap_tracks (size_t index1, size_t index2);
514
515 auto &get_track_registry () const { return *track_registry_; }
516 auto &get_track_registry () { return *track_registry_; }
517
518private:
519 OptionalRef<TrackRegistry> track_registry_;
520 OptionalRef<PortRegistry> port_registry_;
521 OptionalRef<PluginRegistry> plugin_registry_;
522
540 std::vector<TrackUuidReference> tracks_;
541
547 TrackSelectionManager::UuidSet selected_tracks_;
548
549public:
552
555
558
561
564
565private:
571 size_t pinned_tracks_cutoff_ = 0;
572
575 std::atomic<bool> swapping_tracks_ = false;
576
578 SampleProcessor * sample_processor_ = nullptr;
579
580public:
582 Project * project_ = nullptr;
583
585 // int width_ = 0;
586
587 QPointer<dsp::PortConnectionsManager> port_connections_manager_;
588};
The audio engine.
Definition engine.h:111
The ChordTrack class is responsible for managing the chord and scale information in the project.
Definition chord_track.h:43
Descriptor of a file.
A track that can host modulator plugins.
Contains all of the info that will be serialized into a project file.
Definition project.h:72
The Router class manages the processing graph for the audio engine.
Definition router.h:55
A processor to be used in the routing graph for playing samples independent of the timeline.
Represents a track that controls the tempo of the audio.
Definition tempo_track.h:39
A TrackLane belongs to a Track (can have many TrackLanes in a Track) and contains Regions.
Definition track_lane.h:73
Track span that offers helper methods on a range of tracks.
Definition track_span.h:16
Represents a track in the project.
Definition track.h:282
@ Marker
Marker Track's contain named markers at specific Position's in the song.
Definition track.h:328
@ Modulator
Special track to contain global Modulator's.
Definition track.h:338
@ Tempo
Special track for BPM (tempo) and time signature events.
Definition track.h:333
@ Chord
The chord track contains chords that can be used to modify midi in real time or to color the piano ro...
Definition track.h:323
The Tracklist contains all the tracks in the Project.
Definition tracklist.h:32
void select_foldable_children_of_current_selections()
Also selects the children of foldable tracks in the currently selected tracks.
Definition tracklist.h:443
bool track_name_is_unique(const utils::Utf8String &name, TrackUuid track_to_skip) const
Returns whether the track name is not taken.
void import_files(std::optional< std::vector< utils::Utf8String > > uri_list, const FileDescriptor *orig_file, const Track *track, const TrackLane *lane, int index, const zrythm::dsp::Position *pos, TracksReadyCallback ready_cb)
Begins file import Handles a file drop inside the timeline or in empty space in the tracklist.
void mark_track_for_bounce(TrackPtrVariant track_var, bool bounce, bool mark_regions, bool mark_children, bool mark_parents)
Marks the track for bouncing.
MasterTrack * master_track_
The master track, for convenience.
Definition tracklist.h:563
void handle_click(TrackUuid track_id, bool ctrl, bool shift, bool dragged)
Handle a click selection.
void clear_selections_for_object_siblings(const ArrangerObject::Uuid &object_id)
Clears either the timeline selections or the clip editor selections.
Project * project_
Pointer to owner project, if any.
Definition tracklist.h:582
void init_after_cloning(const Tracklist &other, ObjectCloneType clone_type) override
Initializes the cloned object.
PinOption
Used in track search functions.
Definition tracklist.h:44
std::optional< TrackPtrVariant > get_last_track(PinOption pin_opt=PinOption::Both, bool visible_only=false) const
Returns the last Track.
Definition tracklist.h:237
int get_visible_track_diff(Track::TrackUuid src_track, Track::TrackUuid dest_track) const
Returns the number of visible Tracks between src and dest (negative if dest is before src).
void move_plugin(const Plugin::Uuid &plugin_id, const Track::Uuid &target_track_id, plugins::PluginSlot slot, bool confirm_overwrite)
Moves the plugin to the given slot in the given channel.
TrackPtrVariant append_track(auto track_id, AudioEngine &engine, bool publish_events, bool recalc_graph)
Calls insert_track with the given options.
Definition tracklist.h:140
ModulatorTrack * modulator_track_
The modulator track, for convenience.
Definition tracklist.h:560
void set_track_pinned(TrackUuid track_id, bool pinned, int publish_events, int recalc_graph)
Pins or unpins the Track.
void move_track(TrackUuid track_id, int pos, bool always_before_pos, std::optional< std::reference_wrapper< Router > > router)
Moves a track from its current position to the position given by pos.
std::optional< TrackPtrVariant > get_prev_visible_track(Track::TrackUuid track_id) const
Returns the previous visible Track in the same Tracklist as the given one (ie, pinned or not).
TempoTrack * tempo_track_
The tempo track, for convenience.
Definition tracklist.h:557
std::optional< TrackPtrVariant > get_visible_track_after_delta(Track::TrackUuid track_id, int delta) const
Returns the Track after delta visible Track's.
void import_regions(std::vector< std::vector< std::shared_ptr< Region > > > &region_arrays, const FileImportInfo *import_info, TracksReadyCallback ready_cb)
Imports regions from a region array.
std::optional< TrackPtrVariant > get_first_visible_track(bool pinned) const
Returns the first visible Track.
static constexpr std::array< Track::Type, 4 > unique_track_types_
A list of track types that must be unique in the tracklist.
Definition tracklist.h:88
void remove_track(const TrackUuid &track_id)
Removes the given track from the tracklist.
void move_plugin_automation(const Plugin::Uuid &plugin_id, const Track::Uuid &prev_track_id, const Track::Uuid &track_id_to_move_to, zrythm::plugins::PluginSlot new_slot)
Moves the Plugin's automation from one Channel to another.
std::optional< TrackPtrVariant > get_next_visible_track(Track::TrackUuid track_id) const
Returns the next visible Track in the same Tracklist as the given one (ie, pinned or not).
ChordTrack * chord_track_
The chord track, for convenience.
Definition tracklist.h:551
bool multiply_track_heights(double multiplier, bool visible_only, bool check_only, bool fire_events)
Multiplies all tracks' heights and returns if the operation was valid.
void init_loaded(PortRegistry &port_registry, Project *project, SampleProcessor *sample_processor)
Initializes the tracklist when loading a project.
bool is_track_pinned(size_t index) const
Returns whether the track at index is pinned.
Definition tracklist.h:403
TrackPtrVariant insert_track(const TrackUuidReference &track_id, int pos, AudioEngine &engine, bool publish_events, bool recalc_graph)
Adds given track to given spot in tracklist.
MarkerTrack * marker_track_
The marker track, for convenience.
Definition tracklist.h:554
QPointer< dsp::PortConnectionsManager > port_connections_manager_
Width of track widgets.
Definition tracklist.h:587
void move_region_to_track(ArrangerObjectPtrVariant region, const Track::Uuid &to_track_id, int lane_or_at_index, int index)
Moves the Region to the given Track, maintaining the selection status of the Region.
int get_last_pos(PinOption pin_opt=PinOption::Both, bool visible_only=false) const
Returns the index of the last Track.
Represents the position of an object.
Definition position.h:67
Represents a channel strip on the mixer.
Definition channel.h:44
Lightweight UTF-8 string wrapper with safe conversions.
Definition string.h:39
void(*)(const FileImportInfo *) TracksReadyCallback
Called when track(s) are actually imported into the project.
Definition track.h:265
ObjectCloneType
Definition icloneable.h:25
TrackWidgetHighlight
Highlight location.
Definition track.h:82