* improve proxy crash feedback
* Small change in proxy icon (use yellow color to make it more visible)
QString clipType;
QString realPath = e.attribute("resource");
QString id = e.attribute("id");
QString clipType;
QString realPath = e.attribute("resource");
QString id = e.attribute("id");
+ // Tell Kdenlive to recreate proxy
+ e.setAttribute("_replaceproxy", "1");
// Replace proxy url with real clip in MLT producers
QDomNodeList properties;
QDomElement mltProd;
// Replace proxy url with real clip in MLT producers
QDomNodeList properties;
QDomElement mltProd;
bool ProjectItem::hasProxy() const
{
if (m_clip == NULL) return false;
bool ProjectItem::hasProxy() const
{
if (m_clip == NULL) return false;
- if (m_clip->getProperty("proxy").isEmpty() || m_clip->getProperty("proxy") == "-" || data(0, JobProgressRole).toInt() == JOBCRASHED) return false;
+ if (m_clip->getProperty("proxy").size() < 2 || data(0, JobProgressRole).toInt() == JOBCRASHED) return false;
{
m_render = projectRender;
m_listView->setIconSize(QSize((ProjectItem::itemDefaultHeight() - 2) * m_render->dar(), ProjectItem::itemDefaultHeight() - 2));
{
m_render = projectRender;
m_listView->setIconSize(QSize((ProjectItem::itemDefaultHeight() - 2) * m_render->dar(), ProjectItem::itemDefaultHeight() - 2));
+ connect(m_render, SIGNAL(requestProxy(QString)), this, SLOT(slotCreateProxy(QString)));
}
void ProjectList::slotClipSelected()
}
void ProjectList::slotClipSelected()
} else {
item = static_cast <ProjectItem *>(*it);
clip = item->referencedClip();
} else {
item = static_cast <ProjectItem *>(*it);
clip = item->referencedClip();
- if (item->referencedClip()->getProducer() == NULL) {
+ if (clip->getProducer() == NULL) {
bool replace = false;
if (brokenClips.contains(item->clipId())) {
// if this is a proxy clip, disable proxy
bool replace = false;
if (brokenClips.contains(item->clipId())) {
// if this is a proxy clip, disable proxy
xml.removeAttribute("file_hash");
xml.removeAttribute("proxy_out");
}
xml.removeAttribute("file_hash");
xml.removeAttribute("proxy_out");
}
- if (!replace) replace = xml.attribute("replace") == "1";
+ if (!replace) replace = xml.attribute("_replaceproxy") == "1";
+ xml.removeAttribute("_replaceproxy");
if (replace) {
resetThumbsProducer(clip);
}
if (replace) {
resetThumbsProducer(clip);
}
getCachedThumbnail(item);
}
if (item->data(0, DurationRole).toString().isEmpty()) {
getCachedThumbnail(item);
}
if (item->data(0, DurationRole).toString().isEmpty()) {
- item->changeDuration(item->referencedClip()->getProducer()->get_playtime());
+ item->changeDuration(clip->getProducer()->get_playtime());
}
if (clip->isPlaceHolder()) {
QPixmap pixmap = qVariantValue<QPixmap>(item->data(0, Qt::DecorationRole));
}
if (clip->isPlaceHolder()) {
QPixmap pixmap = qVariantValue<QPixmap>(item->data(0, Qt::DecorationRole));
p.end();
item->setData(0, Qt::DecorationRole, pixmap);
}
p.end();
item->setData(0, Qt::DecorationRole, pixmap);
}
+ else if (clip->getProperty("_replaceproxy") == "1") {
+ clip->setProperty("_replaceproxy", QString());
+ slotCreateProxy(clip->getId());
+ }
}
item->setData(0, UsageRole, QString::number(item->numReferences()));
}
}
item->setData(0, UsageRole, QString::number(item->numReferences()));
}
slotUpdateJobStatus(item, PROXYJOB, JOBCRASHED, i18n("Failed to create proxy, empty path."));
return;
}
slotUpdateJobStatus(item, PROXYJOB, JOBCRASHED, i18n("Failed to create proxy, empty path."));
return;
}
-
- ProxyJob *job = new ProxyJob(item->clipType(), id, QStringList() << path << item->clipUrl().path() << item->referencedClip()->producerProperty("_exif_orientation") << m_doc->getDocumentProperty("proxyparams").simplified() << QString::number(m_render->frameRenderWidth()) << QString::number(m_render->renderHeight()));
- if (job->isExclusive() && hasPendingJob(item, job->jobType)) {
- delete job;
- return;
- }
-
if (QFileInfo(path).size() > 0) {
// Proxy already created
setJobStatus(item, PROXYJOB, JOBDONE);
if (QFileInfo(path).size() > 0) {
// Proxy already created
setJobStatus(item, PROXYJOB, JOBDONE);
+ ProxyJob *job = new ProxyJob(item->clipType(), id, QStringList() << path << item->clipUrl().path() << item->referencedClip()->producerProperty("_exif_orientation") << m_doc->getDocumentProperty("proxyparams").simplified() << QString::number(m_render->frameRenderWidth()) << QString::number(m_render->renderHeight()));
+ if (job->isExclusive() && hasPendingJob(item, job->jobType)) {
+ delete job;
+ return;
+ }
+
m_jobList.append(job);
setJobStatus(item, job->jobType, JOBWAITING, 0, job->statusMessage());
slotCheckJobProcess();
m_jobList.append(job);
setJobStatus(item, job->jobType, JOBWAITING, 0, job->statusMessage());
slotCheckJobProcess();
emit addClip(destination, QString(), QString());
}
} else if (job->jobStatus == JOBCRASHED || job->jobStatus == JOBABORTED) {
emit addClip(destination, QString(), QString());
}
} else if (job->jobStatus == JOBCRASHED || job->jobStatus == JOBABORTED) {
- emit updateJobStatus(job->clipId(), job->jobType, job->jobStatus, job->errorMessage());
+ emit updateJobStatus(job->clipId(), job->jobType, job->jobStatus, job->errorMessage(), QString(), job->logDetails());
}
}
// Thread finished, cleanup & update count
}
}
// Thread finished, cleanup & update count
// remove proxy
QMap <QString, QString> newProps;
newProps.insert("proxy", QString());
// remove proxy
QMap <QString, QString> newProps;
newProps.insert("proxy", QString());
- newProps.insert("replace", "1");
// insert required duration for proxy
newProps.insert("proxy_out", item->referencedClip()->producerProperty("out"));
new EditClipCommand(this, item->clipId(), item->referencedClip()->currentProperties(newProps), newProps, true, command);
// insert required duration for proxy
newProps.insert("proxy_out", item->referencedClip()->producerProperty("out"));
new EditClipCommand(this, item->clipId(), item->referencedClip()->currentProperties(newProps), newProps, true, command);
// remove proxy
QMap <QString, QString> newProps;
newProps.insert("proxy", QString());
// remove proxy
QMap <QString, QString> newProps;
newProps.insert("proxy", QString());
- newProps.insert("replace", "1");
new EditClipCommand(this, item->clipId(), item->referencedClip()->properties(), newProps, true, command);
}
}
new EditClipCommand(this, item->clipId(), item->referencedClip()->properties(), newProps, true, command);
}
}
{
if (item->hasProxy()) {
QPainter p(&pix);
{
if (item->hasProxy()) {
QPainter p(&pix);
- QColor c = QPalette().base().color();
- c.setAlpha(200);
- QBrush br(c);
- p.setBrush(br);
- p.setPen(Qt::NoPen);
- QRect r(1, 1, 15, 15);
- p.drawRoundedRect(r, 2, 2);
- p.setPen(QPalette().text().color());
+ QColor c(220, 220, 10, 200);
+ QRect r(0, 0, 12, 12);
+ p.fillRect(r, c);
QFont font = p.font();
font.setBold(true);
p.setFont(font);
QFont font = p.font();
font.setBold(true);
p.setFont(font);
p.drawText(r, Qt::AlignCenter, i18nc("The first letter of Proxy, used as abbreviation", "P"));
}
}
p.drawText(r, Qt::AlignCenter, i18nc("The first letter of Proxy, used as abbreviation", "P"));
}
}
+const QString AbstractClipJob::logDetails() const
+{
+ return m_logDetails;
+}
+
void AbstractClipJob::startJob()
{
}
void AbstractClipJob::startJob()
{
}
bool replaceClip;
const QString clipId() const;
const QString errorMessage() const;
bool replaceClip;
const QString clipId() const;
const QString errorMessage() const;
+ const QString logDetails() const;
void setStatus(CLIPJOBSTATUS status);
virtual const QString destination() const;
virtual void startJob();
void setStatus(CLIPJOBSTATUS status);
virtual const QString destination() const;
virtual void startJob();
protected:
QString m_errorMessage;
protected:
QString m_errorMessage;
QProcess *m_jobProcess;
signals:
QProcess *m_jobProcess;
signals:
{
if (!m_jobProcess || m_jobDuration == 0 || jobStatus == JOBABORTED) return;
QString log = m_jobProcess->readAll();
{
if (!m_jobProcess || m_jobDuration == 0 || jobStatus == JOBABORTED) return;
QString log = m_jobProcess->readAll();
- if (!log.isEmpty()) m_errorMessage.append(log + '\n');
+ if (!log.isEmpty()) m_logDetails.append(log + '\n');
int progress;
// Parse FFmpeg output
if (log.contains("frame=")) {
int progress;
// Parse FFmpeg output
if (log.contains("frame=")) {
if (QFileInfo(m_dest).size() == 0) {
// File was not created
processLogInfo();
if (QFileInfo(m_dest).size() == 0) {
// File was not created
processLogInfo();
- m_errorMessage.append(i18n("Failed to create file."));
+ m_errorMessage.append(i18n("Failed to create proxy clip."));
setStatus(JOBCRASHED);
}
else setStatus(JOBDONE);
setStatus(JOBCRASHED);
}
else setStatus(JOBDONE);
{
if (!m_jobProcess || jobStatus == JOBABORTED) return;
QString log = m_jobProcess->readAll();
{
if (!m_jobProcess || jobStatus == JOBABORTED) return;
QString log = m_jobProcess->readAll();
- if (!log.isEmpty()) m_errorMessage.append(log + '\n');
+ if (!log.isEmpty()) m_logDetails.append(log + '\n');
else return;
int progress;
if (m_isFfmpegJob) {
else return;
int progress;
if (m_isFfmpegJob) {
bool proxyProducer;
if (info.xml.hasAttribute("proxy") && info.xml.attribute("proxy") != "-") {
path = info.xml.attribute("proxy");
bool proxyProducer;
if (info.xml.hasAttribute("proxy") && info.xml.attribute("proxy") != "-") {
path = info.xml.attribute("proxy");
+ // Check for missing proxies
+ if (QFileInfo(path).size() <= 0) {
+ // proxy is missing, re-create it
+ emit requestProxy(info.clipId);
+ proxyProducer = false;
+ path = info.xml.attribute("resource");
+ }
+ else proxyProducer = true;
}
else {
path = info.xml.attribute("resource");
}
else {
path = info.xml.attribute("resource");
*/
void removeInvalidProxy(const QString &id, bool durationError);
void refreshDocumentProducers(bool displayRatioChanged, bool fpsChanged);
*/
void removeInvalidProxy(const QString &id, bool durationError);
void refreshDocumentProducers(bool displayRatioChanged, bool fpsChanged);
+ /** @brief A proxy clip is missing, ask for creation. */
+ void requestProxy(QString);
+
/** @brief A frame's image has to be shown.
*
/** @brief A frame's image has to be shown.
*