diff --git a/gui/win_addJob.ui b/gui/win_addJob.ui index 2f74712..e11cb95 100644 --- a/gui/win_addJob.ui +++ b/gui/win_addJob.ui @@ -695,6 +695,69 @@ + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + 170 + 0 + 0 + + + + + + + + + 170 + 0 + 0 + + + + + + + + + 120 + 120 + 120 + + + + + + + + + 75 + true + + + + Invalid parameter entered! + + + @@ -763,7 +826,11 @@ - + + + You can enter custom command-line options here... + + diff --git a/gui/win_main.ui b/gui/win_main.ui index a75be49..08e5818 100644 --- a/gui/win_main.ui +++ b/gui/win_main.ui @@ -211,6 +211,9 @@ + + WhatsThisCursor + (Version) diff --git a/src/thread_encode.cpp b/src/thread_encode.cpp index 7d2f72f..2163764 100644 --- a/src/thread_encode.cpp +++ b/src/thread_encode.cpp @@ -150,8 +150,47 @@ void EncodeThread::encode(void) bool ok = false; unsigned int frames = 0; + //Use Avisynth? + const bool usePipe = (QFileInfo(m_sourceFileName).suffix().compare("avs", Qt::CaseInsensitive) == 0); + + //Checking x264 version + log(tr("\n--- CHECK VERSION ---\n")); + unsigned int revision_x264 = UINT_MAX; + ok = ((revision_x264 = checkVersionX264(m_x64)) != UINT_MAX); + CHECK_STATUS(m_abort, ok); + + //Checking avs2yuv version + unsigned int revision_avs2yuv = UINT_MAX; + if(usePipe) + { + ok = ((revision_avs2yuv = checkVersionAvs2yuv()) != UINT_MAX); + CHECK_STATUS(m_abort, ok); + } + + //Print versions + log(tr("\nx264 revision: %1 (core #%2)").arg(QString::number(revision_x264 % REV_MULT), QString::number(revision_x264 / REV_MULT))); + if(revision_avs2yuv != UINT_MAX) log(tr("Avs2YUV version: %1.%2.%3").arg(QString::number(revision_avs2yuv / REV_MULT), QString::number((revision_avs2yuv % REV_MULT) / 10),QString::number((revision_avs2yuv % REV_MULT) % 10))); + + //Is x264 revision supported? + if((revision_x264 % REV_MULT) < VER_X264_MINIMUM_REV) + { + log(tr("\nERROR: Your revision of x264 is too old! (Minimum required revision is %2)").arg(QString::number(VER_X264_MINIMUM_REV))); + setStatus(JobStatus_Failed); + return; + } + if((revision_x264 / REV_MULT) != VER_X264_CURRENT_API) + { + 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))); + } + if((revision_avs2yuv != UINT_MAX) && ((revision_avs2yuv % REV_MULT) != 242)) + { + log(tr("\nERROR: Your version of avs2yuv is unsupported (Required version is v0.24bm2)")); + setStatus(JobStatus_Failed); + return; + } + //Detect source info - bool usePipe = (QFileInfo(m_sourceFileName).suffix().compare("avs", Qt::CaseInsensitive) == 0); if(usePipe) { log(tr("\n--- AVS INFO ---\n")); @@ -159,26 +198,6 @@ void EncodeThread::encode(void) CHECK_STATUS(m_abort, ok); } - //Checking version - log(tr("\n--- X264 VERSION ---\n")); - unsigned int revision; - ok = ((revision = checkVersion(m_x64)) != UINT_MAX); - CHECK_STATUS(m_abort, ok); - - //Is revision supported? - log(tr("\nx264 revision: %1 (core #%2)").arg(QString::number(revision % REV_MULT), QString::number(revision / REV_MULT))); - if((revision % REV_MULT) < VER_X264_MINIMUM_REV) - { - log(tr("\nERROR: Your revision of x264 is too old! (Minimum required revision is %2)").arg(QString::number(VER_X264_MINIMUM_REV))); - setStatus(JobStatus_Failed); - return; - } - if((revision / REV_MULT) != VER_X264_CURRENT_API) - { - 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))); - } - //Run encoding passes if(m_options->rcMode() == OptionsModel::RCMode_2Pass) { @@ -423,7 +442,7 @@ QStringList EncodeThread::buildCommandLine(bool usePipe, unsigned int frames, in return cmdLine; } -unsigned int EncodeThread::checkVersion(bool x64) +unsigned int EncodeThread::checkVersionX264(bool x64) { QProcess process; QStringList cmdLine = QStringList() << "--version"; @@ -506,7 +525,98 @@ unsigned int EncodeThread::checkVersion(bool x64) return UINT_MAX; } - return (coreVers * REV_MULT) + revision; + return (coreVers * REV_MULT) + (revision % REV_MULT); +} + +unsigned int EncodeThread::checkVersionAvs2yuv(void) +{ + QProcess process; + + log("\nCreating process:"); + if(!startProcess(process, QString("%1/avs2yuv.exe").arg(m_binDir), QStringList())) + { + return false;; + } + + QRegExp regExpVersion("Avs2YUV (\\d+).(\\d+)bm(\\d)"); + + bool bTimeout = false; + bool bAborted = false; + + unsigned int ver_maj = UINT_MAX; + unsigned int ver_min = UINT_MAX; + unsigned int ver_bld = UINT_MAX; + + while(process.state() != QProcess::NotRunning) + { + if(m_abort) + { + process.kill(); + bAborted = true; + break; + } + if(!process.waitForReadyRead(m_processTimeoutInterval)) + { + if(process.state() == QProcess::Running) + { + process.kill(); + qWarning("Avs2YUV process timed out <-- killing!"); + log("\nPROCESS TIMEOUT !!!"); + bTimeout = true; + break; + } + } + while(process.bytesAvailable() > 0) + { + QList lines = process.readLine().split('\r'); + while(!lines.isEmpty()) + { + QString text = QString::fromUtf8(lines.takeFirst().constData()).simplified(); + int offset = -1; + if((ver_maj == UINT_MAX) || (ver_min == UINT_MAX) || (ver_bld == UINT_MAX)) + { + if(!text.isEmpty()) + { + log(text); + } + } + if((offset = regExpVersion.lastIndexIn(text)) >= 0) + { + bool ok1 = false, ok2 = false, ok3 = false; + unsigned int temp1 = regExpVersion.cap(1).toUInt(&ok1); + unsigned int temp2 = regExpVersion.cap(2).toUInt(&ok2); + unsigned int temp3 = regExpVersion.cap(3).toUInt(&ok3); + if(ok1) ver_maj = temp1; + if(ok2) ver_min = temp2; + if(ok3) ver_bld = temp3; + } + } + } + } + + process.waitForFinished(); + if(process.state() != QProcess::NotRunning) + { + process.kill(); + process.waitForFinished(-1); + } + + if(bTimeout || bAborted || ((process.exitCode() != EXIT_SUCCESS) && (process.exitCode() != 2))) + { + if(!(bTimeout || bAborted)) + { + log(tr("\nPROCESS EXITED WITH ERROR CODE: %1").arg(QString::number(process.exitCode()))); + } + return UINT_MAX; + } + + if((ver_maj == UINT_MAX) || (ver_min == UINT_MAX) || (ver_bld == UINT_MAX)) + { + log(tr("\nFAILED TO DETERMINE AVS2YUV VERSION !!!")); + return UINT_MAX; + } + + return (ver_maj * REV_MULT) + ((ver_min % REV_MULT) * 10) + (ver_bld % 10); } bool EncodeThread::checkProperties(unsigned int &frames) diff --git a/src/thread_encode.h b/src/thread_encode.h index f0a4a3b..4ced328 100644 --- a/src/thread_encode.h +++ b/src/thread_encode.h @@ -86,7 +86,8 @@ protected: void encode(void); bool runEncodingPass(bool x64, bool usePipe, unsigned int frames, int pass = 0, const QString &passLogFile = QString()); QStringList buildCommandLine(bool usePipe, unsigned int frames, int pass = 0, const QString &passLogFile = QString()); - unsigned int checkVersion(bool x64); + unsigned int checkVersionX264(bool x64); + unsigned int checkVersionAvs2yuv(void); bool checkProperties(unsigned int &frames); //Auxiallary Stuff diff --git a/src/win_addJob.cpp b/src/win_addJob.cpp index f4445cc..0e1f2ce 100644 --- a/src/win_addJob.cpp +++ b/src/win_addJob.cpp @@ -54,21 +54,42 @@ g_filters[] = class StringValidator : public QValidator { +public: + StringValidator(QLabel *notifier) : m_notifier(notifier) { m_notifier->hide(); } + 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); + bool invalid = false; + + invalid = invalid || (input.contains(" -B") || input.startsWith("-B")); + invalid = invalid || (input.contains(" -o") || input.startsWith("-o")); + invalid = invalid || (input.contains(" -h") || input.startsWith("-h")); + invalid = invalid || (input.contains(" -p") || input.startsWith("-p")); - if(!invalid) + invalid = invalid || input.contains("--fps", Qt::CaseInsensitive); + invalid = invalid || input.contains("--frames", Qt::CaseInsensitive); + invalid = invalid || input.contains("--preset", Qt::CaseInsensitive); + invalid = invalid || input.contains("--tune", Qt::CaseInsensitive); + invalid = invalid || input.contains("--profile", Qt::CaseInsensitive); + invalid = invalid || input.contains("--stdin", Qt::CaseInsensitive); + invalid = invalid || input.contains("--crf", Qt::CaseInsensitive); + invalid = invalid || input.contains("--bitrate", Qt::CaseInsensitive); + invalid = invalid || input.contains("--qp", Qt::CaseInsensitive); + invalid = invalid || input.contains("--pass", Qt::CaseInsensitive); + invalid = invalid || input.contains("--stats", Qt::CaseInsensitive); + invalid = invalid || input.contains("--output", Qt::CaseInsensitive); + invalid = invalid || input.contains("--help", Qt::CaseInsensitive); + + 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"); + MessageBeep(MB_ICONWARNING); + if(m_notifier->isHidden()) + { + m_notifier->show(); + QTimer::singleShot(1000, m_notifier, SLOT(hide())); + } } - if(invalid) MessageBeep(MB_ICONWARNING); return invalid ? QValidator::Invalid : QValidator::Acceptable; } @@ -76,6 +97,9 @@ class StringValidator : public QValidator { input = input.simplified(); } + +protected: + QLabel *const m_notifier; }; /////////////////////////////////////////////////////////////////////////////// @@ -107,7 +131,8 @@ AddJobDialog::AddJobDialog(QWidget *parent, OptionsModel *options) connect(buttonBrowseOutput, SIGNAL(clicked()), this, SLOT(browseButtonClicked())); //Setup validator - editCustomParams->setValidator(new StringValidator()); + editCustomParams->installEventFilter(this); + editCustomParams->setValidator(new StringValidator(labelNotification)); editCustomParams->clear(); //Install event filter @@ -153,7 +178,10 @@ bool AddJobDialog::eventFilter(QObject *o, QEvent *e) if((o == labelHelpScreen) && (e->type() == QEvent::MouseButtonPress)) { QMessageBox::information(this, tr("Not yet"), tr("Not implemented yet. Please use the '?' menu for now!")); - return true; + } + else if((o == editCustomParams) && (e->type() == QEvent::FocusOut)) + { + editCustomParams->setText(editCustomParams->text().simplified()); } return false; } diff --git a/src/win_main.cpp b/src/win_main.cpp index adc7209..2e9f45d 100644 --- a/src/win_main.cpp +++ b/src/win_main.cpp @@ -66,9 +66,11 @@ MainWindow::MainWindow(bool x64supported) //Update title labelBuildDate->setText(tr("Built on %1 at %2").arg(x264_version_date().toString(Qt::ISODate), QString::fromLatin1(x264_version_time()))); + labelBuildDate->installEventFilter(this); setWindowTitle(QString("%1 (%2 Mode)").arg(windowTitle(), m_x64supported ? "64-Bit" : "32-Bit")); if(PRE_RELEASE) setWindowTitle(QString("%1 | PRE-RELEASE VERSION").arg(windowTitle())); + //Create model m_jobList = new JobListModel(); connect(m_jobList, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, SLOT(jobChangedData(QModelIndex, QModelIndex))); @@ -398,6 +400,16 @@ void MainWindow::resizeEvent(QResizeEvent *e) updateLabel(); } +bool MainWindow::eventFilter(QObject *o, QEvent *e) +{ + if((o == labelBuildDate) && (e->type() == QEvent::MouseButtonPress)) + { + QTimer::singleShot(0, this, SLOT(showAbout())); + return true; + } + return false; +} + /////////////////////////////////////////////////////////////////////////////// // Private functions /////////////////////////////////////////////////////////////////////////////// diff --git a/src/win_main.h b/src/win_main.h index 0ad167f..593da2e 100644 --- a/src/win_main.h +++ b/src/win_main.h @@ -40,6 +40,7 @@ protected: virtual void closeEvent(QCloseEvent *e); virtual void showEvent(QShowEvent *e); virtual void resizeEvent(QResizeEvent *e); + virtual bool eventFilter(QObject *o, QEvent *e); private: bool m_firstShow; diff --git a/x264_launcher.vcxproj b/x264_launcher.vcxproj index 45fa97b..22d4a7a 100644 --- a/x264_launcher.vcxproj +++ b/x264_launcher.vcxproj @@ -107,6 +107,13 @@ + + rmdir /S /Q "$(SolutionDir)bin\$(Configuration)\toolset" +mkdir "$(SolutionDir)bin\$(Configuration)\toolset" +copy "$(SolutionDir)res\toolset\*.exe" "$(SolutionDir)bin\$(Configuration)\toolset" + + Copy Toolset + diff --git a/z_build.bat b/z_build.bat index 557a8f5..8f671a9 100644 --- a/z_build.bat +++ b/z_build.bat @@ -55,7 +55,7 @@ echo !insertmacro SECTION_END >> "%NSIS_FILE%" "%NSIS_PATH%\makensis.exe" "%NSIS_FILE%" if not "%ERRORLEVEL%"=="0" goto BuildError del "%NSIS_FILE%" -del /Q /S "%PACK_PATH%\*.*" +rmdir /Q /S "%PACK_PATH%" REM /////////////////////////////////////////////////////////////////////////// echo. echo Build completed.