File indexing completed on 2024-04-28 08:44:05

0001 /*
0002 SPDX-FileCopyrightText: 2012 Till Theato <root@ttill.de>
0003 SPDX-FileCopyrightText: 2014 Jean-Baptiste Mardelle <jb@kdenlive.org>
0004 This file is part of Kdenlive. See www.kdenlive.org.
0005 
0006 SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0007 */
0008 
0009 #pragma once
0010 
0011 #include "definitions.h"
0012 #include "undohelper.hpp"
0013 
0014 #include <QDateTime>
0015 #include <QDir>
0016 #include <QMutex>
0017 #include <QString>
0018 #include <QReadWriteLock>
0019 #include <memory>
0020 #include <mlt++/Mlt.h>
0021 
0022 class QPixmap;
0023 class Bin;
0024 class AudioStreamInfo;
0025 class EffectStackModel;
0026 class MarkerListModel;
0027 class MarkerSortModel;
0028 
0029 /** @class ClipController
0030  *  @brief Provides a convenience wrapper around the project Bin clip producers.
0031  *  It also holds a QList of track producers for the 'master' producer in case we
0032  *  need to update or replace them
0033  */
0034 class ClipController
0035 {
0036 public:
0037     friend class Bin;
0038     /**
0039      * @brief Constructor.
0040      The constructor is protected because you should call the static Construct instead
0041      * @param bincontroller reference to the bincontroller
0042      * @param producer producer to create reference to
0043      */
0044     explicit ClipController(const QString &id, const std::shared_ptr<Mlt::Producer> &producer = nullptr);
0045 
0046 public:
0047     virtual ~ClipController();
0048 
0049     QMutex producerMutex;
0050 
0051     /** @brief Returns true if the master producer is valid */
0052     bool isValid();
0053 
0054     /** @brief Returns true if the source file exists */
0055     bool sourceExists() const;
0056 
0057     /** @brief Stores the file's creation time */
0058     QDateTime date;
0059 
0060     /** @brief Replaces the master producer and (TODO) the track producers with an updated producer, for example a proxy */
0061     void updateProducer(const std::shared_ptr<Mlt::Producer> &producer);
0062     static const QString producerXml(Mlt::Producer producer, bool includeMeta, bool includeProfile);
0063 
0064     void getProducerXML(QDomDocument &document, bool includeMeta = false, bool includeProfile = true);
0065 
0066     /** @brief Returns a clone of our master producer. Delete after use! */
0067     Mlt::Producer *masterProducer();
0068 
0069     /** @brief Returns the clip's MLT resource */
0070     const QString clipUrl() const;
0071 
0072     /** @brief Returns the clip's type as defined in definitions.h */
0073     ClipType::ProducerType clipType() const;
0074 
0075     /** @brief Returns the MLT's producer id */
0076     const QString binId() const;
0077 
0078     /** @brief Returns this clip's producer. */
0079     virtual std::unique_ptr<Mlt::Producer> getThumbProducer() = 0;
0080 
0081     virtual void reloadProducer(bool refreshOnly = false, bool isProxy = false, bool forceAudioReload = false) = 0;
0082 
0083     /** @brief Rename an audio stream. */
0084     virtual void renameAudioStream(int id, const QString &name) = 0;
0085 
0086     /** @brief Add an audio effect on a specific audio stream for this clip. */
0087     virtual void requestAddStreamEffect(int streamIndex, const QString effectName) = 0;
0088     /** @brief Remove an audio effect on a specific audio stream for this clip. */
0089     virtual void requestRemoveStreamEffect(int streamIndex, const QString effectName) = 0;
0090     virtual QStringList getAudioStreamEffect(int streamIndex) const = 0;
0091 
0092     /** @brief Returns the clip's duration */
0093     GenTime getPlaytime() const;
0094     int getFramePlaytime() const;
0095     /**
0096      * @brief Sets a property.
0097      * @param name name of the property
0098      * @param value the new value
0099      */
0100     void setProducerProperty(const QString &name, const QString &value);
0101     void setProducerProperty(const QString &name, int value);
0102     void setProducerProperty(const QString &name, double value);
0103     /** @brief Reset a property on the MLT producer (=delete the property). */
0104     void resetProducerProperty(const QString &name);
0105 
0106     /**
0107      * @brief Returns the list of all properties starting with prefix. For subclips, the list is of this type:
0108      * { subclip name , subclip in/out } where the subclip in/ou value is a semi-colon separated in/out value, like "25;220"
0109      */
0110     QMap<QString, QString> getPropertiesFromPrefix(const QString &prefix, bool withPrefix = false);
0111 
0112     /**
0113      * @brief Returns the value of a property.
0114      * @param name name o the property
0115      */
0116     QMap<QString, QString> currentProperties(const QMap<QString, QString> &props);
0117     bool hasProducerProperty(const QString &name) const;
0118     QString getProducerProperty(const QString &key) const;
0119     int getProducerIntProperty(const QString &key) const;
0120     qint64 getProducerInt64Property(const QString &key) const;
0121     QColor getProducerColorProperty(const QString &key) const;
0122     double getProducerDoubleProperty(const QString &key) const;
0123 
0124     double originalFps() const;
0125     QString videoCodecProperty(const QString &property) const;
0126     const QString codec(bool audioCodec) const;
0127     const QString getClipHash() const;
0128     const QSize getFrameSize() const;
0129     /** @brief Returns the clip duration as a string like 00:00:02:01. */
0130     const QString getStringDuration();
0131     int getProducerDuration() const;
0132     char *framesToTime(int frames) const;
0133 
0134     /** @brief Returns the MLT producer's service. */
0135     QString serviceName() const;
0136 
0137     /** @brief Returns the original master producer. */
0138     std::shared_ptr<Mlt::Producer> originalProducer();
0139 
0140     /** @brief Holds index of currently selected master clip effect. */
0141     int selectedEffectIndex;
0142 
0143     /** @brief Sets the master producer for this clip when we build the controller without master clip. */
0144     void addMasterProducer(const std::shared_ptr<Mlt::Producer> &producer);
0145 
0146     /** @brief Returns the marker model associated with this clip */
0147     std::shared_ptr<MarkerListModel> getMarkerModel() const;
0148     std::shared_ptr<MarkerSortModel> getFilteredMarkerModel() const;
0149 
0150     void setZone(const QPoint &zone);
0151     bool hasLimitedDuration() const;
0152     void forceLimitedDuration();
0153     Mlt::Properties &properties();
0154     void mirrorOriginalProperties(std::shared_ptr<Mlt::Properties> props);
0155     bool copyEffect(const std::shared_ptr<EffectStackModel> &stackModel, int rowId);
0156     /** @brief Returns true if the bin clip has effects */
0157     bool hasEffects() const;
0158     /** @brief Returns true if the clip contains at least one audio stream */
0159     bool hasAudio() const;
0160     /** @brief Returns true if the clip contains at least one video stream */
0161     bool hasVideo() const;
0162     /** @brief Returns the default state a clip should be in. If the clips contains both video and audio, this defaults to video */
0163     PlaylistState::ClipState defaultState() const;
0164     /** @brief Returns info about clip audio */
0165     const std::unique_ptr<AudioStreamInfo> &audioInfo() const;
0166     /** @brief Returns true if audio thumbnails for this clip are cached */
0167     bool m_audioThumbCreated;
0168     /** @brief When replacing a producer, it is important that we keep some properties, for example force_ stuff and url for proxies
0169      * this method returns a list of properties that we want to keep when replacing a producer . */
0170     static const char *getPassPropertiesList(bool passLength = true);
0171     /** @brief Disable all Kdenlive effects on this clip */
0172     void setBinEffectsEnabled(bool enabled);
0173     /** @brief Returns the number of Kdenlive added effects for this bin clip */
0174     int effectsCount();
0175     /** @brief Returns all urls of external files used by effects on this bin clip (e.g. LUTs)*/
0176     QStringList filesUsedByEffects();
0177 
0178     /** @brief This is the producer that serves as a placeholder while a clip is being loaded. It is created in Core at startup */
0179     static std::shared_ptr<Mlt::Producer> mediaUnavailable;
0180 
0181     /** @brief Returns a ptr to the effetstack associated with this element */
0182     std::shared_ptr<EffectStackModel> getEffectStack() const;
0183 
0184     /** @brief Append an effect to this producer's effect list */
0185     bool addEffect(const QString &effectId, stringMap params = {});
0186 
0187     /** @brief Returns the list of all audio streams indexes for this clip */
0188     QMap <int, QString> audioStreams() const;
0189     /** @brief Returns the absolute audio stream index (usable for MLT's astream property) */
0190     int audioStreamIndex(int stream) const;
0191     /** @brief Returns the number of channels per audio stream. */
0192     QList <int> activeStreamChannels() const;
0193     /** @brief Returns the list of active audio streams indexes for this clip */
0194     QMap <int, QString> activeStreams() const;
0195     /** @brief Returns the list of active audio streams ffmpeg indexes for this clip */
0196     QVector<int> activeFfmpegStreams() const;
0197     /** @brief Returns the count of audio streams for this clip */
0198     int audioStreamsCount() const;
0199     /** @brief Get the path to the original clip url (in case it is proxied) */
0200     const QString getOriginalUrl();
0201     /** @brief Returns true if we are using a proxy for this clip. */
0202     bool hasProxy() const;
0203     /** @brief Delete or re-assign all markers in a category. */
0204     bool removeMarkerCategories(QList<int> toRemove, const QMap<int, int> remapCategories, Fun &undo, Fun &redo);
0205     // This is the helper function that checks if the clip has audio and video and stores the result
0206     void checkAudioVideo();
0207     bool isFullRange() const;
0208 
0209 protected:
0210     /** @brief Mutex to protect the producer properties on read/write */
0211     mutable QReadWriteLock m_producerLock;
0212     virtual void connectEffectStack(){};
0213 
0214     // Update audio stream info
0215     void refreshAudioInfo();
0216     void backupOriginalProperties();
0217     void clearBackupProperties();
0218 
0219     std::shared_ptr<Mlt::Producer> m_masterProducer;
0220     Mlt::Properties *m_properties;
0221     bool m_usesProxy;
0222     std::unique_ptr<AudioStreamInfo> m_audioInfo;
0223     QString m_service;
0224     QString m_path;
0225     int m_videoIndex;
0226     ClipType::ProducerType m_clipType;
0227     bool m_forceLimitedDuration;
0228     bool m_hasMultipleVideoStreams;
0229     QMutex m_effectMutex;
0230     void getInfoForProducer();
0231     // void rebuildEffectList(ProfileInfo info);
0232     std::shared_ptr<EffectStackModel> m_effectStack;
0233     std::shared_ptr<MarkerListModel> m_markerModel;
0234     std::shared_ptr<MarkerSortModel> m_markerFilterModel;
0235     bool m_hasAudio;
0236     bool m_hasVideo;
0237     QMap<int, QStringList> m_streamEffects;
0238     /** @brief Store clip url temporarily while the clip controller has not been created. */
0239     QString m_temporaryUrl;
0240 
0241 private:
0242     /** @brief Temporarily store clip properties until producer is available */
0243     QMap <QString, QVariant> m_tempProps;
0244     QString m_controllerBinId;
0245     /** @brief Build the audio info object */
0246     void buildAudioInfo(int audioIndex);
0247 };