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
30typedef enum {
31 PlaylistTrackType = 0,
32 BlackTrackType,
33 SilentTrackType,
34 AudioTrackType,
35 VideoTrackType
36} TrackType;
37
38typedef struct
39{
40 TrackType type;
41 int number;
42 int mlt_index;
43} Track;
44
45typedef QList<Track> TrackList;
46
47class MultitrackModel : public QAbstractItemModel
48{
49 Q_OBJECT
50 Q_PROPERTY(int trackHeight READ trackHeight WRITE setTrackHeight NOTIFY trackHeightChanged)
51 Q_PROPERTY(int trackHeaderWidth READ trackHeaderWidth WRITE setTrackHeaderWidth NOTIFY
52 trackHeaderWidthChanged FINAL)
53 Q_PROPERTY(double scaleFactor READ scaleFactor WRITE setScaleFactor NOTIFY scaleFactorChanged)
54 Q_PROPERTY(bool filtered READ isFiltered NOTIFY filteredChanged)
55
56public:
58 enum {
59 NameRole = Qt::UserRole + 1,
60 CommentRole,
61 ResourceRole,
62 ServiceRole,
63 IsBlankRole,
64 StartRole,
65 DurationRole,
66 InPointRole,
67 OutPointRole,
68 FramerateRole,
69 IsMuteRole,
70 IsHiddenRole,
71 IsAudioRole,
72 AudioLevelsRole,
73 IsCompositeRole,
74 IsLockedRole,
75 FadeInRole,
76 FadeOutRole,
77 IsTransitionRole,
78 FileHashRole,
79 SpeedRole,
80 IsFilteredRole,
81 IsTopVideoRole,
82 IsBottomVideoRole,
83 IsTopAudioRole,
84 IsBottomAudioRole,
85 AudioIndexRole,
86 GroupRole,
87 GainRole,
88 GainEnabledRole,
89 };
90
91 explicit MultitrackModel(QObject *parent = 0);
92 ~MultitrackModel();
93
94 Mlt::Tractor *tractor() const { return m_tractor; }
95 const TrackList &trackList() const { return m_trackList; }
96
97 int rowCount(const QModelIndex &parent = QModelIndex()) const;
98 int columnCount(const QModelIndex &parent) const;
99 QVariant data(const QModelIndex &index, int role) const;
100 QModelIndex index(int row, int column = 0, const QModelIndex &parent = QModelIndex()) const;
101 QModelIndex makeIndex(int trackIndex, int clipIndex) const;
102 QModelIndex parent(const QModelIndex &index) const;
103 QHash<int, QByteArray> roleNames() const;
104 Q_INVOKABLE void audioLevelsReady(const QPersistentModelIndex &index);
105 const QByteArray *getAudioLevels(int trackIndex, int clipIndex) const;
106 bool createIfNeeded();
107 void addBackgroundTrack();
108 int addAudioTrack();
109 int addVideoTrack();
110 void removeTrack(int trackIndex);
111 void load();
112 void close();
113 int clipIndex(int trackIndex, int position);
114 bool trimClipInValid(int trackIndex, int clipIndex, int delta, bool ripple);
115 bool trimClipOutValid(int trackIndex, int clipIndex, int delta, bool ripple);
116 int trackHeight() const;
117 void setTrackHeight(int height);
118 int trackHeaderWidth() const;
119 void setTrackHeaderWidth(int width);
120 double scaleFactor() const;
121 void setScaleFactor(double scale);
122 bool isTransition(Mlt::Playlist &playlist, int clipIndex) const;
123 void insertTrack(int trackIndex, TrackType type = VideoTrackType);
124 void moveTrack(int fromTrackIndex, int toTrackIndex);
125 void insertOrAdjustBlankAt(QList<int> tracks, int position, int length);
126 bool mergeClipWithNext(int trackIndex, int clipIndex, bool dryrun);
127 std::unique_ptr<Mlt::ClipInfo> findClipByUuid(const QUuid &uuid,
128 int &trackIndex,
129 int &clipIndex);
130 std::unique_ptr<Mlt::ClipInfo> getClipInfo(int trackIndex, int clipIndex);
131 QString getTrackName(int trackIndex);
132 int bottomVideoTrackIndex() const;
133 int mltIndexForTrack(int trackIndex) const;
134 bool checkForEmptyTracks(int trackIndex);
135 QString trackTransitionService();
136
137signals:
138 void created();
139 void aboutToClose();
140 void closed();
141 void modified();
142 void seeked(int position, bool seekPlayer = true);
143 void trackHeightChanged();
144 void trackHeaderWidthChanged();
145 void scaleFactorChanged();
146 void showStatusMessage(QString);
147 void durationChanged();
148 void filteredChanged();
149 void reloadRequested();
150 void appended(int trackIndex, int clipIndex);
151 void inserted(int trackIndex, int clipIndex);
152 void overWritten(int trackIndex, int clipIndex);
153 void removing(Mlt::Service *service);
154 void noMoreEmptyTracks(bool isAudio);
155
156public slots:
157 void refreshTrackList();
158 void setTrackName(int row, const QString &value);
159 void setTrackMute(int row, bool mute);
160 void setTrackHidden(int row, bool hidden);
161 void setTrackComposite(int row, bool composite);
162 void setTrackLock(int row, bool lock);
163 int trimClipIn(int trackIndex, int clipIndex, int delta, bool ripple, bool rippleAllTracks);
164 void notifyClipIn(int trackIndex, int clipIndex);
165 int trimClipOut(int trackIndex, int clipIndex, int delta, bool ripple, bool rippleAllTracks);
166 void notifyClipOut(int trackIndex, int clipIndex);
167 bool moveClip(
168 int fromTrack, int toTrack, int clipIndex, int position, bool ripple, bool rippleAllTracks);
169 int overwriteClip(int trackIndex, Mlt::Producer &clip, int position, bool seek = true);
170 QString overwrite(
171 int trackIndex, Mlt::Producer &clip, int position, bool seek = true, bool notify = true);
172 int insertClip(int trackIndex,
173 Mlt::Producer &clip,
174 int position,
175 bool rippleAllTracks,
176 bool seek = true,
177 bool notify = true);
178 int appendClip(int trackIndex, Mlt::Producer &clip, bool seek = true, bool notify = true);
179 void removeClip(int trackIndex, int clipIndex, bool rippleAllTracks);
180 void liftClip(int trackIndex, int clipIndex);
181 void splitClip(int trackIndex, int clipIndex, int position);
182 void joinClips(int trackIndex, int clipIndex);
183 void changeGain(int trackIndex, int clipIndex, double gain);
184 void fadeIn(int trackIndex, int clipIndex, int duration);
185 void fadeOut(int trackIndex, int clipIndex, int duration);
186 bool addTransitionValid(int fromTrack, int toTrack, int clipIndex, int position, bool ripple);
187 int addTransition(int trackIndex, int clipIndex, int position, bool ripple, bool rippleAllTracks);
188 void removeTransition(int trackIndex, int clipIndex);
189 void removeTransitionByTrimIn(int trackIndex, int clipIndex, int delta);
190 void removeTransitionByTrimOut(int trackIndex, int clipIndex, int delta);
191 bool trimTransitionInValid(int trackIndex, int clipIndex, int delta);
192 void trimTransitionIn(int trackIndex, int clipIndex, int delta, bool slip = false);
193 bool trimTransitionOutValid(int trackIndex, int clipIndex, int delta);
194 void trimTransitionOut(int trackIndex, int clipIndex, int delta, bool slip = false);
195 bool resizeTransitionValid(int trackIndex, int transitionIndex, int delta);
196 bool addTransitionByTrimInValid(int trackIndex, int clipIndex, int delta);
197 int addTransitionByTrimIn(int trackIndex, int clipIndex, int delta);
198 bool addTransitionByTrimOutValid(int trackIndex, int clipIndex, int delta);
199 void addTransitionByTrimOut(int trackIndex, int clipIndex, int delta);
200 bool removeTransitionByTrimInValid(int trackIndex, int clipIndex, int delta);
201 bool removeTransitionByTrimOutValid(int trackIndex, int clipIndex, int delta);
202 void filterAddedOrRemoved(Mlt::Producer *producer);
203 void onFilterChanged(Mlt::Service *service);
204 void reload(bool asynchronous = false);
205 void replace(int trackIndex, int clipIndex, Mlt::Producer &clip, bool copyFilters = true);
206
207private:
208 Mlt::Tractor *m_tractor;
209 TrackList m_trackList;
210 bool m_isMakingTransition;
211
212 void moveClipToEnd(Mlt::Playlist &playlist,
213 int trackIndex,
214 int clipIndex,
215 int position,
216 bool ripple,
217 bool rippleAllTracks);
218 void moveClipInBlank(Mlt::Playlist &playlist,
219 int trackIndex,
220 int clipIndex,
221 int position,
222 bool ripple,
223 bool rippleAllTracks,
224 int duration = 0);
225 void consolidateBlanks(Mlt::Playlist &playlist, int trackIndex);
226 void consolidateBlanksAllTracks();
227 void getAudioLevels();
228 void addBlackTrackIfNeeded();
229 void convertOldDoc();
230 Mlt::Transition *getTransition(const QString &name, int trackIndex) const;
231 Mlt::Filter *getFilter(const QString &name, int trackIndex) const;
232 Mlt::Filter *getFilter(const QString &name, Mlt::Service *service) const;
233 void removeBlankPlaceholder(Mlt::Playlist &playlist, int trackIndex);
234 void retainPlaylist();
235 void loadPlaylist();
236 void removeRegion(int trackIndex, int position, int length);
237 void clearMixReferences(int trackIndex, int clipIndex);
238 bool isFiltered(Mlt::Producer *producer = 0) const;
239 int getDuration();
240 void adjustServiceFilterDurations(Mlt::Service &service, int duration);
241 bool warnIfInvalid(Mlt::Service &service);
242 Mlt::Transition *getVideoBlendTransition(int trackIndex) const;
243 void refreshVideoBlendTransitions();
244 int bottomVideoTrackMltIndex() const;
245 bool hasEmptyTrack(TrackType trackType) const;
246
247 friend class UndoHelper;
248
249private slots:
250 void adjustBackgroundDuration();
251 void adjustTrackFilters();
252};
253
254#endif // MULTITRACKMODEL_H