File indexing completed on 2024-04-14 04:47:29

0001 /*
0002 SPDX-FileCopyrightText: 2014 Till Theato <root@ttill.de>
0003 SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0004 */
0005 
0006 #pragma once
0007 
0008 #include "definitions.h"
0009 #include "jobs/taskmanager.h"
0010 #include "kdenlivecore_export.h"
0011 #include "undohelper.hpp"
0012 #include "utils/timecode.h"
0013 #include <KSharedDataCache>
0014 #include <QColor>
0015 #include <QMutex>
0016 #include <QObject>
0017 #include <QPoint>
0018 #include <QTextEdit>
0019 #include <QThreadPool>
0020 #include <QUrl>
0021 #include <knewstuff_version.h>
0022 #include <memory>
0023 #include <unordered_set>
0024 
0025 #include <mlt++/MltProfile.h>
0026 #include <mlt++/MltPlaylist.h>
0027 
0028 class Bin;
0029 class DocUndoStack;
0030 class EffectStackModel;
0031 class KdenliveDoc;
0032 class LibraryWidget;
0033 class MainWindow;
0034 class MediaCapture;
0035 class MediaBrowser;
0036 class MixerManager;
0037 class Monitor;
0038 class MonitorManager;
0039 class ProfileModel;
0040 class ProjectItemModel;
0041 class ProjectManager;
0042 class SubtitleEdit;
0043 class SubtitleModel;
0044 class TextBasedEdit;
0045 class GuidesList;
0046 class TimeRemap;
0047 
0048 namespace Mlt {
0049     class Repository;
0050     class Producer;
0051 } // namespace Mlt
0052 
0053 #define EXIT_RESTART (42)
0054 #define EXIT_CLEAN_RESTART (43)
0055 #define pCore Core::self()
0056 
0057 /**
0058  * @class Core
0059  * @brief Singleton that provides access to the different parts of Kdenlive
0060  *
0061  * Needs to be initialize before any widgets are created in MainWindow.
0062  * Plugins should be loaded after the widget setup.
0063  */
0064 class /*KDENLIVECORE_EXPORT*/ Core : public QObject
0065 {
0066     Q_OBJECT
0067 
0068 public:
0069     Core(const Core &) = delete;
0070     Core &operator=(const Core &) = delete;
0071     Core(Core &&) = delete;
0072     Core &operator=(Core &&) = delete;
0073 
0074     ~Core() override;
0075 
0076     /**
0077      * @brief Setup the basics of the application, in particular the connection
0078      * with Mlt
0079      * @param MltPath (optional) path to MLT environment
0080      */
0081     static bool build(const QString &packageType, bool testMode = false);
0082 
0083     void initHeadless(const QUrl &url);
0084 
0085     /**
0086      * @brief Init the GUI part of the app and show the main window
0087      * @param inSandbox does the app run in a sanbox? If yes, we use App path to deduce
0088      * other binaries paths (melt, ffmpeg, etc)
0089      * @param MltPath
0090      * @param Url (optional) file to open
0091      * If Url is present, it will be opened, otherwise, if openlastproject is
0092      * set, latest project will be opened. If no file is open after trying this,
0093      * a default new file will be created.
0094      * @param clipsToLoad
0095      */
0096     void initGUI(bool inSandbox, const QString &MltPath, const QUrl &Url, const QString &clipsToLoad = QString());
0097 
0098     /** @brief Returns a pointer to the singleton object. */
0099     static std::unique_ptr<Core> &self();
0100 
0101     /** @brief Delete the global core instance */
0102     static void clean();
0103 
0104     /** @brief Returns a pointer to the main window. */
0105     MainWindow *window();
0106 
0107     /** @brief Open a file using an external app. */
0108     QString openExternalApp(QString appPath, const QStringList args);
0109 
0110     /** @brief Returns a pointer to the project manager. */
0111     ProjectManager *projectManager();
0112     /** @brief Returns a pointer to the current project. */
0113     KdenliveDoc *currentDoc();
0114     /** @brief Returns project's timecode. */
0115     Timecode timecode() const;
0116     /** @brief Returns a pointer to the monitor manager. */
0117     MonitorManager *monitorManager();
0118     /** @brief Returns a pointer to the media browser widget. */
0119     MediaBrowser *mediaBrowser();
0120     /** @brief Returns a pointer to the view of the project bin. */
0121     Bin *bin();
0122     /** @brief Returns a pointer to the view of the active bin (or main bin on no focus). */
0123     Bin *activeBin();
0124     /** @brief Select a clip in the Bin from its id. */
0125     void selectBinClip(const QString &id, bool activateMonitor = true, int frame = -1, const QPoint &zone = QPoint());
0126     /** @brief Selects an item in the current timeline (clip, composition, subtitle). */
0127     void selectTimelineItem(int id);
0128     /** @brief Returns a pointer to the model of the project bin. */
0129     std::shared_ptr<ProjectItemModel> projectItemModel();
0130     /** @brief Returns a pointer to the library. */
0131     LibraryWidget *library();
0132     /** @brief Returns a pointer to the subtitle edit. */
0133     SubtitleEdit *subtitleWidget();
0134     /** @brief Returns a pointer to the text based editing widget. */
0135     TextBasedEdit *textEditWidget();
0136     /** @brief Returns a pointer to the guides list widget. */
0137     GuidesList *guidesList();
0138     /** @brief Returns a pointer to the time remapping widget. */
0139     TimeRemap *timeRemapWidget();
0140     /** @brief Returns true if clip displayed in remap widget is the bin clip with id clipId. */
0141     bool currentRemap(const QString &clipId);
0142     /** @brief Returns a pointer to the audio mixer. */
0143     MixerManager *mixer();
0144     ToolType::ProjectTool activeTool();
0145 
0146     /** @brief Returns a pointer to MLT's repository */
0147     std::unique_ptr<Mlt::Repository> &getMltRepository();
0148 
0149     /** @brief Returns a pointer to the current profile */
0150     std::unique_ptr<ProfileModel> &getCurrentProfile() const;
0151     const QString &getCurrentProfilePath() const;
0152 
0153     /** @brief Define the active profile
0154      *  @returns true if profile exists, false if not found
0155      */
0156     bool setCurrentProfile(const QString profilePath);
0157     /** @brief Returns Sample Aspect Ratio of current profile */
0158     double getCurrentSar() const;
0159     /** @brief Returns Display Aspect Ratio of current profile */
0160     double getCurrentDar() const;
0161 
0162     /** @brief Returns frame rate of current profile */
0163     double getCurrentFps() const;
0164 
0165     /** @brief Returns the frame size (width x height) of current profile */
0166     QSize getCurrentFrameSize() const;
0167     /** @brief Returns the frame display size (width x height) of current profile */
0168     QSize getCurrentFrameDisplaySize() const;
0169     /** @brief Request project monitor refresh, and restore previously active monitor */
0170     void refreshProjectMonitorOnce();
0171     /** @brief Request project monitor refresh if current position is inside range*/
0172     void refreshProjectRange(QPair<int, int> range);
0173     /** @brief Request project monitor refresh if referenced item is under cursor */
0174     void refreshProjectItem(const ObjectId &id);
0175     /** @brief Returns a reference to a monitor (clip or project monitor) */
0176     Monitor *getMonitor(int id);
0177     /** @brief Seek a monitor to position */
0178     void seekMonitor(int id, int position);
0179     /** @brief Returns timeline's active track info (position and tag) */
0180     QPair <int,QString> currentTrackInfo() const;
0181     /** @brief This function must be called whenever the profile used changes */
0182     void profileChanged();
0183 
0184     /** @brief Create and push and undo object based on the corresponding functions
0185         Note that if you class permits and requires it, you should use the macro PUSH_UNDO instead*/
0186     void pushUndo(const Fun &undo, const Fun &redo, const QString &text);
0187     void pushUndo(QUndoCommand *command);
0188     /** @brief display a user info/warning message in statusbar */
0189     void displayMessage(const QString &message, MessageType type, int timeout = -1);
0190     /** @brief display timeline selection info in statusbar */
0191     void displaySelectionMessage(const QString &message);
0192     /** @brief Clear asset view if itemId is displayed. */
0193     void clearAssetPanel(int itemId);
0194     /** @brief Returns the effectstack of a given bin clip. */
0195     std::shared_ptr<EffectStackModel> getItemEffectStack(const QUuid &uuid, int itemType, int itemId);
0196     int getItemPosition(const ObjectId &id);
0197     /** @brief Get item in point. */
0198     int getItemIn(const ObjectId &id);
0199     /** @brief Get item in point, possibly from another timeline. */
0200     int getItemIn(const QUuid &uuid, const ObjectId &id);
0201     int getItemTrack(const ObjectId &id);
0202     int getItemDuration(const ObjectId &id);
0203     QSize getItemFrameSize(const ObjectId &id);
0204     /** @brief Returns the capabilities of a clip: AudioOnly, VideoOnly or Disabled if both are allowed */
0205     PlaylistState::ClipState getItemState(const ObjectId &id);
0206     /** @brief Get a list of video track names with indexes */
0207     QMap<int, QString> getTrackNames(bool videoOnly);
0208     /** @brief Returns the composition A track (MLT index / Track id) */
0209     QPair<int, int> getCompositionATrack(int cid) const;
0210     void setCompositionATrack(int cid, int aTrack);
0211     /** @brief Return true if composition's a_track is automatic (no forced track)
0212      */
0213     bool compositionAutoTrack(int cid) const;
0214     std::shared_ptr<DocUndoStack> undoStack();
0215     double getClipSpeed(int id) const;
0216     /** @brief Mark an item as invalid for timeline preview */
0217     void invalidateItem(ObjectId itemId);
0218     void invalidateRange(QPair<int, int>range);
0219     void prepareShutdown();
0220     void finishShutdown();
0221     /** the keyframe model changed (effect added, deleted, active effect changed), inform timeline */
0222     void updateItemKeyframes(ObjectId id);
0223     /** A fade for clip id changed, update timeline */
0224     void updateItemModel(ObjectId id, const QString &service);
0225     /** Show / hide keyframes for a timeline clip */
0226     void showClipKeyframes(ObjectId id, bool enable);
0227     Mlt::Profile &thumbProfile();
0228     /** @brief Returns the current project duration */
0229     int projectDuration() const;
0230     /** @brief Returns true if current project has some rendered timeline preview  */
0231     bool hasTimelinePreview() const;
0232     /** @brief Returns monitor position  */
0233     int getMonitorPosition(Kdenlive::MonitorId id = Kdenlive::ProjectMonitor) const;
0234     /** @brief Handles audio and video capture **/
0235     void startMediaCapture(int tid, bool, bool);
0236     void stopMediaCapture(int tid, bool, bool);
0237     QStringList getAudioCaptureDevices();
0238     int getMediaCaptureState();
0239     bool isMediaMonitoring() const;
0240     bool isMediaCapturing() const;
0241     MediaCapture *getAudioDevice();
0242     /** @brief Returns Project Folder name for capture output location */
0243     QString getProjectFolderName(bool folderForAudio = false);
0244     /** @brief Returns a timeline clip's bin id */
0245     QString getTimelineClipBinId(int cid);
0246     /** @brief Returns all track ids in timeline */
0247     std::unordered_set<QString> getAllTimelineTracksId();
0248     /** @brief Returns a frame duration from a timecode */
0249     int getDurationFromString(const QString &time);
0250     /** @brief An error occurred within a filter, inform user */
0251     void processInvalidFilter(const QString &service, const QString &id, const QString &message);
0252     /** @brief Update current project's tags */
0253     void updateProjectTags(int previousCount, const QMap <int, QStringList> &tags);
0254     /** @brief Returns the project profile */
0255     Mlt::Profile &getProjectProfile();
0256     /** @brief Returns the consumer profile, that will be scaled
0257      *  according to preview settings. Should only be used on the consumer */
0258     Mlt::Profile &getMonitorProfile();
0259     /** @brief Returns a copy of current timeline's master playlist */
0260     std::unique_ptr<Mlt::Producer> getMasterProducerInstance();
0261     /** @brief Returns a copy of a track's playlist */
0262     std::unique_ptr<Mlt::Producer> getTrackProducerInstance(int tid);
0263     /** @brief Returns the undo stack index (position). */
0264     int undoIndex() const;
0265     /** @brief Enable / disable monitor multitrack view. Returns false if multitrack was not previously enabled */
0266     bool enableMultiTrack(bool enable);
0267     /** @brief Returns number of audio channels for this project. */
0268     int audioChannels();
0269     /** @brief Add guides in the project. */
0270     void addGuides(const QList <int> &guides);
0271     /** @brief Temporarily un/plug a list of clips in timeline. */
0272     void temporaryUnplug(const QList<int> &clipIds, bool hide);
0273     /** @brief Transcode a video file. */
0274     void transcodeFile(const QString &url);
0275     /** @brief Display key binding info in statusbar. */
0276     void setWidgetKeyBinding(const QString &mess = QString());
0277     KSharedDataCache audioThumbCache;
0278     /* @brief The thread job pool for clip jobs, allowing to set a max number of concurrent jobs */
0279     TaskManager taskManager;
0280     /** @brief The number of clip load jobs changed */
0281     void loadingClips(int, bool allowInterrupt = false);
0282     /** @brief Resize current mix item */
0283     void resizeMix(int cid, int duration, MixAlignment align, int leftFrames = -1);
0284     /** @brief Get Mix cut pos (the duration of the mix on the right clip) */
0285     int getMixCutPos(const ObjectId &) const;
0286     /** @brief Get alignment info for a mix item */
0287     MixAlignment getMixAlign(const ObjectId &) const;
0288     /** @brief Closing current document, do some cleanup */
0289     void cleanup();
0290     /** @brief Clear clip reference in timeremap widget */
0291     void clearTimeRemap();
0292     /** @brief Create the dock widgets */
0293     void buildDocks();
0294 #if KNEWSTUFF_VERSION < QT_VERSION_CHECK(5, 98, 0)
0295     /** @brief Instantiates a "Get Hot New Stuff" dialog.
0296      * @param configFile configuration file for KNewStuff
0297      * @return number of installed items */
0298     int getNewStuff(const QString &configFile);
0299 #endif
0300     /** @brief Get the frame size of the clip above a composition */
0301     const QSize getCompositionSizeOnTrack(const ObjectId &id);
0302     void loadTimelinePreview(const QUuid uuid, const QString &chunks, const QString &dirty, bool enablePreview, Mlt::Playlist &playlist);
0303     /** @brief Returns true if the audio mixer widget is visible */
0304     bool audioMixerVisible{false};
0305     QString packageType() { return m_packageType; };
0306     /** @brief Start / stop audio capture */
0307     void switchCapture();
0308     /** @brief Get the uuid of currently active timeline */
0309     const QUuid currentTimelineId() const;
0310     /** @brief Update a sequence AV info (has audio/video) */
0311     void updateSequenceAVType(const QUuid &uuid, int tracksCount);
0312     /** @brief A list of markers type categories {marker type, {color, category name}} */
0313     struct MarkerCategory
0314     {
0315         QColor color;
0316         QString displayName;
0317     };
0318     QMap<int, MarkerCategory> markerTypes;
0319 
0320 private:
0321     explicit Core(const QString &packageType);
0322     static std::unique_ptr<Core> m_self;
0323 
0324     /** @brief Makes sure Qt's locale and system locale settings match. */
0325     void initLocale();
0326 
0327     MainWindow *m_mainWindow{nullptr};
0328     ProjectManager *m_projectManager{nullptr};
0329     MonitorManager *m_monitorManager{nullptr};
0330     std::shared_ptr<ProjectItemModel> m_projectItemModel;
0331     LibraryWidget *m_library{nullptr};
0332     SubtitleEdit *m_subtitleWidget{nullptr};
0333     TextBasedEdit *m_textEditWidget{nullptr};
0334     GuidesList *m_guidesList{nullptr};
0335     TimeRemap *m_timeRemapWidget{nullptr};
0336     MixerManager *m_mixerWidget{nullptr};
0337     MediaBrowser *m_mediaBrowser{nullptr};
0338 
0339     /** @brief Current project's profile path */
0340     QString m_currentProfile;
0341 
0342     QString m_profile;
0343     QString m_packageType;
0344     Timecode m_timecode;
0345     Mlt::Profile m_thumbProfile;
0346     /** @brief Mlt profile used in the consumer 's monitors */
0347     Mlt::Profile m_monitorProfile;
0348     /** @brief Mlt profile used to build the project's clips */
0349     Mlt::Profile m_projectProfile;
0350     bool m_guiConstructed = false;
0351     /** @brief Check that the profile is valid (width is a multiple of 8 and height a multiple of 2 */
0352     void checkProfileValidity();
0353     std::unique_ptr<MediaCapture> m_capture;
0354     QUrl m_mediaCaptureFile;
0355     void resetThumbProfile();
0356 
0357 public Q_SLOTS:
0358     /** @brief Trigger (launch) an action by its actionCollection name */
0359     void triggerAction(const QString &name);
0360     /** @brief Get an action's descriptive text by its actionCollection name */
0361     const QString actionText(const QString &name);
0362     /** @brief Add an action to the app's actionCollection */
0363     void addActionToCollection(const QString &name, QAction *action);
0364     /** @brief display a user info/warning message in the project bin */
0365     void displayBinMessage(const QString &text, int type, const QList<QAction *> &actions = QList<QAction *>(), bool showClose = false, BinMessage::BinCategory messageCategory = BinMessage::BinCategory::NoMessage);
0366     void displayBinLogMessage(const QString &text, int type, const QString logInfo);
0367     /** @brief Create small thumbnails for luma used in compositions */
0368     void buildLumaThumbs(const QStringList &values);
0369     /** @brief Try to find a display name for the given filename.
0370      *  This is especially helpful for mlt's dynamically created luma files without thumb (luma01.pgm, luma02.pgm,...),
0371      *  but also for others as it makes the visible name translatable.
0372      *  @return The name that fits to the filename or if none is found the filename it self
0373      */
0374     const QString nameForLumaFile(const QString &filename);
0375     /** @brief Set current project modified. */
0376     void setDocumentModified();
0377     /** @brief Show currently selected effect zone in timeline ruler. */
0378     void showEffectZone(ObjectId id, QPair <int, int>inOut, bool checked);
0379     void updateMasterZones();
0380     /** @brief Open the proxies test dialog. */
0381     void testProxies();
0382     /** @brief Refresh the monitor profile when project profile changes. */
0383     void updateMonitorProfile();
0384     /** @brief Add a new Bin Widget. */
0385     void addBin(const QString &id = QString());
0386     /** @brief Transcode a bin clip video. */
0387     void transcodeFriendlyFile(const QString &binId, bool checkProfile);
0388     /** @brief Reset audio  monitoring volume and channels. */
0389     void resetAudioMonitoring();
0390     /** @brief Start audio recording (after countdown). */
0391     void startRecording();
0392     /** @brief Show or hide track head audio rec controls. */
0393     void monitorAudio(int tid, bool monitor);
0394 
0395 Q_SIGNALS:
0396     void coreIsReady();
0397     void updateLibraryPath();
0398     //void updateMonitorProfile();
0399     /** @brief Call config dialog on a selected page / tab */
0400     void showConfigDialog(Kdenlive::ConfigPage, int);
0401     void finalizeRecording(const QString &captureFile);
0402     void autoScrollChanged();
0403     /** @brief Update the message about the current loading progress */
0404     void loadingMessageNewStage(const QString &message, int max = -1);
0405     /** @brief Increase the progress of the loading message by 1 */
0406     void loadingMessageIncrease();
0407     /** @brief Hide the message about the loading progress */
0408     void loadingMessageHide();
0409     /** @brief Opening finished, close splash screen */
0410     void closeSplash();
0411     /** @brief Trigger an update of the speech models list */
0412     void voskModelUpdate(const QStringList models);
0413     /** @brief Update current effect zone */
0414     void updateEffectZone(const QPoint p, bool withUndo);
0415     /** @brief The effect stask is about to be deleted, disconnect everything */
0416     void disconnectEffectStack();
0417     /** @brief Add a time remap effect to clip and show keyframes dialog */
0418     void remapClip(int cid);
0419     /** @brief A monitor property changed, check if we need to reset */
0420     void monitorProfileUpdated();
0421     /** @brief Color theme changed, process refresh */
0422     void updatePalette();
0423     /** @brief Emitted when a clip is resized (to handle clip monitor inserted zones) */
0424     void clipInstanceResized(const QString &binId);
0425     /** @brief Contains the project audio levels */
0426     void audioLevelsAvailable(const QVector<double>& levels);
0427     /** @brief A frame was displayed in monitor, update audio mixer */
0428     void updateMixerLevels(int pos);
0429     /** @brief Audio recording was started or stopped*/
0430     void switchTimelineRecord(bool on);
0431     /** @brief Launch audio recording on track tid*/
0432     void recordAudio(int tid, bool record);
0433     /** @brief Inform widgets that the project profile (and possibly fps) changed */
0434     void updateProjectTimecode();
0435     /** @brief Visible guide categories changed, reload snaps in timeline */
0436     void refreshActiveGuides();
0437     /** @brief The default marker category was changed, update guides list button */
0438     void updateDefaultMarkerCategory();
0439     /** @brief The default speech engine was changed */
0440     void speechEngineChanged();
0441     /** @brief Auto fit track height property changed, adjust size */
0442     void autoTrackHeight(bool);
0443     /** @brief The number of missing clips in the project changed, inform user when rendering */
0444     void gotMissingClipsCount(int total, int used);
0445     /** @brief Tell the current progress task to stop */
0446     void stopProgressTask();
0447     /** @brief A project clip was deleted */
0448     void binClipDeleted(int cid);
0449 };