Fix clip proxying

parent 7c558827
......@@ -2127,12 +2127,11 @@ void Bin::slotRemoveInvalidClip(const QString &id, bool replace, const QString &
emit requesteInvalidRemoval(id, clip->url(), errorMessage);
}
void Bin::slotProducerReady(const requestClipInfo &info, ClipController *controller)
void Bin::slotProducerReady(const requestClipInfo &info, std::shared_ptr<Mlt::Producer> producer)
{
// TODO this function should receive a bare producer
std::shared_ptr<ProjectClip> clip = m_itemModel->getClipByBinID(info.clipId);
if (clip) {
if (clip->setProducer(controller->originalProducer(), info.replaceProducer) && !clip->hasProxy()) {
if (producer != nullptr && clip->setProducer(producer, info.replaceProducer) && !clip->hasProxy()) {
emit producerReady(info.clipId);
// Check for file modifications
ClipType t = clip->clipType();
......@@ -2178,7 +2177,7 @@ void Bin::slotProducerReady(const requestClipInfo &info, ClipController *control
}
} else {
// Clip not found, create it
QString groupId = controller->getProducerProperty(QStringLiteral("kdenlive:folderid"));
QString groupId = producer->get("kdenlive:folderid");
std::shared_ptr<ProjectFolder> parentFolder;
if (!groupId.isEmpty() && groupId != QLatin1String("-1")) {
parentFolder = m_itemModel->getFolderByBinId(groupId);
......@@ -2193,7 +2192,7 @@ void Bin::slotProducerReady(const requestClipInfo &info, ClipController *control
parentFolder = m_itemModel->getRootFolder();
}
// TODO at this point, we shouldn't have a controller, but rather a bare producer
std::shared_ptr<ProjectClip> newClip = ProjectClip::construct(info.clipId, m_blankThumb, m_itemModel, controller->originalProducer());
std::shared_ptr<ProjectClip> newClip = ProjectClip::construct(info.clipId, m_blankThumb, m_itemModel, producer);
parentFolder->appendChild(newClip);
emit producerReady(info.clipId);
ClipType t = newClip->clipType();
......
......@@ -383,7 +383,7 @@ public slots:
* @param id the clip id
* @param controller The Controller for this clip
*/
void slotProducerReady(const requestClipInfo &info, ClipController *controller);
void slotProducerReady(const requestClipInfo &info, std::shared_ptr<Mlt::Producer> producer);
void slotRemoveInvalidClip(const QString &id, bool replace, const QString &errorMessage);
/** @brief Create a folder when opening a document */
void slotLoadFolders(const QMap<QString, QString> &foldersData);
......
......@@ -74,6 +74,7 @@ ProjectClip::ProjectClip(const QString &id, const QIcon &thumb, std::shared_ptr<
hash();
connect(this, &ProjectClip::updateJobStatus, this, &ProjectClip::setJobStatus);
connect(this, &ProjectClip::updateThumbProgress, model.get(), &ProjectItemModel::updateThumbProgress);
connect(pCore->binController().get(), &BinController::prepareTimelineReplacement, this, &ProjectClip::prepareTimelineReplacement, Qt::DirectConnection);
}
// static
......@@ -115,6 +116,7 @@ ProjectClip::ProjectClip(const QDomElement &description, const QIcon &thumb, std
connect(this, &ProjectClip::updateJobStatus, this, &ProjectClip::setJobStatus);
connect(this, &ProjectClip::updateThumbProgress, model.get(), &ProjectItemModel::updateThumbProgress);
m_markerModel = std::make_shared<MarkerListModel>(m_binId, pCore->projectManager()->current()->commandStack());
connect(pCore->binController().get(), &BinController::prepareTimelineReplacement, this, &ProjectClip::prepareTimelineReplacement, Qt::DirectConnection);
}
std::shared_ptr<ProjectClip> ProjectClip::construct(const QDomElement &description, const QIcon &thumb, std::shared_ptr<ProjectItemModel> model)
......@@ -339,7 +341,9 @@ bool ProjectClip::setProducer(std::shared_ptr<Mlt::Producer> producer, bool repl
if (!hasProxy()) {
if (auto ptr = m_model.lock()) emit std::static_pointer_cast<ProjectItemModel>(ptr)->refreshPanel(m_binId);
}
if (auto ptr = m_model.lock()) std::static_pointer_cast<ProjectItemModel>(ptr)->onItemUpdated(std::static_pointer_cast<ProjectClip>(shared_from_this()));
if (auto ptr = m_model.lock()) {
std::static_pointer_cast<ProjectItemModel>(ptr)->onItemUpdated(std::static_pointer_cast<ProjectClip>(shared_from_this()));
}
// Make sure we have a hash for this clip
getFileHash();
createAudioThumbs();
......@@ -608,11 +612,6 @@ bool ProjectClip::matches(const QString &condition)
return true;
}
const QString ProjectClip::codec(bool audioCodec) const
{
return codec(audioCodec);
}
bool ProjectClip::rename(const QString &name, int column)
{
QMap<QString, QString> newProperites;
......@@ -1290,3 +1289,17 @@ bool ProjectClip::isIncludedInTimeline()
{
return m_registeredClips.size() > 0;
}
void ProjectClip::prepareTimelineReplacement(const QString &id)
{
if (id == AbstractProjectItem::clipId()) {
for (const auto &clip : m_registeredClips) {
if (auto timeline = clip.second.lock()) {
timeline->requestClipReload(clip.first);
} else {
qDebug() << "Error while reloading clip: timeline unavailable";
Q_ASSERT(false);
}
}
}
}
......@@ -168,10 +168,6 @@ public:
void setWaitingStatus(const QString &id);
/** @brief Returns true if the clip matched a condition, for example vcodec=mpeg1video. */
bool matches(const QString &condition);
/** @brief Returns true if the clip's video codec is equal to @param codec.
* @param audioCodec set to true if you want to check audio codec. When false, this will check the video codec
*/
const QString codec(bool audioCodec) const;
void addClipMarker(QList<CommentedTime> newMarkers, QUndoCommand *groupCommand);
bool deleteClipMarkers(QUndoCommand *groupCommand);
......@@ -253,6 +249,7 @@ private:
private slots:
void updateFfmpegProgress();
void prepareTimelineReplacement(const QString &id);
signals:
void gotAudioData();
......
......@@ -74,6 +74,7 @@ void Core::build(const QString &MltPath)
qRegisterMetaType<stringMap>("stringMap");
qRegisterMetaType<audioByteArray>("audioByteArray");
qRegisterMetaType<QList<ItemInfo>>("QList<ItemInfo>");
qRegisterMetaType<std::shared_ptr<Mlt::Producer>>("std::shared_ptr<Mlt::Producer>");
qRegisterMetaType<QVector<int>>();
qRegisterMetaType<QDomElement>("QDomElement");
qRegisterMetaType<requestClipInfo>("requestClipInfo");
......@@ -159,8 +160,7 @@ void Core::initGUI(const QUrl &Url)
m_monitorManager = new MonitorManager(this);
// Producer queue, creating MLT::Producers on request
m_producerQueue = new ProducerQueue(m_binController);
connect(m_producerQueue, SIGNAL(gotFileProperties(requestClipInfo, ClipController *)), m_binWidget,
SLOT(slotProducerReady(requestClipInfo, ClipController *)), Qt::DirectConnection);
connect(m_producerQueue, &ProducerQueue::gotFileProperties, m_binWidget, &Bin::slotProducerReady, Qt::DirectConnection);
connect(m_producerQueue, &ProducerQueue::replyGetImage, m_binWidget, &Bin::slotThumbnailReady);
connect(m_producerQueue, &ProducerQueue::removeInvalidClip, m_binWidget, &Bin::slotRemoveInvalidClip, Qt::DirectConnection);
connect(m_producerQueue, SIGNAL(addClip(QString, QMap<QString, QString>)), m_binWidget, SLOT(slotAddUrl(QString, QMap<QString, QString>)));
......
......@@ -40,6 +40,15 @@ std::shared_ptr<EffectStackModel> EffectStackModel::construct(std::weak_ptr<Mlt:
return self;
}
void EffectStackModel::resetService(std::weak_ptr<Mlt::Service> service)
{
m_service = std::move(service);
// replant all effects in new service
for (int i = 0; i < rootItem->childCount(); ++i) {
std::static_pointer_cast<EffectItemModel>(rootItem->child(i))->plant(m_service);
}
}
void EffectStackModel::removeEffect(std::shared_ptr<EffectItemModel> effect)
{
int cid = effect->getParentId();
......@@ -177,7 +186,8 @@ void EffectStackModel::importEffects(int cid, std::shared_ptr<EffectStackModel>s
auto clone = EffectItemModel::construct(effect->getAssetId(), shared_from_this());
rootItem->appendChild(clone);
clone->setParameters(effect->getAllParameters());
Fun redo = addEffect_lambda(clone, cid, true);
bool isAudioEffect = EffectsRepository::get()->getType(effect->getAssetId()) == EffectType::Audio;
Fun redo = addEffect_lambda(clone, cid, isAudioEffect);
redo();
}
}
......
......@@ -43,6 +43,7 @@ public:
/* @brief Constructs an effect stack and returns a shared ptr to the constucted object
@param service is the mlt object on which we will plant the effects */
static std::shared_ptr<EffectStackModel> construct(std::weak_ptr<Mlt::Service> service);
void resetService(std::weak_ptr<Mlt::Service> service);
protected:
EffectStackModel(std::weak_ptr<Mlt::Service> service);
......
......@@ -887,9 +887,6 @@ void MainWindow::slotConnectMonitors()
{
// connect(m_projectList, SIGNAL(deleteProjectClips(QStringList,QMap<QString,QString>)), this,
// SLOT(slotDeleteProjectClips(QStringList,QMap<QString,QString>)));
connect(m_projectMonitor->render, SIGNAL(gotFileProperties(requestClipInfo, ClipController *)), pCore->bin(),
SLOT(slotProducerReady(requestClipInfo, ClipController *)), Qt::DirectConnection);
connect(m_clipMonitor, &Monitor::refreshClipThumbnail, pCore->bin(), &Bin::slotRefreshClipThumbnail);
connect(m_projectMonitor, &Monitor::requestFrameForAnalysis, this, &MainWindow::slotMonitorRequestRenderFrame);
connect(m_projectMonitor, &Monitor::createSplitOverlay, this, &MainWindow::createSplitOverlay);
......@@ -3639,7 +3636,7 @@ void MainWindow::slotSwitchMonitors()
{
pCore->monitorManager()->slotSwitchMonitors(!m_clipMonitor->isActive());
if (m_projectMonitor->isActive()) {
pCore->projectManager()->currentTimeline()->projectView()->setFocus();
m_timelineTabs->getCurrentTimeline()->setFocus();
} else {
pCore->bin()->focusBinView();
}
......
......@@ -273,7 +273,6 @@ void BinController::replaceProducer(const QString &id, const std::shared_ptr<Mlt
pasteEffects(id, producer);
ctrl->updateProducer(producer);
replaceBinPlaylistClip(id, producer);
emit prepareTimelineReplacement(id);
producer->set("id", id.toUtf8().constData());
// Remove video only producer
QString videoId = id + QStringLiteral("_video");
......@@ -281,7 +280,8 @@ void BinController::replaceProducer(const QString &id, const std::shared_ptr<Mlt
m_extraClipList.remove(videoId);
}
removeBinPlaylistClip("#" + id);
emit replaceTimelineProducer(id);
emit prepareTimelineReplacement(id);
//emit replaceTimelineProducer(id);
}
void BinController::addClipToBin(const QString &id, const std::shared_ptr<ClipController> &controller) // Mlt::Producer &producer)
......
......@@ -135,7 +135,6 @@ public:
/** @brief Get the list of ids whose clip have the resource indicated by @param url */
const QStringList getBinIdsByResource(const QFileInfo &url) const;
void replaceProducer(const QString &id, const std::shared_ptr<Mlt::Producer> &producer);
void storeMarker(const QString &markerId, const QString &markerHash);
QMap<double, QString> takeGuidesData();
......@@ -172,6 +171,7 @@ public:
public slots:
/** @brief Stored a Bin Folder id / name to MLT's bin playlist. Using an empry folderName deletes the property */
void slotStoreFolder(const QString &folderId, const QString &parentId, const QString &oldParentId, const QString &folderName);
void replaceProducer(const QString &id, const std::shared_ptr<Mlt::Producer> &producer);
private:
/** @brief The MLT playlist holding our Producers */
......
......@@ -121,8 +121,8 @@ void ClipController::addMasterProducer(const std::shared_ptr<Mlt::Producer> &pro
} else {
qDebug() << "Error: impossible to add master producer because bincontroller is not available";
}
m_properties = new Mlt::Properties(producer->get_properties());
m_masterProducer = producer;
m_properties = new Mlt::Properties(m_masterProducer->get_properties());
if (!m_masterProducer->is_valid()) {
m_masterProducer = ClipController::mediaUnavailable;
m_producerLock.unlock();
......@@ -277,7 +277,6 @@ void ClipController::updateProducer(const std::shared_ptr<Mlt::Producer> &produc
// producer has not been initialized
return addMasterProducer(producer);
}
Mlt::Properties passProperties;
// Keep track of necessary properties
QString proxy = producer->get("kdenlive:proxy");
......@@ -289,10 +288,11 @@ void ClipController::updateProducer(const std::shared_ptr<Mlt::Producer> &produc
}
passProperties.pass_list(*m_properties, getPassPropertiesList(m_usesProxy));
delete m_properties;
m_masterProducer = producer;
m_properties = new Mlt::Properties(producer->get_properties());
*m_masterProducer = producer.get();
m_properties = new Mlt::Properties(m_masterProducer->get_properties());
// Pass properties from previous producer
m_properties->pass_list(passProperties, getPassPropertiesList(m_usesProxy));
m_producerLock.unlock();
if (!m_masterProducer->is_valid()) {
qCDebug(KDENLIVE_LOG) << "// WARNING, USING INVALID PRODUCER";
} else {
......@@ -303,6 +303,7 @@ void ClipController::updateProducer(const std::shared_ptr<Mlt::Producer> &produc
}
*/
}
qDebug()<<"// replace finished: "<<clipId()<<" : "<<m_masterProducer->get("resource");
}
Mlt::Producer *ClipController::getTrackProducer(const QString &trackName, PlaylistState::ClipState clipState, double speed)
......
......@@ -511,8 +511,7 @@ void ProducerQueue::processFileProperties()
producer->set(name.toUtf8().constData(), e.firstChild().nodeValue().toUtf8().constData());
}
}
m_binController->replaceProducer(info.clipId, producer);
emit gotFileProperties(info, nullptr);
QMetaObject::invokeMethod(m_binController.get(), "replaceProducer", Qt::QueuedConnection, Q_ARG(const QString&, info.clipId), Q_ARG(const std::shared_ptr<Mlt::Producer>&, producer));
continue;
}
// We are not replacing an existing producer, so set the id
......@@ -836,7 +835,7 @@ void ProducerQueue::processFileProperties()
} else {
// Create the controller
std::shared_ptr<ClipController> controller = ClipController::construct(m_binController, producer);
emit gotFileProperties(info, controller.get());
emit gotFileProperties(info, producer);
}
m_processingClipId.removeAll(info.clipId);
}
......
......@@ -88,7 +88,7 @@ private slots:
signals:
/** @brief The renderer received a reply to a getFileProperties request. */
void gotFileProperties(requestClipInfo, ClipController *);
void gotFileProperties(const requestClipInfo &, std::shared_ptr<Mlt::Producer> producer);
/** @brief The renderer received a reply to a getImage request. */
void replyGetImage(const QString &, const QImage &, bool fromFile = false);
......
......@@ -56,7 +56,8 @@ bool constructTimelineFromMelt(const std::shared_ptr<TimelineItemModel> &timelin
info.imageHeight = 0;
info.clipId = id;
info.replaceProducer = true;
pCore->bin()->slotProducerReady(info, pCore->binController()->getController(id).get());
std::shared_ptr<Mlt::Producer> prod(pCore->binController()->getController(id).get()->originalProducer());
pCore->bin()->slotProducerReady(info, prod);
}
QSet<QString> reserved_names{QLatin1String("playlistmain"), QLatin1String("timeline_preview"), QLatin1String("overlay_track"),
QLatin1String("black_track")};
......@@ -97,7 +98,7 @@ bool constructTimelineFromMelt(const std::shared_ptr<TimelineItemModel> &timelin
int audioTrack = local_playlist.get_int("kdenlive:audio_track");
if (audioTrack == 1) {
// This is an audio track
timeline->setTrackProperty(tid, QStringLiteral("kdenlive:audio_track"), QStringLiteral("1"));
timeline->setTrackProperty(tid, QStringLiteral(""), QStringLiteral("1"));
}
break;
}
......
......@@ -227,6 +227,8 @@ void ClipModel::refreshProducerFromBin()
std::shared_ptr<ProjectClip> binClip = pCore->bin()->getBinClip(m_binClipId);
std::shared_ptr<Mlt::Producer> originalProducer = binClip->originalProducer();
m_producer.reset(originalProducer->cut(in, out));
// replant effect stack in updated service
m_effectStack->resetService(m_producer);
m_producer->set("kdenlive:id", binClip->AbstractProjectItem::clipId().toUtf8().constData());
m_producer->set("_kdenlive_cid", m_id);
m_endlessResize = !binClip->hasLimitedDuration();
......
......@@ -520,7 +520,6 @@ bool TimelineModel::requestClipDeletion(int clipId, Fun &undo, Fun &redo)
// We capture a shared_ptr to the clip, which means that as long as this undo object lives, the clip object is not deleted. To insert it back it is
// sufficient to register it.
registerClip(clip);
//clip->refreshProducerFromBin();
return true;
};
if (operation()) {
......@@ -1597,3 +1596,19 @@ void TimelineModel::adjustAssetRange(int clipId, int in, int out)
{
pCore->adjustAssetRange(clipId, in, out);
}
void TimelineModel::requestClipReload(int clipId)
{
std::function<bool(void)> local_undo = []() { return true; };
std::function<bool(void)> local_redo = []() { return true; };
m_allClips[clipId]->refreshProducerFromBin();
// in order to make the producer change effective, we need to unplant / replant the clip in int track
int old_trackId = getClipTrackId(clipId);
int oldPos = getClipPosition(clipId);
if (old_trackId != -1) {
getTrackById(old_trackId)->requestClipDeletion(clipId, false, local_undo, local_redo);
getTrackById(old_trackId)->requestClipInsertion(clipId, oldPos, false, local_undo, local_redo);
}
}
......@@ -472,6 +472,8 @@ public:
*/
void adjustAssetRange(int clipId, int in, int out);
void requestClipReload(int clipId);
protected:
/* @brief Register a new track. This is a call-back meant to be called from TrackModel
@param pos indicates the number of the track we are adding. If this is -1, then we add at the end.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment