CuteLogger
Fast and simple logging solution for Qt based applications
multitrackmodel.h
1/*
2 * Copyright (c) 2013-2026 Meltytech, LLC
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#ifndef MULTITRACKMODEL_H
19#define MULTITRACKMODEL_H
20
21#include <MltPlaylist.h>
22#include <MltTractor.h>
23#include <QAbstractItemModel>
24#include <QByteArray>
25#include <QList>
26#include <QString>
27
28#include <memory>
29
30class SharedFrame;
31
32typedef enum {
33 PlaylistTrackType = 0,
34 BlackTrackType,
35 SilentTrackType,
36 AudioTrackType,
37 VideoTrackType
38} TrackType;
39
40typedef struct
41{
42 TrackType type;
43 int number;
44 int mlt_index;
45 double audioLevel = -100.0;
46} Track;
47
48typedef QList<Track> TrackList;
49
50class MultitrackModel : public QAbstractItemModel
51{
52 Q_OBJECT
53 Q_PROPERTY(int trackHeight READ trackHeight WRITE setTrackHeight NOTIFY trackHeightChanged)
54 Q_PROPERTY(int trackHeaderWidth READ trackHeaderWidth WRITE setTrackHeaderWidth NOTIFY
55 trackHeaderWidthChanged FINAL)
56 Q_PROPERTY(double scaleFactor READ scaleFactor WRITE setScaleFactor NOTIFY scaleFactorChanged)
57 Q_PROPERTY(bool filtered READ isFiltered NOTIFY filteredChanged)
58 Q_PROPERTY(bool trackLevelIndicatorSupported READ trackLevelIndicatorSupported CONSTANT)
59 Q_PROPERTY(bool hasAudioTracks READ hasAudioTracks NOTIFY hasAudioTracksChanged)
60
61public:
63 enum {
64 NameRole = Qt::UserRole + 1,
65 CommentRole,
66 ResourceRole,
67 ServiceRole,
68 IsBlankRole,
69 StartRole,
70 DurationRole,
71 InPointRole,
72 OutPointRole,
73 FramerateRole,
74 IsMuteRole,
75 IsHiddenRole,
76 IsAudioRole,
77 AudioLevelRole,
78 AudioLevelsRole,
79 IsCompositeRole,
80 IsLockedRole,
81 FadeInRole,
82 FadeOutRole,
83 IsTransitionRole,
84 FileHashRole,
85 SpeedRole,
86 IsFilteredRole,
87 IsTopVideoRole,
88 IsBottomVideoRole,
89 IsTopAudioRole,
90 IsBottomAudioRole,
91 AudioIndexRole,
92 GroupRole,
93 GainRole,
94 GainEnabledRole,
95 IsAdjustmentRole,
96 };
97
98 explicit MultitrackModel(QObject *parent = 0);
99 ~MultitrackModel();
100
101 Mlt::Tractor *tractor() const { return m_tractor; }
102 const TrackList &trackList() const { return m_trackList; }
103
104 int rowCount(const QModelIndex &parent = QModelIndex()) const;
105 int columnCount(const QModelIndex &parent) const;
106 QVariant data(const QModelIndex &index, int role) const;
107 QModelIndex index(int row, int column = 0, const QModelIndex &parent = QModelIndex()) const;
108 QModelIndex makeIndex(int trackIndex, int clipIndex) const;
109 QModelIndex parent(const QModelIndex &index) const;
110 QHash<int, QByteArray> roleNames() const;
111 Q_INVOKABLE void audioLevelsReady(const QPersistentModelIndex &index);
112 const QByteArray *getAudioLevels(int trackIndex, int clipIndex) const;
113 void updateTrackAudioLevels(const SharedFrame &frame);
114 void updateTrackGains(int position);
115 void clearTrackAudioLevels();
116 bool createIfNeeded();
117 void addBackgroundTrack();
118 int addAudioTrack();
119 int addVideoTrack();
120 void removeTrack(int trackIndex);
121 void load();
122 void close();
123 int clipIndex(int trackIndex, int position);
124 void setClipGroup(int trackIndex, int position, int group);
125 void relinkTransitions(int trackIndex, int clipIndex);
126 bool trimClipInValid(int trackIndex, int clipIndex, int delta, bool ripple);
127 bool trimClipOutValid(int trackIndex, int clipIndex, int delta, bool ripple);
128 bool transitionOverlapValid(int fromTrack, int toTrack, int clipIndex, int position, bool ripple);
129 int trackHeight() const;
130 void setTrackHeight(int height);
131 int trackHeaderWidth() const;
132 void setTrackHeaderWidth(int width);
133 double scaleFactor() const;
134 void setScaleFactor(double scale);
135 bool isTransition(Mlt::Playlist &playlist, int clipIndex) const;
136 void insertTrack(int trackIndex, TrackType type = VideoTrackType);
137 void moveTrack(int fromTrackIndex, int toTrackIndex);
138 void insertOrAdjustBlankAt(QList<int> tracks, int position, int length);
139 bool mergeClipWithNext(int trackIndex, int clipIndex, bool dryrun);
140 std::unique_ptr<Mlt::ClipInfo> findClipByUuid(const QUuid &uuid,
141 int &trackIndex,
142 int &clipIndex);
143 std::unique_ptr<Mlt::ClipInfo> getClipInfo(int trackIndex, int clipIndex);
144 Q_INVOKABLE int clipStart(int trackIndex, int clipIndex);
145 QString getTrackName(int trackIndex);
146 int bottomVideoTrackIndex() const;
147 int mltIndexForTrack(int trackIndex) const;
148 bool checkForEmptyTracks(int trackIndex);
149 QString trackTransitionService();
150 bool trackLevelIndicatorSupported() const;
151 bool hasAudioTracks() const;
152 void beginBulkUpdate();
153 void endBulkUpdate(bool changed = true);
154 bool isBulkUpdating() const { return m_bulkUpdateDepth > 0; }
155
156signals:
157 void created();
158 void aboutToClose();
159 void closed();
160 void modified();
161 void seeked(int position, bool seekPlayer = true);
162 void trackHeightChanged();
163 void trackHeaderWidthChanged();
164 void scaleFactorChanged();
165 void showStatusMessage(QString);
166 void durationChanged();
167 void filteredChanged();
168 void hasAudioTracksChanged();
169 void reloadRequested();
170 void appended(int trackIndex, int clipIndex);
171 void inserted(int trackIndex, int clipIndex);
172 void overWritten(int trackIndex, int clipIndex);
173 void removing(Mlt::Service *service);
174 void noMoreEmptyTracks(bool isAudio);
175 void bulkUpdateFinished();
176
177public slots:
178 void refreshTrackList();
179 void setTrackName(int row, const QString &value);
180 void setTrackMute(int row, bool mute);
181 void setTrackHidden(int row, bool hidden);
182 void setTrackComposite(int row, bool composite);
183 void setTrackLock(int row, bool lock);
184 void setTrackGain(int row, double gain);
185 int trimClipIn(int trackIndex, int clipIndex, int delta, bool ripple, bool rippleAllTracks);
186 void notifyClipIn(int trackIndex, int clipIndex);
187 int trimClipOut(int trackIndex, int clipIndex, int delta, bool ripple, bool rippleAllTracks);
188 void notifyClipOut(int trackIndex, int clipIndex);
189 bool moveClip(
190 int fromTrack, int toTrack, int clipIndex, int position, bool ripple, bool rippleAllTracks);
191 int overwriteClip(int trackIndex, Mlt::Producer &clip, int position, bool seek = true);
192 QString overwrite(
193 int trackIndex, Mlt::Producer &clip, int position, bool seek = true, bool notify = true);
194 int insertClip(int trackIndex,
195 Mlt::Producer &clip,
196 int position,
197 bool rippleAllTracks,
198 bool seek = true,
199 bool notify = true);
200 int appendClip(int trackIndex, Mlt::Producer &clip, bool seek = true, bool notify = true);
201 void removeClip(int trackIndex, int clipIndex, bool rippleAllTracks);
202 void liftClip(int trackIndex, int clipIndex, bool consolidate = true);
203 void consolidateBlanks(int trackIndex);
204 void splitClip(int trackIndex, int clipIndex, int position);
205 void joinClips(int trackIndex, int clipIndex);
206 void changeGain(int trackIndex, int clipIndex, double gain);
207 void fadeIn(int trackIndex, int clipIndex, int duration);
208 void fadeOut(int trackIndex, int clipIndex, int duration);
209 bool addTransitionValid(int fromTrack, int toTrack, int clipIndex, int position, bool ripple);
210 int addTransition(int trackIndex, int clipIndex, int position, bool ripple, bool rippleAllTracks);
211 void removeTransition(int trackIndex, int clipIndex);
212 void removeTransitionByTrimIn(int trackIndex, int clipIndex, int delta);
213 void removeTransitionByTrimOut(int trackIndex, int clipIndex, int delta);
214 bool trimTransitionInValid(int trackIndex, int clipIndex, int delta);
215 void trimTransitionIn(int trackIndex, int clipIndex, int delta, bool slip = false);
216 bool trimTransitionOutValid(int trackIndex, int clipIndex, int delta);
217 void trimTransitionOut(int trackIndex, int clipIndex, int delta, bool slip = false);
218 bool resizeTransitionValid(int trackIndex, int transitionIndex, int delta);
219 bool addTransitionByTrimInValid(int trackIndex, int clipIndex, int delta);
220 int addTransitionByTrimIn(int trackIndex, int clipIndex, int delta);
221 bool addTransitionByTrimOutValid(int trackIndex, int clipIndex, int delta);
222 void addTransitionByTrimOut(int trackIndex, int clipIndex, int delta);
223 bool removeTransitionByTrimInValid(int trackIndex, int clipIndex, int delta);
224 bool removeTransitionByTrimOutValid(int trackIndex, int clipIndex, int delta);
225 void filterAddedOrRemoved(Mlt::Producer *producer);
226 void onFilterChanged(Mlt::Service *service);
227 void reload(bool asynchronous = false);
228 void replace(int trackIndex, int clipIndex, Mlt::Producer &clip, bool copyFilters = true);
229
230private:
231 Mlt::Tractor *m_tractor;
232 TrackList m_trackList;
233 bool m_isMakingTransition;
234 bool m_trackLevelIndicatorSupported;
235 bool m_hasAudioTracks;
236 int m_trackGainPosition;
237 int m_bulkUpdateDepth = 0;
238 bool m_bulkAdjustBackgroundPending = false;
239 bool m_bulkAdjustTrackFiltersPending = false;
240 bool m_bulkRefreshBlocked = false;
241 bool m_bulkUpdateChanged = false;
242
243 void moveClipToEnd(Mlt::Playlist &playlist,
244 int trackIndex,
245 int clipIndex,
246 int position,
247 bool ripple,
248 bool rippleAllTracks);
249 void moveClipInBlank(Mlt::Playlist &playlist,
250 int trackIndex,
251 int clipIndex,
252 int position,
253 bool ripple,
254 bool rippleAllTracks,
255 int duration = 0);
256 void consolidateBlanks(Mlt::Playlist &playlist, int trackIndex);
257 void consolidateBlanksAllTracks();
258 void getAudioLevels();
259 void addBlackTrackIfNeeded();
260 void convertOldDoc();
261 void reorderMixTransitions();
262 Mlt::Transition *getTransition(const QString &name, int trackIndex) const;
263 Mlt::Filter *getFilter(const QString &name, int trackIndex) const;
264 Mlt::Filter *getFilter(const QString &name, Mlt::Service *service) const;
265 void removeBlankPlaceholder(Mlt::Playlist &playlist, int trackIndex);
266 void retainPlaylist();
267 void loadPlaylist();
268 void removeRegion(int trackIndex, int position, int length);
269 void clearMixReferences(int trackIndex, int clipIndex);
270 bool isFiltered(Mlt::Producer *producer = 0) const;
271 int getDuration();
272 void adjustServiceFilterDurations(Mlt::Service &service, int duration);
273 bool warnIfInvalid(Mlt::Service &service);
274 Mlt::Transition *getVideoBlendTransition(int trackIndex) const;
275 void refreshVideoBlendTransitions();
276 int bottomVideoTrackMltIndex() const;
277 bool hasEmptyTrack(TrackType trackType) const;
278 Mlt::Filter *ensureTrackAudioLevelFilter(Mlt::Producer *track, int mltTrackIndex) const;
279 void syncTrackAudioLevelFilterPrefixes();
280 void setTrackAudioLevel(int row, double audioLevel);
281 Mlt::Filter *ensureTrackVolumeFilter(Mlt::Producer *track);
282
283 friend class UndoHelper;
284
285private slots:
286 void adjustBackgroundDuration();
287 void adjustTrackFilters();
288};
289
290#endif // MULTITRACKMODEL_H
The SharedFrame provides thread safe access to Mlt::Frame data.
Definition sharedframe.h:49