Implemented initial queue saving/loading support.

This commit is contained in:
LoRd_MuldeR 2014-04-18 14:41:20 +02:00
parent 5cc6f24d53
commit e6d5820b9d
8 changed files with 237 additions and 85 deletions

View File

@ -11,7 +11,7 @@
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>Simple x264 Launcher</string> <string>Simple x264/x265 Launcher</string>
</property> </property>
<widget class="QWidget" name="centralwidget"> <widget class="QWidget" name="centralwidget">
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">

View File

@ -28,6 +28,14 @@
#include <QIcon> #include <QIcon>
#include <QFileInfo> #include <QFileInfo>
#include <QSettings>
static const char *KEY_ENTRY_COUNT = "entry_count";
static const char *KEY_SOURCE_FILE = "source_file";
static const char *KEY_OUTPUT_FILE = "output_file";
static const char *KEY_ENC_OPTIONS = "enc_options";
static const char *JOB_TEMPLATE = "job_%08x";
JobListModel::JobListModel(PreferencesModel *preferences) JobListModel::JobListModel(PreferencesModel *preferences)
{ {
@ -233,19 +241,29 @@ QModelIndex JobListModel::insertJob(EncodeThread *thread)
QString config = "N/A"; QString config = "N/A";
switch(thread->options()->rcMode())
{
case OptionsModel::EncType_X264:
config = QString("x264");
break;
case OptionsModel::EncType_X265:
config = QString("x265");
break;
}
switch(thread->options()->rcMode()) switch(thread->options()->rcMode())
{ {
case OptionsModel::RCMode_CRF: case OptionsModel::RCMode_CRF:
config = QString("CRF@%1").arg(QString::number(thread->options()->quantizer())); config = QString("%1 CRF@%2") .arg(config, QString::number(thread->options()->quantizer()));
break; break;
case OptionsModel::RCMode_CQ: case OptionsModel::RCMode_CQ:
config = QString("CQ@%1").arg(QString::number(qRound(thread->options()->quantizer()))); config = QString("%1 CQ@%2") .arg(config, QString::number(qRound(thread->options()->quantizer())));
break; break;
case OptionsModel::RCMode_2Pass: case OptionsModel::RCMode_2Pass:
config = QString("2Pass@%1").arg(QString::number(thread->options()->bitrate())); config = QString("%1 2Pass@%2").arg(config, QString::number(thread->options()->bitrate()));
break; break;
case OptionsModel::RCMode_ABR: case OptionsModel::RCMode_ABR:
config = QString("ABR@%1").arg(QString::number(thread->options()->bitrate())); config = QString("%1 ABR@%2") .arg(config, QString::number(thread->options()->bitrate()));
break; break;
} }
@ -525,3 +543,89 @@ void JobListModel::updateDetails(const QUuid &jobId, const QString &details)
emit dataChanged(createIndex(index, 3), createIndex(index, 3)); emit dataChanged(createIndex(index, 3), createIndex(index, 3));
} }
} }
size_t JobListModel::saveQueuedJobs(void)
{
const QString appDir = x264_data_path();
QSettings settings(QString("%1/queue.ini").arg(appDir), QSettings::IniFormat);
settings.clear();
settings.setValue(KEY_ENTRY_COUNT, 0);
size_t jobCounter = 0;
for(QList<QUuid>::ConstIterator iter = m_jobs.constBegin(); iter != m_jobs.constEnd(); iter++)
{
if(m_status.value(*iter) == JobStatus_Enqueued)
{
if(const EncodeThread *thread = m_threads.value(*iter))
{
settings.beginGroup(QString().sprintf(JOB_TEMPLATE, jobCounter++));
settings.setValue(KEY_SOURCE_FILE, thread->sourceFileName());
settings.setValue(KEY_OUTPUT_FILE, thread->outputFileName());
settings.beginGroup(KEY_ENC_OPTIONS);
OptionsModel::saveOptions(thread->options(), settings);
settings.endGroup();
settings.endGroup();
settings.setValue(KEY_ENTRY_COUNT, jobCounter);
}
}
}
settings.sync();
return jobCounter;
}
size_t JobListModel::loadQueuedJobs(const SysinfoModel *sysinfo)
{
const QString appDir = x264_data_path();
QSettings settings(QString("%1/queue.ini").arg(appDir), QSettings::IniFormat);
bool ok = false;
const size_t jobCounter = settings.value(KEY_ENTRY_COUNT, 0).toUInt(&ok);
if((!ok) || (jobCounter < 1))
{
return 0;
}
size_t jobsCreated = 0;
for(size_t i = 0; i < jobCounter; i++)
{
settings.beginGroup(QString().sprintf(JOB_TEMPLATE, i));
const QString sourceFileName = settings.value(KEY_SOURCE_FILE, QString()).toString().trimmed();
const QString outputFileName = settings.value(KEY_OUTPUT_FILE, QString()).toString().trimmed();
if(sourceFileName.isEmpty() || outputFileName.isEmpty())
{
settings.endGroup();
continue;
}
settings.beginGroup(KEY_ENC_OPTIONS);
OptionsModel options(sysinfo);
const bool okay = OptionsModel::loadOptions(&options, settings);
settings.endGroup();
settings.endGroup();
if(okay)
{
EncodeThread *thread = new EncodeThread(sourceFileName, outputFileName, &options, sysinfo, m_preferences);
insertJob(thread);
jobsCreated++;
}
}
return jobsCreated;
}
void JobListModel::clearQueuedJobs(void)
{
const QString appDir = x264_data_path();
QSettings settings(QString("%1/queue.ini").arg(appDir), QSettings::IniFormat);
settings.clear();
}

View File

@ -60,6 +60,10 @@ public:
const OptionsModel *getJobOptions(const QModelIndex &index); const OptionsModel *getJobOptions(const QModelIndex &index);
QModelIndex getJobIndexById(const QUuid &id); QModelIndex getJobIndexById(const QUuid &id);
size_t saveQueuedJobs(void);
size_t loadQueuedJobs(const SysinfoModel *sysinfo);
void clearQueuedJobs(void);
protected: protected:
QList<QUuid> m_jobs; QList<QUuid> m_jobs;
QMap<QUuid, QString> m_name; QMap<QUuid, QString> m_name;

View File

@ -124,7 +124,7 @@ bool OptionsModel::equals(const OptionsModel *model)
return equal; return equal;
} }
bool OptionsModel::saveTemplate(OptionsModel *model, const QString &name) bool OptionsModel::saveTemplate(const OptionsModel *model, const QString &name)
{ {
const QString templateName = name.simplified(); const QString templateName = name.simplified();
const QString appDir = x264_data_path(); const QString appDir = x264_data_path();
@ -137,22 +137,12 @@ bool OptionsModel::saveTemplate(OptionsModel *model, const QString &name)
QSettings settings(QString("%1/templates.ini").arg(appDir), QSettings::IniFormat); QSettings settings(QString("%1/templates.ini").arg(appDir), QSettings::IniFormat);
settings.beginGroup(templateName); settings.beginGroup(templateName);
settings.setValue(KEY_ENCODER_TYPE, model->m_encoderType); const bool okay = saveOptions(model, settings);
settings.setValue(KEY_ENCODER_ARCH, model->m_encoderArch);
settings.setValue(KEY_ENCODER_VARIANT, model->m_encoderVariant);
settings.setValue(KEY_RATECTRL_MODE, model->m_rcMode);
settings.setValue(KEY_TARGET_BITRATE, model->m_bitrate);
settings.setValue(KEY_TARGET_QUANT, model->m_quantizer);
settings.setValue(KEY_PRESET_NAME, model->m_preset);
settings.setValue(KEY_TUNING_NAME, model->m_tune);
settings.setValue(KEY_PROFILE_NAME, model->m_profile);
settings.setValue(KEY_CUSTOM_ENCODER, model->m_custom_encoder);
settings.setValue(KEY_CUSTOM_AVS2YUV, model->m_custom_avs2yuv);
settings.endGroup(); settings.endGroup();
settings.sync(); settings.sync();
return true; return okay;
} }
bool OptionsModel::loadTemplate(OptionsModel *model, const QString &name) bool OptionsModel::loadTemplate(OptionsModel *model, const QString &name)
@ -167,57 +157,10 @@ bool OptionsModel::loadTemplate(OptionsModel *model, const QString &name)
QSettings settings(QString("%1/templates.ini").arg(appDir), QSettings::IniFormat); QSettings settings(QString("%1/templates.ini").arg(appDir), QSettings::IniFormat);
settings.beginGroup(name); settings.beginGroup(name);
//For backward-compatibility const bool okay = loadOptions(model, settings);
static const char *legacyKey[] = { "custom_params", "custom_params_x264", NULL };
for(int i = 0; legacyKey[i]; i++)
{
if(settings.contains(legacyKey[i]))
{
settings.setValue(KEY_CUSTOM_ENCODER, settings.value(legacyKey[i]));
settings.remove(legacyKey[i]);
settings.sync();
}
}
if(settings.value(KEY_PROFILE_NAME).toString().compare("auto", Qt::CaseInsensitive) == 0)
{
settings.setValue(KEY_PROFILE_NAME, QString::fromLatin1(OptionsModel::PROFILE_UNRESTRICTED));
}
if(settings.value(KEY_TUNING_NAME).toString().compare("none", Qt::CaseInsensitive) == 0)
{
settings.setValue(KEY_TUNING_NAME, QString::fromLatin1(OptionsModel::TUNING_UNSPECIFIED));
}
bool complete = true;
if(!settings.contains(KEY_ENCODER_TYPE)) complete = false;
if(!settings.contains(KEY_ENCODER_ARCH)) complete = false;
if(!settings.contains(KEY_ENCODER_VARIANT)) complete = false;
if(!settings.contains(KEY_RATECTRL_MODE)) complete = false;
if(!settings.contains(KEY_TARGET_BITRATE)) complete = false;
if(!settings.contains(KEY_TARGET_QUANT)) complete = false;
if(!settings.contains(KEY_PRESET_NAME)) complete = false;
if(!settings.contains(KEY_TUNING_NAME)) complete = false;
if(!settings.contains(KEY_PROFILE_NAME)) complete = false;
if(!settings.contains(KEY_CUSTOM_ENCODER)) complete = false;
if(!settings.contains(KEY_CUSTOM_AVS2YUV)) complete = false;
if(complete)
{
model->setEncType (static_cast<OptionsModel::EncType> (settings.value(KEY_ENCODER_TYPE, model->m_encoderType) .toInt()));
model->setEncArch (static_cast<OptionsModel::EncArch> (settings.value(KEY_ENCODER_ARCH, model->m_encoderArch) .toInt()));
model->setEncVariant (static_cast<OptionsModel::EncVariant>(settings.value(KEY_ENCODER_VARIANT, model->m_encoderVariant).toInt()));
model->setRCMode (static_cast<OptionsModel::RCMode> (settings.value(KEY_RATECTRL_MODE, model->m_rcMode) .toInt()));
model->setBitrate (settings.value(KEY_TARGET_BITRATE, model->m_bitrate).toUInt() );
model->setQuantizer (settings.value(KEY_TARGET_QUANT, model->m_quantizer).toDouble() );
model->setPreset (settings.value(KEY_PRESET_NAME, model->m_preset).toString() );
model->setTune (settings.value(KEY_TUNING_NAME, model->m_tune).toString() );
model->setProfile (settings.value(KEY_PROFILE_NAME, model->m_profile).toString() );
model->setCustomEncParams(settings.value(KEY_CUSTOM_ENCODER, model->m_custom_encoder).toString());
model->setCustomAvs2YUV (settings.value(KEY_CUSTOM_AVS2YUV, model->m_custom_avs2yuv).toString());
}
settings.endGroup(); settings.endGroup();
return complete; return okay;
} }
QMap<QString, OptionsModel*> OptionsModel::loadAllTemplates(const SysinfoModel *sysinfo) QMap<QString, OptionsModel*> OptionsModel::loadAllTemplates(const SysinfoModel *sysinfo)
@ -266,3 +209,73 @@ bool OptionsModel::deleteTemplate(const QString &name)
return false; return false;
} }
bool OptionsModel::saveOptions(const OptionsModel *model, QSettings &settingsFile)
{
settingsFile.setValue(KEY_ENCODER_TYPE, model->m_encoderType);
settingsFile.setValue(KEY_ENCODER_ARCH, model->m_encoderArch);
settingsFile.setValue(KEY_ENCODER_VARIANT, model->m_encoderVariant);
settingsFile.setValue(KEY_RATECTRL_MODE, model->m_rcMode);
settingsFile.setValue(KEY_TARGET_BITRATE, model->m_bitrate);
settingsFile.setValue(KEY_TARGET_QUANT, model->m_quantizer);
settingsFile.setValue(KEY_PRESET_NAME, model->m_preset);
settingsFile.setValue(KEY_TUNING_NAME, model->m_tune);
settingsFile.setValue(KEY_PROFILE_NAME, model->m_profile);
settingsFile.setValue(KEY_CUSTOM_ENCODER, model->m_custom_encoder);
settingsFile.setValue(KEY_CUSTOM_AVS2YUV, model->m_custom_avs2yuv);
return true;
}
bool OptionsModel::loadOptions(OptionsModel *model, QSettings &settingsFile)
{
//For backward-compatibility
static const char *legacyKey[] = { "custom_params", "custom_params_x264", NULL };
for(int i = 0; legacyKey[i]; i++)
{
if(settingsFile.contains(legacyKey[i]))
{
settingsFile.setValue(KEY_CUSTOM_ENCODER, settingsFile.value(legacyKey[i]));
settingsFile.remove(legacyKey[i]);
}
}
if(settingsFile.value(KEY_PROFILE_NAME).toString().compare("auto", Qt::CaseInsensitive) == 0)
{
settingsFile.setValue(KEY_PROFILE_NAME, QString::fromLatin1(OptionsModel::PROFILE_UNRESTRICTED));
}
if(settingsFile.value(KEY_TUNING_NAME).toString().compare("none", Qt::CaseInsensitive) == 0)
{
settingsFile.setValue(KEY_TUNING_NAME, QString::fromLatin1(OptionsModel::TUNING_UNSPECIFIED));
}
bool complete = true;
if(!settingsFile.contains(KEY_ENCODER_TYPE)) complete = false;
if(!settingsFile.contains(KEY_ENCODER_ARCH)) complete = false;
if(!settingsFile.contains(KEY_ENCODER_VARIANT)) complete = false;
if(!settingsFile.contains(KEY_RATECTRL_MODE)) complete = false;
if(!settingsFile.contains(KEY_TARGET_BITRATE)) complete = false;
if(!settingsFile.contains(KEY_TARGET_QUANT)) complete = false;
if(!settingsFile.contains(KEY_PRESET_NAME)) complete = false;
if(!settingsFile.contains(KEY_TUNING_NAME)) complete = false;
if(!settingsFile.contains(KEY_PROFILE_NAME)) complete = false;
if(!settingsFile.contains(KEY_CUSTOM_ENCODER)) complete = false;
if(!settingsFile.contains(KEY_CUSTOM_AVS2YUV)) complete = false;
if(complete)
{
model->setEncType (static_cast<OptionsModel::EncType> (settingsFile.value(KEY_ENCODER_TYPE, model->m_encoderType) .toInt()));
model->setEncArch (static_cast<OptionsModel::EncArch> (settingsFile.value(KEY_ENCODER_ARCH, model->m_encoderArch) .toInt()));
model->setEncVariant (static_cast<OptionsModel::EncVariant>(settingsFile.value(KEY_ENCODER_VARIANT, model->m_encoderVariant).toInt()));
model->setRCMode (static_cast<OptionsModel::RCMode> (settingsFile.value(KEY_RATECTRL_MODE, model->m_rcMode) .toInt()));
model->setBitrate (settingsFile.value(KEY_TARGET_BITRATE, model->m_bitrate) .toUInt() );
model->setQuantizer (settingsFile.value(KEY_TARGET_QUANT, model->m_quantizer) .toDouble());
model->setPreset (settingsFile.value(KEY_PRESET_NAME, model->m_preset) .toString());
model->setTune (settingsFile.value(KEY_TUNING_NAME, model->m_tune) .toString());
model->setProfile (settingsFile.value(KEY_PROFILE_NAME, model->m_profile) .toString());
model->setCustomEncParams(settingsFile.value(KEY_CUSTOM_ENCODER, model->m_custom_encoder).toString());
model->setCustomAvs2YUV (settingsFile.value(KEY_CUSTOM_AVS2YUV, model->m_custom_avs2yuv).toString());
}
return complete;
}

View File

@ -26,6 +26,7 @@
#include <QMap> #include <QMap>
class SysinfoModel; class SysinfoModel;
class QSettings;
class OptionsModel class OptionsModel
{ {
@ -94,11 +95,13 @@ public:
//Static functions //Static functions
static QString rcMode2String(RCMode mode); static QString rcMode2String(RCMode mode);
static bool saveTemplate(OptionsModel *model, const QString &name); static bool saveTemplate(const OptionsModel *model, const QString &name);
static bool loadTemplate(OptionsModel *model, const QString &name); static bool loadTemplate(OptionsModel *model, const QString &name);
static QMap<QString, OptionsModel*> loadAllTemplates(const SysinfoModel *sysinfo); static QMap<QString, OptionsModel*> loadAllTemplates(const SysinfoModel *sysinfo);
static bool templateExists(const QString &name); static bool templateExists(const QString &name);
static bool deleteTemplate(const QString &name); static bool deleteTemplate(const QString &name);
static bool saveOptions(const OptionsModel *model, QSettings &settingsFile);
static bool loadOptions(OptionsModel *model, QSettings &settingsFile);
protected: protected:
EncType m_encoderType; EncType m_encoderType;

View File

@ -46,9 +46,9 @@ public:
~EncodeThread(void); ~EncodeThread(void);
QUuid getId(void) { return this->m_jobId; }; QUuid getId(void) { return this->m_jobId; };
const QString &sourceFileName(void) { return this->m_sourceFileName; } const QString &sourceFileName(void) const { return this->m_sourceFileName; }
const QString &outputFileName(void) { return this->m_outputFileName; } const QString &outputFileName(void) const { return this->m_outputFileName; }
const OptionsModel *options(void) { return m_options; } const OptionsModel *options(void) const { return m_options; }
void pauseJob(void) void pauseJob(void)
{ {

View File

@ -25,8 +25,8 @@
#define VER_X264_MAJOR 2 #define VER_X264_MAJOR 2
#define VER_X264_MINOR 3 #define VER_X264_MINOR 3
#define VER_X264_PATCH 6 #define VER_X264_PATCH 7
#define VER_X264_BUILD 826 #define VER_X264_BUILD 829
#define VER_X264_PORTABLE_EDITION (0) #define VER_X264_PORTABLE_EDITION (0)

View File

@ -970,7 +970,7 @@ void MainWindow::init(void)
//--------------------------------------- //---------------------------------------
//Set Window title //Set Window title
setWindowTitle(QString("%1 (%2)").arg(tr("Simple %1 Launcher").arg(m_sysinfo->has256Support() ? "x264/x265" : "x264"), m_sysinfo->hasX64Support() ? "64-Bit" : "32-Bit")); setWindowTitle(QString("%1 (%2)").arg(windowTitle(), m_sysinfo->hasX64Support() ? "64-Bit" : "32-Bit"));
//Enable drag&drop support for this window, required for Qt v4.8.4+ //Enable drag&drop support for this window, required for Qt v4.8.4+
setAcceptDrops(true); setAcceptDrops(true);
@ -991,6 +991,12 @@ void MainWindow::init(void)
} }
} }
} }
//Load queued jobs
if(m_jobList->loadQueuedJobs(m_sysinfo) > 0)
{
m_label->setVisible(m_jobList->rowCount(QModelIndex()) == 0);
}
} }
/* /*
@ -1159,7 +1165,6 @@ void MainWindow::showEvent(QShowEvent *e)
if(m_status == STATUS_PRE_INIT) if(m_status == STATUS_PRE_INIT)
{ {
setWindowTitle(tr("%1 - Starting...").arg(windowTitle()));
QTimer::singleShot(0, this, SLOT(init())); QTimer::singleShot(0, this, SLOT(init()));
} }
} }
@ -1169,6 +1174,8 @@ void MainWindow::showEvent(QShowEvent *e)
*/ */
void MainWindow::closeEvent(QCloseEvent *e) void MainWindow::closeEvent(QCloseEvent *e)
{ {
bool bJobsHaveBeenSaved = false;
if((m_status != STATUS_IDLE) && (m_status != STATUS_EXITTING)) if((m_status != STATUS_IDLE) && (m_status != STATUS_EXITTING))
{ {
e->ignore(); e->ignore();
@ -1176,6 +1183,7 @@ void MainWindow::closeEvent(QCloseEvent *e)
return; return;
} }
//Make sure we have no running jobs left!
if(m_status != STATUS_EXITTING) if(m_status != STATUS_EXITTING)
{ {
if(countRunningJobs() > 0) if(countRunningJobs() > 0)
@ -1186,30 +1194,50 @@ void MainWindow::closeEvent(QCloseEvent *e)
m_status = STATUS_IDLE; m_status = STATUS_IDLE;
return; return;
} }
//Save pending jobs for next time, if desired by user
if(countPendingJobs() > 0) if(countPendingJobs() > 0)
{ {
m_status = STATUS_BLOCKED; m_status = STATUS_BLOCKED;
int ret = QMessageBox::question(this, tr("Jobs Are Pending"), tr("Do you really want to quit and discard the pending jobs?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No); int ret = QMessageBox::question(this, tr("Jobs Are Pending"), tr("You still have pending jobs. How do you want to proceed?"), tr("Save Pending Jobs"), tr("Discard"));
if(ret != QMessageBox::Yes) if(ret == 0)
{ {
e->ignore(); if(m_jobList->saveQueuedJobs() > 0)
m_status = STATUS_IDLE; {
return; bJobsHaveBeenSaved = true;
}
}
else
{
if(QMessageBox::warning(this, tr("Jobs Are Pending"), tr("Do you really want to discard all pending jobs?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No) != QMessageBox::Yes)
{
e->ignore();
m_status = STATUS_IDLE;
return;
}
} }
} }
} }
//Clear "old" pending jobs for next startup (only if we have not saved "new" jobs already!)
if(!bJobsHaveBeenSaved)
{
m_jobList->clearQueuedJobs();
}
//Delete remaining jobs
while(m_jobList->rowCount(QModelIndex()) > 0) while(m_jobList->rowCount(QModelIndex()) > 0)
{ {
qApp->processEvents(QEventLoop::ExcludeUserInputEvents); if((m_jobList->rowCount(QModelIndex()) % 10) == 0)
{
qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
}
if(!m_jobList->deleteJob(m_jobList->index(0, 0, QModelIndex()))) if(!m_jobList->deleteJob(m_jobList->index(0, 0, QModelIndex())))
{ {
e->ignore(); e->ignore();
m_status = STATUS_BLOCKED; m_status = STATUS_BLOCKED;
QMessageBox::warning(this, tr("Failed To Exit"), tr("Sorry, at least one job could not be deleted!")); QMessageBox::warning(this, tr("Failed To Exit"), tr("Warning: At least one job could not be deleted!"));
m_status = STATUS_IDLE; m_status = STATUS_IDLE;
return;
} }
} }