Zrythm v2.0.0-DEV
a highly automated and intuitive digital audio workstation
Loading...
Searching...
No Matches
project.h
1// SPDX-FileCopyrightText: © 2018-2025 Alexandros Theodotou <alex@zrythm.org>
2// SPDX-License-Identifier: LicenseRef-ZrythmLicense
3
4#pragma once
5
6#include "actions/arranger_object_creator.h"
7#include "actions/arranger_object_selection_operator.h"
8#include "actions/file_importer.h"
9#include "actions/plugin_importer.h"
10#include "actions/track_creator.h"
11#include "dsp/audio_pool.h"
12#include "dsp/engine.h"
13#include "dsp/metronome.h"
14#include "dsp/port_connections_manager.h"
15#include "dsp/snap_grid.h"
16#include "dsp/tempo_map_qml_adapter.h"
17#include "dsp/transport.h"
18#include "engine/session/control_room.h"
19#include "engine/session/midi_mapping.h"
20#include "gui/backend/backend/clip_editor.h"
21#include "gui/backend/plugin_selection_manager.h"
22#include "gui/backend/tool.h"
23#include "gui/backend/track_selection_manager.h"
24#include "gui/dsp/quantize_options.h"
25#include "plugins/plugin.h"
26#include "plugins/plugin_factory.h"
27#include "structure/arrangement/arranger_object_factory.h"
28#include "structure/arrangement/tempo_object_manager.h"
29#include "structure/arrangement/timeline.h"
30#include "structure/scenes/clip_launcher.h"
31#include "structure/scenes/clip_playback_service.h"
32#include "structure/tracks/track_factory.h"
33#include "undo/undo_stack.h"
34#include "utils/progress_info.h"
35
41
42using namespace zrythm;
43
44#define PROJECT (Project::get_active_instance ())
45#define PORT_CONNECTIONS_MGR (PROJECT->port_connections_manager_.get ())
46#define AUDIO_POOL (PROJECT->audio_pool_.get ())
47#define TRANSPORT (PROJECT->transport_)
48
49#define TRACKLIST (PROJECT->tracklist_)
50#define P_CHORD_TRACK (TRACKLIST->singletonTracks ()->chordTrack ())
51#define P_MARKER_TRACK (TRACKLIST->singletonTracks ()->markerTrack ())
52#define P_MASTER_TRACK (TRACKLIST->singletonTracks ()->masterTrack ())
53#define P_MODULATOR_TRACK (TRACKLIST->singletonTracks ()->modulatorTrack ())
54#define SNAP_GRID_TIMELINE (PROJECT->snapGridTimeline ())
55#define SNAP_GRID_EDITOR (PROJECT->snapGridEditor ())
56#define MONITOR_FADER (PROJECT->controlRoom ()->monitor_fader_)
57#define ROUTER (&PROJECT->engine ()->graph_dispatcher ())
58#define AUDIO_ENGINE (PROJECT->engine ())
59
60enum class ProjectPath
61{
62 ProjectFile,
63 BACKUPS,
64
67
70
74
78
79 EXPORTS,
80
81 /* EXPORTS / "stems". */
82 EXPORTS_STEMS,
83
84 POOL,
85
86 FINISHED_FILE,
87};
88
98class Project final : public QObject
99{
100 Q_OBJECT
101 QML_ELEMENT
102 Q_PROPERTY (
103 QString title READ getTitle WRITE setTitle NOTIFY titleChanged FINAL)
104 Q_PROPERTY (
105 QString directory READ getDirectory WRITE setDirectory NOTIFY
106 directoryChanged FINAL)
107 Q_PROPERTY (
108 zrythm::structure::tracks::Tracklist * tracklist READ tracklist CONSTANT
109 FINAL)
110 Q_PROPERTY (
111 zrythm::structure::scenes::ClipLauncher * clipLauncher READ clipLauncher
112 CONSTANT FINAL)
113 Q_PROPERTY (
114 zrythm::structure::scenes::ClipPlaybackService * clipPlaybackService READ
115 clipPlaybackService CONSTANT FINAL)
116 Q_PROPERTY (
117 zrythm::gui::backend::TrackSelectionManager * trackSelectionManager READ
118 trackSelectionManager CONSTANT)
119 Q_PROPERTY (
120 zrythm::structure::arrangement::Timeline * timeline READ getTimeline
121 CONSTANT FINAL)
122 Q_PROPERTY (
123 zrythm::engine::session::ControlRoom * controlRoom READ controlRoom CONSTANT
124 FINAL)
125 Q_PROPERTY (zrythm::dsp::AudioEngine * engine READ engine CONSTANT FINAL)
126 Q_PROPERTY (zrythm::dsp::Metronome * metronome READ metronome CONSTANT)
127 Q_PROPERTY (
128 zrythm::dsp::Transport * transport READ getTransport CONSTANT FINAL)
129 Q_PROPERTY (zrythm::gui::backend::Tool * tool READ getTool CONSTANT FINAL)
130 Q_PROPERTY (ClipEditor * clipEditor READ getClipEditor CONSTANT FINAL)
131 Q_PROPERTY (zrythm::undo::UndoStack * undoStack READ undoStack CONSTANT FINAL)
132 Q_PROPERTY (
133 zrythm::actions::ArrangerObjectCreator * arrangerObjectCreator READ
134 arrangerObjectCreator CONSTANT FINAL)
135 Q_PROPERTY (
136 zrythm::actions::TrackCreator * trackCreator READ trackCreator CONSTANT FINAL)
137 Q_PROPERTY (
138 zrythm::actions::PluginImporter * pluginImporter READ pluginImporter
139 CONSTANT FINAL)
140 Q_PROPERTY (
141 zrythm::actions::FileImporter * fileImporter READ fileImporter CONSTANT FINAL)
142 Q_PROPERTY (
143 zrythm::dsp::TempoMapWrapper * tempoMap READ getTempoMap CONSTANT FINAL)
144 Q_PROPERTY (
146 tempoObjectManager CONSTANT FINAL)
147 Q_PROPERTY (
148 zrythm::dsp::SnapGrid * snapGridTimeline READ snapGridTimeline CONSTANT FINAL)
149 Q_PROPERTY (
150 zrythm::dsp::SnapGrid * snapGridEditor READ snapGridEditor CONSTANT FINAL)
151 QML_UNCREATABLE ("")
152
153public:
155 using TrackUuid = structure::tracks::TrackUuid;
156 using PluginPtrVariant = plugins::PluginPtrVariant;
157 using PluginRegistry = plugins::PluginRegistry;
158
159 static constexpr auto PROJECT_FILE = "project.zpj"sv;
160 static constexpr auto PROJECT_BACKUPS_DIR = "backups"sv;
161 static constexpr auto PROJECT_PLUGINS_DIR = "plugins"sv;
162 static constexpr auto PROJECT_PLUGIN_STATES_DIR = "states"sv;
163 static constexpr auto PROJECT_PLUGIN_EXT_COPIES_DIR = "ext_file_copies"sv;
164 static constexpr auto PROJECT_PLUGIN_EXT_LINKS_DIR = "ext_file_links"sv;
165 static constexpr auto PROJECT_EXPORTS_DIR = "exports"sv;
166 static constexpr auto PROJECT_STEMS_DIR = "stems"sv;
167 static constexpr auto PROJECT_POOL_DIR = "pool"sv;
168 static constexpr auto PROJECT_FINISHED_FILE = "FINISHED"sv;
170public:
171 Project (
172 std::shared_ptr<juce::AudioDeviceManager> device_manager,
173 QObject * parent = nullptr);
174 ~Project () override;
175 Z_DISABLE_COPY_MOVE (Project)
176
177
181 enum class SelectionType
182 {
184 Tracklist,
185
187 Timeline,
188
190 Insert,
191
193 MidiFX,
194
197
199 Modulator,
200
202 Editor,
203 };
204
208 enum class CompressionFlag
209 {
210 PROJECT_COMPRESS_FILE = 0,
211 PROJECT_DECOMPRESS_FILE = 0,
212 PROJECT_COMPRESS_DATA = 1,
213 PROJECT_DECOMPRESS_DATA = 1,
214 };
215
216 // =========================================================
217 // QML interface
218 // =========================================================
219
220 QString getTitle () const;
221 void setTitle (const QString &title);
222 QString getDirectory () const;
223 void setDirectory (const QString &directory);
224 structure::tracks::Tracklist * tracklist () const;
225 structure::scenes::ClipLauncher * clipLauncher () const;
226 structure::scenes::ClipPlaybackService * clipPlaybackService () const;
227 gui::backend::TrackSelectionManager * trackSelectionManager () const;
228 gui::backend::PluginSelectionManager * pluginSelectionManager () const;
229 structure::arrangement::Timeline * getTimeline () const;
230 dsp::Metronome * metronome () const;
231 dsp::Transport * getTransport () const;
232 engine::session::ControlRoom * controlRoom () const;
233 dsp::AudioEngine * engine () const;
234 gui::backend::Tool * getTool () const;
235 ClipEditor * getClipEditor () const;
236 undo::UndoStack * undoStack () const;
237 zrythm::actions::ArrangerObjectCreator * arrangerObjectCreator () const;
238 zrythm::actions::TrackCreator * trackCreator () const;
239 actions::FileImporter * fileImporter () const;
240 actions::PluginImporter * pluginImporter () const;
241 dsp::TempoMapWrapper * getTempoMap () const;
242 dsp::SnapGrid * snapGridTimeline () const;
243 dsp::SnapGrid * snapGridEditor () const;
244 structure::arrangement::TempoObjectManager * tempoObjectManager () const;
245
246 Q_SIGNAL void titleChanged (const QString &title);
247 Q_SIGNAL void directoryChanged (const QString &directory);
248 Q_SIGNAL void aboutToBeDeleted ();
249
251 createArrangerObjectSelectionOperator (
252 QItemSelectionModel * selectionModel) const;
253
254 // =========================================================
255
262 fs::path get_path (ProjectPath path, bool backup) const;
263
264 static Project * get_active_instance ();
265
266 // TODO: delete this getter, no one else should use factory directly
267 auto * getArrangerObjectFactory () const
268 {
269 return arranger_object_factory_.get ();
270 }
271
283 void
284 save (const fs::path &_dir, bool is_backup, bool show_notification, bool async);
285
293 static int autosave_cb (void * data);
294
301 void make_project_dirs (bool is_backup);
302
314 static void compress_or_decompress (
315 bool compress,
316 char ** _dest,
317 size_t * _dest_size,
318 CompressionFlag dest_type,
319 const QByteArray &src);
321 static void compress (
322 char ** _dest,
323 size_t * _dest_size,
324 CompressionFlag dest_type,
325 const QByteArray &src)
326 {
327 compress_or_decompress (true, _dest, _dest_size, dest_type, src);
328 }
329
330 static void decompress (
331 char ** _dest,
332 size_t * _dest_size,
333 CompressionFlag dest_type,
334 const QByteArray &src)
335 {
336 compress_or_decompress (false, _dest, _dest_size, dest_type, src);
337 }
347 std::string get_existing_uncompressed_text (bool backup);
348
349 bool has_unsaved_changes () const;
350
351 friend void init_from (
352 Project &obj,
353 const Project &other,
354 utils::ObjectCloneType clone_type);
355
365 Q_INVOKABLE Project * clone (bool for_backup) const;
366
373 std::optional<fs::path> get_newer_backup ();
374
380 Q_INVOKABLE void activate ();
381
390 get_final_track_dependencies () const;
391
392 auto &get_file_audio_source_registry () const
393 {
394 return *file_audio_source_registry_;
395 }
396 auto &get_track_registry () const { return *track_registry_; }
397 auto &get_plugin_registry () const { return *plugin_registry_; }
398 auto &get_port_registry () const { return *port_registry_; }
399 auto &get_param_registry () const { return *param_registry_; }
400 auto &get_arranger_object_registry () const
401 {
402 return *arranger_object_registry_;
403 }
404
412 std::optional<dsp::PortPtrVariant>
413 find_port_by_id (const dsp::Port::Uuid &id) const
414 {
415 return get_port_registry ().find_by_id (id);
416 }
417
418 dsp::ProcessorParameter *
419 find_param_by_id (const dsp::ProcessorParameter::Uuid &id) const
420 {
421 const auto opt_var = get_param_registry ().find_by_id (id);
422 if (opt_var.has_value ())
423 {
424 return std::get<dsp::ProcessorParameter *> (opt_var.value ());
425 }
426 return nullptr;
427 }
428
429 std::optional<plugins::PluginPtrVariant>
430 find_plugin_by_id (plugins::Plugin::Uuid id) const
431 {
432 return get_plugin_registry ().find_by_id (id);
433 }
434
435 std::optional<zrythm::structure::tracks::TrackPtrVariant>
436 find_track_by_id (structure::tracks::Track::Uuid id) const
437 {
438 return get_track_registry ().find_by_id (id);
439 }
440
441 std::optional<zrythm::structure::arrangement::ArrangerObjectPtrVariant>
442 find_arranger_object_by_id (
443 structure::arrangement::ArrangerObject::Uuid id) const
444 {
445 return get_arranger_object_registry ().find_by_id (id);
446 }
447
448 const auto &get_tempo_map () const { return tempo_map_; }
449
450private:
457 void set_and_create_next_available_backup_dir ();
458
467 void cleanup_plugin_state_dirs (Project &main_project, bool is_backup);
468
472 struct SaveContext
473 {
475 // std::unique_ptr<Project> project_;
476
480 Project * main_project_;
481
483 fs::path project_file_path_;
484
485 bool is_backup_ = false;
486
488 std::atomic_bool finished_ = false;
489
490 bool show_notification_ = false;
491
493 bool has_error_ = false;
494
495 ProgressInfo progress_info_;
496 };
497
501 class SerializeProjectThread final : public juce::Thread
502 {
503 public:
504 SerializeProjectThread (SaveContext &ctx);
505 ~SerializeProjectThread () override;
506 void run () override;
507
508 private:
509 SaveContext &ctx_;
510 };
511
518 static bool idle_saved_callback (SaveContext * ctx);
519
520private:
521 static constexpr auto kTempoMapKey = "tempoMap"sv;
522 static constexpr auto kFileAudioSourceRegistryKey =
523 "fileAudioSourceRegistry"sv;
524 static constexpr auto kPortRegistryKey = "portRegistry"sv;
525 static constexpr auto kParameterRegistryKey = "paramRegistry"sv;
526 static constexpr auto kPluginRegistryKey = "pluginRegistry"sv;
527 static constexpr auto kArrangerObjectRegistryKey = "arrangerObjectRegistry"sv;
528 static constexpr auto kTrackRegistryKey = "trackRegistry"sv;
529 static constexpr auto kTitleKey = "title"sv;
530 static constexpr auto kDatetimeKey = "datetime"sv;
531 static constexpr auto kVersionKey = "version"sv;
532 static constexpr auto kClipEditorKey = "clipEditor"sv;
533 static constexpr auto kTimelineKey = "timeline"sv;
534 static constexpr auto kSnapGridTimelineKey = "snapGridTimeline"sv;
535 static constexpr auto kSnapGridEditorKey = "snapGridEditor"sv;
536 static constexpr auto kQuantizeOptsTimelineKey = "quantizeOptsTimeline"sv;
537 static constexpr auto kQuantizeOptsEditorKey = "quantizeOptsEditor"sv;
538 static constexpr auto kTransportKey = "transport"sv;
539 static constexpr auto kAudioPoolKey = "audioPool"sv;
540 static constexpr auto kTracklistKey = "tracklist"sv;
541 static constexpr auto kRegionLinkGroupManagerKey = "regionLinkGroupManager"sv;
542 static constexpr auto kPortConnectionsManagerKey = "portConnectionsManager"sv;
543 static constexpr auto kMidiMappingsKey = "midiMappings"sv;
544 static constexpr auto kUndoManagerKey = "undoManager"sv;
545 static constexpr auto kUndoStackKey = "undoStack"sv;
546 static constexpr auto kLastSelectionKey = "lastSelection"sv;
547 static constexpr auto kTempoObjectManagerKey = "tempoObjectManager"sv;
548 static constexpr auto DOCUMENT_TYPE = "ZrythmProject"sv;
549 static constexpr auto FORMAT_MAJOR_VER = 2;
550 static constexpr auto FORMAT_MINOR_VER = 1;
551 friend void to_json (nlohmann::json &j, const Project &project);
552 friend void from_json (const nlohmann::json &j, Project &project);
554private:
555 dsp::TempoMap tempo_map_;
557
558 dsp::FileAudioSourceRegistry * file_audio_source_registry_{};
559 dsp::PortRegistry * port_registry_{};
560 dsp::ProcessorParameterRegistry * param_registry_{};
561 PluginRegistry * plugin_registry_{};
562 structure::arrangement::ArrangerObjectRegistry * arranger_object_registry_{};
563 structure::tracks::TrackRegistry * track_registry_{};
564
565public:
568
571
573 fs::path dir_;
574
580 std::optional<fs::path> backup_dir_;
581
582 /* !!! IMPORTANT: order matters (for destruction) !!! */
583
584 // std::optional<gui::actions::UndoableActionPtrVariant>
585 // last_action_in_last_successful_autosave_;
586
588 SteadyTimePoint last_successful_autosave_time_;
589
591 // std::optional<gui::actions::UndoableActionPtrVariant> last_saved_action_;
592
594 std::binary_semaphore save_sem_{ 1 };
595
598
605
612 bool loading_from_backup_ = false;
614 std::shared_ptr<juce::AudioDeviceManager> device_manager_;
615
621
628
631
634
636
643
650 std::unique_ptr<dsp::AudioPool> pool_;
651
653 // structure::arrangement::RegionLinkGroupManager region_link_group_manager_;
654
656 std::unique_ptr<QuantizeOptions> quantize_opts_editor_;
657
659 std::unique_ptr<QuantizeOptions> quantize_opts_timeline_;
660
663
666
668 std::unique_ptr<engine::session::MidiMappings> midi_mappings_;
669
676
680 boost::unordered_flat_map<
681 structure::tracks::TrackUuid,
682 structure::tracks::TrackPtrVariant>
684
687 clip_playback_service_;
688
690
691 std::unique_ptr<structure::arrangement::ArrangerObjectFactory>
692 arranger_object_factory_;
694 std::unique_ptr<structure::tracks::TrackFactory> track_factory_;
695
697 arranger_object_creator_;
701
703 track_selection_manager_;
705 plugin_selection_manager_;
706
708 tempo_object_manager_;
709
717
719 int format_major_ = 0;
720 int format_minor_ = 0;
721};
722
Backend for the clip editor part of the UI.
Definition clip_editor.h:27
std::optional< fs::path > get_newer_backup()
Returns the filepath of a backup (directory), if any, if it has a newer timestamp than main project f...
std::unique_ptr< dsp::AudioPool > pool_
Audio file pool.
Definition project.h:623
std::unique_ptr< engine::session::MidiMappings > midi_mappings_
MIDI bindings.
Definition project.h:641
bool loading_from_backup_
Whether the current is currently being loaded from a backup file.
Definition project.h:585
utils::Utf8String version_
Zrythm version, for serialization.
Definition project.h:570
dsp::DspGraphDispatcher graph_dispatcher_
Graph dispatcher.
Definition project.h:689
gui::backend::Tool * tool_
Currently selected tool (select - normal, select - stretch, edit, delete, ramp, audition).
Definition project.h:593
utils::Utf8String title_
Project title.
Definition project.h:540
CompressionFlag
Flag to pass to project_compress() and project_decompress().
Definition project.h:182
std::string get_existing_uncompressed_text(bool backup)
Returns the uncompressed text representation of the saved project file.
std::optional< fs::path > backup_dir_
Backup dir to save the project during the current save call.
Definition project.h:553
static int autosave_cb(void *data)
Autosave callback.
utils::QObjectUniquePtr< dsp::AudioEngine > audio_engine_
The audio backend.
Definition project.h:620
utils::QObjectUniquePtr< ClipEditor > clip_editor_
Backend for the widget.
Definition project.h:638
static void compress_or_decompress(bool compress, char **_dest, size_t *_dest_size, CompressionFlag dest_type, const QByteArray &src)
Compresses/decompress a project from a file/data to a file/data.
utils::Utf8String datetime_str_
Datetime string to add to the project file.
Definition project.h:543
boost::unordered_flat_map< structure::tracks::TrackUuid, structure::tracks::TrackPtrVariant > tracks_rt_
Realtime cache of tracks.
Definition project.h:656
std::unique_ptr< QuantizeOptions > quantize_opts_editor_
Manager for region link groups.
Definition project.h:629
Q_INVOKABLE void activate()
Connects things up, exposes ports to the backend, calculates the graph and begins processing.
void add_default_tracks()
Adds the default undeletable tracks to the project.
int format_major_
Used when deserializing projects.
Definition project.h:692
std::unique_ptr< QuantizeOptions > quantize_opts_timeline_
Quantize info for the timeline.
Definition project.h:632
std::optional< dsp::PortPtrVariant > find_port_by_id(const dsp::Port::Uuid &id) const
Finds the Port corresponding to the identifier.
Definition project.h:386
utils::QObjectUniquePtr< dsp::Transport > transport_
Timeline metadata like BPM, time signature, etc.
Definition project.h:613
SteadyTimePoint last_successful_autosave_time_
Last successful autosave timestamp.
Definition project.h:561
SelectionType
Selection type, used for controlling which part of the interface is selected, for copy-paste,...
Definition project.h:155
@ Modulator
Modulator slot.
Definition project.h:172
@ Editor
Editor arranger.
Definition project.h:175
@ Timeline
Timeline or pinned timeline.
Definition project.h:160
@ Instrument
Instrument slot.
Definition project.h:169
@ Tracklist
Track selection in tracklist or mixer.
Definition project.h:157
@ Insert
Insert selections in the mixer.
Definition project.h:163
@ MidiFX
MIDI FX selections in the mixer.
Definition project.h:166
Project::SelectionType last_selection_
The last thing selected in the GUI.
Definition project.h:577
utils::QObjectUniquePtr< dsp::PortConnectionsManager > port_connections_manager_
Must be free'd after engine.
Definition project.h:600
utils::QObjectUniquePtr< dsp::SnapGrid > snap_grid_editor_
Snap/Grid info for the editor.
Definition project.h:603
fs::path dir_
Path to save the project in.
Definition project.h:546
void make_project_dirs(bool is_backup)
Creates the project directories.
utils::QObjectUniquePtr< dsp::SnapGrid > snap_grid_timeline_
Snap/Grid info for the timeline.
Definition project.h:606
utils::QObjectUniquePtr< structure::arrangement::Timeline > timeline_
Timeline widget backend.
Definition project.h:635
Q_INVOKABLE Project * clone(bool for_backup) const
Deep-clones the given project.
void save(const fs::path &_dir, bool is_backup, bool show_notification, bool async)
Saves the project to a project file in the given dir.
std::binary_semaphore save_sem_
Used to check if the project has unsaved changes.
Definition project.h:567
fs::path get_path(ProjectPath path, bool backup) const
Returns the requested project path as a newly allocated string.
utils::QObjectUniquePtr< structure::tracks::Tracklist > tracklist_
Tracklist.
Definition project.h:648
The audio engine.
Definition engine.h:22
The DspGraphDispatcher class manages the processing graph for the audio engine.
Metronome processor.
Definition metronome.h:20
Snap/grid information.
Definition snap_grid.h:22
The Transport class represents the transport controls and state for an audio engine.
Definition transport.h:45
Abstraction to control the signal coming in from Master and going out into the speakers.
Manages tempo and time signature objects for a project.
Service for managing clip playback operations.
A higher level wrapper over a track collection that serves as the project's only tracklist.
Definition tracklist.h:23
std::optional< VariantT > find_by_id(const UuidType &id) const noexcept
Returns an object by id.
A unique pointer for QObject objects that also works with QObject-based ownership.
Definition qt.h:38
Lightweight UTF-8 string wrapper with safe conversions.
Definition utf8_string.h:38
ProjectPath
Definition project.h:61
@ PLUGIN_EXT_COPIES
External files for plugin states, under the STATES dir.
Definition project.h:73
@ PLUGIN_EXT_LINKS
External files for plugin states, under the STATES dir.
Definition project.h:77
@ PluginStates
Path for state .ttl files.
Definition project.h:69
@ PLUGINS
Plugins path.
Definition project.h:66
Progress info.