Zrythm v2.0.0-DEV
a highly automated and intuitive digital audio workstation
Loading...
Searching...
No Matches
track_lane.h
1// SPDX-FileCopyrightText: © 2019-2025 Alexandros Theodotou <alex@zrythm.org>
2// SPDX-License-Identifier: LicenseRef-ZrythmLicense
3
4#pragma once
5
6#include <utility>
7
8#include "structure/arrangement/arranger_object_all.h"
9#include "structure/arrangement/arranger_object_owner.h"
10
11namespace zrythm::structure::tracks
12{
13
23class TrackLane
24 : public QObject,
25 public utils::UuidIdentifiableObject<TrackLane>,
26 public arrangement::ArrangerObjectOwner<arrangement::MidiRegion>,
27 public arrangement::ArrangerObjectOwner<arrangement::AudioRegion>
28{
29 Q_OBJECT
30 DEFINE_ARRANGER_OBJECT_OWNER_QML_PROPERTIES (
31 TrackLane,
32 midiRegions,
34 DEFINE_ARRANGER_OBJECT_OWNER_QML_PROPERTIES (
35 TrackLane,
36 audioRegions,
38 Q_PROPERTY (QString name READ name WRITE setName NOTIFY nameChanged)
39 Q_PROPERTY (double height READ height WRITE setHeight NOTIFY heightChanged)
40 Q_PROPERTY (bool muted READ muted WRITE setMuted NOTIFY muteChanged)
41 Q_PROPERTY (bool soloed READ soloed WRITE setSoloed NOTIFY soloChanged)
42 Q_PROPERTY (
43 std::uint8_t midiChannel READ midiChannel WRITE setMidiChannel NOTIFY
44 midiChannelChanged)
45 QML_ELEMENT
46 QML_UNCREATABLE ("")
47
48 static constexpr double DEFAULT_HEIGHT = 48;
49
50public:
54 using SoloedLanesExistFunc = GenericBoolGetter;
55
56 static constexpr auto default_format_str = QT_TR_NOOP_UTF8 ("Lane {}");
57
59 {
60 structure::arrangement::ArrangerObjectRegistry &obj_registry_;
61 dsp::FileAudioSourceRegistry &file_audio_source_registry_;
62 SoloedLanesExistFunc soloed_lanes_exist_func_;
63 };
64
65 TrackLane (TrackLaneDependencies dependencies, QObject * parent = nullptr)
66 : QObject (parent),
67 arrangement::ArrangerObjectOwner<arrangement::MidiRegion> (
68 dependencies.obj_registry_,
69 dependencies.file_audio_source_registry_,
70 *this),
71 arrangement::ArrangerObjectOwner<arrangement::AudioRegion> (
72 dependencies.obj_registry_,
73 dependencies.file_audio_source_registry_,
74 *this),
75 soloed_lanes_exist_func_ (
76 std::move (dependencies.soloed_lanes_exist_func_))
77 {
78 }
79 Z_DISABLE_COPY_MOVE (TrackLane)
80 ~TrackLane () override;
81
82 // ========================================================================
83 // QML Interface
84 // ========================================================================
85
86 QString name () const { return name_.to_qstring (); }
87 void setName (const QString &name)
88 {
89 const auto std_name = utils::Utf8String::from_qstring (name);
90 if (name_ == std_name)
91 return;
92
93 name_ = std_name;
94 Q_EMIT nameChanged (name);
95 }
96 Q_SIGNAL void nameChanged (const QString &name);
97
98 double height () const { return height_; }
99 void setHeight (const double height)
100 {
101 if (utils::math::floats_equal (height_, height))
102 return;
103
104 height_ = height;
105 Q_EMIT heightChanged (height);
106 }
107 Q_SIGNAL void heightChanged (double height);
108
109 bool soloed () const { return solo_; }
110 void setSoloed (bool solo)
111 {
112 if (solo_ == solo)
113 return;
114
115 solo_ = solo;
116 Q_EMIT soloChanged (solo);
117 }
118 Q_SIGNAL void soloChanged (bool solo);
119
120 bool muted () const { return mute_; }
121 void setMuted (bool mute)
122 {
123 if (mute_ == mute)
124 return;
125
126 mute_ = mute;
127 Q_EMIT muteChanged (mute);
128 }
129 Q_SIGNAL void muteChanged (bool mute);
130
133 * muted).
134 */
135 Q_INVOKABLE bool effectivelyMuted () const
136 {
137 if (muted ())
138 return true;
139
140 /* if lane is non-soloed while other soloed lanes exist, this should
141 * be muted */
142 if (soloed_lanes_exist_func_ () && !soloed ())
143 return true;
144
145 return false;
146 }
147
148 std::uint8_t midiChannel () const { return midi_ch_; }
149 void setMidiChannel (std::uint8_t midi_ch)
150 {
151 if (midi_ch_ == midi_ch)
152 return;
153
154 midi_ch_ = midi_ch;
155 Q_EMIT midiChannelChanged (midi_ch);
156 }
157 Q_SIGNAL void midiChannelChanged (std::uint8_t midi_ch);
158
159 // ========================================================================
160
166 void generate_name (size_t index);
167
173 // std::unique_ptr<TrackLaneT> gen_snapshot () const;
174
176 const arrangement::MidiRegion * _) const override
177 {
178 return "midiRegions";
179 }
181 const arrangement::AudioRegion * _) const override
182 {
183 return "audioRegions";
184 }
185
186private:
187 static constexpr std::string_view kNameKey = "name";
188 static constexpr std::string_view kHeightKey = "height";
189 static constexpr std::string_view kMuteKey = "mute";
190 static constexpr std::string_view kSoloKey = "solo";
191 static constexpr std::string_view kMidiChannelKey = "midiChannel";
192 friend void to_json (nlohmann::json &j, const TrackLane &lane)
193 {
194 to_json (j, static_cast<const UuidIdentifiableObject &> (lane));
195 to_json (
196 j,
197 static_cast<const arrangement::ArrangerObjectOwner<
198 arrangement::MidiRegion> &> (lane));
199 to_json (
200 j,
201 static_cast<const arrangement::ArrangerObjectOwner<
202 arrangement::AudioRegion> &> (lane));
203 j[kNameKey] = lane.name_;
204 j[kHeightKey] = lane.height_;
205 j[kMuteKey] = lane.mute_;
206 j[kSoloKey] = lane.solo_;
207 j[kMidiChannelKey] = lane.midi_ch_;
208 }
209 friend void from_json (const nlohmann::json &j, TrackLane &lane)
210 {
211 from_json (j, static_cast<UuidIdentifiableObject &> (lane));
212 from_json (
213 j,
214 static_cast<arrangement::ArrangerObjectOwner<arrangement::MidiRegion> &> (
215 lane));
216 from_json (
217 j,
218 static_cast<arrangement::ArrangerObjectOwner<arrangement::AudioRegion> &> (
219 lane));
220 j.at (kNameKey).get_to (lane.name_);
221 j.at (kHeightKey).get_to (lane.height_);
222 j.at (kMuteKey).get_to (lane.mute_);
223 j.at (kSoloKey).get_to (lane.solo_);
224 j.at (kMidiChannelKey).get_to (lane.midi_ch_);
225 }
226
227 friend void init_from (
228 TrackLane &obj,
229 const TrackLane &other,
230 utils::ObjectCloneType clone_type)
231 {
232 obj.name_ = other.name_;
233 obj.height_ = other.height_;
234 obj.mute_ = other.mute_;
235 obj.solo_ = other.solo_;
236 obj.midi_ch_ = other.midi_ch_;
237 }
238
239private:
240 SoloedLanesExistFunc soloed_lanes_exist_func_;
241
243 utils::Utf8String name_;
244
246 double height_{ DEFAULT_HEIGHT };
247
249 bool mute_{};
250
252 bool solo_{};
253
259 uint8_t midi_ch_ = 0;
260
261 BOOST_DESCRIBE_CLASS (
262 TrackLane,
263 (utils::UuidIdentifiableObject<TrackLane>),
264 (),
265 (),
266 (name_, height_, mute_, solo_, midi_ch_))
267};
268}
A region for playing back audio samples.
A Region containing MIDI events.
Definition midi_region.h:20
A container of MIDI or Audio regions.
Definition track_lane.h:28
Q_INVOKABLE bool effectivelyMuted() const
Returns if the lane is effectively muted (explicitly or implicitly muted).
Definition track_lane.h:133
void generate_name(size_t index)
Generates a default name for the lane at the given index.
std::string get_field_name_for_serialization(const arrangement::MidiRegion *_) const override
Generate a snapshot for playback.
Definition track_lane.h:173
GenericBoolGetter SoloedLanesExistFunc
Function to check if other soloed lanes exist in the owner.
Definition track_lane.h:52
Base class for objects that need to be uniquely identified by UUID.
constexpr bool floats_equal(T a, T b)
Checks if 2 floating point numbers are equal.
Definition math.h:76