if (props.contains("frequency"))
QTreeWidgetItem *item = new QTreeWidgetItem(m_view.clip_aproperties, QStringList() << i18n("Frequency") << props.value("frequency"));
+
CLIPTYPE t = m_clip->clipType();
+
+ if (props.contains("proxy") && props.value("proxy") != "-") {
+ KFileItem f(KFileItem::Unknown, KFileItem::Unknown, KUrl(props.value("proxy")), true);
+ QFrame* line = new QFrame();
+ line->setFrameShape(QFrame::HLine);
+ line->setFrameShadow(QFrame::Sunken);
+ m_proxyContainer = new QFrame();
+ m_proxyContainer->setFrameShape(QFrame::NoFrame);
+ QHBoxLayout *l = new QHBoxLayout;
+ l->addWidget(new QLabel(i18n("Proxy clip: %1").arg(KIO::convertSize(f.size()))));
+ l->addStretch(5);
+ QPushButton *pb = new QPushButton(i18n("Delete proxy"));
+ l->addWidget(pb);
+ connect(pb, SIGNAL(clicked()), this, SLOT(slotDeleteProxy()));
+ m_proxyContainer->setLayout(l);
+ if (t == AUDIO) {
+ m_view.tab_audio->layout()->addWidget(line);
+ m_view.tab_audio->layout()->addWidget(m_proxyContainer);
+ }
+ else {
+ m_view.tab_video->layout()->addWidget(line);
+ m_view.tab_video->layout()->addWidget(m_proxyContainer);
+ }
+ }
+
if (t != AUDIO && t != AV) {
m_view.clip_force_aindex->setEnabled(false);
}
}
}
+void ClipProperties::slotDeleteProxy()
+{
+ QString proxy = m_clip->getProperty("proxy");
+ QFile::remove(proxy);
+ QMap <QString, QString> props;
+ props.insert("proxy", QString());
+ emit applyNewClipProperties(m_clip->getId(), m_clip->properties(), props, false, true);
+ if (m_proxyContainer) delete m_proxyContainer;
+}
+
#include "clipproperties.moc"
void slotUpdateDurationFormat(int ix);
void slotApplyProperties();
void slotModified();
+ void slotDeleteProxy();
private:
Ui::ClipProperties_UI m_view;
bool m_clipNeedsRefresh;
/** clip resource changed, reload it */
bool m_clipNeedsReLoad;
+ /** Frame with proxy info / delete button */
+ QFrame* m_proxyContainer;
signals:
void addMarker(const QString &, GenTime, QString);
enum TRACKTYPE { AUDIOTRACK = 0, VIDEOTRACK = 1 };
+enum PROXYSTATUS { NOPROXY = 0, PROXYWAITING = 1, CREATINGPROXY = 2, PROXYDONE = 3, PROXYCRASHED = 4};
+
struct TrackInfo {
TRACKTYPE type;
QString trackName;
m_audioThumbCreated(false),
m_id(id),
m_placeHolder(xml.hasAttribute("placeholder")),
- m_properties(),
- m_abortProxy(false)
+ m_properties()
{
int type = xml.attribute("type").toInt();
m_clipType = (CLIPTYPE) type;
if (m_clipType == SLIDESHOW) hash = QCryptographicHash::hash(m_properties.value("resource").toAscii().data(), QCryptographicHash::Md5).toHex();
else if (m_clipType == COLOR) hash = QCryptographicHash::hash(m_properties.value("colour").toAscii().data(), QCryptographicHash::Md5).toHex();
else if (m_clipType == TEXT) hash = QCryptographicHash::hash(QString("title" + getId() + m_properties.value("xmldata")).toUtf8().data(), QCryptographicHash::Md5).toHex();
- else hash = m_properties.value("file_hash");
+ else {
+ if (m_properties.contains("file_hash")) hash = m_properties.value("file_hash");
+ else hash = getHash(fileURL().path());
+
+ }
return hash;
}
resetProducerProperty("set.force_full_luma");
} else setProducerProperty("set.force_full_luma", value.toInt());
}
+ else if (key == "proxy") {
+ // If value is "-", that means user manually disabled proxy on this clip
+ if (value.isEmpty() || value == "-") {
+ // reset proxy
+ emit abortProxy(m_id);
+ }
+ else {
+ emit createProxy(m_id);
+ }
+ }
}
QMap <QString, QString> DocClipBase::properties() const
return prod->get(property) == codec;
}
-void DocClipBase::generateProxy(KUrl proxyFolder, QString params)
-{
- if (m_proxyThread.isRunning()) return;
- QStringList parameters;
- parameters << "-i" << m_properties.value("resource");
- foreach(QString s, params.split(' '))
- parameters << s;
- // Make sure we don't block when proxy file already exists
- parameters << "-y";
- if (m_properties.value("file_hash").isEmpty()) getFileHash(m_properties.value("resource"));
- QString proxydir=proxyFolder.path( KUrl::AddTrailingSlash) + "proxy/";
- KStandardDirs::makeDir(proxydir);
- QString path = proxydir + m_properties.value("file_hash") + ".avi";
- setProperty("proxy", path.toUtf8().data());
- if (QFile::exists(path)) {
- emit proxyReady(m_id, true);
- return;
- }
- parameters << path;
- m_proxyThread = QtConcurrent::run(this, &DocClipBase::slotGenerateProxy, parameters);
-}
-
-void DocClipBase::slotGenerateProxy(QStringList parameters)
-{
- QProcess myProcess;
- myProcess.start("ffmpeg", parameters);
- myProcess.waitForStarted();
- int result = -1;
- while (myProcess.state() != QProcess::NotRunning) {
- // building proxy file
- if (m_abortProxy) {
- QString path = getProperty("proxy");
- myProcess.close();
- myProcess.waitForFinished();
- QFile::remove(path);
- m_abortProxy = false;
- result = 1;
- }
- myProcess.waitForFinished(500);
- }
- myProcess.waitForFinished();
- if (result == -1) result = myProcess.exitStatus();
- if (result == 0) emit proxyReady(m_id, true);
- else {
- clearProperty("proxy");
- emit proxyReady(m_id, false);
- }
-}
-void DocClipBase::abortProxy()
-{
- if (m_proxyThread.isRunning()) {
- // Proxy is being created, abort
- m_abortProxy = true;
- }
- else {
- clearProperty("proxy");
- emit proxyReady(m_id, false);
- }
-}
bool hasAudioCodec(const QString &codec) const;
bool checkHash() const;
void setPlaceHolder(bool place);
- /** @brief Generate a proxy clip (lower resolution copy) named like the clip's hash. */
- void generateProxy(KUrl proxyFolder, QString params);
- /** @brief Abort creation of the proxy clip (lower resolution copy). */
- void abortProxy();
private: // Private attributes
/** Holds clip metadata like author, copyright,... */
QMap <QString, QString> m_metadata;
- QFuture<void> m_proxyThread;
- /** Used to kill the proxy thread */
- bool m_abortProxy;
/** Create connections for audio thumbnails */
void slotCreateAudioTimer();
void slotRefreshProducer();
QMap <QString, QString> properties() const;
QMap <QString, QString> metadata() const;
-private slots:
- void slotGenerateProxy(QStringList parameters);
signals:
void gotAudioData();
- void proxyReady(const QString &, bool success);
+ /** @brief Generate a proxy clip (lower resolution copy) named like the clip's hash. */
+ void createProxy(const QString id);
+ /** @brief Abort creation of the proxy clip (lower resolution copy). */
+ void abortProxy(const QString id);
};
#endif
m_documentProperties["zoneout"] = "100";
m_documentProperties["enableproxy"] = QString::number((int) KdenliveSettings::enableproxy());
m_documentProperties["proxyparams"] = KdenliveSettings::proxyparams();
- m_documentProperties["generateproxy"] = QString::number((int) KdenliveSettings::enableproxy());
- m_documentProperties["proxyminsize"] = "1000";
+ m_documentProperties["generateproxy"] = QString::number((int) KdenliveSettings::generateproxy());
+ m_documentProperties["proxyminsize"] = QString::number(KdenliveSettings::proxyminsize());
if (!url.isEmpty()) {
QString tmpFile;
<default>false</default>
</entry>
+ <entry name="generateproxy" type="Bool">
+ <label>Auto generate proxy for new clips.</label>
+ <default>false</default>
+ </entry>
+
+ <entry name="proxyminsize" type="Int">
+ <label>Minimum source size for proxy creation.</label>
+ <default>1000</default>
+ </entry>
+
<entry name="proxyparams" type="String">
<label>Proxy clips transcoding parameters.</label>
<default>-f avi -acodec libmp3lame -ac 2 -ab 92k -ar 48000 -vcodec mpeg2video -g 5 -deinterlace -s 480x270 -b 150k</default>
QWidget *p8 = new QWidget;
m_configProject.setupUi(p8);
m_page8 = addPage(p8, i18n("Project Defaults"), "document-new");
+ connect(m_configProject.kcfg_enableproxy, SIGNAL(toggled(bool)), m_configProject.proxy_frame, SLOT(setEnabled(bool)));
+ m_configProject.proxy_frame->setEnabled(KdenliveSettings::enableproxy());
QWidget *p3 = new QWidget;
m_configTimeline.setupUi(p3);
if (m_configProject.kcfg_enableproxy->isChecked() != KdenliveSettings::enableproxy()) {
KdenliveSettings::setEnableproxy(m_configProject.kcfg_enableproxy->isChecked());
}
+
+ if (m_configProject.kcfg_generateproxy->isChecked() != KdenliveSettings::generateproxy()) {
+ KdenliveSettings::setGenerateproxy(m_configProject.kcfg_generateproxy->isChecked());
+ }
+
+ if (m_configProject.kcfg_proxyminsize->value() != KdenliveSettings::proxyminsize()) {
+ KdenliveSettings::setProxyminsize(m_configProject.kcfg_proxyminsize->value());
+ }
if (m_modified) {
// The transcoding profiles were modified, save.
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_projectMonitor->render, SIGNAL(removeInvalidClip(const QString &, bool)), m_projectList, SLOT(slotRemoveInvalidClip(const QString &, bool)));
+ connect(m_projectMonitor->render, SIGNAL(removeInvalidProxy(const QString &)), m_projectList, SLOT(slotRemoveInvalidProxy(const QString &)));
connect(m_clipMonitor, SIGNAL(refreshClipThumbnail(const QString &, bool)), m_projectList, SLOT(slotRefreshClipThumbnail(const QString &, bool)));
QPoint projectTracks(KdenliveSettings::videotracks(), KdenliveSettings::audiotracks());
bool useProxy = KdenliveSettings::enableproxy();
QString proxyParams = KdenliveSettings::proxyparams();
- bool generateProxy = KdenliveSettings::enableproxy();
- int proxyMinSize = 1000;
+ bool generateProxy = KdenliveSettings::generateproxy();
+ int proxyMinSize = KdenliveSettings::proxyminsize();
if (!showProjectSettings) {
if (!KdenliveSettings::activatetabs())
if (!closeCurrentDocument())
if (KdenliveSettings::videothumbnails() != w->enableVideoThumbs()) slotSwitchVideoThumbs();
if (KdenliveSettings::audiothumbnails() != w->enableAudioThumbs()) slotSwitchAudioThumbs();
if (m_activeDocument->profilePath() != profile) slotUpdateProjectProfile(profile);
- m_activeDocument->setDocumentProperty("proxyparams", w->proxyParams());
- m_activeDocument->setDocumentProperty("generateproxy", QString::number((int) w->generateProxy()));
- m_activeDocument->setDocumentProperty("proxyminsize", QString::number(w->proxyMinSize()));
+ if (m_activeDocument->getDocumentProperty("proxyparams") != w->proxyParams()) {
+ m_activeDocument->setModified();
+ m_activeDocument->setDocumentProperty("proxyparams", w->proxyParams());
+ if (m_activeDocument->clipManager()->clipsCount() > 0 && KMessageBox::questionYesNo(this, i18n("You have changed the proxy parameters. Do you want to recreate all proxy clips for this project?")) == KMessageBox::Yes) {
+ //TODO: rebuild all proxies
+ //m_activeDocument->rebuildAllProxies();
+ }
+ }
+ if (m_activeDocument->getDocumentProperty("generateproxy") != QString::number((int) w->generateProxy())) {
+ m_activeDocument->setModified();
+ m_activeDocument->setDocumentProperty("generateproxy", QString::number((int) w->generateProxy()));
+ }
+ if (m_activeDocument->getDocumentProperty("proxyminsize") != QString::number(w->proxyMinSize())) {
+ m_activeDocument->setModified();
+ m_activeDocument->setDocumentProperty("proxyminsize", QString::number(w->proxyMinSize()));
+ }
if (QString::number((int) w->useProxy()) != m_activeDocument->getDocumentProperty("enableproxy")) {
m_activeDocument->setDocumentProperty("enableproxy", QString::number((int) w->useProxy()));
+ m_activeDocument->setModified();
slotUpdateProxySettings();
}
}
ClipProperties dia(cliplist, m_activeDocument->timecode(), commonproperties, this);
if (dia.exec() == QDialog::Accepted) {
QUndoCommand *command = new QUndoCommand();
+ command->setText(i18n("Edit clips"));
QMap <QString, QString> newImageProps = dia.properties();
// Transparency setting applies only for images
QMap <QString, QString> newProps = newImageProps;
newProps.remove("transparency");
- command->setText(i18n("Edit clips"));
+
for (int i = 0; i < cliplist.count(); i++) {
DocClipBase *clip = cliplist.at(i);
if (clip->clipType() == IMAGE)
const int itemHeight = 38;
ProjectItem::ProjectItem(QTreeWidget * parent, DocClipBase *clip) :
+ QTreeWidgetItem(parent, PROJECTCLIPTYPE),
m_clip(clip),
- m_clipId(clip->getId()),
- QTreeWidgetItem(parent, PROJECTCLIPTYPE)
+ m_clipId(clip->getId())
{
buildItem();
}
ProjectItem::ProjectItem(QTreeWidgetItem * parent, DocClipBase *clip) :
+ QTreeWidgetItem(parent, PROJECTCLIPTYPE),
m_clip(clip),
- m_clipId(clip->getId()),
- QTreeWidgetItem(parent, PROJECTCLIPTYPE)
+ m_clipId(clip->getId())
{
buildItem();
}
}
-void ProjectItem::setProxyStatus(int status)
+void ProjectItem::setProxyStatus(PROXYSTATUS status)
{
- if (status == data(0, ProxyRole).toInt()) return;
setData(0, ProxyRole, status);
- if (m_clip && status == 0) m_clip->abortProxy();
}
bool ProjectItem::hasProxy() const
{
if (m_clip == NULL) return false;
- return !m_clip->getProperty("proxy").isEmpty();
+ if (m_clip->getProperty("proxy").isEmpty() || m_clip->getProperty("proxy") == "-" || data(0, ProxyRole).toInt() == PROXYCRASHED) return false;
+ return true;
+}
+
+bool ProjectItem::isProxyReady() const
+{
+ return (data(0, ProxyRole).toInt() == PROXYDONE);
}
bool ProjectItem::isProxyRunning() const
{
- return (data(0, ProxyRole).toInt() == 1);
+ PROXYSTATUS s = (PROXYSTATUS) data(0, ProxyRole).toInt();
+ if (s == PROXYWAITING || s == CREATINGPROXY) return true;
+ return false;
}
static int itemDefaultHeight();
void slotSetToolTip();
/** \brief Set the status of proxy clip creation. 0 = no proxy, 1 = creating proxy, 2 = proxy created. */
- void setProxyStatus(int status);
+ void setProxyStatus(PROXYSTATUS status);
/** \brief Returns the proxy status for this clip (true means there is a proxy clip). */
bool hasProxy() const;
+ /** \brief Returns true if the proxy for this clip is ready. */
+ bool isProxyReady() const;
/** \brief Returns true if we are currently creating the proxy for this clip. */
bool isProxyRunning() const;
private:
CLIPTYPE m_clipType;
- QString m_clipId;
DocClipBase *m_clip;
+ QString m_clipId;
void buildItem();
#include <KIO/NetAccess>
#include <KFileItem>
#include <KApplication>
+#include <KStandardDirs>
+
#ifdef NEPOMUK
#include <nepomuk/global.h>
#include <nepomuk/resourcemanager.h>
QMap <QString, QString> oldprops;
QMap <QString, QString> newprops;
oldprops["name"] = clip->referencedClip()->getProperty("name");
- newprops["name"] = item->text(0);
- slotUpdateClipProperties(clip, newprops);
- emit projectModified();
- EditClipCommand *command = new EditClipCommand(this, clip->clipId(), oldprops, newprops, false);
- m_commandStack->push(command);
+ if (oldprops.value("name") != item->text(0)) {
+ newprops["name"] = item->text(0);
+ slotUpdateClipProperties(clip, newprops);
+ emit projectModified();
+ EditClipCommand *command = new EditClipCommand(this, clip->clipId(), oldprops, newprops, false);
+ m_commandStack->push(command);
+ }
}
}
}
item = new ProjectItem(m_listView, clip);
}
if (item->data(0, DurationRole).isNull()) item->setData(0, DurationRole, i18n("Loading"));
+ connect(clip, SIGNAL(createProxy(const QString)), this, SLOT(slotCreateProxy(const QString)));
+ connect(clip, SIGNAL(abortProxy(const QString)), this, SLOT(slotAbortProxy(const QString)));
if (getProperties) {
m_listView->processLayout();
m_refreshed = false;
- // Proxy clips
- CLIPTYPE t = clip->clipType();
- if ((t == VIDEO || t == AV || t == UNKNOWN) && useProxy()) {
- if (clip->getProperty("proxy").isEmpty()) {
-
- //connect(clip, SIGNAL(proxyReady(const QString&, bool)), this, SLOT(slotGotProxy(const QString&, bool)));
- //setProxyStatus(item, 1);
- //clip->generateProxy(m_doc->projectFolder(), proxyParams());
- }
- else {
- // Proxy clip already created
- setProxyStatus(item, 2);
- QDomElement e = clip->toXML().cloneNode().toElement();
- e.removeAttribute("file_hash");
- m_infoQueue.insert(clip->getId(), e);
- }
- }
- //else {
- // We don't use proxies
- // remove file_hash so that we load all properties for the clip
- QDomElement e = clip->toXML().cloneNode().toElement();
- e.removeAttribute("file_hash");
- m_infoQueue.insert(clip->getId(), e);
- //}
- //m_render->getFileProperties(clip->toXML(), clip->getId(), true);
+ QDomElement e = clip->toXML().cloneNode().toElement();
+ e.removeAttribute("file_hash");
+ m_infoQueue.insert(clip->getId(), e);
}
- else if (!clip->getProperty("proxy").isEmpty()) {
- connect(clip, SIGNAL(proxyReady(const QString&, bool)), this, SLOT(slotGotProxy(const QString&, bool)));
- setProxyStatus(item, 1);
- clip->generateProxy(m_doc->projectFolder(), proxyParams());
+ else if (item->hasProxy() && !item->isProxyRunning()) {
+ slotCreateProxy(clip->getId());
}
clip->askForAudioThumbs();
m_queueRunner = QtConcurrent::run(this, &ProjectList::slotProcessNextClipInQueue);
}
-void ProjectList::slotGotProxy(const QString &id, bool success)
+void ProjectList::slotGotProxy(const QString &id)
{
ProjectItem *item = getItemById(id);
if (item) {
- if (success) {
- // Proxy clip successfully created
- setProxyStatus(item, 2);
- QDomElement e = item->referencedClip()->toXML().cloneNode().toElement();
- e.removeAttribute("file_hash");
- e.setAttribute("replace", 1);
- m_infoQueue.insert(id, e);
- if (!m_queueRunner.isRunning() && m_processingClips.isEmpty()) m_queueRunner = QtConcurrent::run(this, &ProjectList::slotProcessNextClipInQueue);
- }
- else setProxyStatus(item, 0);
- update();
+ // Proxy clip successfully created
+ QDomElement e = item->referencedClip()->toXML().cloneNode().toElement();
+ //e.removeAttribute("file_hash");
+ e.setAttribute("replace", 1);
+ m_infoQueue.insert(id, e);
+ if (!m_queueRunner.isRunning() && m_processingClips.isEmpty()) m_queueRunner = QtConcurrent::run(this, &ProjectList::slotProcessNextClipInQueue);
}
}
}
}
+void ProjectList::slotRemoveInvalidProxy(const QString &id)
+{
+ ProjectItem *item = getItemById(id);
+ if (item) {
+ item->setProxyStatus(PROXYCRASHED);
+ QString path = item->referencedClip()->getProperty("proxy");
+ KUrl proxyFolder(m_doc->projectFolder().path( KUrl::AddTrailingSlash) + "proxy/");
+
+ //Security check: make sure the invalid proxy file is in the proxy folder
+ if (proxyFolder.isParentOf(KUrl(path))) {
+ QFile::remove(path);
+ }
+ }
+ m_processingClips.removeAll(id);
+ if (!m_queueRunner.isRunning() && m_processingClips.isEmpty()) m_queueRunner = QtConcurrent::run(this, &ProjectList::slotProcessNextClipInQueue);
+}
+
void ProjectList::slotAddColorClip()
{
if (!m_commandStack)
m_timecode = doc->timecode();
m_commandStack = doc->commandStack();
m_doc = doc;
+ m_proxyList.clear();
QMap <QString, QString> flist = doc->clipManager()->documentFolderList();
QMapIterator<QString, QString> f(flist);
item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsDropEnabled);
toReload = clipId;
}
- if (!useProxy() && item->referencedClip()->getProperty("proxy").isEmpty()) setProxyStatus(item, 0);
+
+ // Proxy stuff
QString size = properties.value("frame_size");
DocClipBase *clip = item->referencedClip();
- if (useProxy() && (item->clipType() == AV || item->clipType() == VIDEO) && generateProxy() && size.section('x', 0, 0).toInt() > proxyMinSize()) {
+ if (!useProxy() && item->referencedClip()->getProperty("proxy").isEmpty()) setProxyStatus(item, NOPROXY);
+ if (useProxy() && generateProxy() && item->referencedClip()->getProperty("proxy") == "-") setProxyStatus(item, NOPROXY);
+ else if (useProxy() && !item->isProxyRunning() && (item->clipType() == AV || item->clipType() == VIDEO) && generateProxy() && size.section('x', 0, 0).toInt() > proxyMinSize()) {
if (clip->getProperty("proxy").isEmpty()) {
- connect(clip, SIGNAL(proxyReady(const QString&, bool)), this, SLOT(slotGotProxy(const QString&, bool)));
- setProxyStatus(item, 1);
- clip->generateProxy(m_doc->projectFolder(), proxyParams());
+ QString proxydir = m_doc->projectFolder().path( KUrl::AddTrailingSlash) + "proxy/";
+ clip->setProperty("proxy", proxydir + item->referencedClip()->getClipHash() + ".avi");
}
}
+
clip->setProducer(producer, replace);
clip->askForAudioThumbs();
if (!replace && item->data(0, Qt::DecorationRole).isNull())
}
item = static_cast<ProjectItem *>(*it);
if (item && item->referencedClip() != NULL) {
- QString proxy = item->referencedClip()->getProperty("proxy");
- if (!proxy.isEmpty()) list.insert(proxy, item->clipUrl().path());
+ if (item->hasProxy()) {
+ QString proxy = item->referencedClip()->getProperty("proxy");
+ list.insert(proxy, item->clipUrl().path());
+ }
}
++it;
}
return list;
}
+void ProjectList::slotCreateProxy(const QString id)
+{
+ ProjectItem *item = getItemById(id);
+ if (!item || item->isProxyRunning()) return;
+ setProxyStatus(id, PROXYWAITING);
+ if (m_abortProxyId.contains(id)) m_abortProxyId.removeAll(id);
+ QtConcurrent::run(this, &ProjectList::slotGenerateProxy, id);
+}
+
+void ProjectList::slotAbortProxy(const QString id)
+{
+ if (m_proxyList.contains(id)) m_proxyList.removeAll(id);
+ ProjectItem *item = getItemById(id);
+ if (item) {
+ if (item->isProxyReady()) slotGotProxy(id);
+ else if (item->isProxyRunning()) m_abortProxyId << id;
+ setProxyStatus(id, NOPROXY);
+ }
+}
+
+void ProjectList::slotGenerateProxy(const QString id)
+{
+ setProxyStatus(id, CREATINGPROXY);
+ ProjectItem *item = getItemById(id);
+ if (item == NULL) return;
+ QString path = item->referencedClip()->getProperty("proxy");
+ if (path.isEmpty()) {
+ setProxyStatus(id, PROXYCRASHED);
+ return;
+ }
+
+ QString url = item->clipUrl().path();
+
+ if (QFile::exists(path)) {
+ setProxyStatus(id, PROXYDONE);
+ slotGotProxy(id);
+ return;
+ }
+ else {
+ // Make sure proxy path is writable
+ QFile file(path);
+ if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
+ setProxyStatus(id, PROXYCRASHED);
+ return;
+ }
+ file.close();
+ QFile::remove(path);
+ }
+
+ QStringList parameters;
+ parameters << "-i" << url;
+ QString params = proxyParams();
+ foreach(QString s, params.split(' '))
+ parameters << s;
+
+ // Make sure we don't block when proxy file already exists
+ parameters << "-y";
+ parameters << path;
+ QProcess myProcess;
+ myProcess.start("ffmpeg", parameters);
+ myProcess.waitForStarted();
+ int result = -1;
+ while (myProcess.state() != QProcess::NotRunning) {
+ // building proxy file
+ if (m_abortProxyId.contains(id)) {
+ myProcess.close();
+ myProcess.waitForFinished();
+ m_abortProxyId.removeAll(id);
+ QFile::remove(path);
+ setProxyStatus(id, NOPROXY);
+ result = -2;
+
+ }
+ myProcess.waitForFinished(500);
+ }
+ myProcess.waitForFinished();
+ if (result == -1) result = myProcess.exitStatus();
+ if (result == 0) {
+ // proxy successfully created
+ setProxyStatus(id, PROXYDONE);
+ slotGotProxy(id);
+ }
+ else if (result == 1) {
+ // Proxy process crashed
+ QFile::remove(path);
+ setProxyStatus(id, PROXYCRASHED);
+ }
+}
+
void ProjectList::updateProxyConfig()
{
ProjectItem *item;
if (generateProxy() && useProxy()) {
DocClipBase *clip = item->referencedClip();
if (clip->getProperty("frame_size").section('x', 0, 0).toInt() > proxyMinSize()) {
- connect(clip, SIGNAL(proxyReady(const QString &, bool)), this, SLOT(slotGotProxy(const QString &, bool)));
- setProxyStatus(item, 1);
- clip->generateProxy(m_doc->projectFolder(), proxyParams());
+ kDebug()<<"// UPDATE ST PROXY";
+ slotCreateProxy(clip->getId());
+ setProxyStatus(item, PROXYWAITING);
}
}
- else if (!item->referencedClip()->getProperty("proxy").isEmpty()) {
+ else if (!item->hasProxy()) {
// remove proxy
item->referencedClip()->clearProperty("proxy");
QDomElement e = item->toXml().cloneNode().toElement();
{
QList<QTreeWidgetItem *> list = m_listView->selectedItems();
QTreeWidgetItem *listItem;
+ QUndoCommand *command = new QUndoCommand();
+ command->setText(i18np("Edit clip", "Edit clips", list.count()));
+
+ // Make sure the proxy folder exists
+ QString proxydir = m_doc->projectFolder().path( KUrl::AddTrailingSlash) + "proxy/";
+ KStandardDirs::makeDir(proxydir);
+
+ QMap <QString, QString> newProps;
+ if (!doProxy) newProps.insert("proxy", "-");
for (int i = 0; i < list.count(); i++) {
listItem = list.at(i);
if (listItem->type() == PROJECTFOLDERTYPE) {
CLIPTYPE t = item->clipType();
if ((t == VIDEO || t == AV || t == UNKNOWN) && item->referencedClip()) {
if (doProxy) {
- DocClipBase *clip = item->referencedClip();
- connect(clip, SIGNAL(proxyReady(const QString&, bool)), this, SLOT(slotGotProxy(const QString&, bool)));
- setProxyStatus(item, 1);
- clip->generateProxy(m_doc->projectFolder(), proxyParams());
- }
- else if (!item->referencedClip()->getProperty("proxy").isEmpty()) {
- // remove proxy
- if (!item->isProxyRunning()) {
- setProxyStatus(item, 0);
- QDomElement e = item->toXml().cloneNode().toElement();
- e.removeAttribute("file_hash");
- e.setAttribute("replace", 1);
- m_infoQueue.insert(item->clipId(), e);
- }
- else setProxyStatus(item, 0);
+ newProps.clear();
+ QString path = proxydir + item->referencedClip()->getClipHash() + ".avi";
+ newProps.insert("proxy", path);
}
+ new EditClipCommand(this, item->clipId(), item->referencedClip()->properties(), newProps, true, command);
}
}
}
- if (!m_infoQueue.isEmpty() && !m_queueRunner.isRunning() && m_processingClips.isEmpty()) m_queueRunner = QtConcurrent::run(this, &ProjectList::slotProcessNextClipInQueue);
+ m_doc->commandStack()->push(command);
+ //if (!m_infoQueue.isEmpty() && !m_queueRunner.isRunning() && m_processingClips.isEmpty()) m_queueRunner = QtConcurrent::run(this, &ProjectList::slotProcessNextClipInQueue);
+}
+
+void ProjectList::setProxyStatus(const QString id, PROXYSTATUS status)
+{
+ ProjectItem *item = getItemById(id);
+ setProxyStatus(item, status);
}
-void ProjectList::setProxyStatus(ProjectItem *item, int status)
+void ProjectList::setProxyStatus(ProjectItem *item, PROXYSTATUS status)
{
+ if (item == NULL) return;
monitorItemEditing(false);
item->setProxyStatus(status);
monitorItemEditing(true);
QString proxyText;
QBrush brush;
QColor color;
- if (proxy == 1) {
- proxyText = i18n("Generating proxy...");
- brush = option.palette.highlight();
- color = option.palette.color(QPalette::HighlightedText);
- }
- else {
+ if (proxy == PROXYDONE) {
proxyText = i18n("Proxy");
brush = option.palette.mid();
color = option.palette.color(QPalette::WindowText);
}
+ else {
+ if (proxy == CREATINGPROXY) proxyText = i18n("Generating proxy...");
+ else if (proxy == PROXYWAITING) proxyText = i18n("Waiting proxy...");
+ else if (proxy == PROXYCRASHED) proxyText = i18n("proxy crashed");
+ brush = option.palette.highlight();
+ color = option.palette.color(QPalette::HighlightedText);
+ }
+
txtBounding = painter->boundingRect(r2, Qt::AlignRight | Qt::AlignVCenter, " " + proxyText + " ");
painter->setPen(Qt::NoPen);
painter->setBrush(brush);
void slotRefreshClipThumbnail(const QString &clipId, bool update = true);
void slotRefreshClipThumbnail(QTreeWidgetItem *item, bool update = true);
void slotRemoveInvalidClip(const QString &id, bool replace);
+ void slotRemoveInvalidProxy(const QString &id);
void slotSelectClip(const QString &ix);
/** @brief Prepares removing the selected items. */
QList <QString> m_thumbnailQueue;
QAction *m_proxyAction;
QStringList m_processingClips;
+ /** @brief Holds a list of ids for the clips that need to be proxied. */
+ QStringList m_proxyList;
+ /** @brief Holds a list of proxy clip that should be aborted. */
+ QStringList m_abortProxyId;
+
void requestClipThumbnail(const QString id);
/** @brief Creates an EditFolderCommand to change the name of an folder item. */
/** @brief Set the Proxy status on a clip.
* @param item The clip item to set status
- * @param status The status (1 = creating proxy, 2 = proxy is ok) */
- void setProxyStatus(ProjectItem *item, int status);
+ * @param status The proxy status (see definitions.h) */
+ void setProxyStatus(const QString id, PROXYSTATUS status);
+ void setProxyStatus(ProjectItem *item, PROXYSTATUS status);
+
void monitorItemEditing(bool enable);
private slots:
/** @brief Add a sequence from the stopmotion widget. */
void slotAddOrUpdateSequence(const QString frameName);
/** @brief A proxy clip was created, update display. */
- void slotGotProxy(const QString &id, bool success);
+ void slotGotProxy(const QString &id);
/** @brief Enable / disable proxy for current clip. */
void slotProxyCurrentItem(bool doProxy);
+ /** @brief Put clip in the proxy waiting list. */
+ void slotCreateProxy(const QString id);
+ /** @brief Stop creation of this clip's proxy. */
+ void slotAbortProxy(const QString id);
+ /** @brief Start creation of proxy clip. */
+ void slotGenerateProxy(const QString id);
signals:
void clipSelected(DocClipBase *, QPoint zone = QPoint());
}
else {
enable_proxy->setChecked(KdenliveSettings::enableproxy());
- generate_proxy->setChecked(KdenliveSettings::enableproxy());
- proxy_minsize->setValue(1000);
+ generate_proxy->setChecked(KdenliveSettings::generateproxy());
+ proxy_minsize->setValue(KdenliveSettings::proxyminsize());
proxy_params->setText(KdenliveSettings::proxyparams());
proxy_box->setEnabled(KdenliveSettings::enableproxy());
}
void Render::getFileProperties(const QDomElement xml, const QString &clipId, int imageHeight, bool replaceProducer, bool selectClip)
{
QString path;
- if (xml.hasAttribute("proxy")) path = xml.attribute("proxy");
+ if (xml.hasAttribute("proxy") && xml.attribute("proxy") != "-") path = xml.attribute("proxy");
else path = xml.attribute("resource");
KUrl url = KUrl(path);
Mlt::Producer *producer = NULL;
if (producer == NULL || producer->is_blank() || !producer->is_valid()) {
kDebug() << " / / / / / / / / ERROR / / / / // CANNOT LOAD PRODUCER: ";
- emit removeInvalidClip(clipId, replaceProducer);
+ if (xml.hasAttribute("proxy") && xml.attribute("proxy") != "-") {
+ // Proxy file is corrupted
+ emit removeInvalidProxy(clipId);
+ }
+ else emit removeInvalidClip(clipId, replaceProducer);
delete producer;
return;
}
void durationChanged(int);
void rendererPosition(int);
void rendererStopped(int);
+ /** @brief The clip is not valid, should be removed from project. */
void removeInvalidClip(const QString &, bool replaceProducer);
+ /** @brief The proxy is not valid, should be deleted. */
+ void removeInvalidProxy(const QString &);
void refreshDocumentProducers();
/** @brief A frame's image has to be shown.
<string>Clip Properties</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
- <item row="7" column="1" colspan="2">
+ <item row="8" column="1" colspan="2">
<spacer name="verticalSpacer_4">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
- <item row="2" column="0" colspan="4">
+ <item row="3" column="0" colspan="4">
<widget class="KLineEdit" name="clip_path">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
- <item row="3" column="0" colspan="4">
+ <item row="4" column="0" colspan="4">
<widget class="QLabel" name="label_description">
<property name="text">
<string>Description</string>
</property>
</widget>
</item>
- <item row="4" column="0" colspan="4">
+ <item row="5" column="0" colspan="4">
<widget class="KLineEdit" name="clip_description"/>
</item>
- <item row="5" column="0">
+ <item row="6" column="0">
<widget class="QLabel" name="label_duration">
<property name="text">
<string>Duration</string>
</property>
</widget>
</item>
- <item row="5" column="1">
+ <item row="6" column="1">
<widget class="KRestrictedLine" name="clip_duration">
<property name="inputMask">
<string>99:99:99:99; </string>
</property>
</widget>
</item>
- <item row="5" column="2">
+ <item row="6" column="2">
<widget class="QLabel" name="label_size">
<property name="text">
<string>Size:</string>
</property>
</widget>
</item>
- <item row="5" column="3">
+ <item row="6" column="3">
<widget class="QLabel" name="clip_filesize">
<property name="text">
<string>File size</string>
</property>
</widget>
</item>
- <item row="8" column="0" colspan="4">
+ <item row="9" column="0" colspan="4">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
- <item row="6" column="0" colspan="4">
+ <item row="7" column="0" colspan="4">
<widget class="QTabWidget" name="tabWidget">
<property name="tabPosition">
<enum>QTabWidget::South</enum>
<attribute name="title">
<string>Video</string>
</attribute>
- <layout class="QGridLayout" name="gridLayout">
- <item row="0" column="0" colspan="2">
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
<widget class="QTreeWidget" name="clip_vproperties">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
<attribute name="title">
<string>Audio</string>
</attribute>
- <layout class="QGridLayout" name="gridLayout_4">
- <item row="0" column="0" colspan="2">
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
<widget class="QTreeWidget" name="clip_aproperties">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</widget>
</widget>
</item>
+ <item row="2" column="0">
+ <widget class="Line" name="line">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
</layout>
</widget>
<customwidgets>
<rect>
<x>0</x>
<y>0</y>
- <width>264</width>
- <height>304</height>
+ <width>312</width>
+ <height>294</height>
</rect>
</property>
<property name="windowTitle">
</spacer>
</item>
<item row="2" column="0" colspan="5">
- <widget class="QGroupBox" name="groupBox">
- <property name="title">
- <string>Proxy clips</string>
+ <widget class="QCheckBox" name="kcfg_enableproxy">
+ <property name="text">
+ <string>Enable proxy clips</string>
</property>
- <property name="checked">
- <bool>false</bool>
+ </widget>
+ </item>
+ <item row="3" column="0" colspan="5">
+ <widget class="QFrame" name="proxy_frame">
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
</property>
<layout class="QGridLayout" name="gridLayout">
+ <property name="margin">
+ <number>0</number>
+ </property>
<item row="0" column="0">
- <widget class="QCheckBox" name="kcfg_enableproxy">
+ <widget class="QCheckBox" name="kcfg_generateproxy">
<property name="text">
- <string>Generate proxy clips</string>
+ <string>Generate proxy if clip larger than</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="KIntSpinBox" name="kcfg_proxyminsize">
+ <property name="suffix">
+ <string>pixels</string>
+ </property>
+ <property name="maximum">
+ <number>10000</number>
+ </property>
+ <property name="value">
+ <number>1000</number>
</property>
</widget>
</item>
</property>
</widget>
</item>
- <item row="2" column="0">
- <widget class="QPlainTextEdit" name="kcfg_proxyparams">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- </widget>
+ <item row="2" column="0" colspan="2">
+ <widget class="QPlainTextEdit" name="kcfg_proxyparams"/>
</item>
</layout>
</widget>
</item>
- <item row="3" column="0">
+ <item row="4" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>