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 "dsp/tempo_map.h"
7#include "structure/arrangement/arranger_object_span.h"
8#include "structure/tracks/track.h"
9#include "structure/tracks/track_span.h"
10
11#include <QtQmlIntegration>
12
13struct FileImportInfo;
14
15#define TRACKLIST (PROJECT->tracklist_)
16
17namespace zrythm::engine::session
18{
19class Router;
20}
21
22class Project;
23
24namespace zrythm::structure::tracks
25{
26class ChordTrack;
27class ModulatorTrack;
28class MasterTrack;
29class MarkerTrack;
30
38class Tracklist final : public QAbstractListModel
39{
40 Q_OBJECT
41 QML_ELEMENT
42
43public:
44 using TrackUuid = Track::Uuid;
45 using ArrangerObjectPtrVariant = arrangement::ArrangerObjectPtrVariant;
46 using Region = arrangement::Region;
47 using ArrangerObject = arrangement::ArrangerObject;
48
52 enum class PinOption
53 {
54 PinnedOnly,
55 UnpinnedOnly,
56 Both,
57 };
58
59 enum TrackRoles
60 {
61 TrackPtrRole = Qt::UserRole + 1,
62 TrackNameRole,
63 };
64
65public:
66 explicit Tracklist (
67 Project &project,
68 PortRegistry &port_registry,
69 TrackRegistry &track_registry,
70 dsp::PortConnectionsManager &port_connections_manager,
71 const dsp::TempoMap &tempo_map);
72 explicit Tracklist (
73 engine::session::SampleProcessor &sample_processor,
74 PortRegistry &port_registry,
75 TrackRegistry &track_registry,
76 dsp::PortConnectionsManager &port_connections_manager,
77 const dsp::TempoMap &tempo_map);
78 Z_DISABLE_COPY_MOVE (Tracklist)
79 ~Tracklist () override;
80
81 // ========================================================================
82 // QML Interface
83 // ========================================================================
84 QHash<int, QByteArray> roleNames () const override;
85 int rowCount (const QModelIndex &parent = QModelIndex ()) const override;
86 QVariant
87 data (const QModelIndex &index, int role = Qt::DisplayRole) const override;
88
89 Q_INVOKABLE void setExclusivelySelectedTrack (QVariant track);
90
91 // ========================================================================
92
96 static constexpr std::array<Track::Type, 4> unique_track_types_ = {
98 };
99
100 auto get_track_span () const { return TrackSpan{ tracks_ }; }
101
102 bool is_auditioner () const { return sample_processor_ != nullptr; }
103
104 friend void init_from (
105 Tracklist &obj,
106 const Tracklist &other,
107 utils::ObjectCloneType clone_type);
108
113 PortRegistry &port_registry,
114 Project * project,
115 engine::session::SampleProcessor * sample_processor);
116
117 void init_loaded (PortRegistry &port_registry, Project &project)
118 {
119 init_loaded (port_registry, &project, nullptr);
120 }
121 void init_loaded (
122 PortRegistry &port_registry,
123 engine::session::SampleProcessor &sample_processor)
124 {
125 init_loaded (port_registry, nullptr, &sample_processor);
126 }
127
135 TrackPtrVariant insert_track (
136 const TrackUuidReference &track_id,
137 int pos,
139 bool publish_events,
140 bool recalc_graph);
141
145 TrackPtrVariant append_track (
146 auto track_id,
148 bool publish_events,
149 bool recalc_graph)
150 {
151 return insert_track (
152 track_id, tracks_.size (), engine, publish_events, recalc_graph);
153 }
154
161 void remove_track (const TrackUuid &track_id);
162
173 TrackUuid track_id,
174 int pos,
175 bool always_before_pos,
176 std::optional<std::reference_wrapper<engine::session::Router>> router);
177
178 std::optional<TrackPtrVariant> get_track (const TrackUuid &id) const
179 {
180 auto span = get_track_span ();
181 auto it = std::ranges::find (span, id, TrackSpan::uuid_projection);
182 if (it == span.end ()) [[unlikely]]
183 {
184 return std::nullopt;
185 }
186 return std::make_optional (*it);
187 }
188
193 TrackUuid track_id,
194 bool pinned,
195 int publish_events,
196 int recalc_graph);
197
198 ChordTrack * get_chord_track () const;
199
206 std::optional<TrackPtrVariant> get_first_visible_track (bool pinned) const;
207
212 std::optional<TrackPtrVariant>
213 get_prev_visible_track (Track::TrackUuid track_id) const;
214
219 std::optional<TrackPtrVariant>
220 get_next_visible_track (Track::TrackUuid track_id) const;
221
229 int
230 get_last_pos (PinOption pin_opt = PinOption::Both, bool visible_only = false)
231 const;
232
239 std::optional<TrackPtrVariant>
240 get_last_track (PinOption pin_opt = PinOption::Both, bool visible_only = false)
241 const
242 {
243 return get_track_span ().get_track_by_pos (
244 get_last_pos (pin_opt, visible_only));
245 }
246
255 std::optional<TrackPtrVariant>
256 get_visible_track_after_delta (Track::TrackUuid track_id, int delta) const;
257
266 Track::TrackUuid src_track,
267 Track::TrackUuid dest_track) const;
268
275 double multiplier,
276 bool visible_only,
277 bool check_only,
278 bool fire_events);
279
283 void handle_click (TrackUuid track_id, bool ctrl, bool shift, bool dragged);
284
285 std::vector<ArrangerObjectPtrVariant> get_timeline_objects_in_range (
286 std::optional<std::pair<dsp::Position, dsp::Position>> range = std::nullopt)
287 const;
288
294 void
296
304
314 std::vector<std::vector<std::shared_ptr<Region>>> &region_arrays,
315 const FileImportInfo * import_info,
316 TracksReadyCallback ready_cb);
317
336 ArrangerObjectPtrVariant region,
337 const Track::Uuid &to_track_id,
338 int lane_or_at_index,
339 int index);
340
345 const Plugin::Uuid &plugin_id,
346 const Track::Uuid &prev_track_id,
347 const Track::Uuid &track_id_to_move_to,
349
359 const Plugin::Uuid &plugin_id,
360 const Track::Uuid &target_track_id,
362 bool confirm_overwrite);
363
364 Channel * get_channel_for_plugin (const Plugin::Uuid &plugin_id);
365
380 std::optional<std::vector<utils::Utf8String>> uri_list,
381 const FileDescriptor * orig_file,
382 const Track * track,
383 const TrackLane * lane,
384 int index,
385 const zrythm::dsp::Position * pos,
386 TracksReadyCallback ready_cb);
387
388#if 0
396 void handle_move_or_copy (
397 Track &this_track,
398 TrackWidgetHighlight location,
399 GdkDragAction action);
400#endif
401
407 bool
408 track_name_is_unique (const utils::Utf8String &name, TrackUuid track_to_skip)
409 const;
410
414 bool is_track_pinned (size_t index) const
415 {
416 return index < pinned_tracks_cutoff_;
417 }
418
419 auto get_track_index (const Track::TrackUuid &track_id) const
420 {
421 return std::distance (
422 tracks_.begin (),
423 std::ranges::find (tracks_, track_id, &TrackUuidReference::id));
424 }
425
426 auto get_track_at_index (size_t index) const
427 {
428 if (index >= tracks_.size ())
429 throw std::out_of_range ("Track index out of range");
430 return get_track_span ().at (index);
431 }
432
433 auto get_track_ref_at_index (size_t index) const
434 {
435 if (index >= tracks_.size ())
436 throw std::out_of_range ("Track index out of range");
437 return tracks_.at (index);
438 }
439
440 bool is_track_pinned (Track::TrackUuid track_id) const
441 {
442 return is_track_pinned (get_track_index (track_id));
443 }
444
445 auto get_selection_manager ()
446 {
447 return TrackSelectionManager{ selected_tracks_, *track_registry_ };
448 }
449
455 {
456 auto selected_vec = std::ranges::to<std::vector> (selected_tracks_);
457 TrackSpan span{ *track_registry_, selected_vec };
458 std::ranges::for_each (span, [&] (auto &&track_var) {
459 std::visit (
460 [&] (auto &&track_ref) {
461 using TrackT = base_type<decltype (track_ref)>;
462 if constexpr (std::derived_from<TrackT, FoldableTrack>)
463 {
464 for (int i = 1; i < track_ref->size_; ++i)
465 {
466 const size_t child_pos =
467 get_track_index (track_ref->get_uuid ()) + i;
468 const auto &child_track_var = get_track_at_index (child_pos);
469 get_selection_manager ().append_to_selection (
470 TrackSpan::uuid_projection (child_track_var));
471 }
472 }
473 },
474 track_var);
475 });
476 }
477
478 auto get_pinned_tracks_cutoff_index () const { return pinned_tracks_cutoff_; }
479 void set_pinned_tracks_cutoff_index (size_t index)
480 {
481 pinned_tracks_cutoff_ = index;
482 }
483 auto track_count () const { return tracks_.size (); }
484
494 TrackPtrVariant track_var,
495 bool bounce,
496 bool mark_regions,
497 bool mark_children,
498 bool mark_parents);
499
500 void mark_all_tracks_for_bounce (bool bounce)
501 {
502 get_track_span ().mark_all_tracks_for_bounce (*this, bounce);
503 }
504
505 void disconnect_plugin (const Plugin::Uuid &plugin_id);
506
507 std::string print_port_connection (const dsp::PortConnection &conn) const;
508
509private:
510 static constexpr auto kPinnedTracksCutoffKey = "pinnedTracksCutoff"sv;
511 static constexpr auto kTracksKey = "tracks"sv;
512 static constexpr auto kSelectedTracksKey = "selectedTracks"sv;
513 friend void to_json (nlohmann::json &j, const Tracklist &t)
514 {
515 j = nlohmann::json{
516 { kPinnedTracksCutoffKey, t.pinned_tracks_cutoff_ },
517 { kTracksKey, t.tracks_ },
518 { kSelectedTracksKey, t.selected_tracks_ },
519 };
520 }
521 friend void from_json (const nlohmann::json &j, Tracklist &t)
522 {
523 j.at (kPinnedTracksCutoffKey).get_to (t.pinned_tracks_cutoff_);
524 j.at (kTracksKey).get_to (t.tracks_);
525 j.at (kSelectedTracksKey).get_to (t.selected_tracks_);
526 }
527
528 void swap_tracks (size_t index1, size_t index2);
529
536 void disconnect_port (const Port::Uuid &port_id);
537
544 void disconnect_channel (Channel &channel);
545
546 // FIXME: public access
547public:
551 void disconnect_fader (Fader &fader);
552
553private:
557 void disconnect_track_processor (TrackProcessor &track_processor);
558
562 void disconnect_track (Track &track);
563
564 auto &get_track_registry () const { return *track_registry_; }
565 auto &get_track_registry () { return *track_registry_; }
566
567private:
568 const dsp::TempoMap &tempo_map_;
569
570 OptionalRef<TrackRegistry> track_registry_;
571 OptionalRef<PortRegistry> port_registry_;
572 OptionalRef<PluginRegistry> plugin_registry_;
573
591 std::vector<TrackUuidReference> tracks_;
592
598 TrackSelectionManager::UuidSet selected_tracks_;
599
600public:
603
606
609
612
613private:
619 size_t pinned_tracks_cutoff_ = 0;
620
623 std::atomic<bool> swapping_tracks_ = false;
624
626 engine::session::SampleProcessor * sample_processor_ = nullptr;
627
633 mutable QHash<Port::Uuid, AutomationTrack *> port_to_at_mappings_;
634
635public:
637 Project * project_ = nullptr;
638
640 // int width_ = 0;
641
642 QPointer<dsp::PortConnectionsManager> port_connections_manager_;
643};
644}
Descriptor of a file.
Contains all of the info that will be serialized into a project file.
Definition project.h:73
A connection between two ports.
Represents the position of an object.
Definition position.h:65
The Router class manages the processing graph for the audio engine.
Definition router.h:51
A processor to be used in the routing graph for playing samples independent of the timeline.
Base class for all objects in the arranger.
A region (clip) is an object on the timeline that contains either MidiNote's or AudioClip's.
Definition region.h:110
Represents a channel strip on the mixer.
Definition channel.h:38
The ChordTrack class is responsible for managing the chord and scale information in the project.
Definition chord_track.h:39
A Fader is a processor that is used for volume controls and pan.
Definition fader.h:44
A track that can host modulator plugins.
A TrackLane belongs to a Track (can have many TrackLanes in a Track) and contains Regions.
Definition track_lane.h:70
A TrackProcessor is a processor that is used as the first entry point when processing a track.
Track span that offers helper methods on a range of tracks.
Definition track_span.h:21
Represents a track in the project.
Definition track.h:276
@ Marker
Marker Track's contain named markers at specific Position's in the song.
Definition track.h:326
@ Modulator
Special track to contain global Modulator's.
Definition track.h:331
@ 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:321
The Tracklist contains all the tracks in the Project.
Definition tracklist.h:39
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 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.
void set_track_pinned(TrackUuid track_id, bool pinned, int publish_events, int recalc_graph)
Pins or unpins the Track.
void init_loaded(PortRegistry &port_registry, Project *project, engine::session::SampleProcessor *sample_processor)
Initializes the tracklist when loading a project.
TrackPtrVariant insert_track(const TrackUuidReference &track_id, int pos, engine::device_io::AudioEngine &engine, bool publish_events, bool recalc_graph)
Adds given track to given spot in tracklist.
PinOption
Used in track search functions.
Definition tracklist.h:53
void clear_selections_for_object_siblings(const ArrangerObject::Uuid &object_id)
Clears either the timeline selections or the clip editor selections.
std::optional< TrackPtrVariant > get_first_visible_track(bool pinned) const
Returns the first visible Track.
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.
ChordTrack * chord_track_
The chord track, for convenience.
Definition tracklist.h:602
void select_foldable_children_of_current_selections()
Also selects the children of foldable tracks in the currently selected tracks.
Definition tracklist.h:454
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.
Project * project_
Pointer to owner project, if any.
Definition tracklist.h:637
MarkerTrack * marker_track_
The marker track, for convenience.
Definition tracklist.h:605
MasterTrack * master_track_
The master track, for convenience.
Definition tracklist.h:611
QPointer< dsp::PortConnectionsManager > port_connections_manager_
Width of track widgets.
Definition tracklist.h:642
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.
void handle_click(TrackUuid track_id, bool ctrl, bool shift, bool dragged)
Handle a click selection.
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.
AutomationTrack * get_automation_track_for_port(const Port::Uuid &port_id) const
Gets the automation track for a port.
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).
std::optional< TrackPtrVariant > get_visible_track_after_delta(Track::TrackUuid track_id, int delta) const
Returns the Track after delta visible Track's.
bool is_track_pinned(size_t index) const
Returns whether the track at index is pinned.
Definition tracklist.h:414
void remove_track(const TrackUuid &track_id)
Removes the given track from the tracklist.
bool track_name_is_unique(const utils::Utf8String &name, TrackUuid track_to_skip) const
Returns whether the track name is not taken.
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).
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).
TrackPtrVariant append_track(auto track_id, engine::device_io::AudioEngine &engine, bool publish_events, bool recalc_graph)
Calls insert_track with the given options.
Definition tracklist.h:145
ModulatorTrack * modulator_track_
The modulator track, for convenience.
Definition tracklist.h:608
void move_track(TrackUuid track_id, int pos, bool always_before_pos, std::optional< std::reference_wrapper< engine::session::Router > > router)
Moves a track from its current position to the position given by pos.
void disconnect_fader(Fader &fader)
Disconnects all ports connected to the fader.
int get_last_pos(PinOption pin_opt=PinOption::Both, bool visible_only=false) const
Returns the index of the last Track.
std::optional< TrackPtrVariant > get_last_track(PinOption pin_opt=PinOption::Both, bool visible_only=false) const
Returns the last Track.
Definition tracklist.h:240
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:96
void mark_track_for_bounce(TrackPtrVariant track_var, bool bounce, bool mark_regions, bool mark_children, bool mark_parents)
Marks the track for bouncing.
Lightweight UTF-8 string wrapper with safe conversions.
Definition string.h:39
TrackWidgetHighlight
Highlight location.
Definition track.h:82
Wrapper around std::optional<std::reference_wrapper<T>> that provides a more convenient API.
Definition types.h:308