diff --git a/gui/win_addJob.ui b/gui/win_addJob.ui
index 1f9bcec..625fc15 100644
--- a/gui/win_addJob.ui
+++ b/gui/win_addJob.ui
@@ -7,7 +7,7 @@
0
0
560
- 498
+ 494
@@ -411,7 +411,7 @@
-
-
+
0
@@ -495,7 +495,7 @@
-
-
+
0
@@ -545,7 +545,7 @@
- Advanced Options
+ Advanced Encoder Options
-
@@ -590,6 +590,51 @@
-
+
+
+
+
+
+
+ 0
+ 0
+ 255
+
+
+
+
+
+
+
+
+ 0
+ 0
+ 255
+
+
+
+
+
+
+
+
+ 120
+ 120
+ 120
+
+
+
+
+
+
+
+
+ true
+
+
+
+ PointingHandCursor
+
Show Help Screen
@@ -598,7 +643,11 @@
-
-
+
+
+ true
+
+
@@ -630,6 +679,16 @@
-
+
-
+
+
+ Start Job Immediately
+
+
+ true
+
+
+
-
@@ -692,9 +751,8 @@
spinQuantizer
spinBitrate
cbxPreset
- comboBox_3
- comboBox_2
- lineEdit_3
+ cbxTuning
+ cbxProfile
diff --git a/gui/win_main.ui b/gui/win_main.ui
index 5af2cb2..f602e81 100644
--- a/gui/win_main.ui
+++ b/gui/win_main.ui
@@ -223,6 +223,12 @@
?
+
+
+
+
+
+
@@ -243,7 +249,52 @@
:/buttons/information.png:/buttons/information.png
- About
+ About...
+
+
+
+
+
+ :/buttons/world_link.png:/buttons/world_link.png
+
+
+ MuldeR's Web-Site
+
+
+
+
+
+ :/buttons/world_link.png:/buttons/world_link.png
+
+
+ Official x264 Web-Site
+
+
+
+
+
+ :/buttons/world_link.png:/buttons/world_link.png
+
+
+ Komisar's Web-Site
+
+
+
+
+
+ :/buttons/world_link.png:/buttons/world_link.png
+
+
+ Jarod's Web-Site
+
+
+
+
+
+ :/buttons/book_open.png:/buttons/book_open.png
+
+
+ MeWiki - x264 Settings
diff --git a/res/buttons/book_open.png b/res/buttons/book_open.png
new file mode 100644
index 0000000..7d863f9
Binary files /dev/null and b/res/buttons/book_open.png differ
diff --git a/res/buttons/world_link.png b/res/buttons/world_link.png
new file mode 100644
index 0000000..b8edc12
Binary files /dev/null and b/res/buttons/world_link.png differ
diff --git a/res/resources.qrc b/res/resources.qrc
index 010ed4a..c832467 100644
--- a/res/resources.qrc
+++ b/res/resources.qrc
@@ -4,6 +4,7 @@
icons/movie.ico
buttons/accept.png
buttons/add.png
+ buttons/book_open.png
buttons/cancel.png
buttons/clock_pause.png
buttons/clock_stop.png
@@ -15,5 +16,6 @@
buttons/lightning.png
buttons/play.png
buttons/play_big.png
+ buttons/world_link.png
diff --git a/src/model_jobList.cpp b/src/model_jobList.cpp
index 4b6773d..ff6300b 100644
--- a/src/model_jobList.cpp
+++ b/src/model_jobList.cpp
@@ -24,6 +24,7 @@
#include "thread_encode.h"
#include
+#include
JobListModel::JobListModel(void)
{
@@ -101,7 +102,7 @@ QVariant JobListModel::data(const QModelIndex &index, int role) const
switch(index.column())
{
case 0:
- return m_jobs.at(index.row()).toString();
+ return m_name.value(m_jobs.at(index.row()));
break;
case 1:
switch(m_status.value(m_jobs.at(index.row())))
@@ -211,6 +212,7 @@ QModelIndex JobListModel::insertJob(EncodeThread *thread)
beginInsertRows(QModelIndex(), m_jobs.count(), m_jobs.count());
m_jobs.append(id);
+ m_name.insert(id, QFileInfo(thread->sourceFileName()).completeBaseName());
m_status.insert(id, EncodeThread::JobStatus_Enqueued);
m_progress.insert(id, 0);
m_threads.insert(id, thread);
diff --git a/src/model_jobList.h b/src/model_jobList.h
index 4987908..a78e818 100644
--- a/src/model_jobList.h
+++ b/src/model_jobList.h
@@ -54,6 +54,7 @@ public:
protected:
QList m_jobs;
+ QMap m_name;
QMap m_threads;
QMap m_status;
QMap m_progress;
diff --git a/src/thread_encode.cpp b/src/thread_encode.cpp
index 40cdef8..eb84e47 100644
--- a/src/thread_encode.cpp
+++ b/src/thread_encode.cpp
@@ -22,9 +22,11 @@
#include "thread_encode.h"
#include "global.h"
-EncodeThread::EncodeThread(void)
+EncodeThread::EncodeThread(const QString &sourceFileName, const QString &outputFileName)
:
- m_jobId(QUuid::createUuid())
+ m_jobId(QUuid::createUuid()),
+ m_sourceFileName(sourceFileName),
+ m_outputFileName(outputFileName)
{
m_abort = false;
}
diff --git a/src/thread_encode.h b/src/thread_encode.h
index 9072a7b..3205a0f 100644
--- a/src/thread_encode.h
+++ b/src/thread_encode.h
@@ -43,14 +43,20 @@ public:
JobStatus_Aborted = 9
};
- EncodeThread(void);
+ EncodeThread(const QString &sourceFileName, const QString &outputFileName);
~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; };
+
void abortJob(void) { m_abort = true; }
protected:
const QUuid m_jobId;
+ const QString m_sourceFileName;
+ const QString m_outputFileName;
+
volatile bool m_abort;
virtual void run(void);
diff --git a/src/win_addJob.cpp b/src/win_addJob.cpp
index aa12ff1..ad289c4 100644
--- a/src/win_addJob.cpp
+++ b/src/win_addJob.cpp
@@ -27,6 +27,39 @@
#include
#include
#include
+#include
+#include
+#include
+
+///////////////////////////////////////////////////////////////////////////////
+// Validator
+///////////////////////////////////////////////////////////////////////////////
+
+class StringValidator : public QValidator
+{
+ virtual State validate(QString &input, int &pos) const
+ {
+ bool invalid = input.simplified().compare(input) && input.simplified().append(" ").compare(input) &&
+ input.simplified().prepend(" ").compare(input) && input.simplified().append(" ").prepend(" ").compare(input);
+
+ if(!invalid)
+ {
+ invalid = invalid || input.contains("--fps");
+ invalid = invalid || input.contains("--frames");
+ invalid = invalid || input.contains("--preset");
+ invalid = invalid || input.contains("--tune");
+ invalid = invalid || input.contains("--profile");
+ }
+
+ if(invalid) MessageBeep(MB_ICONWARNING);
+ return invalid ? QValidator::Invalid : QValidator::Acceptable;
+ }
+
+ virtual void fixup(QString &input) const
+ {
+ input = input.simplified();
+ }
+};
///////////////////////////////////////////////////////////////////////////////
// Constructor & Destructor
@@ -46,20 +79,128 @@ AddJobDialog::AddJobDialog(QWidget *parent)
//Activate combobox
connect(cbxRateControlMode, SIGNAL(currentIndexChanged(int)), this, SLOT(modeIndexChanged(int)));
+
+ //Activate buttons
+ connect(buttonBrowseSource, SIGNAL(clicked()), this, SLOT(browseButtonClicked()));
+ connect(buttonBrowseOutput, SIGNAL(clicked()), this, SLOT(browseButtonClicked()));
+
+ //Setup validator
+ cbxCustomParams->setValidator(new StringValidator());
+ cbxCustomParams->addItem("--bluray-compat --vbv-maxrate 40000 --vbv-bufsize 30000 --level 4.1 --keyint 25 --open-gop --slices 4");
+ cbxCustomParams->clearEditText();
}
AddJobDialog::~AddJobDialog(void)
{
}
+///////////////////////////////////////////////////////////////////////////////
+// Events
+///////////////////////////////////////////////////////////////////////////////
+
void AddJobDialog::showEvent(QShowEvent *event)
{
QDialog::showEvent(event);
modeIndexChanged(cbxRateControlMode->currentIndex());
}
+///////////////////////////////////////////////////////////////////////////////
+// Slots
+///////////////////////////////////////////////////////////////////////////////
+
void AddJobDialog::modeIndexChanged(int index)
{
spinQuantizer->setEnabled(index == 0 || index == 1);
spinBitrate->setEnabled(index == 2 || index == 3);
}
+
+void AddJobDialog::accept(void)
+{
+ if(editSource->text().trimmed().isEmpty())
+ {
+ QMessageBox::warning(this, tr("Not Found!"), tr("Please select a valid source file first!"));
+ return;
+ }
+
+ QFileInfo sourceFile = QFileInfo(editSource->text());
+ if(!(sourceFile.exists() && sourceFile.isFile()))
+ {
+ QMessageBox::warning(this, tr("Not Found!"), tr("The selected source file could not be found!"));
+ return;
+ }
+
+ QFileInfo outputDir = QFileInfo(QFileInfo(editOutput->text()).path());
+ if(!(outputDir.exists() && outputDir.isDir() && outputDir.isWritable()))
+ {
+ QMessageBox::warning(this, tr("Not Writable!"), tr("Output directory does not exist or is not writable!"));
+ return;
+ }
+
+ QFileInfo outputFile = QFileInfo(editOutput->text());
+ if(outputFile.exists() && outputFile.isFile())
+ {
+ if(QMessageBox::question(this, tr("Already Exists!"), tr("Output file already exists! Overwrite?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No) != QMessageBox::Yes)
+ {
+ return;
+ }
+ }
+ if(outputFile.exists() && (!outputFile.isFile()))
+ {
+ QMessageBox::warning(this, tr("Not a File!"), tr("Selected output files does not appear to be a file!"));
+ return;
+ }
+
+ QDialog::accept();
+}
+
+void AddJobDialog::browseButtonClicked(void)
+{
+ QString initialDir = QDesktopServices::storageLocation(QDesktopServices::MoviesLocation);
+
+ if(QObject::sender() == buttonBrowseSource)
+ {
+ QString filters;
+ filters += tr("Avisynth Scripts (*.avs)").append(";;");
+ filters += tr("Matroska Files (*.mkv)").append(";;");
+ filters += tr("MPEG-4 Part 14 Container (*.mp4)").append(";;");
+ filters += tr("Audio Video Interleaved (*.avi)").append(";;");
+ filters += tr("Flash Video (*.flv)").append(";;");
+
+ QString filePath = QFileDialog::getOpenFileName(this, tr("Open Source File"), initialDir, filters);
+
+ if(!(filePath.isNull() || filePath.isEmpty()))
+ {
+ editSource->setText(filePath);
+
+ QString path = QFileInfo(filePath).path();
+ QString name = QFileInfo(filePath).completeBaseName();
+
+ QString outPath = QString("%1/%2.mkv").arg(path, name);
+
+ if(QFileInfo(outPath).exists())
+ {
+ int i = 2;
+ while(QFileInfo(outPath).exists())
+ {
+ outPath = QString("%1/%2 (%3).mkv").arg(path, name, QString::number(i++));
+ }
+ }
+
+ editOutput->setText(outPath);
+ }
+ }
+ else if(QObject::sender() == buttonBrowseOutput)
+ {
+ QString filters;
+ filters += tr("Matroska Files (*.mkv)").append(";;");
+ filters += tr("MPEG-4 Part 14 Container (*.mp4)").append(";;");
+ filters += tr("H.264 Elementary Stream (*.264)").append(";;");
+
+ QString filePath = QFileDialog::getSaveFileName(this, tr("Choose Output File"), initialDir, filters);
+
+ if(!(filePath.isNull() || filePath.isEmpty()))
+ {
+ editOutput->setText(filePath);
+ }
+ }
+}
diff --git a/src/win_addJob.h b/src/win_addJob.h
index 5d0f69a..527ebc2 100644
--- a/src/win_addJob.h
+++ b/src/win_addJob.h
@@ -23,7 +23,7 @@
#include "uic_win_addJob.h"
-class AddJobDialog: public QDialog, private Ui::AddJobDialog
+class AddJobDialog : public QDialog, private Ui::AddJobDialog
{
Q_OBJECT
@@ -31,9 +31,21 @@ public:
AddJobDialog(QWidget *parent);
~AddJobDialog(void);
+ QString sourceFile(void) { return editSource->text(); }
+ QString outputFile(void) { return editOutput->text(); }
+ QString preset(void) { return cbxPreset->itemText(cbxPreset->currentIndex()); }
+ QString tuning(void) { return cbxTuning->itemText(cbxTuning->currentIndex()); }
+ QString profile(void) { return cbxProfile->itemText(cbxProfile->currentIndex()); }
+ QString params(void) { return cbxCustomParams->currentText().simplified(); }
+ bool runImmediately(void) { return checkBoxRun->isChecked(); }
+ void setRunImmediately(bool run) { checkBoxRun->setChecked(run); }
+
protected:
virtual void AddJobDialog::showEvent(QShowEvent *event);
private slots:
void modeIndexChanged(int index);
+ void browseButtonClicked(void);
+
+ virtual void accept(void);
};
diff --git a/src/win_main.cpp b/src/win_main.cpp
index 4d28261..bef3f42 100644
--- a/src/win_main.cpp
+++ b/src/win_main.cpp
@@ -29,6 +29,10 @@
#include
#include
#include
+#include
+#include
+
+const char *home_url = "http://mulder.brhack.net/";
///////////////////////////////////////////////////////////////////////////////
// Constructor & Destructor
@@ -75,6 +79,11 @@ MainWindow::MainWindow(bool x64supported)
//Enable menu
connect(actionAbout, SIGNAL(triggered()), this, SLOT(showAbout()));
+ connect(actionWebMulder, SIGNAL(triggered()), this, SLOT(showWebLink()));
+ connect(actionWebX264, SIGNAL(triggered()), this, SLOT(showWebLink()));
+ connect(actionWebKomisar, SIGNAL(triggered()), this, SLOT(showWebLink()));
+ connect(actionWebJarod, SIGNAL(triggered()), this, SLOT(showWebLink()));
+ connect(actionWebWiki, SIGNAL(triggered()), this, SLOT(showWebLink()));
}
MainWindow::~MainWindow(void)
@@ -89,13 +98,25 @@ MainWindow::~MainWindow(void)
void MainWindow::addButtonPressed(void)
{
AddJobDialog *addDialog = new AddJobDialog(this);
+ addDialog->setRunImmediately(!havePendingJobs());
int result = addDialog->exec();
if(result == QDialog::Accepted)
{
- EncodeThread *thrd = new EncodeThread();
+ EncodeThread *thrd = new EncodeThread
+ (
+ addDialog->sourceFile(),
+ addDialog->outputFile()
+ );
+
QModelIndex newIndex = m_jobList->insertJob(thrd);
- jobsView->selectRow(newIndex.row());
+
+ if(addDialog->runImmediately())
+ {
+ jobsView->selectRow(newIndex.row());
+ QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
+ m_jobList->startJob(newIndex);
+ }
}
X264_DELETE(addDialog);
@@ -181,7 +202,6 @@ void MainWindow::jobLogExtended(const QModelIndex & parent, int start, int end)
void MainWindow::showAbout(void)
{
QString text;
- const char *url = "http://mulder.brhack.net/";
text += QString().sprintf("Simple x264 Launcher v%u.%02u - use 64-Bit x264 with 32-Bit Avisynth
", x264_version_major(), x264_version_minor());
text += QString().sprintf("Copyright (c) 2004-%04d LoRd_MuldeR <mulder2@gmx.de>. Some rights reserved.
", qMax(x264_version_date().year(),QDate::currentDate().year()));
@@ -189,11 +209,20 @@ void MainWindow::showAbout(void)
text += QString().sprintf("This program is free software: you can redistribute it and/or modify
");
text += QString().sprintf("it under the terms of the GNU General Public License <http://www.gnu.org/>.
");
text += QString().sprintf("Note that this program is distributed with ABSOLUTELY NO WARRANTY.
");
- text += QString().sprintf("Please check the web-site at %s for updates !!!
", url, url);
+ text += QString().sprintf("Please check the web-site at %s for updates !!!
", home_url, home_url);
QMessageBox::information(this, tr("About..."), text.replace("-", "−"));
}
+void MainWindow::showWebLink(void)
+{
+ if(QObject::sender() == actionWebMulder) QDesktopServices::openUrl(QUrl(home_url));
+ if(QObject::sender() == actionWebX264) QDesktopServices::openUrl(QUrl("http://www.x264.com/"));
+ if(QObject::sender() == actionWebKomisar) QDesktopServices::openUrl(QUrl("http://komisar.gin.by/"));
+ if(QObject::sender() == actionWebJarod) QDesktopServices::openUrl(QUrl("http://www.x264.nl/"));
+ if(QObject::sender() == actionWebWiki) QDesktopServices::openUrl(QUrl("http://mewiki.project357.com/wiki/X264_Settings"));
+}
+
void MainWindow::launchNextJob(void)
{
const int rows = m_jobList->rowCount(QModelIndex());
@@ -227,24 +256,36 @@ void MainWindow::launchNextJob(void)
void MainWindow::closeEvent(QCloseEvent *e)
{
- const int rows = m_jobList->rowCount(QModelIndex());
-
- for(int i = 0; i < rows; i++)
+ if(havePendingJobs())
{
- EncodeThread::JobStatus status = m_jobList->getJobStatus(m_jobList->index(i, 0, QModelIndex()));
- if(status != EncodeThread::JobStatus_Completed && status != EncodeThread::JobStatus_Aborted && status != EncodeThread::JobStatus_Failed)
- {
- e->ignore();
- MessageBeep(MB_ICONWARNING);
- break;
- }
+ e->ignore();
+ MessageBeep(MB_ICONWARNING);
+ return;
}
+
+ QMainWindow::closeEvent(e);
}
///////////////////////////////////////////////////////////////////////////////
// Private functions
///////////////////////////////////////////////////////////////////////////////
+bool MainWindow::havePendingJobs(void)
+{
+ const int rows = m_jobList->rowCount(QModelIndex());
+
+ for(int i = 0; i < rows; i++)
+ {
+ EncodeThread::JobStatus status = m_jobList->getJobStatus(m_jobList->index(i, 0, QModelIndex()));
+ if(status != EncodeThread::JobStatus_Completed && status != EncodeThread::JobStatus_Aborted && status != EncodeThread::JobStatus_Failed)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
void MainWindow::updateButtons(EncodeThread::JobStatus status)
{
qDebug("MainWindow::updateButtons(void)");
diff --git a/src/win_main.h b/src/win_main.h
index 1449ccf..adc59cc 100644
--- a/src/win_main.h
+++ b/src/win_main.h
@@ -42,6 +42,7 @@ private:
const bool m_x64supported;
void updateButtons(EncodeThread::JobStatus status);
+ bool havePendingJobs(void);
private slots:
void addButtonPressed(void);
@@ -51,5 +52,6 @@ private slots:
void jobChangedData(const QModelIndex &top, const QModelIndex &bottom);
void jobLogExtended(const QModelIndex & parent, int start, int end);
void showAbout(void);
+ void showWebLink(void);
void launchNextJob(void);
};