Zrythm v2.0.0-DEV
a highly automated and intuitive digital audio workstation
Loading...
Searching...
No Matches
track_span.h
1// SPDX-FileCopyrightText: © 2025 Alexandros Theodotou <alex@zrythm.org>
2// SPDX-License-Identifier: LicenseRef-ZrythmLicense
3
4#pragma once
5
6#include "structure/tracks/track_all.h"
7
8namespace zrythm::structure::tracks
9{
13class TrackSpan : public utils::UuidIdentifiableObjectView<TrackRegistry>
14{
15public:
17 using VariantType = typename Base::VariantType;
18 using TrackUuid = typename Base::UuidType;
19 using Base::Base; // Inherit constructors
20
21 using ArrangerObjectRegistry = arrangement::ArrangerObjectRegistry;
22
23 bool contains_track (const TrackUuid &id) const
24 {
25 return std::ranges::contains (*this, id, Base::uuid_projection);
26 }
27
28 static auto name_projection (const VariantType &track_var)
29 {
30 return std::visit (
31 [] (const auto &track) { return track->get_name (); }, track_var);
32 }
33 static auto foldable_projection (const VariantType &track_var)
34 {
35 return std::visit (
36 [] (const auto &track) {
37 using TrackT = base_type<decltype (track)>;
39 },
40 track_var);
41 }
42
43#define DEFINE_PROJECTION_FOR_TRACK_TYPE(func_name, base_class) \
44 static auto func_name##_projection (const VariantType &track_var) \
45 { \
46 return std::visit ( \
47 [] (const auto &track) { \
48 auto &track_ref = *track; \
49 using TrackT = base_type<decltype (track_ref)>; \
50 if constexpr (std::derived_from<TrackT, base_class>) \
51 { \
52 return track_ref.func_name (); \
53 } \
54 else \
55 { \
56 return false; \
57 } \
58 }, \
59 track_var); \
60 }
61 DEFINE_PROJECTION_FOR_TRACK_TYPE (enabled, Track)
62
63 template <typename BaseType>
64 static auto derived_type_transformation (const VariantType &track_var)
65 {
66 return std::visit (
67 [] (const auto &track) {
68 using TrackT = base_type<decltype (track)>;
69 if constexpr (!std::derived_from<TrackT, BaseType>)
70 {
71 throw std::runtime_error (
72 "Must filter before using this transformation.");
73 }
74 return dynamic_cast<BaseType *> (track);
75 },
76 track_var);
77 }
78
79 std::optional<VariantType>
80 get_track_by_name (const utils::Utf8String &name) const
81 {
82 auto it = std::ranges::find (*this, name, name_projection);
83 return it != this->end () ? std::make_optional (*it) : std::nullopt;
84 }
85
86 bool contains_track_name (const utils::Utf8String &name) const
87 {
88 return std::ranges::contains (*this, name, name_projection);
89 }
90
91 MasterTrack &get_master_track () const
92 {
93 auto it = std::ranges::find_if (*this, [] (const auto &track_var) {
94 return std::holds_alternative<MasterTrack *> (track_var);
95 });
96 if (it == this->end ())
97 {
98 throw std::runtime_error ("Master track not found");
99 }
100 return *std::get<MasterTrack *> (*it);
101 }
102
107 {
108 std::ranges::for_each (*this, [&] (auto &&track_var) {
109 std::visit (
110 [&] (auto &&tr) { tr->setVisible (!tr->visible ()); }, track_var);
111 });
112 }
113
114#if 0
118 void select_last_visible ()
119 {
120 auto res = std::ranges::find_last_if (*this, visible_projection);
121 if (!res.empty ())
122 {
123 std::visit (
124 [&] (auto &&tr) { select_single (tr->get_uuid ()); }, res.front ());
125 }
126 }
127
128 void select_all_visible_tracks ()
129 {
130 std::ranges::for_each (
131 *this | std::views::filter (visible_projection), [] (auto &&track_var) {
132 std::visit ([] (auto &&tr) { tr->setSelected (true); }, track_var);
133 });
134 }
135#endif
136
142 {
143 return std::ranges::any_of (*this, [&] (auto &&track_var) {
144 return std::visit (
145 [] (auto &&tr) { return !tr->has_automation (); }, track_var);
146 });
147 }
148
149 bool contains_undeletable_track () const
150 {
151 return std::ranges::any_of (*this, [&] (auto &&track_var) {
152 return std::visit (
153 [] (auto &&tr) { return !tr->is_deletable (); }, track_var);
154 });
155 }
156
157 bool contains_uncopyable_track () const
158 {
159 return std::ranges::any_of (*this, [&] (auto &&track_var) {
160 return std::visit (
161 [] (auto &&tr) { return !tr->is_copyable (); }, track_var);
162 });
163 }
164
165 bool contains_uninstantiated_plugin () const
166 {
167 return std::ranges::any_of (*this, [] (const auto &track_var) {
168 return std::visit (
169 [&] (auto &&tr) { return tr->contains_uninstantiated_plugin (); },
170 track_var);
171 });
172 }
173
177 template <typename T> void get_plugins (T &container)
178 {
179 std::ranges::for_each (*this, [&container] (const auto &track_var) {
180 std::visit (
181 [&container] (auto &&track) { track->collect_plugins (container); },
182 track_var);
183 });
184 }
185
186 void deselect_all_plugins ()
187 {
188 // TODO?
189 }
190
191 static bool currently_soloed_projection (const VariantType &var)
192 {
193 return std::visit (
194 [] (auto &&track) {
195 if (!track->channel ())
196 return false;
197 return track->channel ()->fader ()->currently_soloed ();
198 },
199 var);
200 }
201 static bool currently_muted_projection (const VariantType &var)
202 {
203 return std::visit (
204 [] (auto &&track) {
205 if (!track->channel ())
206 return false;
207 return track->channel ()->fader ()->currently_muted ();
208 },
209 var);
210 }
211 static bool currently_listened_projection (const VariantType &var)
212 {
213 return std::visit (
214 [] (auto &&track) {
215 if (!track->channel ())
216 return false;
217 return track->channel ()->fader ()->currently_listened ();
218 },
219 var);
220 }
221
222 static bool soloed_projection (const VariantType &var)
223 {
224 return std::visit (
225 [] (auto &&track) {
226 if (!track->channel ())
227 return false;
228 const auto * solo = track->channel ()->fader ()->solo ();
229 return solo->range ().is_toggled (solo->baseValue ());
230 },
231 var);
232 }
233 static bool muted_projection (const VariantType &var)
234 {
235 return std::visit (
236 [] (auto &&track) {
237 if (!track->channel ())
238 return false;
239 const auto * mute = track->channel ()->fader ()->mute ();
240 return mute->range ().is_toggled (mute->baseValue ());
241 },
242 var);
243 }
244 static bool listened_projection (const VariantType &var)
245 {
246 return std::visit (
247 [] (auto &&track) {
248 if (!track->channel ())
249 return false;
250 const auto * listen = track->channel ()->fader ()->listen ();
251 return listen->range ().is_toggled (listen->baseValue ());
252 },
253 var);
254 }
255
256 auto has_soloed () const
257 {
258 return std::ranges::any_of (*this, currently_soloed_projection);
259 }
260
261 auto has_listened () const
262 {
263 return std::ranges::any_of (*this, currently_listened_projection);
264 }
265
266 auto get_num_muted_tracks () const
267 {
268 return std::ranges::count_if (*this, muted_projection);
269 }
270
271 auto get_num_soloed_tracks () const
272 {
273 return std::ranges::count_if (*this, soloed_projection);
274 }
275
276 auto get_num_listened_tracks () const
277 {
278 return std::ranges::count_if (*this, listened_projection);
279 }
280
285 void set_caches (CacheType types)
286 {
287 std::ranges::for_each (*this, [&] (const auto &track_var) {
288 std::visit ([&] (auto &&track) { track->set_caches (types); }, track_var);
289 });
290 }
291
299// depreacted: use from/to json
300#if 0
301 std::vector<VariantType> create_snapshots (
302 QObject &owner,
303 TrackRegistry &track_registry,
304 PluginRegistry &plugin_registry,
305 PortRegistry &port_registry,
306 ArrangerObjectRegistry &obj_registry) const
307 {
308 return std::ranges::to<std::vector> (
309 *this | std::views::transform ([&] (const auto &track_var) {
310 return std::visit (
311 [&] (auto &&track) -> VariantType {
312 return utils::clone_qobject (
313 *track, &owner, utils::ObjectCloneType::Snapshot, track_registry,
314 plugin_registry, port_registry, obj_registry, false);
315 },
316 track_var);
317 }));
318 }
319
320 std::vector<TrackUuidReference>
321 create_new_identities (FinalTrackDependencies track_deps) const
322 {
323 return std::ranges::to<std::vector> (
324 *this | std::views::transform ([&] (const auto &track_var) {
325 return std::visit (
326 [&] (auto &&track) -> TrackUuidReference {
327 return track_deps.track_registry_.clone_object (*track, track_deps);
328 },
329 track_var);
330 }));
331 }
332#endif
333};
334
335static_assert (std::ranges::random_access_range<TrackSpan>);
336}
Track span that offers helper methods on a range of tracks.
Definition track_span.h:14
void get_plugins(T &container)
Fills in the given array with all plugins in the tracklist.
Definition track_span.h:177
void toggle_visibility()
Toggle visibility of the tracks in this collection.
Definition track_span.h:106
void set_caches(CacheType types)
Set various caches (snapshots, track name hashes, plugin input/output ports, etc).
Definition track_span.h:285
bool contains_non_automatable_track() const
Returns whether the tracklist selections contains a track that cannot have automation lanes.
Definition track_span.h:141
Represents a track in the project.
Definition track.h:54
Lightweight UTF-8 string wrapper with safe conversions.
Definition utf8_string.h:38
A unified view over UUID-identified objects that supports:
@ Snapshot
Creates a snapshot of the object with the same identity.
Definition icloneable.h:23