Zrythm v2.0.0-alpha.1
a highly automated and intuitive digital audio workstation
Loading...
Searching...
No Matches
clip_slot.h
1// SPDX-FileCopyrightText: © 2025-2026 Alexandros Theodotou <alex@zrythm.org>
2// SPDX-License-Identifier: LicenseRef-ZrythmLicense
3
4#pragma once
5
6#include "dsp/timebase.h"
7#include "structure/arrangement/arranger_object_all.h"
8#include "structure/arrangement/clip.h"
9#include "structure/tracks/track_collection.h"
10
11#include <QtQmlIntegration/qqmlintegration.h>
12
13#include <nlohmann/json_fwd.hpp>
14
15namespace zrythm::structure::scenes
16{
17
18class ClipSlot : public QObject
19{
20 Q_OBJECT
21 Q_PROPERTY (
22 zrythm::structure::arrangement::Clip * clipObject READ clip WRITE setClip
23 NOTIFY clipObjectChanged)
24 Q_PROPERTY (ClipState state READ state WRITE setState NOTIFY stateChanged)
25 QML_ELEMENT
26 QML_UNCREATABLE ("")
27 QML_EXTENDED_NAMESPACE (zrythm::structure::tracks)
28
29public:
30 enum class ClipState
31 {
32 Stopped,
33 PlayQueued,
34 Playing,
35 StopQueued,
36 };
37 Q_ENUM (ClipState)
38
39 ClipSlot (utils::IObjectRegistry &registry, QObject * parent = nullptr);
40
41 arrangement::Clip * clip () const
42 {
43 if (clip_ref_.has_value ())
44 {
45 return qobject_cast<arrangement::Clip *> (clip_ref_->get ());
46 }
47 return nullptr;
48 }
50 std::optional<arrangement::ArrangerObjectUuidReference> clipReference () const
51 {
52 return clip_ref_;
53 }
54 void setClip (arrangement::Clip * clip);
55 Q_SIGNAL void clipObjectChanged (arrangement::Clip * clip);
56
57 // Clip management
58 Q_INVOKABLE void clearClip ()
59 {
60 if (!clip_ref_.has_value ())
61 {
62 return;
63 }
64
65 if (auto * clip = this->clip ())
66 {
67 if (auto * tp = clip->timebaseProvider ())
68 tp->setSource (nullptr);
69 }
70 clip_ref_.reset ();
71 Q_EMIT clipObjectChanged (nullptr);
72 }
73
74 ClipState state () const { return state_.load (); }
75 void setState (ClipState state);
76 Q_SIGNAL void stateChanged (ClipState state);
77
78 void setTimebaseProvider (dsp::TimebaseProvider * provider)
79 {
80 timebase_provider_ = provider;
81 }
82
83private:
84 static constexpr auto kClipIdKey = "clipId"sv;
85 friend void to_json (nlohmann::json &j, const ClipSlot &slot);
86 friend void from_json (const nlohmann::json &j, ClipSlot &slot);
87
88private:
89 std::optional<arrangement::ArrangerObjectUuidReference> clip_ref_;
90 utils::IObjectRegistry &registry_;
91 QPointer<dsp::TimebaseProvider> timebase_provider_;
92 std::atomic<ClipState> state_{ ClipState::Stopped };
93};
94
95class ClipSlotList : public QAbstractListModel
96{
97 Q_OBJECT
98 QML_ELEMENT
99 QML_UNCREATABLE ("")
100
101public:
102 ClipSlotList (
103 utils::IObjectRegistry &registry,
104 const tracks::TrackCollection &track_collection,
105 QObject * parent = nullptr);
106 Q_DISABLE_COPY_MOVE (ClipSlotList)
107
108 enum ClipSlotListRoles
109 {
110 ClipSlotPtrRole = Qt::UserRole + 1,
111 };
112 Q_ENUM (ClipSlotListRoles)
113
114 // ========================================================================
115 // QML Interface
116 // ========================================================================
117
118 Q_INVOKABLE ClipSlot * clipSlotForTrack (const tracks::Track * track) const
119 {
120 return clip_slots_
121 .at (track_collection_.get_track_index (track->get_uuid ()))
122 .get ();
123 }
124
125 QHash<int, QByteArray> roleNames () const override
126 {
127 QHash<int, QByteArray> roles;
128 roles[ClipSlotPtrRole] = "clipSlot";
129 return roles;
130 }
131 int rowCount (const QModelIndex &parent = QModelIndex ()) const override
132 {
133 if (parent.isValid ())
134 return 0;
135 return static_cast<int> (clip_slots_.size ());
136 }
137 QVariant
138 data (const QModelIndex &index, int role = Qt::DisplayRole) const override
139 {
140 const auto index_int = index.row ();
141 if (!index.isValid () || index_int >= static_cast<int> (clip_slots_.size ()))
142 return {};
143
144 if (role == ClipSlotPtrRole)
145 {
146 return QVariant::fromValue (clip_slots_.at (index_int).get ());
147 }
148
149 return {};
150 }
151
152 // ========================================================================
153
154 auto &clip_slots () const { return clip_slots_; }
155
156private:
157 friend void to_json (nlohmann::json &j, const ClipSlotList &list);
158 friend void from_json (const nlohmann::json &j, ClipSlotList &list);
159
160private:
161 // These must be in the order of tracks in the tracklist.
162 std::vector<utils::QObjectUniquePtr<ClipSlot>> clip_slots_;
163
164 utils::IObjectRegistry &registry_;
165 const tracks::TrackCollection &track_collection_;
166};
167}
Intermediate base class for all clip types.
Definition clip.h:37
std::optional< arrangement::ArrangerObjectUuidReference > clipReference() const
Returns a copy of the current clip reference (nullopt if empty).
Definition clip_slot.h:48
A collection of tracks that provides a QAbstractListModel interface.
Represents a track in the project.
Definition track.h:60
Abstract interface for a UUID-keyed object registry.