1 /* 2 SPDX-FileCopyrightText: 2014 Till Theato <root@ttill.de> 3 SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 4 */ 5 6 #ifndef CORE_H 7 #define CORE_H 8 9 #include "definitions.h" 10 #include "jobs/taskmanager.h" 11 #include "kdenlivecore_export.h" 12 #include "undohelper.hpp" 13 #include <QMutex> 14 #include <QObject> 15 #include <QColor> 16 #include <QUrl> 17 #include <memory> 18 #include <QPoint> 19 #include <QThreadPool> 20 #include <QTextEdit> 21 #include <KSharedDataCache> 22 #include <unordered_set> 23 #include "timecode.h" 24 25 #include <mlt++/MltProfile.h> 26 #include <mlt++/MltPlaylist.h> 27 28 class Bin; 29 class DocUndoStack; 30 class EffectStackModel; 31 class KdenliveDoc; 32 class LibraryWidget; 33 class MainWindow; 34 class MediaCapture; 35 class MixerManager; 36 class Monitor; 37 class MonitorManager; 38 class ProfileModel; 39 class ProjectItemModel; 40 class ProjectManager; 41 class SubtitleEdit; 42 class SubtitleModel; 43 class TextBasedEdit; 44 class TimeRemap; 45 46 namespace Mlt { 47 class Repository; 48 class Producer; 49 } // namespace Mlt 50 51 #define EXIT_RESTART (42) 52 #define EXIT_CLEAN_RESTART (43) 53 #define pCore Core::self() 54 55 /** 56 * @class Core 57 * @brief Singleton that provides access to the different parts of Kdenlive 58 * 59 * Needs to be initialize before any widgets are created in MainWindow. 60 * Plugins should be loaded after the widget setup. 61 */ 62 class /*KDENLIVECORE_EXPORT*/ Core : public QObject 63 { 64 Q_OBJECT 65 66 public: 67 Core(const Core &) = delete; 68 Core &operator=(const Core &) = delete; 69 Core(Core &&) = delete; 70 Core &operator=(Core &&) = delete; 71 72 ~Core() override; 73 74 /** 75 * @brief Setup the basics of the application, in particular the connection 76 * with Mlt 77 * @param isAppImage do we expect an AppImage (if yes, we use App path to deduce 78 * other binaries paths (melt, ffmpeg, etc) 79 * @param MltPath (optional) path to MLT environment 80 */ 81 static bool build(bool testMode = false); 82 83 /** 84 * @brief Init the GUI part of the app and show the main window 85 * @param Url (optional) file to open 86 * If Url is present, it will be opened, otherwise, if openlastproject is 87 * set, latest project will be opened. If no file is open after trying this, 88 * a default new file will be created. */ 89 void initGUI(bool isAppImage, const QString &MltPath, const QUrl &Url, const QString &clipsToLoad = QString()); 90 91 /** @brief Returns a pointer to the singleton object. */ 92 static std::unique_ptr<Core> &self(); 93 94 /** @brief Delete the global core instance */ 95 static void clean(); 96 97 /** @brief Returns a pointer to the main window. */ 98 MainWindow *window(); 99 100 /** @brief Returns a pointer to the project manager. */ 101 ProjectManager *projectManager(); 102 /** @brief Returns a pointer to the current project. */ 103 KdenliveDoc *currentDoc(); 104 /** @brief Returns project's timecode. */ 105 Timecode timecode() const; 106 /** @brief Returns a pointer to the monitor manager. */ 107 MonitorManager *monitorManager(); 108 /** @brief Returns a pointer to the view of the project bin. */ 109 Bin *bin(); 110 /** @brief Returns a pointer to the view of the active bin (or main bin on no focus). */ 111 Bin *activeBin(); 112 /** @brief Select a clip in the Bin from its id. */ 113 void selectBinClip(const QString &id, bool activateMonitor = true, int frame = -1, const QPoint &zone = QPoint()); 114 /** @brief Selects an item in the current timeline (clip, composition, subtitle). */ 115 void selectTimelineItem(int id); 116 /** @brief Returns a pointer to the model of the project bin. */ 117 std::shared_ptr<ProjectItemModel> projectItemModel(); 118 /** @brief Returns a pointer to the library. */ 119 LibraryWidget *library(); 120 /** @brief Returns a pointer to the subtitle edit. */ 121 SubtitleEdit *subtitleWidget(); 122 /** @brief Returns a pointer to the text based editing widget. */ 123 TextBasedEdit *textEditWidget(); 124 /** @brief Returns a pointer to the time remapping widget. */ 125 TimeRemap *timeRemapWidget(); 126 /** @brief Returns true if clip displayed in remap widget is the bin clip with id clipId. */ 127 bool currentRemap(const QString &clipId); 128 /** @brief Returns a pointer to the audio mixer. */ 129 MixerManager *mixer(); 130 ToolType::ProjectTool activeTool(); 131 132 /** @brief Returns a pointer to MLT's repository */ 133 std::unique_ptr<Mlt::Repository> &getMltRepository(); 134 135 /** @brief Returns a pointer to the current profile */ 136 std::unique_ptr<ProfileModel> &getCurrentProfile() const; 137 const QString &getCurrentProfilePath() const; 138 139 /** @brief Define the active profile 140 * @returns true if profile exists, false if not found 141 */ 142 bool setCurrentProfile(const QString &profilePath); 143 /** @brief Returns Sample Aspect Ratio of current profile */ 144 double getCurrentSar() const; 145 /** @brief Returns Display Aspect Ratio of current profile */ 146 double getCurrentDar() const; 147 148 /** @brief Returns frame rate of current profile */ 149 double getCurrentFps() const; 150 151 /** @brief Returns the frame size (width x height) of current profile */ 152 QSize getCurrentFrameSize() const; 153 /** @brief Returns the frame display size (width x height) of current profile */ 154 QSize getCurrentFrameDisplaySize() const; 155 /** @brief Request project monitor refresh */ 156 void requestMonitorRefresh(); 157 /** @brief Request project monitor refresh if current position is inside range*/ 158 void refreshProjectRange(QPair<int, int> range); 159 /** @brief Request project monitor refresh if referenced item is under cursor */ 160 void refreshProjectItem(const ObjectId &id); 161 /** @brief Returns a reference to a monitor (clip or project monitor) */ 162 Monitor *getMonitor(int id); 163 /** @brief Returns timeline's active track info (position and tag) */ 164 QPair <int,QString> currentTrackInfo() const; 165 /** @brief This function must be called whenever the profile used changes */ 166 void profileChanged(); 167 168 /** @brief Create and push and undo object based on the corresponding functions 169 Note that if you class permits and requires it, you should use the macro PUSH_UNDO instead*/ 170 void pushUndo(const Fun &undo, const Fun &redo, const QString &text); 171 void pushUndo(QUndoCommand *command); 172 /** @brief display a user info/warning message in statusbar */ 173 void displayMessage(const QString &message, MessageType type, int timeout = -1); 174 /** @brief Clear asset view if itemId is displayed. */ 175 void clearAssetPanel(int itemId); 176 /** @brief Returns the effectstack of a given bin clip. */ 177 std::shared_ptr<EffectStackModel> getItemEffectStack(int itemType, int itemId); 178 int getItemPosition(const ObjectId &id); 179 int getItemIn(const ObjectId &id); 180 int getItemTrack(const ObjectId &id); 181 int getItemDuration(const ObjectId &id); 182 QSize getItemFrameSize(const ObjectId &id); 183 /** @brief Returns the capabilities of a clip: AudioOnly, VideoOnly or Disabled if both are allowed */ 184 PlaylistState::ClipState getItemState(const ObjectId &id); 185 /** @brief Get a list of video track names with indexes */ 186 QMap<int, QString> getTrackNames(bool videoOnly); 187 /** @brief Returns the composition A track (MLT index / Track id) */ 188 QPair<int, int> getCompositionATrack(int cid) const; 189 void setCompositionATrack(int cid, int aTrack); 190 /** @brief Return true if composition's a_track is automatic (no forced track) 191 */ 192 bool compositionAutoTrack(int cid) const; 193 std::shared_ptr<DocUndoStack> undoStack(); 194 double getClipSpeed(int id) const; 195 /** @brief Mark an item as invalid for timeline preview */ 196 void invalidateItem(ObjectId itemId); 197 void invalidateRange(QPair<int, int>range); 198 void prepareShutdown(); 199 /** the keyframe model changed (effect added, deleted, active effect changed), inform timeline */ 200 void updateItemKeyframes(ObjectId id); 201 /** A fade for clip id changed, update timeline */ 202 void updateItemModel(ObjectId id, const QString &service); 203 /** Show / hide keyframes for a timeline clip */ 204 void showClipKeyframes(ObjectId id, bool enable); 205 Mlt::Profile *thumbProfile(); 206 /** @brief Returns the current project duration */ 207 int projectDuration() const; 208 /** @brief Returns true if current project has some rendered timeline preview */ 209 bool hasTimelinePreview() const; 210 /** @brief Returns current timeline cursor position */ 211 int getTimelinePosition() const; 212 /** @brief Handles audio and video capture **/ 213 void startMediaCapture(int tid, bool, bool); 214 void stopMediaCapture(int tid, bool, bool); 215 QStringList getAudioCaptureDevices(); 216 int getMediaCaptureState(); 217 bool isMediaCapturing(); 218 MediaCapture *getAudioDevice(); 219 /** @brief Returns Project Folder name for capture output location */ 220 QString getProjectFolderName(); 221 /** @brief Returns a timeline clip's bin id */ 222 QString getTimelineClipBinId(int cid); 223 /** @brief Returns all track ids in timeline */ 224 std::unordered_set<QString> getAllTimelineTracksId(); 225 /** @brief Returns a frame duration from a timecode */ 226 int getDurationFromString(const QString &time); 227 /** @brief An error occurred within a filter, inform user */ 228 void processInvalidFilter(const QString service, const QString id, const QString message); 229 /** @brief Update current project's tags */ 230 void updateProjectTags(QMap <QString, QString> tags); 231 /** @brief Returns the project profile */ 232 Mlt::Profile *getProjectProfile(); 233 /** @brief Returns the consumer profile, that will be scaled 234 * according to preview settings. Should only be used on the consumer */ 235 Mlt::Profile &getMonitorProfile(); 236 /** @brief Returns a copy of current timeline's master playlist */ 237 std::unique_ptr<Mlt::Producer> getMasterProducerInstance(); 238 /** @brief Returns a copy of a track's playlist */ 239 std::unique_ptr<Mlt::Producer> getTrackProducerInstance(int tid); 240 /** @brief Returns the undo stack index (position). */ 241 int undoIndex() const; 242 /** @brief Enable / disable monitor multitrack view. Returns false if multitrack was not previously enabled */ 243 bool enableMultiTrack(bool enable); 244 /** @brief Returns number of audio channels for this project. */ 245 int audioChannels(); 246 /** @brief Add guides in the project. */ 247 void addGuides(QList <int> guides); 248 /** @brief Temporarily un/plug a list of clips in timeline. */ 249 void temporaryUnplug(QList<int> clipIds, bool hide); 250 /** @brief Returns the current doc's subtitle model. */ 251 std::shared_ptr<SubtitleModel> getSubtitleModel(bool enforce = false); 252 /** @brief Transcode a video file. */ 253 void transcodeFile(const QString url); 254 /** @brief Display key binding info in statusbar. */ 255 void setWidgetKeyBinding(const QString &mess = QString()); 256 KSharedDataCache audioThumbCache; 257 /* @brief The thread job pool for clip jobs, allowing to set a max number of concurrent jobs */ 258 TaskManager taskManager; 259 /** @brief The number of clip load jobs changed */ 260 void loadingClips(int); 261 /** @brief Resize current mix item */ 262 void resizeMix(int cid, int duration, MixAlignment align, int rightFrames = -1); 263 /** @brief Get Mix cut pos (the duration of the mix on the right clip) */ 264 int getMixCutPos(int cid) const; 265 /** @brief Get alignment info for a mix item */ 266 MixAlignment getMixAlign(int cid) const; 267 /** @brief Closing current document, do some cleanup */ 268 void cleanup(); 269 /** @brief Instantiates a "Get Hot New Stuff" dialog. 270 * @param configFile configuration file for KNewStuff 271 * @return number of installed items */ 272 int getNewStuff(const QString &configFile); 273 /** @brief Get the frame size of the clip above a composition */ 274 const QSize getCompositionSizeOnTrack(const ObjectId &id); 275 void loadTimelinePreview(const QString &chunks, const QString &dirty, const QDateTime &documentDate, int enablePreview, Mlt::Playlist &playlist); 276 277 private: 278 explicit Core(); 279 static std::unique_ptr<Core> m_self; 280 281 /** @brief Makes sure Qt's locale and system locale settings match. */ 282 void initLocale(); 283 284 MainWindow *m_mainWindow{nullptr}; 285 ProjectManager *m_projectManager{nullptr}; 286 MonitorManager *m_monitorManager{nullptr}; 287 std::shared_ptr<ProjectItemModel> m_projectItemModel; 288 LibraryWidget *m_library{nullptr}; 289 SubtitleEdit *m_subtitleWidget{nullptr}; 290 TextBasedEdit *m_textEditWidget{nullptr}; 291 TimeRemap *m_timeRemapWidget{nullptr}; 292 MixerManager *m_mixerWidget{nullptr}; 293 294 /** @brief Current project's profile path */ 295 QString m_currentProfile; 296 297 QString m_profile; 298 Timecode m_timecode; 299 std::unique_ptr<Mlt::Profile> m_thumbProfile; 300 /** @brief Mlt profile used in the consumer 's monitors */ 301 Mlt::Profile m_monitorProfile; 302 /** @brief Mlt profile used to build the project's clips */ 303 std::unique_ptr<Mlt::Profile> m_projectProfile; 304 bool m_guiConstructed = false; 305 /** @brief Check that the profile is valid (width is a multiple of 8 and height a multiple of 2 */ 306 void checkProfileValidity(); 307 std::unique_ptr<MediaCapture> m_capture; 308 QUrl m_mediaCaptureFile; 309 QMutex m_thumbProfileMutex; 310 311 public slots: 312 /** @brief Trigger (launch) an action by its actionCollection name */ 313 void triggerAction(const QString &name); 314 /** @brief Get an action's descriptive text by its actionCollection name */ 315 const QString actionText(const QString &name); 316 /** @brief display a user info/warning message in the project bin */ 317 void displayBinMessage(const QString &text, int type, const QList<QAction *> &actions = QList<QAction *>(), bool showClose = false, BinMessage::BinCategory messageCategory = BinMessage::BinCategory::NoMessage); 318 void displayBinLogMessage(const QString &text, int type, const QString &logInfo); 319 /** @brief Create small thumbnails for luma used in compositions */ 320 void buildLumaThumbs(const QStringList &values); 321 /** @brief Try to find a display name for the given filename. 322 * This is espacally helpfull for mlt's dynamically created luma files without thumb (luma01.pgm, luma02.pgm,...), 323 * but also for others as it makes the visible name translatable. 324 * @return The name that fits to the filename or if none is found the filename it self 325 */ 326 const QString nameForLumaFile(const QString filename); 327 /** @brief Set current project modified. */ 328 void setDocumentModified(); 329 /** @brief Show currently selected effect zone in timeline ruler. */ 330 void showEffectZone(ObjectId id, QPair <int, int>inOut, bool checked); 331 void updateMasterZones(); 332 /** @brief Open the proxies test dialog. */ 333 void testProxies(); 334 /** @brief Refresh the monitor profile when project profile changes. */ 335 void updateMonitorProfile(); 336 /** @brief Add a new Bin Widget. */ 337 void addBin(const QString &id = QString()); 338 339 signals: 340 void coreIsReady(); 341 void updateLibraryPath(); 342 //void updateMonitorProfile(); 343 /** @brief Call config dialog on a selected page / tab */ 344 void showConfigDialog(int, int); 345 void finalizeRecording(const QString &captureFile); 346 void autoScrollChanged(); 347 /** @brief Send a message to splash screen if still displayed */ 348 void loadingMessageUpdated(const QString &, int progress = 0, int max = -1); 349 /** @brief Opening finished, close splash screen */ 350 void closeSplash(); 351 /** @brief Trigger an update of the the speech models list */ 352 void voskModelUpdate(const QStringList models); 353 /** @brief This signal means that VOSK and/or SRT module availability changed*/ 354 void updateVoskAvailability(); 355 /** @brief Update current effect zone */ 356 void updateEffectZone(const QPoint p, bool withUndo); 357 /** @brief The effect stask is about to be deleted, disconnect everything */ 358 void disconnectEffectStack(); 359 /** @brief Add a time remap effect to clip and show keyframes dialog */ 360 void remapClip(int cid); 361 /** @brief A monitor property changed, check if we need to reset */ 362 void monitorProfileUpdated(); 363 /** @brief Color theme changed, process refresh */ 364 void updatePalette(); 365 /** @brief Emitted when a clip is resized (to handle clip monitor inserted zones) */ 366 void clipInstanceResized(const QString &binId); 367 }; 368 369 #endif 370