Zrythm v2.0.0-DEV
a highly automated and intuitive digital audio workstation
Loading...
Searching...
No Matches
recording_manager.h
1// SPDX-FileCopyrightText: © 2019, 2023-2025 Alexandros Theodotou <alex@zrythm.org>
2// SPDX-License-Identifier: LicenseRef-ZrythmLicense
3
4#pragma once
5
6#include <semaphore>
7
8#include "engine/session/recording_event.h"
9#include "structure/arrangement/automation_point.h"
10#include "structure/tracks/track_all.h"
11#include "utils/mpmc_queue.h"
12#include "utils/object_pool.h"
13#include "utils/types.h"
14
15namespace zrythm::structure::tracks
16{
17class TrackProcessor;
18}
19
20#define RECORDING_MANAGER (gZrythm->recording_manager_)
21
22namespace zrythm::engine::session
23{
24QT_WARNING_PUSH
25QT_WARNING_DISABLE_DEPRECATED
39class RecordingManager : public QObject
40{
41public:
42 using AutomationTrack = structure::tracks::AutomationTrack;
43 using AutomationRegion = structure::arrangement::AutomationRegion;
44 using AutomationPoint = structure::arrangement::AutomationPoint;
45
46public:
52 RecordingManager (QObject * parent = nullptr);
53 Q_DISABLE_COPY_MOVE (RecordingManager)
54 ~RecordingManager () override;
55
67 structure::tracks::TrackPtrVariant track_var,
68 const EngineProcessTimeInfo &time_nfo,
69 const dsp::MidiEventVector * midi_events,
70 std::optional<structure::tracks::TrackProcessor::ConstStereoPortPair>
71 stereo_ports);
72
73 Q_SLOT void process_events ();
74
85 double start_pos,
86 std::optional<double> end_pos,
87 int pitch,
88 int vel);
89
100
107 signed_frame_t pos,
108 std::vector<AutomationPoint *> &aps) const;
109
110private:
111 void handle_start_recording (const RecordingEvent &ev, bool is_automation);
112
130 bool handle_resume_event (const RecordingEvent &ev);
131
138 void handle_pause_event (const RecordingEvent &ev);
139
146 AutomationPoint * create_automation_point (
147 AutomationTrack * at,
148 AutomationRegion &region,
149 float val,
150 float normalized_val,
151 signed_frame_t pos_frames);
152
153 void handle_stop_recording (bool is_automation);
154
162 void delete_automation_points (
163 AutomationTrack * at,
164 AutomationRegion &region,
165 signed_frame_t pos_frames);
166
170 void handle_audio_event (const RecordingEvent &ev);
171
175 void handle_midi_event (const RecordingEvent &ev);
176
180 void handle_automation_event (const RecordingEvent &ev);
181
182 static utils::Utf8String
183 gen_name_for_recording_clip (const utils::Utf8String &track_name, int lane)
184 {
186 fmt::format (
187 "{} - lane {} - recording", track_name,
188 /* add 1 to get human friendly index */
189 lane + 1));
190 }
191
192 std::optional<structure::arrangement::ArrangerObjectPtrVariant>
193 get_recording_region_for_track (
194 const structure::tracks::Track::Uuid &track_id) const;
195
196public:
199
202
210
212 std::vector<structure::arrangement::ArrangerObjectPtrVariant>
214
218 std::vector<structure::arrangement::ArrangerObject::Uuid> recorded_ids_;
219
224 std::unordered_map<
225 structure::arrangement::ArrangerObjectUuid,
226 std::vector<QPointer<structure::arrangement::MidiNote>>>
228
233 std::unordered_map<
235 std::vector<QPointer<AutomationTrack>>>
237
239 std::unordered_map<
240 structure::arrangement::ArrangerObjectUuid,
241 QPointer<AutomationPoint>>
243
249 std::unordered_map<
253
264 std::unordered_set<structure::tracks::Track::Uuid>
266
267 std::unordered_set<structure::tracks::Track::Uuid>
268 tracks_recording_start_was_sent_to_;
269
276 std::unordered_set<structure::tracks::Track::Uuid> tracks_recording_was_paused_;
277
279 std::vector<structure::arrangement::AutomationPoint *> pending_aps_;
280
281 bool currently_processing_ = false;
282 std::binary_semaphore processing_sem_{ 1 };
283
284 bool freeing_ = false;
285
286private:
290 std::unique_ptr<juce::TimeSliceThread> time_slice_thread_;
291};
292QT_WARNING_POP
293
294} // namespace zrythm::engine::session
Multiple Producer Multiple Consumer lock-free queue.
Definition mpmc_queue.h:65
Thread-safe, realtime-safe object pool.
Definition object_pool.h:19
A lock-free thread-safe vector of MidiEvents.
Definition midi_event.h:78
std::vector< structure::arrangement::ArrangerObject::Uuid > recorded_ids_
Recorded region identifiers, to be used for creating the undoable actions.
int num_active_recordings_
Number of recordings currently in progress.
std::unordered_set< structure::tracks::Track::Uuid > tracks_recording_stop_was_sent_to_
Tracks that recording stop event was sent.
ObjectPool< RecordingEvent > event_obj_pool_
Memory pool of event structs to avoid real time allocation.
std::unordered_map< structure::arrangement::ArrangerObjectUuid, QPointer< AutomationPoint > > last_recorded_aps_per_region_
Last recorded automation points.
void start_unended_note(structure::arrangement::MidiRegion &mr, double start_pos, std::optional< double > end_pos, int pitch, int vel)
Starts an unended note with the given pitch and velocity and adds it to midi_notes_.
std::unordered_map< structure::tracks::Track::Uuid, std::vector< QPointer< AutomationTrack > > > ats_in_record_mode_
Cache of automation tracks in record mode, used to avoid looping over all automation tracks.
structure::arrangement::MidiNote * pop_unended_note(structure::arrangement::MidiRegion &mr, int pitch)
Returns the midi note with the given pitch from the unended notes.
void handle_recording(structure::tracks::TrackPtrVariant track_var, const EngineProcessTimeInfo &time_nfo, const dsp::MidiEventVector *midi_events, std::optional< structure::tracks::TrackProcessor::ConstStereoPortPair > stereo_ports)
Handles the recording logic inside the process cycle.
RecordingManager(QObject *parent=nullptr)
Creates the event queue and starts the event loop.
MPMCQueue< RecordingEvent * > event_queue_
Event queue.
std::vector< structure::arrangement::AutomationPoint * > pending_aps_
Pending recorded automation points.
std::vector< structure::arrangement::ArrangerObjectPtrVariant > objects_before_start_
Cloned objects before starting recording.
std::unordered_set< structure::tracks::Track::Uuid > tracks_recording_was_paused_
This must only be set by the RecordingManager when temporarily pausing recording, eg when looping or ...
std::unordered_map< structure::arrangement::ArrangerObjectUuid, std::vector< QPointer< structure::arrangement::MidiNote > > > unended_notes_per_region_
Unended notes started in recording with MIDI NOTE ON signal but haven't received a NOTE OFF yet.
void get_aps_since_last_recorded(const structure::arrangement::AutomationRegion &ar, signed_frame_t pos, std::vector< AutomationPoint * > &aps) const
Returns the automation points since the last recorded automation point (if the last recorded automati...
std::unordered_map< structure::tracks::Track::Uuid, structure::arrangement::ArrangerObject::Uuid > recording_region_per_track_
Region currently recording on.
An automation point inside an AutomationTrack.
Represents an automation region, which contains a collection of automation points.
A MIDI note inside a Region shown in the piano roll.
Definition midi_note.h:20
A Region containing MIDI events.
Definition midi_region.h:20
A TrackProcessor is a standalone processor that is used as the first step when processing a track in ...
Lightweight UTF-8 string wrapper with safe conversions.
Definition utf8_string.h:38
static constexpr Utf8String from_utf8_encoded_string(std::string_view str)
Construct from a std::string_view that we are 100% sure is UTF8-encoded.
Definition utf8_string.h:81
int_fast64_t signed_frame_t
Signed type for frame index.
Definition types.h:75
Common struct to pass around during processing to avoid repeating the data in function arguments.
Definition types.h:133