Zrythm v2.0.0-DEV
a highly automated and intuitive digital audio workstation
Loading...
Searching...
No Matches
automation_track.h
1// SPDX-FileCopyrightText: © 2018-2022, 2024-2025 Alexandros Theodotou <alex@zrythm.org>
2// SPDX-License-Identifier: LicenseRef-ZrythmLicense
3
4#ifndef __AUDIO_AUTOMATION_TRACK_H__
5#define __AUDIO_AUTOMATION_TRACK_H__
6
7#include "zrythm-config.h"
8
9#include "dsp/position.h"
10#include "gui/dsp/arranger_object_all.h"
11#include "gui/dsp/arranger_object_owner.h"
12#include "gui/dsp/automation_point.h"
13#include "gui/dsp/port.h"
14
15#include <QtQmlIntegration>
16
19
25
28
29constexpr int AUTOMATION_TRACK_DEFAULT_HEIGHT = 48;
30
31enum class AutomationRecordMode
32{
33 Touch,
34 Latch,
35 NUM_AUTOMATION_RECORD_MODES,
36};
37
38DEFINE_ENUM_FORMATTER (
39 AutomationRecordMode,
40 AutomationRecordMode,
41 QT_TR_NOOP_UTF8 ("Touch"),
42 QT_TR_NOOP_UTF8 ("Latch"));
43
44class AutomationTrack final
45 : public QObject,
46 public ICloneable<AutomationTrack>,
47 public ArrangerObjectOwner<AutomationRegion>
48{
49 Q_OBJECT
50 QML_ELEMENT
51 Q_PROPERTY (double height READ getHeight WRITE setHeight NOTIFY heightChanged)
52 Q_PROPERTY (QString label READ getLabel NOTIFY labelChanged)
53 Q_PROPERTY (
54 int automationMode READ getAutomationMode WRITE setAutomationMode NOTIFY
55 automationModeChanged)
56 Q_PROPERTY (
57 int recordMode READ getRecordMode WRITE setRecordMode NOTIFY
58 recordModeChanged)
59 DEFINE_ARRANGER_OBJECT_OWNER_QML_PROPERTIES (
61 regions,
63
64public:
65 using Position = dsp::Position;
66 using PortUuid = Port::Uuid;
67 using TrackGetter = std::function<TrackPtrVariant ()>;
68
69public:
72 PortRegistry &port_registry,
73 ArrangerObjectRegistry &obj_registry,
74 TrackGetter track_getter,
75 const ControlPort::Uuid &port_id);
76
77public:
78 // ========================================================================
79 // QML Interface
80 // ========================================================================
81
82 QString getLabel () const;
83 Q_SIGNAL void labelChanged (QString label);
84
85 double getHeight () const { return height_; }
86 void setHeight (double height);
87 Q_SIGNAL void heightChanged (double height);
88
89 int getAutomationMode () const
90 {
91 return ENUM_VALUE_TO_INT (automation_mode_);
92 }
93 void setAutomationMode (int automation_mode);
94 Q_SIGNAL void automationModeChanged (int automation_mode);
95
96 int getRecordMode () const { return ENUM_VALUE_TO_INT (record_mode_); }
97 void setRecordMode (int record_mode);
98 Q_SIGNAL void recordModeChanged (int record_mode);
99
100 // ========================================================================
101
102 void init_loaded ();
103
104 bool validate () const;
105
116 static AutomationTrack *
117 find_from_port_id (const PortUuid &id, bool basic_search);
118
123 void set_port_id (const PortUuid &port_id);
124
132 [[gnu::hot]] static AutomationTrack * find_from_port (
133 const ControlPort &port,
134 const AutomatableTrack * track,
135 bool basic_search);
136
137 void set_automation_mode (AutomationMode mode, bool fire_events);
138
139 void swap_record_mode ()
140 {
141 record_mode_ = static_cast<AutomationRecordMode> (
142 (static_cast<int> (record_mode_) + 1)
143 % static_cast<int> (AutomationRecordMode::NUM_AUTOMATION_RECORD_MODES));
144 }
145
146 AutomationTracklist * get_automation_tracklist () const;
147
156 [[gnu::hot]] bool should_read_automation (RtTimePoint cur_time) const;
157
174 [[gnu::hot]] bool
175 should_be_recording (RtTimePoint cur_time, bool record_aps) const;
176
180 void set_index (int index);
181
185 void
187 override;
188
189 TrackPtrVariant get_track () const;
190
199 get_ap_before_pos (const Position &pos, bool ends_after, bool use_snapshots)
200 const;
201
210 get_region_before_pos (const Position &pos, bool ends_after, bool use_snapshots)
211 const;
212
213 ControlPort &get_port () const;
214
230 const Position &pos,
231 bool normalized,
232 bool ends_after,
233 bool use_snapshots) const;
234
235 static int get_y_px_from_height_and_normalized_val (
236 const float height,
237 const float normalized_val)
238 {
239 return static_cast<int> (height - normalized_val * height);
240 }
241
246 int get_y_px_from_normalized_val (float normalized_val) const
247 {
248 return get_y_px_from_height_and_normalized_val (
249 static_cast<float> (height_), normalized_val);
250 }
251
252 void set_caches (CacheType types);
253
254 bool contains_automation () const { return !get_children_vector ().empty (); }
255
256 bool verify () const;
257
258 Location get_location (const AutomationRegion &) const override;
259
260 std::string
261 get_field_name_for_serialization (const AutomationRegion *) const override
262 {
263 return "regions";
264 }
265
266private:
267 static constexpr std::string_view kIndexKey = "index";
268 static constexpr std::string_view kPortIdKey = "portId";
269 static constexpr std::string_view kCreatedKey = "created";
270 static constexpr std::string_view kAutomationModeKey = "automationMode";
271 static constexpr std::string_view kRecordModeKey = "recordMode";
272 static constexpr std::string_view kVisibleKey = "visible";
273 static constexpr std::string_view kHeightKey = "height";
274 friend void to_json (nlohmann::json &j, const AutomationTrack &track)
275 {
276 to_json (j, static_cast<const ArrangerObjectOwner &> (track));
277 j[kIndexKey] = track.index_;
278 j[kPortIdKey] = track.port_id_;
279 j[kCreatedKey] = track.created_;
280 j[kAutomationModeKey] = track.automation_mode_;
281 j[kRecordModeKey] = track.record_mode_;
282 j[kVisibleKey] = track.visible_;
283 j[kHeightKey] = track.height_;
284 }
285 friend void from_json (const nlohmann::json &j, AutomationTrack &track)
286 {
287 from_json (j, static_cast<ArrangerObjectOwner &> (track));
288 j.at (kIndexKey).get_to (track.index_);
289 j.at (kPortIdKey).get_to (track.port_id_);
290 j.at (kCreatedKey).get_to (track.created_);
291 j.at (kAutomationModeKey).get_to (track.automation_mode_);
292 j.at (kRecordModeKey).get_to (track.record_mode_);
293 j.at (kVisibleKey).get_to (track.visible_);
294 j.at (kHeightKey).get_to (track.height_);
295 }
296
297public:
298 PortRegistry &port_registry_;
299 ArrangerObjectRegistry &object_registry_;
300 TrackGetter track_getter_;
301
303 int index_ = 0;
304
306 PortUuid port_id_;
307
309 bool created_ = false;
310
318 bool visible_ = false;
319
321 int y_ = 0;
322
324 double height_ = AUTOMATION_TRACK_DEFAULT_HEIGHT;
325
328
330 AutomationMode automation_mode_ = AutomationMode::Read;
331
333 AutomationRecordMode record_mode_ = (AutomationRecordMode) 0;
334
337 bool recording_started_ = false;
338
341
350
358 bool recording_paused_ = false;
359
360private:
362 // AutomationTracklist * atl_ = nullptr;
363
365 // std::optional<std::reference_wrapper<ControlPort>> port_;
366};
367
368#endif // __AUDIO_AUTOMATION_TRACK_H__
Interface for a track that has automatable parameters.
An automation point inside an AutomationTrack.
Represents an automation region, which contains a collection of automation points.
Each track has an automation tracklist with automation tracks to be generated at runtime,...
Control port specifics.
Represents the position of an object.
Definition position.h:67
AutomationRegion * get_region_before_pos(const Position &pos, bool ends_after, bool use_snapshots) const
Returns the Region that starts before given Position, if any.
int get_y_px_from_normalized_val(float normalized_val) const
Returns the y pixels from the value based on the allocation of the automation track.
double height_
Position of multipane handle.
void set_port_id(const PortUuid &port_id)
Clone the given port identifier and take ownership of the clone.
bool should_read_automation(RtTimePoint cur_time) const
Returns whether the automation in the automation track should be read.
bool recording_start_sent_
This is a flag to let the recording manager know that a START signal was already sent for recording.
bool created_
Whether it has been created by the user yet or not.
AutomationMode
FIXME: move to a more appropriate place.
bool visible_
Whether visible or not.
static AutomationTrack * find_from_port_id(const PortUuid &id, bool basic_search)
void init_after_cloning(const AutomationTrack &other, ObjectCloneType clone_type) override
Clones the AutomationTrack.
PortUuid port_id_
Identifier of the Port this AutomationTrack is for (owned pointer).
AutomationTrack(PortRegistry &port_registry, ArrangerObjectRegistry &obj_registry, TrackGetter track_getter, const ControlPort::Uuid &port_id)
Creates an automation track for the given Port.
void set_index(int index)
Sets the index of the AutomationTrack in the AutomationTracklist.
bool recording_paused_
This must only be set by the RecordingManager when temporarily pausing recording, eg when looping or ...
float get_val_at_pos(const Position &pos, bool normalized, bool ends_after, bool use_snapshots) const
Returns the actual parameter value at the given position.
int index_
Index in parent AutomationTracklist.
constexpr int AUTOMATION_RECORDING_TOUCH_REL_MS
Release time in ms when in touch record mode.
bool should_be_recording(RtTimePoint cur_time, bool record_aps) const
Returns if the automation track should currently be recording data.
AutomationMode automation_mode_
Automation mode.
static AutomationTrack * find_from_port(const ControlPort &port, const AutomatableTrack *track, bool basic_search)
Finds the AutomationTrack associated with port.
float last_recorded_value_
Last value recorded in this automation track.
AutomationPoint * get_ap_before_pos(const Position &pos, bool ends_after, bool use_snapshots) const
Returns the automation point before the Position on the timeline.
AutomationRecordMode record_mode_
Automation record mode, when automation_mode_ is set to record.
int y_
Y local to track.
AutomationRegion * recording_region_
Region currently recording to.
bool recording_started_
To be set to true when recording starts (when the first change is received) and false when recording ...
ObjectCloneType
Definition icloneable.h:25