connect(m_listView, SIGNAL(showProperties(DocClipBase *)), this, SIGNAL(showClipProperties(DocClipBase *)));
connect(this, SIGNAL(cancelRunningJob(const QString, stringMap )), this, SLOT(slotCancelRunningJob(const QString, stringMap)));
- connect(this, SIGNAL(processLog(ProjectItem *, int , int)), this, SLOT(slotProcessLog(ProjectItem *, int , int)));
+ connect(this, SIGNAL(processLog(const QString, int , int)), this, SLOT(slotProcessLog(const QString, int , int)));
- connect(this, SIGNAL(jobCrashed(const QString &, const QString &, const QString &, const QString)), this, SLOT(slotJobCrashed(const QString &, const QString &, const QString &, const QString)));
+ connect(this, SIGNAL(updateJobStatus(const QString &, int, int, const QString &, const QString &, const QString)), this, SLOT(slotUpdateJobStatus(const QString &, int, int, const QString &, const QString &, const QString)));
+
+ connect(this, SIGNAL(checkJobProcess()), this, SLOT(slotCheckJobProcess()));
+ connect(this, SIGNAL(gotProxy(const QString)), this, SLOT(slotGotProxyForId(const QString)));
m_listViewDelegate = new ItemDelegate(m_listView);
m_listView->setItemDelegate(m_listViewDelegate);
QTreeWidgetItemIterator it(m_listView);
ProjectItem *item;
- while (*it && !(m_abortAllJobs && m_closing)) {
+ while (*it && !m_closing) {
if ((*it)->type() == PROJECTCLIPTYPE) {
item = static_cast <ProjectItem *>(*it);
if (item->referencedClip()->getProperty("proxy") == proxyPath)
}
}
+void ProjectList::slotGotProxyForId(const QString id)
+{
+ if (m_closing) return;
+ ProjectItem *item = getItemById(id);
+ slotGotProxy(item);
+}
+
void ProjectList::slotGotProxy(ProjectItem *item)
{
if (item == NULL) return;
bool replace = false;
if (brokenClips.contains(item->clipId())) {
// if this is a proxy clip, disable proxy
+ item->setConditionalJobStatus(NOJOB, PROXYJOB);
discardJobs(item->clipId(), PROXYJOB);
clip->setProperty("proxy", "-");
replace = true;
kDebug() << "Proxy duration is wrong, try changing transcoding parameters.";
emit displayMessage(i18n("Proxy clip unusable (duration is different from original)."), -2);
}
- slotJobCrashed(item, i18n("Failed to create proxy for %1. check parameters", item->text(0)), "project_settings");
+ slotUpdateJobStatus(item, PROXYJOB, JOBCRASHED, i18n("Failed to create proxy for %1. check parameters", item->text(0)), "project_settings");
QString path = item->referencedClip()->getProperty("proxy");
KUrl proxyFolder(m_doc->projectFolder().path( KUrl::AddTrailingSlash) + "proxy/");
{
QString toReload;
ProjectItem *item = getItemById(clipId);
-
int queue = m_render->processingItems();
if (item && producer) {
monitorItemEditing(false);
// Proxy stuff
QString size = properties.value("frame_size");
if (!useProxy() && clip->getProperty("proxy").isEmpty()) {
+ item->setConditionalJobStatus(NOJOB, PROXYJOB);
discardJobs(clipId, PROXYJOB);
}
if (useProxy() && generateProxy() && clip->getProperty("proxy") == "-") {
+ item->setConditionalJobStatus(NOJOB, PROXYJOB);
discardJobs(clipId, PROXYJOB);
}
else if (useProxy() && !item->hasProxy() && !hasPendingProxy(item)) {
if (!item || hasPendingProxy(item) || item->referencedClip()->isPlaceHolder()) return;
QString path = item->referencedClip()->getProperty("proxy");
if (path.isEmpty()) {
- slotJobCrashed(item, i18n("Failed to create proxy, empty path."));
+ slotUpdateJobStatus(item, PROXYJOB, JOBCRASHED, i18n("Failed to create proxy, empty path."));
return;
}
}
if (QFileInfo(path).size() > 0) {
// Proxy already created
- setJobStatus(item, JOBDONE);
+ setJobStatus(item, PROXYJOB, JOBDONE);
slotGotProxy(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()));
m_jobList.append(job);
- setJobStatus(item, JOBWAITING);
- startJobProcess();
+ setJobStatus(item, job->jobType, JOBWAITING);
+ slotCheckJobProcess();
}
void ProjectList::slotCutClipJob(const QString &id, QPoint zone)
if (!extraParams.isEmpty()) jobParams << extraParams;
CutClipJob *job = new CutClipJob(item->clipType(), id, jobParams);
m_jobList.append(job);
- setJobStatus(item, JOBWAITING);
+ setJobStatus(item, job->jobType, JOBWAITING);
- startJobProcess();
+ slotCheckJobProcess();
}
-void ProjectList::startJobProcess()
+void ProjectList::slotCheckJobProcess()
{
if (!m_jobThreads.futures().isEmpty()) {
// Remove inactive threads
m_jobThreads.addFuture(futures.at(i));
}
}
+ if (m_jobList.isEmpty()) return;
int count = 0;
+ m_jobMutex.lock();
for (int i = 0; i < m_jobList.count(); i++) {
if (m_jobList.at(i)->jobStatus == JOBWORKING || m_jobList.at(i)->jobStatus == JOBWAITING)
count ++;
i--;
}
}
+
emit jobCount(count);
+ m_jobMutex.unlock();
if (m_jobThreads.futures().isEmpty() || m_jobThreads.futures().count() < KdenliveSettings::proxythreads()) m_jobThreads.addFuture(QtConcurrent::run(this, &ProjectList::slotProcessJobs));
}
void ProjectList::slotAbortProxy(const QString id, const QString path)
{
- QTreeWidgetItemIterator it(m_listView);
ProjectItem *item = getItemById(id);
if (!item) return;
if (!item->isProxyRunning()) slotGotProxy(item);
+ item->setConditionalJobStatus(NOJOB, PROXYJOB);
discardJobs(id, PROXYJOB);
}
emit projectModified();
AbstractClipJob *job = NULL;
int count = 0;
+ m_jobMutex.lock();
for (int i = 0; i < m_jobList.count(); i++) {
- if (job == NULL && m_jobList.at(i)->jobStatus == JOBWAITING) {
- m_jobList.at(i)->jobStatus = JOBWORKING;
- job = m_jobList.at(i);
+ if (m_jobList.at(i)->jobStatus == JOBWAITING) {
+ if (job == NULL) {
+ m_jobList.at(i)->jobStatus = JOBWORKING;
+ job = m_jobList.at(i);
+ }
count++;
}
- else if (m_jobList.at(i)->jobStatus == JOBWORKING || m_jobList.at(i)->jobStatus == JOBWAITING)
+ else if (m_jobList.at(i)->jobStatus == JOBWORKING)
count ++;
}
// Set jobs count
emit jobCount(count);
+ m_jobMutex.unlock();
+
if (job == NULL) {
break;
}
// Make sure destination path is writable
QFile file(destination);
if (!file.open(QIODevice::WriteOnly)) {
- emit jobCrashed(processingItem->clipId(), i18n("Cannot write to path: %1", destination));
+ emit updateJobStatus(job->clipId(), job->jobType, JOBCRASHED, i18n("Cannot write to path: %1", destination));
m_processingProxy.removeAll(destination);
job->setStatus(JOBCRASHED);
continue;
if (jobProcess == NULL) {
// job is finished
if (success) {
- setJobStatus(processingItem, JOBDONE);
- if (job->jobType == PROXYJOB) slotGotProxy(destination);
+ emit updateJobStatus(job->clipId(), job->jobType, JOBDONE);
+ if (job->jobType == PROXYJOB) emit gotProxy(job->clipId());
//TODO: set folder for transcoded clips
else if (job->jobType == CUTJOB) emit addClip(destination, QString(), QString());
job->setStatus(JOBDONE);
}
else {
QFile::remove(destination);
- emit jobCrashed(processingItem->clipId(), job->errorMessage());
+ emit updateJobStatus(job->clipId(), job->jobType, JOBCRASHED, job->errorMessage());
job->setStatus(JOBCRASHED);
}
m_processingProxy.removeAll(destination);
}
else {
int progress = job->processLogInfo();
- if (progress > 0) emit processLog(processingItem, progress, job->jobType);
+ if (progress > 0) emit processLog(job->clipId(), progress, job->jobType);
}
jobProcess->waitForFinished(500);
}
if (result != -2 && QFileInfo(destination).size() == 0) {
job->processLogInfo();
- emit jobCrashed(processingItem->clipId(), i18n("Failed to create file"), QString(), job->errorMessage());
+ emit updateJobStatus(job->clipId(), job->jobType, JOBCRASHED, i18n("Failed to create file"), QString(), job->errorMessage());
job->setStatus(JOBCRASHED);
result = -2;
}
if (result == QProcess::NormalExit) {
// proxy successfully created
- setJobStatus(processingItem, JOBDONE);
- if (job->jobType == PROXYJOB) slotGotProxy(destination);
+ emit updateJobStatus(job->clipId(), job->jobType, JOBDONE);
+ if (job->jobType == PROXYJOB) emit gotProxy(job->clipId());
//TODO: set folder for transcoded clips
else if (job->jobType == CUTJOB) {
CutClipJob *cutJob = static_cast<CutClipJob *>(job);
else if (result == QProcess::CrashExit) {
// Proxy process crashed
QFile::remove(destination);
- emit jobCrashed(processingItem->clipId(), i18n("Job crashed"), QString(), job->errorMessage());
+ emit updateJobStatus(job->clipId(), job->jobType, JOBCRASHED, i18n("Job crashed"), QString(), job->errorMessage());
job->setStatus(JOBCRASHED);
}
continue;
}
// Thread finished, cleanup & update count
- int count = 0;
- for (int i = 0; i < m_jobList.count(); i++) {
- if (m_jobList.at(i)->jobStatus == JOBWORKING || m_jobList.at(i)->jobStatus == JOBWAITING) {
- count ++;
- }
- else {
- AbstractClipJob *job = m_jobList.takeAt(i);
- delete job;
- i--;
- }
- }
- // Set jobs count
- emit jobCount(count);
+ QTimer::singleShot(200, this, SIGNAL(checkJobProcess()));
}
else delete command;
}
-void ProjectList::slotProcessLog(ProjectItem *item, int progress, int type)
+void ProjectList::slotProcessLog(const QString id, int progress, int type)
{
- kDebug()<<"// SET STATUS: "<<progress;
- setJobStatus(item, JOBWORKING, progress, (JOBTYPE) type);
+ ProjectItem *item = getItemById(id);
+ setJobStatus(item, (JOBTYPE) type, JOBWORKING, progress);
}
void ProjectList::slotProxyCurrentItem(bool doProxy, ProjectItem *itemToProxy)
QFile::remove(proxyPath);
}
-void ProjectList::setJobStatus(ProjectItem *item, CLIPJOBSTATUS status, int progress, JOBTYPE jobType, const QString &statusMessage)
+void ProjectList::setJobStatus(ProjectItem *item, JOBTYPE jobType, CLIPJOBSTATUS status, int progress, const QString &statusMessage)
{
if (item == NULL || (m_abortAllJobs && m_closing)) return;
monitorItemEditing(false);
- item->setJobStatus(status, progress, jobType);
+ item->setJobStatus(jobType, status, progress);
if (status == JOBCRASHED) {
DocClipBase *clip = item->referencedClip();
if (!clip) {
m_jobThreads.clearFutures();
QUndoCommand *command = new QUndoCommand();
command->setText(i18np("Cancel job", "Cancel jobs", m_jobList.count()));
+ m_jobMutex.lock();
for (int i = 0; i < m_jobList.count(); i++) {
ProjectItem *item = getItemById(m_jobList.at(i)->clipId());
if (!item || !item->referencedClip()) continue;
QMap <QString, QString> oldProps = item->referencedClip()->currentProperties(newProps);
new EditClipCommand(this, m_jobList.at(i)->clipId(), oldProps, newProps, true, command);
}
+ m_jobMutex.unlock();
if (command->childCount() > 0) {
m_doc->commandStack()->push(command);
}
bool ProjectList::hasPendingProxy(ProjectItem *item)
{
if (!item || !item->referencedClip() || m_abortAllJobs) return false;
+ AbstractClipJob *job;
+ QMutexLocker lock(&m_jobMutex);
for (int i = 0; i < m_jobList.count(); i++) {
if (m_abortAllJobs) break;
- if (m_jobList.at(i)->clipId() == item->clipId() && m_jobList.at(i)->jobType == PROXYJOB) return true;
+ job = m_jobList.at(i);
+ if (job->clipId() == item->clipId() && job->jobType == PROXYJOB && (job->jobStatus == JOBWAITING || job->jobStatus == JOBWORKING)) return true;
}
- if (item->isProxyRunning()) return true;
+
return false;
}
void ProjectList::deleteJobsForClip(const QString &clipId)
{
+ QMutexLocker lock(&m_jobMutex);
for (int i = 0; i < m_jobList.count(); i++) {
if (m_abortAllJobs) break;
if (m_jobList.at(i)->clipId() == clipId) {
}
}
-void ProjectList::slotJobCrashed(const QString &id, const QString &label, const QString &actionName, const QString details)
+void ProjectList::slotUpdateJobStatus(const QString &id, int type, int status, const QString &label, const QString &actionName, const QString details)
{
ProjectItem *item = getItemById(id);
if (!item) return;
- slotJobCrashed(item, label, actionName, details);
+ slotUpdateJobStatus(item, type, status, label, actionName, details);
}
-void ProjectList::slotJobCrashed(ProjectItem *item, const QString &label, const QString &actionName, const QString details)
+void ProjectList::slotUpdateJobStatus(ProjectItem *item, int type, int status, const QString &label, const QString &actionName, const QString details)
{
+ item->setJobStatus((JOBTYPE) type, (CLIPJOBSTATUS) status);
+ if (status != JOBCRASHED) return;
#if KDE_IS_VERSION(4,7,0)
m_infoMessage->animatedHide();
m_errorLog.clear();
}
if (!actionName.isEmpty()) {
- QAction *action;
+ QAction *action = NULL;
QList< KActionCollection * > collections = KActionCollection::allCollections();
for (int i = 0; i < collections.count(); i++) {
KActionCollection *coll = collections.at(i);
m_infoMessage->addAction(m_logAction);
}
m_infoMessage->animatedShow();
-#else
- item->setJobStatus(JOBCRASHED);
#endif
}
}
void ProjectList::discardJobs(const QString &id, JOBTYPE type) {
+ QMutexLocker lock(&m_jobMutex);
for (int i = 0; i < m_jobList.count(); i++) {
if (m_jobList.at(i)->clipId() == id && m_jobList.at(i)->jobType == type) {
// discard this job
QStringList m_processingClips;
/** @brief Holds a list of proxy urls that are currently being created. */
QStringList m_processingProxy;
- QMutex m_mutex;
+ QMutex m_jobMutex;
bool m_abortAllJobs;
/** @brief We are cleaning up the project list, so stop processing signals. */
bool m_closing;
/** @brief Set the Proxy status on a clip.
* @param item The clip item to set status
+ * @param jobType The job type
* @param status The job status (see definitions.h)
* @param progress The job progress (in percents)
- * @param jobType The job type
* @param statusMessage The job info message */
- void setJobStatus(ProjectItem *item, CLIPJOBSTATUS status, int progress = 0, JOBTYPE jobType = NOJOBTYPE, const QString &statusMessage = QString());
+ void setJobStatus(ProjectItem *item, JOBTYPE jobType, CLIPJOBSTATUS status, int progress = 0, const QString &statusMessage = QString());
void monitorItemEditing(bool enable);
/** @brief Get cached thumbnail for a project's clip or create it if no cache. */
void getCachedThumbnail(ProjectItem *item);
/** @brief The clip is about to be reloaded, cancel thumbnail requests. */
void resetThumbsProducer(DocClipBase *clip);
/** @brief Check if it is necessary to start a job thread. */
- void startJobProcess();
+ void slotCheckJobProcess();
/** @brief Check if a clip has a running or pending proxy process. */
bool hasPendingProxy(ProjectItem *item);
/** @brief Delete pending jobs for a clip. */
/** @brief Discard a running clip jobs. */
void slotCancelRunningJob(const QString id, stringMap);
/** @brief Update a clip's job status. */
- void slotProcessLog(ProjectItem *item, int progress, int);
+ void slotProcessLog(const QString, int progress, int);
/** @brief A clip job crashed, inform user. */
- void slotJobCrashed(const QString &id, const QString &label, const QString &actionName, const QString details);
- void slotJobCrashed(ProjectItem *item, const QString &label, const QString &actionName = QString(), const QString details = QString());
+ void slotUpdateJobStatus(const QString &id, int type, int status, const QString &label, const QString &actionName, const QString details);
+ void slotUpdateJobStatus(ProjectItem *item, int type, int status, const QString &label, const QString &actionName = QString(), const QString details = QString());
/** @brief Display error log for last failed job. */
void slotShowJobLog();
+ /** @brief A proxy clip is ready. */
+ void slotGotProxyForId(const QString);
signals:
void clipSelected(DocClipBase *, QPoint zone = QPoint(), bool forceUpdate = false);
/** @brief Set number of running jobs. */
void jobCount(int);
void cancelRunningJob(const QString, stringMap);
- void processLog(ProjectItem *, int , int);
+ void processLog(const QString, int , int);
void addClip(const QString, const QString &, const QString &);
- void jobCrashed(const QString, const QString &label, const QString &actionName = QString(), const QString details = QString());
+ void updateJobStatus(const QString, int, int, const QString &label = QString(), const QString &actionName = QString(), const QString details = QString());
+ void checkJobProcess();
+ void gotProxy(const QString);
};
#endif