int duration;
};
+typedef QMap<QString, QString> stringMap;
+
struct ItemInfo {
/** startPos is the position where the clip starts on the track */
GenTime startPos;
void KThumb::setProducer(Mlt::Producer *producer)
{
+ m_mutex.lock();
m_requestedThumbs.clear();
m_intraFramesQueue.clear();
m_future.waitForFinished();
m_intra.waitForFinished();
- m_mutex.lock();
m_producer = producer;
- m_mutex.unlock();
// FIXME: the profile() call leaks an object, but trying to free
// it leads to a double-free in Profile::~Profile()
if (producer) {
m_dar = producer->profile()->dar();
m_ratio = (double) producer->profile()->width() / producer->profile()->height();
}
-
+ m_mutex.unlock();
}
void KThumb::clearProducer()
m_stopmotion(NULL)
{
qRegisterMetaType<QVector<int16_t> > ();
-
+ qRegisterMetaType<stringMap> ("stringMap");
// Init locale
QLocale systemLocale = QLocale();
systemLocale.setNumberOptions(QLocale::OmitGroupSeparator);
connect(m_projectList, SIGNAL(deleteProjectClips(QStringList, QMap<QString, QString>)), this, SLOT(slotDeleteProjectClips(QStringList, QMap<QString, QString>)));
connect(m_projectList, SIGNAL(showClipProperties(DocClipBase *)), this, SLOT(slotShowClipProperties(DocClipBase *)));
connect(m_projectList, SIGNAL(showClipProperties(QList <DocClipBase *>, QMap<QString, QString>)), this, SLOT(slotShowClipProperties(QList <DocClipBase *>, QMap<QString, QString>)));
- connect(m_projectList, SIGNAL(getFileProperties(const QDomElement, const QString &, int, bool, bool)), m_projectMonitor->render, SLOT(getFileProperties(const QDomElement, const QString &, int, bool, bool)));
- connect(m_projectMonitor->render, SIGNAL(replyGetImage(const QString &, const QPixmap &)), m_projectList, SLOT(slotReplyGetImage(const QString &, const QPixmap &)));
- connect(m_projectMonitor->render, SIGNAL(replyGetFileProperties(const QString &, Mlt::Producer*, const QMap < QString, QString > &, const QMap < QString, QString > &, bool, bool)), m_projectList, SLOT(slotReplyGetFileProperties(const QString &, Mlt::Producer*, const QMap < QString, QString > &, const QMap < QString, QString > &, bool, bool)));
+ connect(m_projectList, SIGNAL(getFileProperties(const QDomElement, const QString &, int, bool)), m_projectMonitor->render, SLOT(getFileProperties(const QDomElement, const QString &, int, bool)));
+ connect(m_projectMonitor->render, SIGNAL(replyGetImage(const QString &, const QString &, int, int)), m_projectList, SLOT(slotReplyGetImage(const QString &, const QString &, int, int)));
+ connect(m_projectMonitor->render, SIGNAL(replyGetImage(const QString &, const QImage &)), m_projectList, SLOT(slotReplyGetImage(const QString &, const QImage &)));
+ connect(m_projectMonitor->render, SIGNAL(replyGetFileProperties(const QString &, Mlt::Producer*, const stringMap &, const stringMap &, bool, bool)), m_projectList, SLOT(slotReplyGetFileProperties(const QString &, Mlt::Producer*, const stringMap &, const stringMap &, bool, bool)));
connect(m_projectMonitor->render, SIGNAL(removeInvalidClip(const QString &, bool)), m_projectList, SLOT(slotRemoveInvalidClip(const QString &, bool)));
m_transcodeAction(NULL),
m_doc(NULL),
m_refreshed(false),
- m_infoQueue(),
m_thumbnailQueue(),
m_abortAllProxies(false)
{
ProjectList::~ProjectList()
{
m_abortAllProxies = true;
+ m_thumbnailQueue.clear();
delete m_menu;
m_listView->blockSignals(true);
m_listView->clear();
e.setAttribute("length", length);
}
}
- emit getFileProperties(e, item->clipId(), m_listView->iconSize().height(), true, false);
+ emit getFileProperties(e, item->clipId(), m_listView->iconSize().height(), true);
}
}
}
item = new ProjectItem(m_listView, clip);
}
if (item->data(0, DurationRole).isNull()) item->setData(0, DurationRole, i18n("Loading"));
+ QString proxy = clip->getProperty("proxy");
+ if (!proxy.isEmpty() && proxy != "-") slotCreateProxy(clip->getId());
connect(clip, SIGNAL(createProxy(const QString &)), this, SLOT(slotCreateProxy(const QString &)));
connect(clip, SIGNAL(abortProxy(const QString &, const QString &)), this, SLOT(slotAbortProxy(const QString, const QString)));
if (getProperties) {
+ int height = m_listView->iconSize().height();
+ int width = (int)(height * m_render->dar());
+ QPixmap pix = KIcon("video-x-generic").pixmap(QSize(width, height));
+ item->setData(0, Qt::DecorationRole, pix);
+ //item->setFlags(Qt::ItemIsSelectable);
m_listView->processLayout();
QDomElement e = clip->toXML().cloneNode().toElement();
e.removeAttribute("file_hash");
- m_mutex.lock();
- m_infoQueue.insert(clip->getId(), e);
- m_mutex.unlock();
+ emit getFileProperties(e, clip->getId(), m_listView->iconSize().height(), true);
}
else if (item->hasProxy() && !item->isProxyRunning()) {
slotCreateProxy(clip->getId());
if (m_listView->isEnabled()) {
updateButtons();
}
-
- //if (getProperties && m_processingClips.isEmpty())
- //m_queueRunner = QtConcurrent::run(this, &ProjectList::slotProcessNextClipInQueue);
- if (getProperties)
- QtConcurrent::run(this, &ProjectList::slotProcessNextClipInQueue);
}
void ProjectList::slotGotProxy(const QString &proxyPath)
e.setAttribute("length", length);
}
}
- e.setAttribute("replace", 1);
- m_mutex.lock();
- m_infoQueue.insert(clip->getId(), e);
- m_mutex.unlock();
- //if (!m_queueRunner.isRunning() && m_processingClips.isEmpty()) m_queueRunner = QtConcurrent::run(this, &ProjectList::slotProcessNextClipInQueue);
- QtConcurrent::run(this, &ProjectList::slotProcessNextClipInQueue);
+ emit getFileProperties(e, clip->getId(), m_listView->iconSize().height(), true);
}
void ProjectList::slotResetProjectList()
m_abortAllProxies = true;
m_proxyThreads.waitForFinished();
m_proxyThreads.clearFutures();
+ m_thumbnailQueue.clear();
m_listView->clear();
emit clipSelected(NULL);
- m_thumbnailQueue.clear();
- m_infoQueue.clear();
m_refreshed = false;
m_abortAllProxies = false;
}
-void ProjectList::slotProcessNextClipInQueue()
-{
- if (m_infoQueue.isEmpty()) {
- emit processNextThumbnail();
- return;
- }
- QMutexLocker locker(&m_mutex);
- QMap<QString, QDomElement>::const_iterator j = m_infoQueue.constBegin();
- if (j != m_infoQueue.constEnd()) {
- QDomElement dom = j.value().cloneNode().toElement();
- const QString id = j.key();
- m_infoQueue.remove(id);
- m_processingClips.append(id);
- locker.unlock();
- bool replace;
- if (dom.hasAttribute("replace")) {
- // Proxy action was enabled / disabled and we want to replace current producer
- dom.removeAttribute("replace");
- replace = true;
- }
- else replace = false;
- bool selectClip = !replace;
- if (m_infoQueue.count() > 1) selectClip = false;
- emit getFileProperties(dom, id, m_listView->iconSize().height(), replace, selectClip);
- }
-}
-
void ProjectList::slotUpdateClip(const QString &id)
{
ProjectItem *item = getItemById(id);
xml.removeAttribute("file_hash");
xml.removeAttribute("proxy_out");
}
- m_mutex.lock();
- m_infoQueue.insert(clip->getId(), xml);
- m_mutex.unlock();
- QtConcurrent::run(this, &ProjectList::slotProcessNextClipInQueue);
+ emit getFileProperties(xml, clip->getId(), m_listView->iconSize().height(), xml.attribute("replace") == "1");
}
else {
item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDropEnabled);
item->setData(0, Qt::DecorationRole, pixmap);
}
}
- } else {
+ } else {
if (displayRatioChanged || item->data(0, Qt::DecorationRole).isNull())
requestClipThumbnail(clip->getId());
if (item->data(0, DurationRole).toString().isEmpty()) {
}
++it;
}
-
- //if (!m_queueRunner.isRunning() && m_processingClips.isEmpty()) m_queueRunner = QtConcurrent::run(this, &ProjectList::slotProcessNextClipInQueue);
- //QtConcurrent::run(this, &ProjectList::slotProcessNextClipInQueue);
- /*while (!m_infoQueue.isEmpty()) {
- QtConcurrent::run(this, &ProjectList::slotProcessNextClipInQueue);
- }*/
if (m_listView->isEnabled())
monitorItemEditing(true);
m_listView->setSortingEnabled(true);
- if (m_infoQueue.isEmpty()) {
+ if (m_render->processingItems() == 0) {
slotProcessNextThumbnail();
}
}
ProjectItem *item = getItemById(id);
m_processingClips.removeAll(id);
m_thumbnailQueue.removeAll(id);
- //if (!m_queueRunner.isRunning() && m_processingClips.isEmpty()) m_queueRunner = QtConcurrent::run(this, &ProjectList::slotProcessNextClipInQueue);
- QtConcurrent::run(this, &ProjectList::slotProcessNextClipInQueue);
if (item) {
+ item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsDropEnabled);
const QString path = item->referencedClip()->fileURL().path();
if (item->referencedClip()->isPlaceHolder()) replace = false;
if (!path.isEmpty()) {
{
ProjectItem *item = getItemById(id);
if (item) {
+ item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsDropEnabled);
if (durationError) {
kDebug() << "Proxy duration is wrong, try changing transcoding parameters.";
emit displayMessage(i18n("Proxy clip unusable (duration is different from original)."), -2);
}
m_processingClips.removeAll(id);
m_thumbnailQueue.removeAll(id);
- //if (!m_queueRunner.isRunning() && m_processingClips.isEmpty()) m_queueRunner = QtConcurrent::run(this, &ProjectList::slotProcessNextClipInQueue);
- QtConcurrent::run(this, &ProjectList::slotProcessNextClipInQueue);
}
void ProjectList::slotAddColorClip()
m_abortAllProxies = true;
m_proxyThreads.waitForFinished();
m_proxyThreads.clearFutures();
+ m_thumbnailQueue.clear();
m_listView->clear();
m_processingClips.clear();
+
m_listView->setSortingEnabled(false);
emit clipSelected(NULL);
- m_thumbnailQueue.clear();
- m_infoQueue.clear();
m_refreshed = false;
m_fps = doc->fps();
m_timecode = doc->timecode();
void ProjectList::slotCheckForEmptyQueue()
{
- if (m_processingClips.isEmpty() && m_thumbnailQueue.isEmpty() && m_infoQueue.isEmpty()) {
+ if (m_render->processingItems() == 0 && m_thumbnailQueue.isEmpty()) {
if (!m_refreshed) {
emit loadingIsOver();
emit displayMessage(QString(), -1);
void ProjectList::requestClipThumbnail(const QString id)
{
if (!m_thumbnailQueue.contains(id)) m_thumbnailQueue.append(id);
+ slotProcessNextThumbnail();
}
void ProjectList::slotProcessNextThumbnail()
{
- if (m_thumbnailQueue.isEmpty() && m_infoQueue.isEmpty()) {
- slotCheckForEmptyQueue();
+ if (m_render->processingItems() > 0) {
return;
}
- if (!m_infoQueue.isEmpty()) {
- //QTimer::singleShot(300, this, SLOT(slotProcessNextThumbnail()));
+ if (m_thumbnailQueue.isEmpty()) {
+ slotCheckForEmptyQueue();
return;
}
- if (m_thumbnailQueue.count() > 1) {
- int max = m_doc->clipManager()->clipsCount();
- emit displayMessage(i18n("Loading thumbnails"), (int)(100 *(max - m_thumbnailQueue.count()) / max));
- }
+ int max = m_doc->clipManager()->clipsCount();
+ emit displayMessage(i18n("Loading thumbnails"), (int)(100 *(max - m_thumbnailQueue.count()) / max));
slotRefreshClipThumbnail(m_thumbnailQueue.takeFirst(), false);
}
}
}
-void ProjectList::slotReplyGetFileProperties(const QString &clipId, Mlt::Producer *producer, const QMap < QString, QString > &properties, const QMap < QString, QString > &metadata, bool replace, bool selectClip)
+void ProjectList::slotReplyGetFileProperties(const QString &clipId, Mlt::Producer *producer, const stringMap &properties, const stringMap &metadata, bool replace, bool refreshThumbnail)
{
QString toReload;
ProjectItem *item = getItemById(clipId);
- if (!m_refreshed) {
- // we are still finishing to load the document
- selectClip = false;
+
+ int queue = m_render->processingItems();
+ if (queue == 0) {
+ m_listView->setEnabled(true);
}
- m_processingClips.removeAll(clipId);
- if (m_infoQueue.isEmpty() && m_processingClips.isEmpty()) m_listView->setEnabled(true);
if (item && producer) {
//m_listView->blockSignals(true);
monitorItemEditing(false);
DocClipBase *clip = item->referencedClip();
item->setProperties(properties, metadata);
- if (clip->isPlaceHolder() && producer->is_valid()) {
- clip->setValid();
+ if (producer->is_valid()) {
+ if (clip->isPlaceHolder()) {
+ clip->setValid();
+ toReload = clipId;
+ }
item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsDropEnabled);
- toReload = clipId;
}
clip->setProducer(producer, replace);
clip->askForAudioThumbs();
+ if (refreshThumbnail) m_thumbnailQueue.append(clipId);
// Proxy stuff
QString size = properties.value("frame_size");
if (!useProxy() && clip->getProperty("proxy").isEmpty()) setProxyStatus(item, NOPROXY);
if (m_listView->isEnabled())
monitorItemEditing(true);
} else kDebug() << "//////// COULD NOT FIND CLIP TO UPDATE PRPS...";
- if (selectClip && m_infoQueue.isEmpty()) {
- if (item && m_infoQueue.isEmpty() && m_thumbnailQueue.isEmpty() && m_processingClips.isEmpty()) {
+ if (queue == 0) {
+ if (item && m_thumbnailQueue.isEmpty()) {
m_listView->setCurrentItem(item);
bool updatedProfile = false;
if (item->parent()) {
}
} else {
int max = m_doc->clipManager()->clipsCount();
- emit displayMessage(i18n("Loading clips"), (int)(100 *(max - m_infoQueue.count()) / max));
+ emit displayMessage(i18n("Loading clips"), (int)(100 *(max - queue) / max));
}
+ processNextThumbnail();
}
if (item && m_listView->isEnabled() && replace) {
// update clip in clip monitor
}
if (!toReload.isEmpty())
emit clipNeedsReload(toReload, true);
-
- //if (!m_queueRunner.isRunning() && m_processingClips.isEmpty()) m_queueRunner = QtConcurrent::run(this, &ProjectList::slotProcessNextClipInQueue);
- QtConcurrent::run(this, &ProjectList::slotProcessNextClipInQueue);
}
bool ProjectList::adjustProjectProfileToItem(ProjectItem *item)
return m_doc->getDocumentProperty("generateimageproxy").toInt();
}
-void ProjectList::slotReplyGetImage(const QString &clipId, const QPixmap &pix)
+void ProjectList::slotReplyGetImage(const QString &clipId, const QImage &img)
+{
+ QPixmap pix = QPixmap::fromImage(img);
+ setThumbnail(clipId, pix);
+}
+
+void ProjectList::slotReplyGetImage(const QString &clipId, const QString &name, int width, int height)
+{
+ QPixmap pix = KIcon(name).pixmap(QSize(width, height));
+ setThumbnail(clipId, pix);
+}
+
+void ProjectList::setThumbnail(const QString &clipId, const QPixmap &pix)
{
ProjectItem *item = getItemById(clipId);
if (item && !pix.isNull()) {
monitorItemEditing(false);
item->setData(0, Qt::DecorationRole, pix);
monitorItemEditing(true);
+ //update();
m_doc->cachePixmap(item->getClipHash(), pix);
if (m_listView->isEnabled())
m_listView->blockSignals(false);
void ProjectList::slotForceProcessing(const QString &id)
{
- while (m_infoQueue.contains(id)) {
- slotProcessNextClipInQueue();
- }
+ m_render->forceProcessing(id);
}
void ProjectList::slotAddOrUpdateSequence(const QString frameName)
}
if (command->childCount() > 0) m_doc->commandStack()->push(command);
else delete command;
- //if (!m_infoQueue.isEmpty() && !m_queueRunner.isRunning() && m_processingClips.isEmpty()) m_queueRunner = QtConcurrent::run(this, &ProjectList::slotProcessNextClipInQueue);
- QtConcurrent::run(this, &ProjectList::slotProcessNextClipInQueue);
}
void ProjectList::slotProxyCurrentItem(bool doProxy)
m_doc->commandStack()->push(command);
}
else delete command;
- //if (!m_infoQueue.isEmpty() && !m_queueRunner.isRunning() && m_processingClips.isEmpty()) m_queueRunner = QtConcurrent::run(this, &ProjectList::slotProcessNextClipInQueue);
- if (!m_infoQueue.isEmpty()) QtConcurrent::run(this, &ProjectList::slotProcessNextClipInQueue);
}
public slots:
void setDocument(KdenliveDoc *doc);
void updateAllClips(bool displayRatioChanged, bool fpsChanged);
- void slotReplyGetImage(const QString &clipId, const QPixmap &pix);
- void slotReplyGetFileProperties(const QString &clipId, Mlt::Producer *producer, const QMap < QString, QString > &properties, const QMap < QString, QString > &metadata, bool replace, bool selectClip);
+ void slotReplyGetImage(const QString &clipId, const QImage &img);
+ void slotReplyGetImage(const QString &clipId, const QString &name, int width, int height);
+ void slotReplyGetFileProperties(const QString &clipId, Mlt::Producer *producer, const stringMap &properties, const stringMap &metadata, bool replace, bool refreshThumbnail);
void slotAddClip(DocClipBase *clip, bool getProperties);
void slotDeleteClip(const QString &clipId);
void slotUpdateClip(const QString &id);
QToolButton *m_addButton;
QToolButton *m_deleteButton;
QToolButton *m_editButton;
- QMap <QString, QDomElement> m_infoQueue;
+ //QMap <QString, QDomElement> m_infoQueue;
QMap <QString, QDomElement> m_producerQueue;
QList <QString> m_thumbnailQueue;
QAction *m_proxyAction;
/** @brief Process ffmpeg output to find out process progress. */
void processLogInfo(const QString &path, int *duration, const QString &log);
void monitorItemEditing(bool enable);
+ /** @brief Set thumbnail for a project's clip. */
+ void setThumbnail(const QString &clipId, const QPixmap &pix);
private slots:
void slotClipSelected();
/** @brief This is triggered when a clip description has been modified. */
void slotItemEdited(QTreeWidgetItem *item, int column);
void slotUpdateClipProperties(ProjectItem *item, QMap <QString, QString> properties);
- void slotProcessNextClipInQueue();
void slotProcessNextThumbnail();
void slotCheckForEmptyQueue();
void slotPauseMonitor();
signals:
void clipSelected(DocClipBase *, QPoint zone = QPoint());
- void getFileProperties(const QDomElement, const QString &, int pixHeight, bool, bool);
+ void getFileProperties(const QDomElement, const QString &, int pixHeight, bool);
void receivedClipDuration(const QString &);
void showClipProperties(DocClipBase *);
void showClipProperties(QList <DocClipBase *>, QMap<QString, QString> commonproperties);
#include <QDir>
#include <QString>
#include <QApplication>
+#include <QtConcurrentRun>
#include <cstdlib>
#include <cstdarg>
#include <QDebug>
+
static void kdenlive_callback(void* /*ptr*/, int level, const char* fmt, va_list vl)
{
// kDebug() << "log level" << level << QString().vsprintf(fmt, vl).simplified();
{
if (profile.isEmpty()) profile = KdenliveSettings::current_profile();
buildConsumer(profile);
-
m_mltProducer = m_blackClip->cut(0, 50);
m_mltConsumer->connect(*m_mltProducer);
m_mltProducer->set_speed(0.0);
void Render::closeMlt()
{
//delete m_osdTimer;
+ m_requestList.clear();
+ m_infoThread.waitForFinished();
if (m_mltConsumer) delete m_mltConsumer;
if (m_mltProducer) delete m_mltProducer;
/*if (m_mltProducer) {
double current_dar = m_mltProfile->dar();
delete m_blackClip;
m_blackClip = NULL;
+ m_requestList.clear();
+ m_infoThread.waitForFinished();
if (m_mltProducer) {
pos = m_mltProducer->position();
}
}
-void Render::getFileProperties(const QDomElement &xml, const QString &clipId, int imageHeight, bool replaceProducer, bool selectClip)
+void Render::getFileProperties(const QDomElement &xml, const QString &clipId, int imageHeight, bool replaceProducer)
+{
+ requestClipInfo info;
+ info.xml = xml;
+ info.clipId = clipId;
+ info.imageHeight = imageHeight;
+ info.replaceProducer = replaceProducer;
+ m_requestList.append(info);
+ if (!m_infoThread.isRunning())
+ m_infoThread = QtConcurrent::run(this, &Render::getFileProperties2);
+}
+
+void Render::forceProcessing(const QString &id)
+{
+ m_infoMutex.lock();
+ for (int i = 0; i < m_requestList.count(); i++) {
+ requestClipInfo info = m_requestList.at(i);
+ if (info.clipId == id) {
+ if (i == 0) break;
+ else {
+ m_requestList.removeAt(i);
+ m_requestList.prepend(info);
+ break;
+ }
+ }
+ }
+ m_infoMutex.unlock();
+}
+
+int Render::processingItems() const
{
+ int count = m_requestList.count();
+ if (m_infoThread.isRunning()) count++;
+ return count;
+}
+
+void Render::getFileProperties2()
+{
+ while (!m_requestList.isEmpty()) {
+ m_infoMutex.lock();
+ requestClipInfo info = m_requestList.takeFirst();
+ m_infoMutex.unlock();
+
QString path;
QLocale locale;
bool proxyProducer;
- if (xml.hasAttribute("proxy") && xml.attribute("proxy") != "-") {
- path = xml.attribute("proxy");
+ if (info.xml.hasAttribute("proxy") && info.xml.attribute("proxy") != "-") {
+ path = info.xml.attribute("proxy");
proxyProducer = true;
}
else {
- path = xml.attribute("resource");
+ path = info.xml.attribute("resource");
proxyProducer = false;
}
KUrl url(path);
Mlt::Producer *producer = NULL;
- CLIPTYPE type = (CLIPTYPE)xml.attribute("type").toInt();
- //kDebug() << "PROFILE WIDT: "<< xml.attribute("mlt_service") << ": "<< m_mltProfile->width() << "\n...................\n\n";
- /*if (xml.attribute("type").toInt() == TEXT && !QFile::exists(url.path())) {
+ CLIPTYPE type = (CLIPTYPE)info.xml.attribute("type").toInt();
+ //kDebug() << "PROFILE WIDT: "<< info.xml.attribute("mlt_service") << ": "<< m_mltProfile->width() << "\n...................\n\n";
+ /*if (info.xml.attribute("type").toInt() == TEXT && !QFile::exists(url.path())) {
emit replyGetFileProperties(clipId, producer, QMap < QString, QString >(), QMap < QString, QString >(), replaceProducer);
return;
}*/
if (type == COLOR) {
- producer = new Mlt::Producer(*m_mltProfile, 0, ("colour:" + xml.attribute("colour")).toUtf8().constData());
+ producer = new Mlt::Producer(*m_mltProfile, 0, ("colour:" + info.xml.attribute("colour")).toUtf8().constData());
} else if (type == TEXT) {
- producer = new Mlt::Producer(*m_mltProfile, 0, ("kdenlivetitle:" + xml.attribute("resource")).toUtf8().constData());
- if (producer && producer->is_valid() && xml.hasAttribute("xmldata"))
- producer->set("xmldata", xml.attribute("xmldata").toUtf8().constData());
+ producer = new Mlt::Producer(*m_mltProfile, 0, ("kdenlivetitle:" + info.xml.attribute("resource")).toUtf8().constData());
+ if (producer && producer->is_valid() && info.xml.hasAttribute("xmldata"))
+ producer->set("xmldata", info.xml.attribute("xmldata").toUtf8().constData());
} else if (url.isEmpty()) {
QDomDocument doc;
QDomElement mlt = doc.createElement("mlt");
QDomElement play = doc.createElement("playlist");
doc.appendChild(mlt);
mlt.appendChild(play);
- play.appendChild(doc.importNode(xml, true));
+ play.appendChild(doc.importNode(info.xml, true));
producer = new Mlt::Producer(*m_mltProfile, "xml-string", doc.toString().toUtf8().constData());
} else {
- char *resTag = qstrdup(QString("nocache:" + path).toUtf8().constData());
producer = new Mlt::Producer(*m_mltProfile, path.toUtf8().constData());
- delete[] resTag;
}
kDebug() << " / / / / / / / / ERROR / / / / // CANNOT LOAD PRODUCER: "<<path;
if (proxyProducer) {
// Proxy file is corrupted
- emit removeInvalidProxy(clipId, false);
+ emit removeInvalidProxy(info.clipId, false);
}
- else emit removeInvalidClip(clipId, replaceProducer);
+ else emit removeInvalidClip(info.clipId, info.replaceProducer);
delete producer;
- return;
+ continue;
}
- if (proxyProducer && xml.hasAttribute("proxy_out")) {
- producer->set("length", xml.attribute("proxy_out").toInt() + 1);
- producer->set("out", xml.attribute("proxy_out").toInt());
- if (producer->get_out() != xml.attribute("proxy_out").toInt()) {
+ if (proxyProducer && info.xml.hasAttribute("proxy_out")) {
+ producer->set("length", info.xml.attribute("proxy_out").toInt() + 1);
+ producer->set("out", info.xml.attribute("proxy_out").toInt());
+ if (producer->get_out() != info.xml.attribute("proxy_out").toInt()) {
// Proxy file length is different than original clip length, this will corrupt project so disable this proxy clip
- emit removeInvalidProxy(clipId, true);
+ emit removeInvalidProxy(info.clipId, true);
delete producer;
- return;
+ continue;
}
}
- if (xml.hasAttribute("force_aspect_ratio")) {
- double aspect = xml.attribute("force_aspect_ratio").toDouble();
+ if (info.xml.hasAttribute("force_aspect_ratio")) {
+ double aspect = info.xml.attribute("force_aspect_ratio").toDouble();
if (aspect > 0) producer->set("force_aspect_ratio", aspect);
}
- if (xml.hasAttribute("force_aspect_num") && xml.hasAttribute("force_aspect_den")) {
- int width = xml.attribute("frame_size").section('x', 0, 0).toInt();
- int height = xml.attribute("frame_size").section('x', 1, 1).toInt();
- int aspectNumerator = xml.attribute("force_aspect_num").toInt();
- int aspectDenominator = xml.attribute("force_aspect_den").toInt();
+ if (info.xml.hasAttribute("force_aspect_num") && info.xml.hasAttribute("force_aspect_den")) {
+ int width = info.xml.attribute("frame_size").section('x', 0, 0).toInt();
+ int height = info.xml.attribute("frame_size").section('x', 1, 1).toInt();
+ int aspectNumerator = info.xml.attribute("force_aspect_num").toInt();
+ int aspectDenominator = info.xml.attribute("force_aspect_den").toInt();
if (aspectDenominator != 0 && width != 0)
producer->set("force_aspect_ratio", double(height) * aspectNumerator / aspectDenominator / width);
}
- if (xml.hasAttribute("force_fps")) {
- double fps = xml.attribute("force_fps").toDouble();
+ if (info.xml.hasAttribute("force_fps")) {
+ double fps = info.xml.attribute("force_fps").toDouble();
if (fps > 0) producer->set("force_fps", fps);
}
- if (xml.hasAttribute("force_progressive")) {
+ if (info.xml.hasAttribute("force_progressive")) {
bool ok;
- int progressive = xml.attribute("force_progressive").toInt(&ok);
+ int progressive = info.xml.attribute("force_progressive").toInt(&ok);
if (ok) producer->set("force_progressive", progressive);
}
- if (xml.hasAttribute("force_tff")) {
+ if (info.xml.hasAttribute("force_tff")) {
bool ok;
- int fieldOrder = xml.attribute("force_tff").toInt(&ok);
+ int fieldOrder = info.xml.attribute("force_tff").toInt(&ok);
if (ok) producer->set("force_tff", fieldOrder);
}
- if (xml.hasAttribute("threads")) {
- int threads = xml.attribute("threads").toInt();
+ if (info.xml.hasAttribute("threads")) {
+ int threads = info.xml.attribute("threads").toInt();
if (threads != 1) producer->set("threads", threads);
}
- if (xml.hasAttribute("video_index")) {
- int vindex = xml.attribute("video_index").toInt();
+ if (info.xml.hasAttribute("video_index")) {
+ int vindex = info.xml.attribute("video_index").toInt();
if (vindex != 0) producer->set("video_index", vindex);
}
- if (xml.hasAttribute("audio_index")) {
- int aindex = xml.attribute("audio_index").toInt();
+ if (info.xml.hasAttribute("audio_index")) {
+ int aindex = info.xml.attribute("audio_index").toInt();
if (aindex != 0) producer->set("audio_index", aindex);
}
- if (xml.hasAttribute("force_colorspace")) {
- int colorspace = xml.attribute("force_colorspace").toInt();
+ if (info.xml.hasAttribute("force_colorspace")) {
+ int colorspace = info.xml.attribute("force_colorspace").toInt();
if (colorspace != 0) producer->set("force_colorspace", colorspace);
}
- if (xml.hasAttribute("full_luma")) {
- int full_luma = xml.attribute("full_luma").toInt();
+ if (info.xml.hasAttribute("full_luma")) {
+ int full_luma = info.xml.attribute("full_luma").toInt();
if (full_luma != 0) producer->set("set.force_full_luma", full_luma);
}
int clipOut = 0;
int duration = 0;
- if (xml.hasAttribute("out")) clipOut = xml.attribute("out").toInt();
+ if (info.xml.hasAttribute("out")) clipOut = info.xml.attribute("out").toInt();
// setup length here as otherwise default length (currently 15000 frames in MLT) will be taken even if outpoint is larger
if (type == COLOR || type == TEXT || type == IMAGE || type == SLIDESHOW) {
int length;
- if (xml.hasAttribute("length")) {
+ if (info.xml.hasAttribute("length")) {
if (clipOut > 0) duration = clipOut + 1;
- length = xml.attribute("length").toInt();
+ length = info.xml.attribute("length").toInt();
clipOut = length - 1;
}
- else length = xml.attribute("out").toInt() - xml.attribute("in").toInt();
+ else length = info.xml.attribute("out").toInt() - info.xml.attribute("in").toInt();
producer->set("length", length);
}
- if (clipOut > 0) producer->set_in_and_out(xml.attribute("in").toInt(), clipOut);
+ if (clipOut > 0) producer->set_in_and_out(info.xml.attribute("in").toInt(), clipOut);
- producer->set("id", clipId.toUtf8().constData());
+ producer->set("id", info.clipId.toUtf8().constData());
- if (xml.hasAttribute("templatetext"))
- producer->set("templatetext", xml.attribute("templatetext").toUtf8().constData());
+ if (info.xml.hasAttribute("templatetext"))
+ producer->set("templatetext", info.xml.attribute("templatetext").toUtf8().constData());
- if ((!replaceProducer && xml.hasAttribute("file_hash")) || xml.hasAttribute("proxy")) {
+ if ((!info.replaceProducer && info.xml.hasAttribute("file_hash")) || info.xml.hasAttribute("proxy")) {
// Clip already has all properties
- if (replaceProducer) emit blockClipMonitor(clipId);
- // Querying a frame is required by MLT, otherwise the producer is not correctly initialised
- //Mlt::Frame *frame = producer->get_frame();
- //delete frame;
- emit replyGetFileProperties(clipId, producer, QMap < QString, QString >(), QMap < QString, QString >(), replaceProducer, selectClip);
- return;
+ if (info.replaceProducer) emit blockClipMonitor(info.clipId);
+ emit replyGetFileProperties(info.clipId, producer, stringMap(), stringMap(), info.replaceProducer, true);
+ continue;
}
- int imageWidth = (int)((double) imageHeight * m_mltProfile->width() / m_mltProfile->height() + 0.5);
- int fullWidth = (int)((double) imageHeight * m_mltProfile->dar() + 0.5);
- QMap < QString, QString > filePropertyMap;
- QMap < QString, QString > metadataPropertyMap;
+ int imageWidth = (int)((double) info.imageHeight * m_mltProfile->width() / m_mltProfile->height() + 0.5);
+ int fullWidth = (int)((double) info.imageHeight * m_mltProfile->dar() + 0.5);
+ stringMap filePropertyMap;
+ stringMap metadataPropertyMap;
- int frameNumber = xml.attribute("thumbnail", "0").toInt();
+ int frameNumber = info.xml.attribute("thumbnail", "0").toInt();
if (frameNumber != 0) producer->seek(frameNumber);
filePropertyMap["duration"] = QString::number(duration > 0 ? duration : producer->get_playtime());
Mlt::Frame *frame = producer->get_frame();
if (type == SLIDESHOW) {
- int ttl = xml.hasAttribute("ttl") ? xml.attribute("ttl").toInt() : 0;
+ int ttl = info.xml.hasAttribute("ttl") ? info.xml.attribute("ttl").toInt() : 0;
if (ttl) producer->set("ttl", ttl);
- if (!xml.attribute("animation").isEmpty()) {
+ if (!info.xml.attribute("animation").isEmpty()) {
Mlt::Filter *filter = new Mlt::Filter(*m_mltProfile, "affine");
if (filter && filter->is_valid()) {
int cycle = ttl;
- QString geometry = SlideshowClip::animationToGeometry(xml.attribute("animation"), cycle);
+ QString geometry = SlideshowClip::animationToGeometry(info.xml.attribute("animation"), cycle);
if (!geometry.isEmpty()) {
- if (xml.attribute("animation").contains("low-pass")) {
+ if (info.xml.attribute("animation").contains("low-pass")) {
Mlt::Filter *blur = new Mlt::Filter(*m_mltProfile, "boxblur");
if (blur && blur->is_valid())
producer->attach(*blur);
}
}
}
- if (xml.attribute("fade") == "1") {
+ if (info.xml.attribute("fade") == "1") {
// user wants a fade effect to slideshow
Mlt::Filter *filter = new Mlt::Filter(*m_mltProfile, "luma");
if (filter && filter->is_valid()) {
if (ttl) filter->set("cycle", ttl);
- if (xml.hasAttribute("luma_duration") && !xml.attribute("luma_duration").isEmpty()) filter->set("duration", xml.attribute("luma_duration").toInt());
- if (xml.hasAttribute("luma_file") && !xml.attribute("luma_file").isEmpty()) {
- filter->set("luma.resource", xml.attribute("luma_file").toUtf8().constData());
- if (xml.hasAttribute("softness")) {
- int soft = xml.attribute("softness").toInt();
+ if (info.xml.hasAttribute("luma_duration") && !info.xml.attribute("luma_duration").isEmpty()) filter->set("duration", info.xml.attribute("luma_duration").toInt());
+ if (info.xml.hasAttribute("luma_file") && !info.xml.attribute("luma_file").isEmpty()) {
+ filter->set("luma.resource", info.xml.attribute("luma_file").toUtf8().constData());
+ if (info.xml.hasAttribute("softness")) {
+ int soft = info.xml.attribute("softness").toInt();
filter->set("luma.softness", (double) soft / 100.0);
}
}
producer->attach(*filter);
}
}
- if (xml.attribute("crop") == "1") {
+ if (info.xml.attribute("crop") == "1") {
// user wants to center crop the slides
Mlt::Filter *filter = new Mlt::Filter(*m_mltProfile, "crop");
if (filter && filter->is_valid()) {
QImage img;
do {
variance = 100;
- img = KThumb::getFrame(frame, imageWidth, fullWidth, imageHeight);
+ img = KThumb::getFrame(frame, imageWidth, fullWidth, info.imageHeight);
variance = KThumb::imageVariance(img);
if (frameNumber == 0 && variance< 6) {
// Thumbnail is not interesting (for example all black, seek to fetch better thumb
variance = -1;
}
} while (variance == -1);
- QPixmap pix = QPixmap::fromImage(img);
- emit replyGetImage(clipId, pix);
-
+ emit replyGetImage(info.clipId, img);
} else if (frame->get_int("test_audio") == 0) {
- QPixmap pixmap = KIcon("audio-x-generic").pixmap(QSize(fullWidth, imageHeight));
- emit replyGetImage(clipId, pixmap);
+ emit replyGetImage(info.clipId, "audio-x-generic", fullWidth, info.imageHeight);
filePropertyMap["type"] = "audio";
}
}
metadataPropertyMap[ name.section('.', 0, -2)] = value;
}
producer->seek(0);
- if (replaceProducer) emit blockClipMonitor(clipId);
- emit replyGetFileProperties(clipId, producer, filePropertyMap, metadataPropertyMap, replaceProducer, selectClip);
+ if (info.replaceProducer) emit blockClipMonitor(info.clipId);
+ emit replyGetFileProperties(info.clipId, producer, filePropertyMap, metadataPropertyMap, info.replaceProducer);
// FIXME: should delete this to avoid a leak...
//delete producer;
+ }
}
kWarning() << "/////// ERROR, TRYING TO USE NULL MLT CONSUMER";
error = -1;
}
+ m_requestList.clear();
+ m_infoThread.waitForFinished();
if (m_mltProducer) {
m_mltProducer->set_speed(0);
}
blockSignals(true);
-
m_locale = QLocale();
m_mltProducer = new Mlt::Producer(*m_mltProfile, "xml-string", playlist.toUtf8().constData());
#include <QList>
#include <QEvent>
#include <QMutex>
+#include <QFuture>
class QTimer;
class QPixmap;
class Service;
};
+struct requestClipInfo {
+ QDomElement xml;
+ QString clipId;
+ int imageHeight;
+ bool replaceProducer;
+};
+
class MltErrorEvent : public QEvent
{
public:
/** @brief Returns a pointer to the main producer. */
Mlt::Producer *getProducer();
+ /** @brief Returns the number of clips to process (When requesting clip info). */
+ int processingItems() const;
+ /** @brief Force processing of clip with selected id. */
+ void forceProcessing(const QString &id);
private:
QTimer *m_osdTimer;
QMutex m_mutex;
+ QMutex m_infoMutex;
/** @brief A human-readable description of this renderer. */
int m_winid;
QLocale m_locale;
+ QFuture <void> m_infoThread;
+ QList <requestClipInfo> m_requestList;
void closeMlt();
void mltCheckLength(Mlt::Tractor *tractor);
signals:
/** @brief The renderer received a reply to a getFileProperties request. */
- void replyGetFileProperties(const QString &clipId, Mlt::Producer*, const QMap < QString, QString > &, const QMap < QString, QString > &, bool, bool);
+ void replyGetFileProperties(const QString &clipId, Mlt::Producer*, const stringMap &, const stringMap &, bool replaceProducer, bool refreshThumbnail = false);
/** @brief The renderer received a reply to a getImage request. */
- void replyGetImage(const QString &, const QPixmap &);
+ void replyGetImage(const QString &, const QString &, int, int);
+ void replyGetImage(const QString &, const QImage &);
/** @brief The renderer stopped, either playing or rendering. */
void stopped();
@param selectClip If true, clip item will be selected in project view
* Upon return, the result will be emitted via replyGetFileProperties().
* Wraps the VEML command of the same name. */
- void getFileProperties(const QDomElement &xml, const QString &clipId, int imageHeight, bool replaceProducer = true, bool selectClip = false);
+ void getFileProperties(const QDomElement &xml, const QString &clipId, int imageHeight, bool replaceProducer = true);
+
+ void getFileProperties2();
void exportFileToFirewire(QString srcFileName, int port, GenTime startTime, GenTime endTime);
void mltSavePlaylist();