From 56f69242fee94baa6a0ed504b9cc51e0b5eb04ae Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Mardelle Date: Fri, 31 Oct 2008 09:42:09 +0000 Subject: [PATCH] Try to fix audio mixing bug ( http://www.kdenlive.org:80/mantis/view.php?id=228 ) Warning: this is a large commit with important changes. it probably breaks loading of current kdenlive project files, I will fix this if bugs are reported svn path=/branches/KDE4/; revision=2605 --- src/clipmanager.cpp | 3 +- src/clipmanager.h | 2 +- src/customtrackview.cpp | 12 ++-- src/docclipbase.cpp | 102 +++++++++++++++++++++++------- src/docclipbase.h | 6 +- src/kdenlivedoc.cpp | 133 ++++++++++++++++++++++++++++++++++------ src/kdenlivedoc.h | 4 +- src/mainwindow.cpp | 3 +- src/monitor.cpp | 7 +++ src/monitor.h | 1 + src/projectlistview.cpp | 2 +- src/renderer.cpp | 24 ++++++-- src/renderer.h | 4 +- src/trackview.cpp | 4 +- 14 files changed, 244 insertions(+), 63 deletions(-) diff --git a/src/clipmanager.cpp b/src/clipmanager.cpp index ad18f93f..e8bd52ae 100644 --- a/src/clipmanager.cpp +++ b/src/clipmanager.cpp @@ -125,8 +125,9 @@ DocClipBase *ClipManager::getClipAt(int pos) { return m_clipList.at(pos); } -DocClipBase *ClipManager::getClipById(const QString &clipId) { +DocClipBase *ClipManager::getClipById(QString clipId) { //kDebug() << "++++ CLIP MAN, LOOKING FOR CLIP ID: " << clipId; + clipId = clipId.section('_', 0, 0); for (int i = 0; i < m_clipList.count(); i++) { if (m_clipList.at(i)->getId() == clipId) { //kDebug() << "++++ CLIP MAN, FOUND FOR CLIP ID: " << clipId; diff --git a/src/clipmanager.h b/src/clipmanager.h index 3fd66c62..cfa0565a 100644 --- a/src/clipmanager.h +++ b/src/clipmanager.h @@ -53,7 +53,7 @@ Q_OBJECT public: void slotAddTextClipFile(const QString titleName, const QString imagePath, const QString xml, const QString group, const QString &groupId); void slotAddColorClipFile(const QString name, const QString color, QString duration, const QString group, const QString &groupId); void slotAddSlideshowClipFile(const QString name, const QString path, int count, const QString duration, const bool loop, const bool fade, const QString &luma_duration, const QString &luma_file, const int softness, const QString group, const QString &groupId); - DocClipBase *getClipById(const QString &clipId); + DocClipBase *getClipById(QString clipId); void slotDeleteClip(const QString & clipId); void setThumbsProgress(const QString &message, int progress); void checkAudioThumbs(); diff --git a/src/customtrackview.cpp b/src/customtrackview.cpp index ac804748..087477d9 100644 --- a/src/customtrackview.cpp +++ b/src/customtrackview.cpp @@ -1136,7 +1136,7 @@ void CustomTrackView::dropEvent(QDropEvent * event) { m_document->renderer()->mltAddTransition(tr->transitionTag(), endTrack, m_scene->m_tracksList.count() - info.track, info.startPos, info.endPos, tr->toXML()); } info.track = m_scene->m_tracksList.count() - item->track(); - m_document->renderer()->mltInsertClip(info, item->xml(), item->baseClip()->producer()); + m_document->renderer()->mltInsertClip(info, item->xml(), item->baseClip()->producer(item->track())); item->setSelected(true); } m_document->setModified(true); @@ -1277,11 +1277,11 @@ void CustomTrackView::mouseReleaseEvent(QMouseEvent * event) { if (m_selectionGroup == NULL) { // we are moving one clip, easy if (m_dragItem->type() == AVWIDGET && (m_dragItemInfo.startPos != info.startPos || m_dragItemInfo.track != info.track)) { - bool success = m_document->renderer()->mltMoveClip((int)(m_scene->m_tracksList.count() - m_dragItemInfo.track), (int)(m_scene->m_tracksList.count() - m_dragItem->track()), (int) m_dragItemInfo.startPos.frames(m_document->fps()), (int)(m_dragItem->startPos().frames(m_document->fps()))); + ClipItem *item = static_cast (m_dragItem); + bool success = m_document->renderer()->mltMoveClip((int)(m_scene->m_tracksList.count() - m_dragItemInfo.track), (int)(m_scene->m_tracksList.count() - m_dragItem->track()), (int) m_dragItemInfo.startPos.frames(m_document->fps()), (int)(m_dragItem->startPos().frames(m_document->fps())), item->baseClip()->producer(info.track)); if (success) { MoveClipCommand *command = new MoveClipCommand(this, m_dragItemInfo, info, false); m_commandStack->push(command); - ClipItem *item = static_cast (m_dragItem); if (item->baseClip()->isTransparent()) { // Also move automatic transition Transition *tr = getTransitionItemAt((int) m_dragItemInfo.startPos.frames(m_document->fps()) + 1, m_dragItemInfo.track); @@ -1347,7 +1347,7 @@ void CustomTrackView::mouseReleaseEvent(QMouseEvent * event) { ClipItem *clip = static_cast (item); new AddTimelineClipCommand(this, clip->xml(), clip->clipProducer(), info, clip->effectList(), false, false, moveClips); info.track = m_scene->m_tracksList.count() - info.track; - m_document->renderer()->mltInsertClip(info, clip->xml(), clip->baseClip()->producer()); + m_document->renderer()->mltInsertClip(info, clip->xml(), clip->baseClip()->producer(info.track)); } else { Transition *tr = static_cast (item); ItemInfo transitionInfo = tr->info(); @@ -1587,7 +1587,7 @@ void CustomTrackView::addClip(QDomElement xml, const QString &clipId, ItemInfo i baseclip->addReference(); m_document->updateClip(baseclip->getId()); info.track = m_scene->m_tracksList.count() - info.track; - m_document->renderer()->mltInsertClip(info, xml, baseclip->producer()); + m_document->renderer()->mltInsertClip(info, xml, baseclip->producer(info.track)); for (int i = 0; i < item->effectsCount(); i++) { m_document->renderer()->mltAddEffect(info.track, info.startPos, item->getEffectArgs(item->effectAt(i)), false); } @@ -1653,7 +1653,7 @@ void CustomTrackView::moveClip(const ItemInfo start, const ItemInfo end) { } //kDebug() << "----------------  Move CLIP FROM: " << startPos.x() << ", END:" << endPos.x() << ",TRACKS: " << startPos.y() << " TO " << endPos.y(); - bool success = m_document->renderer()->mltMoveClip((int)(m_scene->m_tracksList.count() - start.track), (int)(m_scene->m_tracksList.count() - end.track), (int) start.startPos.frames(m_document->fps()), (int)end.startPos.frames(m_document->fps())); + bool success = m_document->renderer()->mltMoveClip((int)(m_scene->m_tracksList.count() - start.track), (int)(m_scene->m_tracksList.count() - end.track), (int) start.startPos.frames(m_document->fps()), (int)end.startPos.frames(m_document->fps()), item->baseClip()->producer(end.track)); if (success) { item->setPos((int) end.startPos.frames(m_document->fps()), (int)(end.track * m_tracksHeight + 1)); if (item->baseClip()->isTransparent()) { diff --git a/src/docclipbase.cpp b/src/docclipbase.cpp index 40560034..bf26e183 100644 --- a/src/docclipbase.cpp +++ b/src/docclipbase.cpp @@ -23,7 +23,7 @@ #include "clipmanager.h" DocClipBase::DocClipBase(ClipManager *clipManager, QDomElement xml, const QString &id): - m_id(id), m_description(QString()), m_refcount(0), m_audioThumbCreated(false), m_duration(GenTime()), m_thumbProd(NULL), m_audioTimer(NULL), m_clipProducer(NULL), m_properties(QMap ()), audioFrameChache(QMap > ()) { + m_id(id), m_description(QString()), m_refcount(0), m_audioThumbCreated(false), m_duration(GenTime()), m_thumbProd(NULL), m_audioTimer(NULL), m_properties(QMap ()), audioFrameChache(QMap > ()), m_baseTrackProducers(QList ()) { int type = xml.attribute("type").toInt(); m_clipType = (CLIPTYPE) type; m_name = xml.attribute("name"); @@ -64,7 +64,7 @@ DocClipBase::DocClipBase(ClipManager *clipManager, QDomElement xml, const QStrin DocClipBase::~DocClipBase() { if (m_thumbProd) delete m_thumbProd; - if (m_clipProducer) delete m_clipProducer; + qDeleteAll(m_baseTrackProducers); } void DocClipBase::slotCreateAudioTimer() { @@ -120,6 +120,7 @@ const CLIPTYPE & DocClipBase::clipType() const { void DocClipBase::setClipType(CLIPTYPE type) { m_clipType = type; + m_properties.insert("type", QString::number((int) type)); if (m_thumbProd && m_audioTimer == NULL && (m_clipType == AV || m_clipType == AUDIO)) slotCreateAudioTimer(); @@ -366,17 +367,72 @@ QString DocClipBase::markerComment(GenTime t) { void DocClipBase::setProducer(Mlt::Producer *producer) { if (producer == NULL) return; - m_clipProducer = producer; - m_clipProducer->set("transparency", m_properties.value("transparency").toInt()); - if (m_thumbProd) m_thumbProd->setProducer(producer); + QString id = producer->get("id"); + kDebug() << "// SET PRODUCER: " << id; + if (id.contains('_')) { + // this is a subtrack producer, insert it at correct place + int pos = id.section('_', 1, 1).toInt(); + kDebug() << "// POS = " << pos << ", MAX: " << m_baseTrackProducers.count(); + if (pos >= m_baseTrackProducers.count()) { + while (m_baseTrackProducers.count() - 1 < pos) { + m_baseTrackProducers.append(NULL); + } + } + kDebug() << "// POS = " << pos << ", NEW MAX: " << m_baseTrackProducers.count(); + if (m_baseTrackProducers.at(pos) == NULL) m_baseTrackProducers[pos] = producer; + } else m_baseTrackProducers.append(producer); + //m_clipProducer = producer; + //m_clipProducer->set("transparency", m_properties.value("transparency").toInt()); + if (m_thumbProd && !m_thumbProd->hasProducer()) m_thumbProd->setProducer(producer); +} + +Mlt::Producer *DocClipBase::producer(int track) { + if (track == -1 || (m_clipType != AUDIO && m_clipType != AV)) { + if (m_baseTrackProducers.count() == 0) return NULL; + int i; + for (i = 0; i < m_baseTrackProducers.count(); i++) + if (m_baseTrackProducers.at(i) != NULL) break; + if (i < m_baseTrackProducers.count()) return m_baseTrackProducers.at(i); + return NULL; + } + if (track >= m_baseTrackProducers.count()) { + while (m_baseTrackProducers.count() - 1 < track) { + m_baseTrackProducers.append(NULL); + } + } + if (m_baseTrackProducers.at(track) == NULL) { + int i; + for (i = 0; i < m_baseTrackProducers.count(); i++) + if (m_baseTrackProducers.at(i) != NULL) break; + if (i >= m_baseTrackProducers.count()) return NULL; + m_baseTrackProducers[track] = new Mlt::Producer(*m_baseTrackProducers.at(i)->profile(), m_baseTrackProducers.at(i)->get("resource")); + if (m_properties.contains("force_aspect_ratio")) m_baseTrackProducers[track]->set("force_aspect_ratio", m_properties.value("force_aspect_ratio").toDouble()); + if (m_properties.contains("threads")) m_baseTrackProducers[track]->set("threads", m_properties.value("threads").toInt()); + if (m_properties.contains("video_index")) m_baseTrackProducers[track]->set("video_index", m_properties.value("video_index").toInt()); + if (m_properties.contains("audio_index")) m_baseTrackProducers[track]->set("audio_index", m_properties.value("audio_index").toInt()); + char *tmp = (char *) qstrdup(QString(getId() + '_' + QString::number(track)).toUtf8().data()); + m_baseTrackProducers[track]->set("id", tmp); + delete[] tmp; + } + return m_baseTrackProducers.at(track); +} + +void DocClipBase::setProducerProperty(const char *name, int data) { + for (int i = 0; i < m_baseTrackProducers.count(); i++) { + if (m_baseTrackProducers.at(i) != NULL) + m_baseTrackProducers[i]->set(name, data); + } } -Mlt::Producer *DocClipBase::producer() { - return m_clipProducer; +void DocClipBase::setProducerProperty(const char *name, const char *data) { + for (int i = 0; i < m_baseTrackProducers.count(); i++) { + if (m_baseTrackProducers.at(i) != NULL) + m_baseTrackProducers[i]->set(name, data); + } } void DocClipBase::slotRefreshProducer() { - if (m_clipProducer == NULL) return; + if (m_baseTrackProducers.count() == 0) return; kDebug() << "//////////// REFRESH CLIP !!!!!!!!!!!!!!!!"; if (m_clipType == SLIDESHOW) { /*char *tmp = (char *) qstrdup(getProperty("resource").toUtf8().data()); @@ -385,12 +441,12 @@ void DocClipBase::slotRefreshProducer() { delete m_clipProducer; m_clipProducer = new Mlt::Producer(producer.get_producer()); if (!getProperty("out").isEmpty()) m_clipProducer->set_in_and_out(getProperty("in").toInt(), getProperty("out").toInt());*/ - m_clipProducer->set("ttl", getProperty("ttl").toInt()); + setProducerProperty("ttl", getProperty("ttl").toInt()); //m_clipProducer->set("id", getProperty("id")); if (getProperty("fade") == "1") { // we want a fade filter effect kDebug() << "//////////// FADE WANTED"; - Mlt::Service clipService(m_clipProducer->get_service()); + Mlt::Service clipService(m_baseTrackProducers.at(0)->get_service()); int ct = 0; Mlt::Filter *filter = clipService.filter(ct); while (filter) { @@ -414,7 +470,7 @@ void DocClipBase::slotRefreshProducer() { } } else { // filter does not exist, create it... - Mlt::Filter *filter = new Mlt::Filter(*(m_clipProducer->profile()), "luma"); + Mlt::Filter *filter = new Mlt::Filter(*(m_baseTrackProducers.at(0)->profile()), "luma"); filter->set("period", getProperty("ttl").toInt() - 1); filter->set("luma.out", getProperty("luma_duration").toInt()); QString resource = getProperty("luma_file"); @@ -429,7 +485,7 @@ void DocClipBase::slotRefreshProducer() { } } else { kDebug() << "//////////// FADE NOT WANTED!!!"; - Mlt::Service clipService(m_clipProducer->get_service()); + Mlt::Service clipService(m_baseTrackProducers.at(0)->get_service()); int ct = 0; Mlt::Filter *filter = clipService.filter(0); while (filter) { @@ -465,33 +521,33 @@ void DocClipBase::setProperty(const QString &key, const QString &value) { m_properties.insert(key, value); if (key == "resource") m_thumbProd->updateClipUrl(KUrl(value)); else if (key == "out") setDuration(GenTime(value.toInt(), KdenliveSettings::project_fps())); - else if (key == "transparency") m_clipProducer->set("transparency", value.toInt()); + //else if (key == "transparency") m_clipProducer->set("transparency", value.toInt()); else if (key == "colour") { char *tmp = (char *) qstrdup(value.toUtf8().data()); - m_clipProducer->set("colour", tmp); + setProducerProperty("colour", tmp); delete[] tmp; } else if (key == "xmldata") { - m_clipProducer->set("force_reload", 1); + setProducerProperty("force_reload", 1); } else if (key == "force_aspect_ratio") { if (value.isEmpty()) { m_properties.remove("force_aspect_ratio"); - m_clipProducer->set("force_aspect_ratio", 0); - } else m_clipProducer->set("force_aspect_ratio", value.toDouble()); + setProducerProperty("force_aspect_ratio", 0); + } else setProducerProperty("force_aspect_ratio", value.toDouble()); } else if (key == "threads") { if (value.isEmpty()) { m_properties.remove("threads"); - m_clipProducer->set("threads", 1); - } else m_clipProducer->set("threads", value.toInt()); + setProducerProperty("threads", 1); + } else setProducerProperty("threads", value.toInt()); } else if (key == "video_index") { if (value.isEmpty()) { m_properties.remove("video_index"); - m_clipProducer->set("video_index", m_properties.value("default_video").toInt()); - } else m_clipProducer->set("video_index", value.toInt()); + setProducerProperty("video_index", m_properties.value("default_video").toInt()); + } else setProducerProperty("video_index", value.toInt()); } else if (key == "audio_index") { if (value.isEmpty()) { m_properties.remove("audio_index"); - m_clipProducer->set("audio_index", m_properties.value("default_audio").toInt()); - } else m_clipProducer->set("audio_index", value.toInt()); + setProducerProperty("audio_index", m_properties.value("default_audio").toInt()); + } else setProducerProperty("audio_index", value.toInt()); } } diff --git a/src/docclipbase.h b/src/docclipbase.h index 893b325f..cc427b0d 100644 --- a/src/docclipbase.h +++ b/src/docclipbase.h @@ -111,7 +111,7 @@ Q_OBJECT public: } void setProducer(Mlt::Producer *producer); - Mlt::Producer *producer(); + Mlt::Producer *producer(int track = -1); /*virtual DocClipAVFile *toDocClipAVFile() { return 0; @@ -197,7 +197,7 @@ private: // Private attributes /** The number of times this clip is used in the project - the number of references to this clip * that exist. */ uint m_refcount; - Mlt::Producer *m_clipProducer; + QList m_baseTrackProducers; CLIPTYPE m_clipType; /** A list of snap markers; these markers are added to a clips snap-to points, and are displayed as necessary. */ @@ -219,6 +219,8 @@ private: // Private attributes /** Create connections for audio thumbnails */ void slotCreateAudioTimer(); void slotRefreshProducer(); + void setProducerProperty(const char *name, const char *data); + void setProducerProperty(const char *name, int data); public slots: void updateAudioThumbnail(QMap > data); diff --git a/src/kdenlivedoc.cpp b/src/kdenlivedoc.cpp index 59d34d76..db4b3ef3 100644 --- a/src/kdenlivedoc.cpp +++ b/src/kdenlivedoc.cpp @@ -56,10 +56,10 @@ KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, QUndoGroup m_zoom = infoXml.attribute("zoom", "7").toInt(); setProfilePath(profilePath); double version = infoXml.attribute("version").toDouble(); - if (version < 0.7) convertDocument(version); + if (version < 0.8) convertDocument(version); else { //delete all mlt producers and instead, use Kdenlive saved producers - QDomNodeList prods = m_document.elementsByTagName("producer"); + /*QDomNodeList prods = m_document.elementsByTagName("producer"); int maxprod = prods.count(); int pos = 0; for (int i = 0; i < maxprod; i++) { @@ -68,19 +68,22 @@ KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, QUndoGroup if (prodId == "black" || prodId.startsWith("slowmotion")) pos++; else westley.removeChild(m); - } - prods = m_document.elementsByTagName("kdenlive_producer"); + }*/ + /*prods = m_document.elementsByTagName("kdenlive_producer"); maxprod = prods.count(); for (int i = 0; i < maxprod; i++) { prods.at(0).toElement().setTagName("producer"); westley.insertBefore(prods.at(0), QDomNode()); - } + }*/ } QDomElement e; QDomNodeList producers = m_document.elementsByTagName("producer"); + QDomNodeList infoproducers = m_document.elementsByTagName("kdenlive_producer"); const int max = producers.count(); + const int infomax = infoproducers.count(); + if (max > 0) { - m_documentLoadingStep = 100.0 / (max + m_document.elementsByTagName("entry").count()); + m_documentLoadingStep = 100.0 / (max + infomax + m_document.elementsByTagName("entry").count()); parent->slotGotProgressInfo(i18n("Loading project clips"), (int) m_documentLoadingProgress); } @@ -89,11 +92,27 @@ KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, QUndoGroup if (m_documentLoadingStep > 0) { m_documentLoadingProgress += m_documentLoadingStep; parent->slotGotProgressInfo(QString(), (int) m_documentLoadingProgress); - qApp->processEvents(); + //qApp->processEvents(); } QString prodId = e.attribute("id"); if (!e.isNull() && prodId != "black" && !prodId.startsWith("slowmotion")/*&& prodId.toInt() > 0*/) { - addClip(e, prodId); + // addClip(e, prodId, false); + kDebug() << "// PROD: " << prodId; + } + } + + for (int i = 0; i < infomax; i++) { + e = infoproducers.item(i).cloneNode().toElement(); + if (m_documentLoadingStep > 0) { + m_documentLoadingProgress += m_documentLoadingStep; + parent->slotGotProgressInfo(QString(), (int) m_documentLoadingProgress); + //qApp->processEvents(); + } + QString prodId = e.attribute("id"); + if (!e.isNull() && prodId != "black" && !prodId.startsWith("slowmotion")) { + e.setTagName("producer"); + addClipInfo(e, prodId); + kDebug() << "// NLIVE PROD: " << prodId; } } @@ -254,7 +273,9 @@ void KdenliveDoc::slotAutoSave() { kDebug() << "ERROR; CANNOT CREATE AUTOSAVE FILE"; } kDebug() << "// AUTOSAVE FILE: " << m_autosave->fileName(); - m_render->saveSceneList(m_autosave->fileName(), documentInfoXml()); + QDomDocument doc; + doc.setContent(m_render->sceneList()); + saveSceneList(m_autosave->fileName(), doc); } } @@ -268,6 +289,10 @@ int KdenliveDoc::zoom() const { void KdenliveDoc::convertDocument(double version) { // Opening a old Kdenlive document + if (version == 0.7) { + // TODO: convert 0.7 files to the new document format. + return; + } QDomNode westley = m_document.elementsByTagName("westley").at(1); QDomNode tractor = m_document.elementsByTagName("tractor").at(0); QDomNode kdenlivedoc = m_document.elementsByTagName("kdenlivedoc").at(0); @@ -533,6 +558,48 @@ QString KdenliveDoc::colorToString(const QColor& c) { return ret; } +void KdenliveDoc::saveSceneList(const QString &path, QDomDocument sceneList) { + QDomNode wes = sceneList.elementsByTagName("westley").at(0); + + QDomElement addedXml = sceneList.createElement("kdenlivedoc"); + QDomElement markers = sceneList.createElement("markers"); + addedXml.setAttribute("version", "0.8"); + addedXml.setAttribute("profile", profilePath()); + addedXml.setAttribute("position", m_render->seekPosition().frames(m_fps)); + addedXml.setAttribute("zoom", m_zoom); + + QDomElement e; + QList list = m_clipManager->documentClipList(); + for (int i = 0; i < list.count(); i++) { + e = list.at(i)->toXML(); + e.setTagName("kdenlive_producer"); + addedXml.appendChild(sceneList.importNode(e, true)); + QList < CommentedTime > marks = list.at(i)->commentedSnapMarkers(); + for (int j = 0; j < marks.count(); j++) { + QDomElement marker = sceneList.createElement("marker"); + marker.setAttribute("time", marks.at(j).time().ms() / 1000); + marker.setAttribute("comment", marks.at(j).comment()); + marker.setAttribute("id", e.attribute("id")); + markers.appendChild(marker); + } + } + addedXml.appendChild(markers); + if (!m_guidesXml.isNull()) addedXml.appendChild(sceneList.importNode(m_guidesXml, true)); + + wes.appendChild(addedXml); + //wes.appendChild(doc.importNode(kdenliveData, true)); + + QFile file(path); + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { + kWarning() << "////// ERROR writing to file: " << path; + return; + } + QTextStream out(&file); + out << sceneList.toString(); + file.close(); + +} + QDomElement KdenliveDoc::documentInfoXml() { QDomDocument doc; QDomElement e; @@ -620,7 +687,7 @@ void KdenliveDoc::setRenderer(Render *render) { if (m_render) return; m_render = render; emit progressInfo(i18n("Loading playlist..."), 0); - qApp->processEvents(); + //qApp->processEvents(); if (m_render) { m_render->setSceneList(m_document.toString(), m_startPos); checkProjectClips(); @@ -632,12 +699,16 @@ void KdenliveDoc::checkProjectClips() { if (m_render == NULL) return; QList prods = m_render->producersList(); QString id ; + QString prodId ; + QString prodTrack ; for (int i = 0; i < prods.count(); i++) { id = prods.at(i)->get("id"); - DocClipBase *clip = m_clipManager->getClipById(id); - if (clip && clip->producer() == NULL) { - clip->setProducer(prods.at(i)); - } + prodId = id.section('_', 0, 0); + prodTrack = id.section('_', 1, 1); + kDebug() << "CHECK PRO CLIP, ID: " << id; + DocClipBase *clip = m_clipManager->getClipById(prodId); + if (clip) clip->setProducer(prods.at(i)); + kDebug() << "CHECK PRO CLIP, ID: " << id << " DONE"; if (clip && clip->clipType() == TEXT && !QFile::exists(clip->fileURL().path())) { // regenerate text clip image if required kDebug() << "// TITLE: " << clip->getProperty("titlename") << " Preview file: " << clip->getProperty("resource") << " DOES NOT EXIST"; @@ -787,11 +858,35 @@ QString KdenliveDoc::description() const { return m_url.fileName() + " / " + m_profile.description; } -void KdenliveDoc::addClip(const QDomElement &elem, const QString &clipId) { - DocClipBase *clip = new DocClipBase(m_clipManager, elem, clipId); - kDebug() << "///////// DOCUM, CREATING NEW CLIP, ID:" << clipId << ", PAR ID:" << elem.attribute("groupid"); - m_clipManager->addClip(clip); - emit addProjectClip(clip); +void KdenliveDoc::addClip(QDomElement elem, QString clipId, bool createClipItem) { + const QString producerId = clipId.section('_', 0, 0); + int subtrack = clipId.section('_', 1, 1).toInt(); + DocClipBase *clip = m_clipManager->getClipById(producerId); + if (clip == NULL) { + elem.setAttribute("id", producerId); + clip = new DocClipBase(m_clipManager, elem, producerId); + m_clipManager->addClip(clip); + } + if (createClipItem) emit addProjectClip(clip); +} + +void KdenliveDoc::addClipInfo(QDomElement elem, QString clipId) { + DocClipBase *clip = m_clipManager->getClipById(clipId); + if (clip == NULL) { + addClip(elem, clipId); + } else { + QMap properties; + QDomNamedNodeMap attributes = elem.attributes(); + QString attrname; + for (unsigned int i = 0; i < attributes.count(); i++) { + attrname = attributes.item(i).nodeName(); + if (attrname != "resource") + properties.insert(attrname, attributes.item(i).nodeValue()); + kDebug() << attrname << " = " << attributes.item(i).nodeValue(); + } + clip->setProperties(properties); + emit addProjectClip(clip); + } } void KdenliveDoc::addFolder(const QString foldername, const QString &clipId, bool edit) { diff --git a/src/kdenlivedoc.h b/src/kdenlivedoc.h index 5a9d3990..ce1ffafd 100644 --- a/src/kdenlivedoc.h +++ b/src/kdenlivedoc.h @@ -66,7 +66,8 @@ Q_OBJECT public: QDomElement m_guidesXml; QDomElement guidesXml() const; ClipManager *clipManager(); - void addClip(const QDomElement &elem, const QString &clipId); + void addClip(QDomElement elem, QString clipId, bool createClipItem = true); + void addClipInfo(QDomElement elem, QString clipId); void addFolder(const QString foldername, const QString &clipId, bool edit); void deleteFolder(const QString foldername, const QString &clipId); void slotAddClipFile(const KUrl url, const QString group, const QString &groupId = QString()); @@ -104,6 +105,7 @@ Q_OBJECT public: int zoom() const; const double dar(); double projectDuration() const; + void saveSceneList(const QString &path, QDomDocument sceneList); private: KUrl m_url; diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 7e2ed60c..387906a1 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -934,7 +934,8 @@ void MainWindow::closeCurrentDocument() { } void MainWindow::saveFileAs(const QString &outputFileName) { - m_projectMonitor->saveSceneList(outputFileName, m_activeDocument->documentInfoXml()); + QDomDocument currentSceneList = m_projectMonitor->sceneList(); + m_activeDocument->saveSceneList(outputFileName, currentSceneList); m_activeDocument->setUrl(KUrl(outputFileName)); if (m_activeDocument->m_autosave == NULL) { m_activeDocument->m_autosave = new KAutoSaveFile(KUrl(outputFileName), this); diff --git a/src/monitor.cpp b/src/monitor.cpp index 9ad543b5..95d5ec22 100644 --- a/src/monitor.cpp +++ b/src/monitor.cpp @@ -557,6 +557,13 @@ void Monitor::saveSceneList(QString path, QDomElement info) { render->saveSceneList(path, info); } +QDomDocument Monitor::sceneList() { + if (render == NULL) return QDomDocument(); + QDomDocument doc; + doc.setContent(render->sceneList()); + return doc; +} + MonitorRefresh::MonitorRefresh(QWidget* parent): QWidget(parent), m_renderer(NULL) { setAttribute(Qt::WA_PaintOnScreen); setAttribute(Qt::WA_OpaquePaintEvent); //setAttribute(Qt::WA_NoSystemBackground); diff --git a/src/monitor.h b/src/monitor.h index 4d97a4b7..6e989dc9 100644 --- a/src/monitor.h +++ b/src/monitor.h @@ -56,6 +56,7 @@ public: bool isActive() const; void pause(); void setupMenu(QMenu *goMenu); + QDomDocument sceneList(); protected: virtual void mousePressEvent(QMouseEvent * event); diff --git a/src/projectlistview.cpp b/src/projectlistview.cpp index a720b9da..d7de11cc 100644 --- a/src/projectlistview.cpp +++ b/src/projectlistview.cpp @@ -116,7 +116,7 @@ void ProjectListView::mouseDoubleClickEvent(QMouseEvent * event) { if ((columnAt(event->pos().x()) == 1)) QTreeWidget::mouseDoubleClickEvent(event); } else { if ((columnAt(event->pos().x()) == 2)) QTreeWidget::mouseDoubleClickEvent(event); - else emit showProperties(item->referencedClip()); + else emit showProperties(item->referencedClip()); } } diff --git a/src/renderer.cpp b/src/renderer.cpp index 36df5e29..e0ce8c47 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -1943,12 +1943,12 @@ bool Render::mltResizeClipStart(ItemInfo info, GenTime diff) { return true; } -bool Render::mltMoveClip(int startTrack, int endTrack, GenTime moveStart, GenTime moveEnd) { - return mltMoveClip(startTrack, endTrack, (int) moveStart.frames(m_fps), (int) moveEnd.frames(m_fps)); +bool Render::mltMoveClip(int startTrack, int endTrack, GenTime moveStart, GenTime moveEnd, Mlt::Producer *prod) { + return mltMoveClip(startTrack, endTrack, (int) moveStart.frames(m_fps), (int) moveEnd.frames(m_fps), prod); } -bool Render::mltMoveClip(int startTrack, int endTrack, int moveStart, int moveEnd) { +bool Render::mltMoveClip(int startTrack, int endTrack, int moveStart, int moveEnd, Mlt::Producer *prod) { m_isBlocked = true; m_mltConsumer->set("refresh", 0); @@ -1994,7 +1994,23 @@ bool Render::mltMoveClip(int startTrack, int endTrack, int moveStart, int moveEn Mlt::Producer clipProducer(trackPlaylist.replace_with_blank(clipIndex)); trackPlaylist.consolidate_blanks(0); destTrackPlaylist.consolidate_blanks(1); - int newIndex = destTrackPlaylist.insert_at(moveEnd, clipProducer, 1); + Mlt::Producer *clip = prod->cut(clipProducer.get_in(), clipProducer.get_out()); + + // move all effects to the correct producer + Mlt::Service clipService(clipProducer.get_service()); + Mlt::Service newClipService(clip->get_service()); + + int ct = 0; + Mlt::Filter *filter = clipService.filter(ct); + while (filter) { + if (filter->get("kdenlive_ix") != 0) { + clipService.detach(*filter); + newClipService.attach(*filter); + } else ct++; + filter = clipService.filter(ct); + } + + int newIndex = destTrackPlaylist.insert_at(moveEnd, clip, 1); destTrackPlaylist.consolidate_blanks(0); /*if (QString(clipProducer.parent().get("transparency")).toInt() == 1) { kDebug() << "//////// moving clip transparency"; diff --git a/src/renderer.h b/src/renderer.h index 45688b92..1298b441 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -153,8 +153,8 @@ Q_OBJECT public: void mltCutClip(int track, GenTime position); bool mltResizeClipEnd(ItemInfo info, GenTime clipDuration); bool mltResizeClipStart(ItemInfo info, GenTime diff); - bool mltMoveClip(int startTrack, int endTrack, GenTime pos, GenTime moveStart); - bool mltMoveClip(int startTrack, int endTrack, int pos, int moveStart); + bool mltMoveClip(int startTrack, int endTrack, GenTime pos, GenTime moveStart, Mlt::Producer *prod); + bool mltMoveClip(int startTrack, int endTrack, int pos, int moveStart, Mlt::Producer *prod); bool mltRemoveClip(int track, GenTime position); bool mltRemoveEffect(int track, GenTime position, QString index, bool doRefresh = true); bool mltAddEffect(int track, GenTime position, QHash args, bool doRefresh = true); diff --git a/src/trackview.cpp b/src/trackview.cpp index de5eb9bd..43187610 100644 --- a/src/trackview.cpp +++ b/src/trackview.cpp @@ -201,7 +201,7 @@ void TrackView::parseDocument(QDomDocument doc) { ItemInfo transitionInfo; QString transitionId; if (mlt_service == "composite") { - kDebug() << "//////////\n\nADDING COMPO TRANS\n\n " << mlt_geometry << "\n\n//////////"; + // When adding composite transition, check if it is a wipe transition if (mlt_geometry == "0%,0%:100%x100%") transitionId = "alphatransparency"; else if (mlt_geometry.count(';') == 1) { mlt_geometry.remove(QChar('%'), Qt::CaseInsensitive); @@ -379,7 +379,7 @@ int TrackView::slotAddProjectTrack(int ix, QDomElement xml, bool videotrack) { hasSpeedAttribute = true; id = idString.section(":", 1, 1); speed = idString.section(":", 2, 2).toDouble(); - } + } else id = id.section('_', 0, 0); DocClipBase *clip = m_doc->clipManager()->getClipById(id); if (clip != NULL) { int out = elem.attribute("out").toInt(); -- 2.39.2