Added "Pause" support.

This commit is contained in:
LoRd_MuldeR 2012-02-02 02:13:02 +01:00
parent 405e7d2382
commit 2a3325b02f
17 changed files with 371 additions and 58 deletions

View File

@ -621,7 +621,12 @@
</property> </property>
<item> <item>
<property name="text"> <property name="text">
<string>High</string> <string>Auto</string>
</property>
</item>
<item>
<property name="text">
<string>Baseline</string>
</property> </property>
</item> </item>
<item> <item>
@ -631,7 +636,22 @@
</item> </item>
<item> <item>
<property name="text"> <property name="text">
<string>Baseline</string> <string>High</string>
</property>
</item>
<item>
<property name="text">
<string>High10</string>
</property>
</item>
<item>
<property name="text">
<string>High422</string>
</property>
</item>
<item>
<property name="text">
<string>High444</string>
</property> </property>
</item> </item>
</widget> </widget>

View File

@ -68,6 +68,12 @@
</property> </property>
<item> <item>
<widget class="QProgressBar" name="progressBar"> <widget class="QProgressBar" name="progressBar">
<property name="mouseTracking">
<bool>false</bool>
</property>
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
<property name="value"> <property name="value">
<number>0</number> <number>0</number>
</property> </property>
@ -252,6 +258,29 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QPushButton" name="buttonPauseJob">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimumSize">
<size>
<width>104</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Pause Job</string>
</property>
<property name="icon">
<iconset resource="../res/resources.qrc">
<normaloff>:/buttons/pause.png</normaloff>:/buttons/pause.png</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item> <item>
<widget class="QPushButton" name="buttonAbortJob"> <widget class="QPushButton" name="buttonAbortJob">
<property name="enabled"> <property name="enabled">
@ -289,6 +318,8 @@
<property name="title"> <property name="title">
<string>File</string> <string>File</string>
</property> </property>
<addaction name="actionPreferences"/>
<addaction name="separator"/>
<addaction name="actionExit"/> <addaction name="actionExit"/>
</widget> </widget>
<widget class="QMenu" name="menu"> <widget class="QMenu" name="menu">
@ -312,6 +343,7 @@
<addaction name="actionJob_New"/> <addaction name="actionJob_New"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionJob_Start"/> <addaction name="actionJob_Start"/>
<addaction name="actionJob_Pause"/>
<addaction name="actionJob_Abort"/> <addaction name="actionJob_Abort"/>
</widget> </widget>
<addaction name="menuFile"/> <addaction name="menuFile"/>
@ -423,6 +455,33 @@
<string>Abort Job</string> <string>Abort Job</string>
</property> </property>
</action> </action>
<action name="actionJob_Pause">
<property name="checkable">
<bool>true</bool>
</property>
<property name="enabled">
<bool>false</bool>
</property>
<property name="icon">
<iconset resource="../res/resources.qrc">
<normaloff>:/buttons/pause.png</normaloff>:/buttons/pause.png</iconset>
</property>
<property name="text">
<string>Pause Job</string>
</property>
</action>
<action name="actionPreferences">
<property name="enabled">
<bool>false</bool>
</property>
<property name="icon">
<iconset resource="../res/resources.qrc">
<normaloff>:/buttons/wrench.png</normaloff>:/buttons/wrench.png</iconset>
</property>
<property name="text">
<string>Preferences</string>
</property>
</action>
</widget> </widget>
<tabstops> <tabstops>
<tabstop>buttonAddJob</tabstop> <tabstop>buttonAddJob</tabstop>
@ -500,5 +559,21 @@
</hint> </hint>
</hints> </hints>
</connection> </connection>
<connection>
<sender>actionJob_Pause</sender>
<signal>toggled(bool)</signal>
<receiver>buttonPauseJob</receiver>
<slot>setChecked(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>547</x>
<y>617</y>
</hint>
</hints>
</connection>
</connections> </connections>
</ui> </ui>

BIN
res/buttons/clock_play.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 943 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 598 B

BIN
res/buttons/hourglass.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 744 B

BIN
res/buttons/pause.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 799 B

BIN
res/buttons/suspended.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 484 B

BIN
res/buttons/wrench.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 610 B

View File

@ -7,19 +7,25 @@
<file>buttons/book_open.png</file> <file>buttons/book_open.png</file>
<file>buttons/cancel.png</file> <file>buttons/cancel.png</file>
<file>buttons/clock_pause.png</file> <file>buttons/clock_pause.png</file>
<file>buttons/clock_play.png</file>
<file>buttons/clock_stop.png</file> <file>buttons/clock_stop.png</file>
<file>buttons/control_pause.png</file>
<file>buttons/cross.png</file> <file>buttons/cross.png</file>
<file>buttons/disk.png</file> <file>buttons/disk.png</file>
<file>buttons/door_in.png</file> <file>buttons/door_in.png</file>
<file>buttons/error.png</file> <file>buttons/error.png</file>
<file>buttons/exclamation.png</file> <file>buttons/exclamation.png</file>
<file>buttons/find.png</file> <file>buttons/find.png</file>
<file>buttons/hourglass.png</file>
<file>buttons/information.png</file> <file>buttons/information.png</file>
<file>buttons/lightning.png</file> <file>buttons/lightning.png</file>
<file>buttons/page_paste.png</file> <file>buttons/page_paste.png</file>
<file>buttons/pause.png</file>
<file>buttons/play.png</file> <file>buttons/play.png</file>
<file>buttons/play_big.png</file> <file>buttons/play_big.png</file>
<file>buttons/suspended.png</file>
<file>buttons/world_link.png</file> <file>buttons/world_link.png</file>
<file>buttons/wrench.png</file>
<file>images/x264.png</file> <file>images/x264.png</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@ -131,6 +131,15 @@ QVariant JobListModel::data(const QModelIndex &index, int role) const
case EncodeThread::JobStatus_Failed: case EncodeThread::JobStatus_Failed:
return QVariant::fromValue<QString>(tr("Failed!")); return QVariant::fromValue<QString>(tr("Failed!"));
break; break;
case EncodeThread::JobStatus_Pausing:
return QVariant::fromValue<QString>(tr("Pausing..."));
break;
case EncodeThread::JobStatus_Paused:
return QVariant::fromValue<QString>(tr("Paused."));
break;
case EncodeThread::JobStatus_Resuming:
return QVariant::fromValue<QString>(tr("Resuming..."));
break;
case EncodeThread::JobStatus_Aborting: case EncodeThread::JobStatus_Aborting:
return QVariant::fromValue<QString>(tr("Aborting...")); return QVariant::fromValue<QString>(tr("Aborting..."));
break; break;
@ -161,7 +170,7 @@ QVariant JobListModel::data(const QModelIndex &index, int role) const
switch(m_status.value(m_jobs.at(index.row()))) switch(m_status.value(m_jobs.at(index.row())))
{ {
case EncodeThread::JobStatus_Enqueued: case EncodeThread::JobStatus_Enqueued:
return QIcon(":/buttons/clock_pause.png"); return QIcon(":/buttons/hourglass.png");
break; break;
case EncodeThread::JobStatus_Starting: case EncodeThread::JobStatus_Starting:
return QIcon(":/buttons/lightning.png"); return QIcon(":/buttons/lightning.png");
@ -180,6 +189,15 @@ QVariant JobListModel::data(const QModelIndex &index, int role) const
case EncodeThread::JobStatus_Failed: case EncodeThread::JobStatus_Failed:
return QIcon(":/buttons/exclamation.png"); return QIcon(":/buttons/exclamation.png");
break; break;
case EncodeThread::JobStatus_Pausing:
return QIcon(":/buttons/clock_pause.png");
break;
case EncodeThread::JobStatus_Paused:
return QIcon(":/buttons/suspended.png");
break;
case EncodeThread::JobStatus_Resuming:
return QIcon(":/buttons/clock_play.png");
break;
case EncodeThread::JobStatus_Aborting: case EncodeThread::JobStatus_Aborting:
return QIcon(":/buttons/clock_stop.png"); return QIcon(":/buttons/clock_stop.png");
break; break;
@ -267,6 +285,41 @@ bool JobListModel::startJob(const QModelIndex &index)
return false; return false;
} }
bool JobListModel::pauseJob(const QModelIndex &index)
{
if(index.isValid() && index.row() >= 0 && index.row() < m_jobs.count())
{
QUuid id = m_jobs.at(index.row());
EncodeThread::JobStatus status = m_status.value(id);
if((status == EncodeThread::JobStatus_Indexing) || (status == EncodeThread::JobStatus_Running) ||
(status == EncodeThread::JobStatus_Running_Pass1) || (status == EncodeThread::JobStatus_Running_Pass2))
{
updateStatus(id, EncodeThread::JobStatus_Pausing);
m_threads.value(id)->pauseJob();
return true;
}
}
return false;
}
bool JobListModel::resumeJob(const QModelIndex &index)
{
if(index.isValid() && index.row() >= 0 && index.row() < m_jobs.count())
{
QUuid id = m_jobs.at(index.row());
EncodeThread::JobStatus status = m_status.value(id);
if(status == EncodeThread::JobStatus_Paused)
{
updateStatus(id, EncodeThread::JobStatus_Resuming);
m_threads.value(id)->resumeJob();
return true;
}
}
return false;
}
bool JobListModel::abortJob(const QModelIndex &index) bool JobListModel::abortJob(const QModelIndex &index)
{ {
if(index.isValid() && index.row() >= 0 && index.row() < m_jobs.count()) if(index.isValid() && index.row() >= 0 && index.row() < m_jobs.count())

View File

@ -46,6 +46,8 @@ public:
QModelIndex insertJob(EncodeThread *thread); QModelIndex insertJob(EncodeThread *thread);
bool startJob(const QModelIndex &index); bool startJob(const QModelIndex &index);
bool pauseJob(const QModelIndex &index);
bool resumeJob(const QModelIndex &index);
bool abortJob(const QModelIndex &index); bool abortJob(const QModelIndex &index);
LogFileModel *getLogFile(const QModelIndex &index); LogFileModel *getLogFile(const QModelIndex &index);
EncodeThread::JobStatus getJobStatus(const QModelIndex &index); EncodeThread::JobStatus getJobStatus(const QModelIndex &index);

View File

@ -32,7 +32,7 @@ OptionsModel::OptionsModel(void)
m_quantizer = 22; m_quantizer = 22;
m_preset = "Medium"; m_preset = "Medium";
m_tune = "None"; m_tune = "None";
m_profile = "High"; m_profile = "Auto";
m_custom = ""; m_custom = "";
} }

View File

@ -81,9 +81,11 @@ EncodeThread::EncodeThread(const QString &sourceFileName, const QString &outputF
m_options(new OptionsModel(*options)), m_options(new OptionsModel(*options)),
m_binDir(binDir), m_binDir(binDir),
m_x64(x64), m_x64(x64),
m_handle_jobObject(NULL) m_handle_jobObject(NULL),
m_semaphorePaused(0)
{ {
m_abort = false; m_abort = false;
m_pause = false;
} }
EncodeThread::~EncodeThread(void) EncodeThread::~EncodeThread(void)
@ -103,20 +105,13 @@ EncodeThread::~EncodeThread(void)
void EncodeThread::run(void) void EncodeThread::run(void)
{ {
m_progress = 0; __try
m_status = JobStatus_Starting;
try
{ {
encode(); checkedRun();
} }
catch(char *msg) __except(1)
{ {
log(tr("EXCEPTION ERROR: ").append(QString::fromLatin1(msg))); qWarning("STRUCTURED EXCEPTION ERROR IN ENCODE THREAD !!!");
}
catch(...)
{
log(tr("EXCEPTION ERROR !!!"));
} }
if(m_handle_jobObject) if(m_handle_jobObject)
@ -126,6 +121,45 @@ void EncodeThread::run(void)
} }
} }
void EncodeThread::checkedRun(void)
{
m_progress = 0;
m_status = JobStatus_Starting;
try
{
try
{
encode();
}
catch(char *msg)
{
log(tr("EXCEPTION ERROR IN THREAD: ").append(QString::fromLatin1(msg)));
setStatus(JobStatus_Failed);
}
catch(...)
{
log(tr("UNHANDLED EXCEPTION ERROR IN THREAD !!!"));
setStatus(JobStatus_Failed);
}
}
catch(...)
{
RaiseException(EXCEPTION_ACCESS_VIOLATION, 0, 0, NULL);
}
}
void EncodeThread::start(Priority priority)
{
qDebug("Thread starting...");
m_abort = false;
m_pause = false;
while(m_semaphorePaused.tryAcquire(1, 0));
QThread::start(priority);
}
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Encode functions // Encode functions
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@ -183,9 +217,10 @@ void EncodeThread::encode(void)
log(tr("\nWARNING: Your revision of x264 uses an unsupported core (API) version, take care!")); log(tr("\nWARNING: Your revision of x264 uses an unsupported core (API) version, take care!"));
log(tr("This application works best with x264 core (API) version %2.").arg(QString::number(VER_X264_CURRENT_API))); log(tr("This application works best with x264 core (API) version %2.").arg(QString::number(VER_X264_CURRENT_API)));
} }
if((revision_avs2yuv != UINT_MAX) && ((revision_avs2yuv % REV_MULT) != 242)) if((revision_avs2yuv != UINT_MAX) && ((revision_avs2yuv % REV_MULT) != VER_x264_AVS2YUV_VER))
{ {
log(tr("\nERROR: Your version of avs2yuv is unsupported (Required version is v0.24bm2)")); log(tr("\nERROR: Your version of avs2yuv is unsupported (Required version: v0.24 BugMaster's mod 2)"));
log(tr("You can find the required version at: http://komisar.gin.by/tools/avs2yuv/"));
setStatus(JobStatus_Failed); setStatus(JobStatus_Failed);
return; return;
} }
@ -267,7 +302,13 @@ bool EncodeThread::runEncodingPass(bool x64, bool usePipe, unsigned int frames,
bool bTimeout = false; bool bTimeout = false;
bool bAborted = false; bool bAborted = false;
//Main processing loop
while(processEncode.state() != QProcess::NotRunning) while(processEncode.state() != QProcess::NotRunning)
{
unsigned int waitCounter = 0;
//Wait until new output is available
forever
{ {
if(m_abort) if(m_abort)
{ {
@ -276,9 +317,29 @@ bool EncodeThread::runEncodingPass(bool x64, bool usePipe, unsigned int frames,
bAborted = true; bAborted = true;
break; break;
} }
if(!processEncode.waitForReadyRead(m_processTimeoutInterval)) if(m_pause && (processEncode.state() == QProcess::Running))
{
JobStatus previousStatus = m_status;
setStatus(JobStatus_Paused);
log(tr("Job paused by user at %1, %2.").arg(QDate::currentDate().toString(Qt::ISODate), QTime::currentTime().toString( Qt::ISODate)));
bool ok[2] = {false, false};
Q_PID pid[2] = {processEncode.pid(), processAvisynth.pid()};
if(pid[0]) { ok[0] = (SuspendThread(pid[0]->hThread) != (DWORD)(-1)); }
if(pid[1]) { ok[1] = (SuspendThread(pid[1]->hThread) != (DWORD)(-1)); }
while(m_pause) m_semaphorePaused.acquire();
while(m_semaphorePaused.tryAcquire(1, 0));
if(pid[0]) { if(ok[0]) ResumeThread(pid[0]->hThread); }
if(pid[1]) { if(ok[1]) ResumeThread(pid[1]->hThread); }
if(!m_abort) setStatus(previousStatus);
log(tr("Job resumed by user at %1, %2.").arg(QDate::currentDate().toString(Qt::ISODate), QTime::currentTime().toString( Qt::ISODate)));
waitCounter = 0;
continue;
}
if(!processEncode.waitForReadyRead(2500))
{ {
if(processEncode.state() == QProcess::Running) if(processEncode.state() == QProcess::Running)
{
if(waitCounter++ > m_processTimeoutCounter)
{ {
processEncode.kill(); processEncode.kill();
qWarning("x264 process timed out <-- killing!"); qWarning("x264 process timed out <-- killing!");
@ -286,7 +347,23 @@ bool EncodeThread::runEncodingPass(bool x64, bool usePipe, unsigned int frames,
bTimeout = true; bTimeout = true;
break; break;
} }
continue;
} }
}
if(m_abort || (m_pause && (processEncode.state() == QProcess::Running)))
{
continue;
}
break;
}
//Exit main processing loop now?
if(bAborted || bTimeout)
{
break;
}
//Process all output
while(processEncode.bytesAvailable() > 0) while(processEncode.bytesAvailable() > 0)
{ {
QList<QByteArray> lines = processEncode.readLine().split('\r'); QList<QByteArray> lines = processEncode.readLine().split('\r');
@ -339,10 +416,13 @@ bool EncodeThread::runEncodingPass(bool x64, bool usePipe, unsigned int frames,
processAvisynth.waitForFinished(-1); processAvisynth.waitForFinished(-1);
} }
if(!(bTimeout || bAborted))
{
while(processAvisynth.bytesAvailable() > 0) while(processAvisynth.bytesAvailable() > 0)
{ {
log(tr("av2y [info]: %1").arg(QString::fromUtf8(processAvisynth.readLine()).simplified())); log(tr("av2y [info]: %1").arg(QString::fromUtf8(processAvisynth.readLine()).simplified()));
} }
}
if(usePipe && (processAvisynth.exitCode() != EXIT_SUCCESS)) if(usePipe && (processAvisynth.exitCode() != EXIT_SUCCESS))
{ {
@ -412,12 +492,17 @@ QStringList EncodeThread::buildCommandLine(bool usePipe, unsigned int frames, in
cmdLine << "--stats" << QDir::toNativeSeparators(passLogFile); cmdLine << "--stats" << QDir::toNativeSeparators(passLogFile);
} }
cmdLine << "--preset" << m_options->preset().toLower();
if(m_options->tune().compare("none", Qt::CaseInsensitive)) if(m_options->tune().compare("none", Qt::CaseInsensitive))
{ {
cmdLine << "--tune" << m_options->tune().toLower(); cmdLine << "--tune" << m_options->tune().toLower();
} }
cmdLine << "--preset" << m_options->preset().toLower(); if(m_options->profile().compare("auto", Qt::CaseInsensitive))
{
cmdLine << "--profile" << m_options->profile().toLower();
}
if(!m_options->custom().isEmpty()) if(!m_options->custom().isEmpty())
{ {
@ -453,7 +538,7 @@ unsigned int EncodeThread::checkVersionX264(bool x64)
return false;; return false;;
} }
QRegExp regExpVersion("x264 (\\d)\\.(\\d+)\\.(\\d+) ([0-9A-Fa-f]{7})"); QRegExp regExpVersion("\\bx264 (\\d)\\.(\\d+)\\.(\\d+)\\b");
bool bTimeout = false; bool bTimeout = false;
bool bAborted = false; bool bAborted = false;
@ -469,7 +554,7 @@ unsigned int EncodeThread::checkVersionX264(bool x64)
bAborted = true; bAborted = true;
break; break;
} }
if(!process.waitForReadyRead(m_processTimeoutInterval)) if(!process.waitForReadyRead())
{ {
if(process.state() == QProcess::Running) if(process.state() == QProcess::Running)
{ {
@ -538,14 +623,15 @@ unsigned int EncodeThread::checkVersionAvs2yuv(void)
return false;; return false;;
} }
QRegExp regExpVersion("Avs2YUV (\\d+).(\\d+)bm(\\d)"); QRegExp regExpVersionMod("\\bAvs2YUV (\\d+).(\\d+)bm(\\d)\\b");
QRegExp regExpVersionOld("\\bAvs2YUV (\\d+).(\\d+)\\b");
bool bTimeout = false; bool bTimeout = false;
bool bAborted = false; bool bAborted = false;
unsigned int ver_maj = UINT_MAX; unsigned int ver_maj = UINT_MAX;
unsigned int ver_min = UINT_MAX; unsigned int ver_min = UINT_MAX;
unsigned int ver_bld = UINT_MAX; unsigned int ver_mod = 0;
while(process.state() != QProcess::NotRunning) while(process.state() != QProcess::NotRunning)
{ {
@ -555,7 +641,7 @@ unsigned int EncodeThread::checkVersionAvs2yuv(void)
bAborted = true; bAborted = true;
break; break;
} }
if(!process.waitForReadyRead(m_processTimeoutInterval)) if(!process.waitForReadyRead())
{ {
if(process.state() == QProcess::Running) if(process.state() == QProcess::Running)
{ {
@ -573,22 +659,30 @@ unsigned int EncodeThread::checkVersionAvs2yuv(void)
{ {
QString text = QString::fromUtf8(lines.takeFirst().constData()).simplified(); QString text = QString::fromUtf8(lines.takeFirst().constData()).simplified();
int offset = -1; int offset = -1;
if((ver_maj == UINT_MAX) || (ver_min == UINT_MAX) || (ver_bld == UINT_MAX)) if((ver_maj == UINT_MAX) || (ver_min == UINT_MAX) || (ver_mod == UINT_MAX))
{ {
if(!text.isEmpty()) if(!text.isEmpty())
{ {
log(text); log(text);
} }
} }
if((offset = regExpVersion.lastIndexIn(text)) >= 0) if((offset = regExpVersionMod.lastIndexIn(text)) >= 0)
{ {
bool ok1 = false, ok2 = false, ok3 = false; bool ok1 = false, ok2 = false, ok3 = false;
unsigned int temp1 = regExpVersion.cap(1).toUInt(&ok1); unsigned int temp1 = regExpVersionMod.cap(1).toUInt(&ok1);
unsigned int temp2 = regExpVersion.cap(2).toUInt(&ok2); unsigned int temp2 = regExpVersionMod.cap(2).toUInt(&ok2);
unsigned int temp3 = regExpVersion.cap(3).toUInt(&ok3); unsigned int temp3 = regExpVersionMod.cap(3).toUInt(&ok3);
if(ok1) ver_maj = temp1;
if(ok2) ver_min = temp2;
if(ok3) ver_mod = temp3;
}
else if((offset = regExpVersionOld.lastIndexIn(text)) >= 0)
{
bool ok1 = false, ok2 = false;
unsigned int temp1 = regExpVersionOld.cap(1).toUInt(&ok1);
unsigned int temp2 = regExpVersionOld.cap(2).toUInt(&ok2);
if(ok1) ver_maj = temp1; if(ok1) ver_maj = temp1;
if(ok2) ver_min = temp2; if(ok2) ver_min = temp2;
if(ok3) ver_bld = temp3;
} }
} }
} }
@ -610,13 +704,13 @@ unsigned int EncodeThread::checkVersionAvs2yuv(void)
return UINT_MAX; return UINT_MAX;
} }
if((ver_maj == UINT_MAX) || (ver_min == UINT_MAX) || (ver_bld == UINT_MAX)) if((ver_maj == UINT_MAX) || (ver_min == UINT_MAX))
{ {
log(tr("\nFAILED TO DETERMINE AVS2YUV VERSION !!!")); log(tr("\nFAILED TO DETERMINE AVS2YUV VERSION !!!"));
return UINT_MAX; return UINT_MAX;
} }
return (ver_maj * REV_MULT) + ((ver_min % REV_MULT) * 10) + (ver_bld % 10); return (ver_maj * REV_MULT) + ((ver_min % REV_MULT) * 10) + (ver_mod % 10);
} }
bool EncodeThread::checkProperties(unsigned int &frames) bool EncodeThread::checkProperties(unsigned int &frames)
@ -653,12 +747,12 @@ bool EncodeThread::checkProperties(unsigned int &frames)
bAborted = true; bAborted = true;
break; break;
} }
if(!process.waitForReadyRead(m_processTimeoutInterval)) if(!process.waitForReadyRead())
{ {
if(process.state() == QProcess::Running) if(process.state() == QProcess::Running)
{ {
process.kill(); process.kill();
qWarning("x264 process timed out <-- killing!"); qWarning("Avs2YUV process timed out <-- killing!");
log("\nPROCESS TIMEOUT !!!"); log("\nPROCESS TIMEOUT !!!");
bTimeout = true; bTimeout = true;
break; break;
@ -760,7 +854,7 @@ void EncodeThread::setStatus(JobStatus newStatus)
if(m_status != newStatus) if(m_status != newStatus)
{ {
m_status = newStatus; m_status = newStatus;
if((newStatus != JobStatus_Completed) && (newStatus != JobStatus_Failed) && (newStatus != JobStatus_Aborted)) if((newStatus != JobStatus_Completed) && (newStatus != JobStatus_Failed) && (newStatus != JobStatus_Aborted) && (newStatus != JobStatus_Paused))
{ {
setProgress(0); setProgress(0);
} }

View File

@ -25,6 +25,7 @@
#include <QUuid> #include <QUuid>
#include <QMutex> #include <QMutex>
#include <QStringList> #include <QStringList>
#include <QSemaphore>
class OptionsModel; class OptionsModel;
class QProcess; class QProcess;
@ -44,8 +45,11 @@ public:
JobStatus_Running_Pass2 = 5, JobStatus_Running_Pass2 = 5,
JobStatus_Completed = 6, JobStatus_Completed = 6,
JobStatus_Failed = 7, JobStatus_Failed = 7,
JobStatus_Aborting = 8, JobStatus_Pausing = 8,
JobStatus_Aborted = 9 JobStatus_Paused = 9,
JobStatus_Resuming = 10,
JobStatus_Aborting = 11,
JobStatus_Aborted = 12
}; };
EncodeThread(const QString &sourceFileName, const QString &outputFileName, const OptionsModel *options, const QString &binDir, bool x64); EncodeThread(const QString &sourceFileName, const QString &outputFileName, const OptionsModel *options, const QString &binDir, bool x64);
@ -55,11 +59,25 @@ public:
const QString &sourceFileName(void) { return this->m_sourceFileName; }; const QString &sourceFileName(void) { return this->m_sourceFileName; };
const QString &outputFileName(void) { return this->m_outputFileName; }; const QString &outputFileName(void) { return this->m_outputFileName; };
void abortJob(void) { m_abort = true; } void pauseJob(void)
{
m_pause = true;
}
void resumeJob(void)
{
m_pause = false;
m_semaphorePaused.release();
}
void abortJob(void)
{
m_abort = true;
m_pause = false;
m_semaphorePaused.release();
}
protected: protected:
static QMutex m_mutex_startProcess; static QMutex m_mutex_startProcess;
static const int m_processTimeoutInterval = 60000; static const int m_processTimeoutCounter = 24;
//Constants //Constants
const QUuid m_jobId; const QUuid m_jobId;
@ -71,6 +89,10 @@ protected:
//Flags //Flags
volatile bool m_abort; volatile bool m_abort;
volatile bool m_pause;
//Synchronization
QSemaphore m_semaphorePaused;
//Job handle //Job handle
void *m_handle_jobObject; void *m_handle_jobObject;
@ -81,6 +103,7 @@ protected:
//Entry point //Entry point
virtual void run(void); virtual void run(void);
virtual void checkedRun(void);
//Encode functions //Encode functions
void encode(void); void encode(void);
@ -104,5 +127,8 @@ signals:
void progressChanged(const QUuid &jobId, unsigned int newProgress); void progressChanged(const QUuid &jobId, unsigned int newProgress);
void messageLogged(const QUuid &jobId, const QString &text); void messageLogged(const QUuid &jobId, const QString &text);
void detailsChanged(const QUuid &jobId, const QString &details); void detailsChanged(const QUuid &jobId, const QString &details);
public slots:
void start(Priority priority = InheritPriority);
}; };

View File

@ -24,3 +24,4 @@
#define VER_X264_MINIMUM_REV (2146) #define VER_X264_MINIMUM_REV (2146)
#define VER_X264_CURRENT_API (120) #define VER_X264_CURRENT_API (120)
#define VER_x264_AVS2YUV_VER (242)

View File

@ -37,7 +37,7 @@
const char *home_url = "http://mulder.brhack.net/"; const char *home_url = "http://mulder.brhack.net/";
#define PRE_RELEASE (1) #define PRE_RELEASE (0)
#define SET_FONT_BOLD(WIDGET,BOLD) { QFont _font = WIDGET->font(); _font.setBold(BOLD); WIDGET->setFont(_font); } #define SET_FONT_BOLD(WIDGET,BOLD) { QFont _font = WIDGET->font(); _font.setBold(BOLD); WIDGET->setFont(_font); }
#define SET_TEXT_COLOR(WIDGET,COLOR) { QPalette _palette = WIDGET->palette(); _palette.setColor(QPalette::WindowText, (COLOR)); _palette.setColor(QPalette::Text, (COLOR)); WIDGET->setPalette(_palette); } #define SET_TEXT_COLOR(WIDGET,COLOR) { QPalette _palette = WIDGET->palette(); _palette.setColor(QPalette::WindowText, (COLOR)); _palette.setColor(QPalette::Text, (COLOR)); WIDGET->setPalette(_palette); }
@ -96,6 +96,7 @@ MainWindow::MainWindow(bool x64supported)
connect(buttonAddJob, SIGNAL(clicked()), this, SLOT(addButtonPressed())); connect(buttonAddJob, SIGNAL(clicked()), this, SLOT(addButtonPressed()));
connect(buttonStartJob, SIGNAL(clicked()), this, SLOT(startButtonPressed())); connect(buttonStartJob, SIGNAL(clicked()), this, SLOT(startButtonPressed()));
connect(buttonAbortJob, SIGNAL(clicked()), this, SLOT(abortButtonPressed())); connect(buttonAbortJob, SIGNAL(clicked()), this, SLOT(abortButtonPressed()));
connect(buttonPauseJob, SIGNAL(toggled(bool)), this, SLOT(pauseButtonPressed(bool)));
//Enable menu //Enable menu
connect(actionAbout, SIGNAL(triggered()), this, SLOT(showAbout())); connect(actionAbout, SIGNAL(triggered()), this, SLOT(showAbout()));
@ -182,6 +183,18 @@ void MainWindow::abortButtonPressed(void)
m_jobList->abortJob(jobsView->currentIndex()); m_jobList->abortJob(jobsView->currentIndex());
} }
void MainWindow::pauseButtonPressed(bool checked)
{
if(checked)
{
m_jobList->pauseJob(jobsView->currentIndex());
}
else
{
m_jobList->resumeJob(jobsView->currentIndex());
}
}
void MainWindow::jobSelected(const QModelIndex & current, const QModelIndex & previous) void MainWindow::jobSelected(const QModelIndex & current, const QModelIndex & previous)
{ {
qDebug("Job selected: %d", current.row()); qDebug("Job selected: %d", current.row());
@ -349,6 +362,23 @@ void MainWindow::init(void)
int val = QMessageBox::warning(this, tr("Avisynth Missing"), tr("<nobr>It appears that Avisynth is not currently installed on your computer.<br>Thus Avisynth input will not be working at all!<br><br>Please download and install Avisynth:<br><a href=\"http://sourceforge.net/projects/avisynth2/files/AviSynth%202.5/\">http://sourceforge.net/projects/avisynth2/files/AviSynth 2.5/</a></nobr>").replace("-", "&minus;"), tr("Quit"), tr("Ignore")); int val = QMessageBox::warning(this, tr("Avisynth Missing"), tr("<nobr>It appears that Avisynth is not currently installed on your computer.<br>Thus Avisynth input will not be working at all!<br><br>Please download and install Avisynth:<br><a href=\"http://sourceforge.net/projects/avisynth2/files/AviSynth%202.5/\">http://sourceforge.net/projects/avisynth2/files/AviSynth 2.5/</a></nobr>").replace("-", "&minus;"), tr("Quit"), tr("Ignore"));
if(val != 1) { close(); qApp->exit(-1); return; } if(val != 1) { close(); qApp->exit(-1); return; }
} }
//Check for expiration
if(x264_version_date().addMonths(6) < QDate::currentDate())
{
QMessageBox msgBox(this);
msgBox.setIcon(QMessageBox::Information);
msgBox.setWindowTitle(tr("Update Notification"));
msgBox.setWindowFlags(Qt::Window | Qt::WindowTitleHint | Qt::CustomizeWindowHint);
msgBox.setText(tr("<nobr><tt>Oups, this version of 'Simple x264 Launcher' is more than 6 months old.<br><br>Please check the official web-site at <a href=\"%1\">%1</a> for updates!<br></tt></nobr>").replace("-", "&minus;").arg(home_url));
QPushButton *btn1 = msgBox.addButton(tr("Discard"), QMessageBox::NoRole);
QPushButton *btn2 = msgBox.addButton(tr("Discard"), QMessageBox::AcceptRole);
btn1->setEnabled(false);
btn2->setVisible(false);
QTimer::singleShot(5000, btn1, SLOT(hide()));
QTimer::singleShot(5000, btn2, SLOT(show()));
msgBox.exec();
}
} }
void MainWindow::updateLabel(void) void MainWindow::updateLabel(void)
@ -435,9 +465,14 @@ void MainWindow::updateButtons(EncodeThread::JobStatus status)
qDebug("MainWindow::updateButtons(void)"); qDebug("MainWindow::updateButtons(void)");
buttonStartJob->setEnabled(status == EncodeThread::JobStatus_Enqueued); buttonStartJob->setEnabled(status == EncodeThread::JobStatus_Enqueued);
buttonAbortJob->setEnabled(status == EncodeThread::JobStatus_Indexing || status == EncodeThread::JobStatus_Running || buttonAbortJob->setEnabled(status == EncodeThread::JobStatus_Indexing || status == EncodeThread::JobStatus_Running || status == EncodeThread::JobStatus_Running_Pass1 || status == EncodeThread::JobStatus_Running_Pass2 || status == EncodeThread::JobStatus_Paused);
status == EncodeThread::JobStatus_Running_Pass1 || status == EncodeThread::JobStatus_Running_Pass2 ); buttonPauseJob->setEnabled(status == EncodeThread::JobStatus_Indexing || status == EncodeThread::JobStatus_Running || status == EncodeThread::JobStatus_Paused || status == EncodeThread::JobStatus_Running_Pass1 || status == EncodeThread::JobStatus_Running_Pass2);
buttonPauseJob->setChecked(status == EncodeThread::JobStatus_Paused || status == EncodeThread::JobStatus_Pausing);
actionJob_Start->setEnabled(buttonStartJob->isEnabled()); actionJob_Start->setEnabled(buttonStartJob->isEnabled());
actionJob_Abort->setEnabled(buttonAbortJob->isEnabled()); actionJob_Abort->setEnabled(buttonAbortJob->isEnabled());
actionJob_Pause->setEnabled(buttonPauseJob->isEnabled());
actionJob_Pause->setChecked(buttonPauseJob->isChecked());
editDetails->setEnabled(status != EncodeThread::JobStatus_Paused);
} }

View File

@ -65,6 +65,7 @@ private slots:
void jobChangedData(const QModelIndex &top, const QModelIndex &bottom); void jobChangedData(const QModelIndex &top, const QModelIndex &bottom);
void jobLogExtended(const QModelIndex & parent, int start, int end); void jobLogExtended(const QModelIndex & parent, int start, int end);
void launchNextJob(void); void launchNextJob(void);
void pauseButtonPressed(bool checked);
void showAbout(void); void showAbout(void);
void showWebLink(void); void showWebLink(void);
void startButtonPressed(void); void startButtonPressed(void);