diff --git a/gui/win_main.ui b/gui/win_main.ui
index bd1dabf..e26ab73 100644
--- a/gui/win_main.ui
+++ b/gui/win_main.ui
@@ -11,7 +11,7 @@
- Simple x264 Launcher
+ Simple x264/x265 Launcher
diff --git a/src/model_jobList.cpp b/src/model_jobList.cpp
index 781ac51..f265f70 100644
--- a/src/model_jobList.cpp
+++ b/src/model_jobList.cpp
@@ -28,6 +28,14 @@
#include
#include
+#include
+
+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)
{
@@ -233,19 +241,29 @@ QModelIndex JobListModel::insertJob(EncodeThread *thread)
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())
{
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;
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;
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;
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;
}
@@ -525,3 +543,89 @@ void JobListModel::updateDetails(const QUuid &jobId, const QString &details)
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::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();
+}
diff --git a/src/model_jobList.h b/src/model_jobList.h
index a941a7e..648b9f3 100644
--- a/src/model_jobList.h
+++ b/src/model_jobList.h
@@ -60,6 +60,10 @@ public:
const OptionsModel *getJobOptions(const QModelIndex &index);
QModelIndex getJobIndexById(const QUuid &id);
+ size_t saveQueuedJobs(void);
+ size_t loadQueuedJobs(const SysinfoModel *sysinfo);
+ void clearQueuedJobs(void);
+
protected:
QList m_jobs;
QMap m_name;
diff --git a/src/model_options.cpp b/src/model_options.cpp
index 082571c..76a3628 100644
--- a/src/model_options.cpp
+++ b/src/model_options.cpp
@@ -124,7 +124,7 @@ bool OptionsModel::equals(const OptionsModel *model)
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 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);
settings.beginGroup(templateName);
- settings.setValue(KEY_ENCODER_TYPE, model->m_encoderType);
- 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);
-
+ const bool okay = saveOptions(model, settings);
+
settings.endGroup();
settings.sync();
- return true;
+ return okay;
}
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);
settings.beginGroup(name);
- //For backward-compatibility
- 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 (settings.value(KEY_ENCODER_TYPE, model->m_encoderType) .toInt()));
- model->setEncArch (static_cast (settings.value(KEY_ENCODER_ARCH, model->m_encoderArch) .toInt()));
- model->setEncVariant (static_cast(settings.value(KEY_ENCODER_VARIANT, model->m_encoderVariant).toInt()));
- model->setRCMode (static_cast (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());
- }
+ const bool okay = loadOptions(model, settings);
settings.endGroup();
- return complete;
+ return okay;
}
QMap OptionsModel::loadAllTemplates(const SysinfoModel *sysinfo)
@@ -266,3 +209,73 @@ bool OptionsModel::deleteTemplate(const QString &name)
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 (settingsFile.value(KEY_ENCODER_TYPE, model->m_encoderType) .toInt()));
+ model->setEncArch (static_cast (settingsFile.value(KEY_ENCODER_ARCH, model->m_encoderArch) .toInt()));
+ model->setEncVariant (static_cast(settingsFile.value(KEY_ENCODER_VARIANT, model->m_encoderVariant).toInt()));
+ model->setRCMode (static_cast (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;
+}
diff --git a/src/model_options.h b/src/model_options.h
index 72cee6e..95d94de 100644
--- a/src/model_options.h
+++ b/src/model_options.h
@@ -26,6 +26,7 @@
#include
class SysinfoModel;
+class QSettings;
class OptionsModel
{
@@ -94,11 +95,13 @@ public:
//Static functions
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 QMap loadAllTemplates(const SysinfoModel *sysinfo);
static bool templateExists(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:
EncType m_encoderType;
diff --git a/src/thread_encode.h b/src/thread_encode.h
index bfbccae..673c845 100644
--- a/src/thread_encode.h
+++ b/src/thread_encode.h
@@ -46,9 +46,9 @@ public:
~EncodeThread(void);
QUuid getId(void) { return this->m_jobId; };
- const QString &sourceFileName(void) { return this->m_sourceFileName; }
- const QString &outputFileName(void) { return this->m_outputFileName; }
- const OptionsModel *options(void) { return m_options; }
+ const QString &sourceFileName(void) const { return this->m_sourceFileName; }
+ const QString &outputFileName(void) const { return this->m_outputFileName; }
+ const OptionsModel *options(void) const { return m_options; }
void pauseJob(void)
{
diff --git a/src/version.h b/src/version.h
index aab170b..86f6e3c 100644
--- a/src/version.h
+++ b/src/version.h
@@ -25,8 +25,8 @@
#define VER_X264_MAJOR 2
#define VER_X264_MINOR 3
-#define VER_X264_PATCH 6
-#define VER_X264_BUILD 826
+#define VER_X264_PATCH 7
+#define VER_X264_BUILD 829
#define VER_X264_PORTABLE_EDITION (0)
diff --git a/src/win_main.cpp b/src/win_main.cpp
index 4a767f8..ac25891 100644
--- a/src/win_main.cpp
+++ b/src/win_main.cpp
@@ -970,7 +970,7 @@ void MainWindow::init(void)
//---------------------------------------
//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+
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)
{
- setWindowTitle(tr("%1 - Starting...").arg(windowTitle()));
QTimer::singleShot(0, this, SLOT(init()));
}
}
@@ -1169,6 +1174,8 @@ void MainWindow::showEvent(QShowEvent *e)
*/
void MainWindow::closeEvent(QCloseEvent *e)
{
+ bool bJobsHaveBeenSaved = false;
+
if((m_status != STATUS_IDLE) && (m_status != STATUS_EXITTING))
{
e->ignore();
@@ -1176,6 +1183,7 @@ void MainWindow::closeEvent(QCloseEvent *e)
return;
}
+ //Make sure we have no running jobs left!
if(m_status != STATUS_EXITTING)
{
if(countRunningJobs() > 0)
@@ -1186,30 +1194,50 @@ void MainWindow::closeEvent(QCloseEvent *e)
m_status = STATUS_IDLE;
return;
}
-
+
+ //Save pending jobs for next time, if desired by user
if(countPendingJobs() > 0)
{
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);
- if(ret != QMessageBox::Yes)
+ 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 == 0)
{
- e->ignore();
- m_status = STATUS_IDLE;
- return;
+ if(m_jobList->saveQueuedJobs() > 0)
+ {
+ 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)
{
- 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())))
{
e->ignore();
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;
- return;
}
}