diff --git a/src/model_sysinfo.h b/src/model_sysinfo.h index cf36580..2369b9c 100644 --- a/src/model_sysinfo.h +++ b/src/model_sysinfo.h @@ -108,7 +108,8 @@ public: SYSINFO_MAKE_FLAG(VapourSynth) SYSINFO_MAKE_PATH(AVS) - SYSINFO_MAKE_PATH(VPS) + SYSINFO_MAKE_PATH(VPS32) + SYSINFO_MAKE_PATH(VPS64) SYSINFO_MAKE_PATH(App) protected: diff --git a/src/source_vapoursynth.cpp b/src/source_vapoursynth.cpp index a86044f..2838130 100644 --- a/src/source_vapoursynth.cpp +++ b/src/source_vapoursynth.cpp @@ -30,7 +30,7 @@ #include static const unsigned int VER_X264_VSPIPE_API = 3; -static const unsigned int VER_X264_VSPIPE_VER = 43; +static const unsigned int VER_X264_VSPIPE_VER = 46; // ------------------------------------------------------------ // Encoder Info @@ -41,7 +41,7 @@ class VapoursyntSourceInfo : public AbstractSourceInfo public: virtual QString getBinaryPath(const SysinfoModel *const sysinfo, const bool& x64) const { - return QString("%1/core%2/vspipe.exe").arg(sysinfo->getVPSPath(), (x64 ? "64" : "32")); + return QString("%1/vspipe.exe").arg(x64 ? sysinfo->getVPS64Path() : sysinfo->getVPS32Path()); } }; @@ -79,12 +79,20 @@ QString VapoursynthSource::getName(void) const bool VapoursynthSource::isSourceAvailable() { - if(!(m_sysinfo->hasVapourSynth() && (!m_sysinfo->getVPSPath().isEmpty()) && QFileInfo(getBinaryPath()).isFile())) + if (m_sysinfo->hasVapourSynth()) { - log(tr("\nVPY INPUT REQUIRES VAPOURSYNTH, BUT IT IS *NOT* AVAILABLE !!!")); - return false; + if (m_sysinfo->getVapourSynth(SysinfoModel::VapourSynth_X86) && (!m_sysinfo->getVPS32Path().isEmpty())) + { + return true; + } + if (m_sysinfo->getVapourSynth(SysinfoModel::VapourSynth_X64) && (!m_sysinfo->getVPS64Path().isEmpty())) + { + return true; + } } - return true; + + log(tr("\nVPY INPUT REQUIRES VAPOURSYNTH, BUT IT IS *NOT* AVAILABLE !!!")); + return false; } void VapoursynthSource::checkVersion_init(QList &patterns, QStringList &cmdLine) diff --git a/src/thread_vapoursynth.cpp b/src/thread_vapoursynth.cpp index 22efd7b..fe200d5 100644 --- a/src/thread_vapoursynth.cpp +++ b/src/thread_vapoursynth.cpp @@ -30,6 +30,7 @@ #include #include #include +#include //Internal #include "global.h" @@ -38,14 +39,25 @@ //CRT #include -//Const -static const bool ENABLE_PORTABLE_VPS = true; - //Static QMutex VapourSynthCheckThread::m_vpsLock; QScopedPointer VapourSynthCheckThread::m_vpsExePath[2]; QScopedPointer VapourSynthCheckThread::m_vpsDllPath[2]; +//Const +static const char* const VPS_REG_KEYS = "SOFTWARE\\VapourSynth"; +static const char* const VPS_REG_NAME = "Path"; + +//Default VapurSynth architecture +#if _WIN64 || __x86_64__ +#define VAPOURSYNTH_DEF VAPOURSYNTH_X64 +#else +#define VAPOURSYNTH_DEF VAPOURSYNTH_X86; +#endif + +//Enable detection of "portabel" edition? +#define ENABLE_PORTABLE_VPS true + //------------------------------------- // Auxilary functions //------------------------------------- @@ -54,12 +66,12 @@ QScopedPointer VapourSynthCheckThread::m_vpsDllPath[2]; #define BOOLIFY(X) ((X) ? '1' : '0') #define VPS_BITNESS(X) (((X) + 1U) * 32U) -static inline QString &cleanDir(QString &path) +static inline QString& cleanDir(QString& path) { - if(!path.isEmpty()) + if (!path.isEmpty()) { path = QDir::fromNativeSeparators(path); - while(path.endsWith('/')) + while (path.endsWith('/')) { path.chop(1); } @@ -71,13 +83,14 @@ static inline QString &cleanDir(QString &path) // External API //------------------------------------- -bool VapourSynthCheckThread::detect(SysinfoModel *sysinfo) +bool VapourSynthCheckThread::detect(SysinfoModel* sysinfo) { - sysinfo->clearVapourSynth(); - sysinfo->clearVPSPath(); - QMutexLocker lock(&m_vpsLock); + sysinfo->clearVapourSynth(); + sysinfo->clearVPS32Path(); + sysinfo->clearVPS64Path(); + QEventLoop loop; VapourSynthCheckThread thread; @@ -85,17 +98,17 @@ bool VapourSynthCheckThread::detect(SysinfoModel *sysinfo) connect(&thread, SIGNAL(finished()), &loop, SLOT(quit())); connect(&thread, SIGNAL(terminated()), &loop, SLOT(quit())); - + thread.start(); QTimer::singleShot(30000, &loop, SLOT(quit())); - + qDebug("VapourSynth thread has been created, please wait..."); loop.exec(QEventLoop::ExcludeUserInputEvents); qDebug("VapourSynth thread finished."); QApplication::restoreOverrideCursor(); - if(!thread.wait(1000)) + if (!thread.wait(1000)) { qWarning("VapourSynth thread encountered timeout -> probably deadlock!"); thread.terminate(); @@ -103,24 +116,31 @@ bool VapourSynthCheckThread::detect(SysinfoModel *sysinfo) return false; } - if(thread.getException()) + if (thread.getException()) { qWarning("VapourSynth thread encountered an exception !!!"); return false; } - if(thread.getSuccess()) - { - sysinfo->setVapourSynth(SysinfoModel::VapourSynth_X86, thread.getSuccess() & VAPOURSYNTH_X86); - sysinfo->setVapourSynth(SysinfoModel::VapourSynth_X64, thread.getSuccess() & VAPOURSYNTH_X64); - sysinfo->setVPSPath(thread.getPath()); - qDebug("VapourSynth support is officially enabled now! [x86=%c, x64=%c]", BOOLIFY(sysinfo->getVapourSynth(SysinfoModel::VapourSynth_X86)), BOOLIFY(sysinfo->getVapourSynth(SysinfoModel::VapourSynth_X64))); - } - else + if (!thread.getSuccess()) { qWarning("VapourSynth could not be found -> VapourSynth support disabled!"); + return false; } + if (thread.getSuccess() & VAPOURSYNTH_X86) + { + sysinfo->setVapourSynth(SysinfoModel::VapourSynth_X86, true); + sysinfo->setVPS32Path(thread.getPath32()); + } + + if (thread.getSuccess() & VAPOURSYNTH_X64) + { + sysinfo->setVapourSynth(SysinfoModel::VapourSynth_X64, true); + sysinfo->setVPS64Path(thread.getPath64()); + } + + qDebug("VapourSynth support is officially enabled now! [x86=%c, x64=%c]", BOOLIFY(sysinfo->getVapourSynth(SysinfoModel::VapourSynth_X86)), BOOLIFY(sysinfo->getVapourSynth(SysinfoModel::VapourSynth_X64))); return true; } @@ -130,7 +150,8 @@ bool VapourSynthCheckThread::detect(SysinfoModel *sysinfo) VapourSynthCheckThread::VapourSynthCheckThread(void) { - m_vpsPath.clear(); + m_vpsPath[0U].clear(); + m_vpsPath[1U].clear(); } VapourSynthCheckThread::~VapourSynthCheckThread(void) @@ -139,61 +160,39 @@ VapourSynthCheckThread::~VapourSynthCheckThread(void) void VapourSynthCheckThread::run(void) { - m_vpsPath.clear(); + m_vpsPath[0U].clear(); + m_vpsPath[1U].clear(); StarupThread::run(); } int VapourSynthCheckThread::threadMain(void) { - static const char *VPS_CORE_DIR[] = - { - "core32", - "core64", - NULL - }; static const int VPS_BIT_FLAG[] = { VAPOURSYNTH_X86, VAPOURSYNTH_X64, NULL }; - static const char *VPS_REG_KEYS[] = - { - "SOFTWARE\\VapourSynth", - "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\VapourSynth_is1", - NULL - }; - static const char *VPS_REG_NAME[] = - { - "Path", - "InstallLocation", - "Inno Setup: App Path", - NULL - }; static const MUtils::Registry::reg_scope_t REG_SCOPE[3] = { - MUtils::Registry::scope_default, MUtils::Registry::scope_wow_x32, - MUtils::Registry::scope_wow_x64 + MUtils::Registry::scope_wow_x64, + MUtils::Registry::scope_default }; - QString vapoursynthPath; + QHash vapoursynthPath; int flags = 0; //Look for "portable" VapourSynth version - if (ENABLE_PORTABLE_VPS) + for (size_t i = 0; i < 2U; i++) { - const QString vpsPortableDir = QString("%1/extra/VapourSynth").arg(QCoreApplication::applicationDirPath()); + const QString vpsPortableDir = QString("%1/extra/VapourSynth-%u").arg(QCoreApplication::applicationDirPath(), VPS_BITNESS(i)); if (VALID_DIR(vpsPortableDir)) { - for (size_t i = 0; VPS_CORE_DIR[i]; i++) + const QFileInfo vpsPortableFile = QFileInfo(QString("%1/vspipe.exe").arg(vpsPortableDir)); + if (vpsPortableFile.exists() && vpsPortableFile.isFile()) { - const QFileInfo vpsPortableDll = QFileInfo(QString("%1/%2/VapourSynth.dll").arg(vpsPortableDir, QString::fromLatin1(VPS_CORE_DIR[i]))); - if (vpsPortableDll.exists() && vpsPortableDll.isFile()) - { - vapoursynthPath = vpsPortableDir; - break; - } + vapoursynthPath.insert(VPS_BIT_FLAG[i], vpsPortableDir); } } } @@ -201,34 +200,26 @@ int VapourSynthCheckThread::threadMain(void) //Read VapourSynth path from registry if (vapoursynthPath.isEmpty()) { - for (size_t i = 0; VPS_REG_KEYS[i]; i++) + for (size_t i = 0; i < 3U; i++) { - for (size_t j = 0; VPS_REG_NAME[j]; j++) + if (MUtils::Registry::reg_key_exists(MUtils::Registry::root_machine, QString::fromLatin1(VPS_REG_KEYS), REG_SCOPE[i])) { - for (size_t k = 0; k < 3; k++) + QString vpsInstallPath; + if (MUtils::Registry::reg_value_read(MUtils::Registry::root_machine, QString::fromLatin1(VPS_REG_KEYS), QString::fromLatin1(VPS_REG_NAME), vpsInstallPath, REG_SCOPE[i])) { - if (MUtils::Registry::reg_key_exists(MUtils::Registry::root_machine, QString::fromLatin1(VPS_REG_KEYS[i]), REG_SCOPE[k])) + if (VALID_DIR(vpsInstallPath)) { - QString temp; - if (MUtils::Registry::reg_value_read(MUtils::Registry::root_machine, QString::fromLatin1(VPS_REG_KEYS[i]), QString::fromLatin1(VPS_REG_NAME[j]), temp, REG_SCOPE[k])) + const QString vpsCorePath = QString("%1/core").arg(cleanDir(vpsInstallPath)); + if (VALID_DIR(vpsCorePath)) { - temp = cleanDir(temp); - if (VALID_DIR(temp)) + const int flag = getVapourSynthType(REG_SCOPE[i]); + if (!vapoursynthPath.contains(flag)) { - vapoursynthPath = temp; - break; + vapoursynthPath.insert(flag, vpsCorePath); } } } } - if (!vapoursynthPath.isEmpty()) - { - break; - } - } - if (!vapoursynthPath.isEmpty()) - { - break; } } } @@ -241,22 +232,31 @@ int VapourSynthCheckThread::threadMain(void) } //Validate the VapourSynth installation now! - qDebug("VapourSynth Dir: %s", vapoursynthPath.toUtf8().constData()); - for (size_t i = 0; VPS_CORE_DIR[i]; i++) + for (size_t i = 0; i < 2U; i++) { - QFile *vpsExeFile, *vpsDllFile; - if (isVapourSynthComplete(QString("%1/%2").arg(vapoursynthPath, QString::fromLatin1(VPS_CORE_DIR[i])), vpsExeFile, vpsDllFile)) + if (vapoursynthPath.contains(VPS_BIT_FLAG[i])) { - if (vpsExeFile && checkVapourSynth(vpsExeFile->fileName())) + const QString path = vapoursynthPath[VPS_BIT_FLAG[i]]; + qDebug("VapourSynth %u-Bit \"core\" path: %s", VPS_BITNESS(i), MUTILS_UTF8(path)); + QFile *vpsExeFile, *vpsDllFile; + if (isVapourSynthComplete(path, vpsExeFile, vpsDllFile)) { - flags |= VPS_BIT_FLAG[i]; - qDebug("VapourSynth %u-Bit edition found!", VPS_BITNESS(i)); - m_vpsExePath[i].reset(vpsExeFile); - m_vpsDllPath[i].reset(vpsDllFile); + if (vpsExeFile && checkVapourSynth(vpsExeFile->fileName())) + { + qDebug("VapourSynth %u-Bit edition found!", VPS_BITNESS(i)); + m_vpsExePath[i].reset(vpsExeFile); + m_vpsDllPath[i].reset(vpsDllFile); + m_vpsPath[i] = path; + flags |= VPS_BIT_FLAG[i]; + } + else + { + qWarning("VapourSynth %u-Bit edition was found, but version check has failed!", VPS_BITNESS(i)); + } } else { - qWarning("VapourSynth %u-Bit edition was found, but version check has failed!", VPS_BITNESS(i)); + qWarning("VapourSynth %u-Bit edition was found, but appears to be incomplete!", VPS_BITNESS(i)); } } else @@ -265,12 +265,6 @@ int VapourSynthCheckThread::threadMain(void) } } - //Return VapourSynth path - if(flags) - { - m_vpsPath = vapoursynthPath; - } - return flags; } @@ -278,6 +272,19 @@ int VapourSynthCheckThread::threadMain(void) // Internal functions //------------------------------------- +VapourSynthCheckThread::VapourSynthFlags VapourSynthCheckThread::getVapourSynthType(const int scope) +{ + switch (scope) + { + case MUtils::Registry::scope_wow_x32: + return VAPOURSYNTH_X86; + case MUtils::Registry::scope_wow_x64: + return VAPOURSYNTH_X64; + default: + return VAPOURSYNTH_DEF; + } +} + bool VapourSynthCheckThread::isVapourSynthComplete(const QString &vsCorePath, QFile *&vpsExeFile, QFile *&vpsDllFile) { bool complete = false; diff --git a/src/thread_vapoursynth.h b/src/thread_vapoursynth.h index 83b9d76..83b9fef 100644 --- a/src/thread_vapoursynth.h +++ b/src/thread_vapoursynth.h @@ -47,10 +47,11 @@ protected: VapourSynthCheckThread(void); ~VapourSynthCheckThread(void); - QString getPath(void) { return m_vpsPath; } + QString getPath32(void) { return m_vpsPath[0U]; } + QString getPath64(void) { return m_vpsPath[1U]; } private: - QString m_vpsPath; + QString m_vpsPath[2]; static QMutex m_vpsLock; static QScopedPointer VapourSynthCheckThread::m_vpsExePath[2]; @@ -63,6 +64,7 @@ private: virtual int threadMain(void); //Internal functions + static VapourSynthFlags getVapourSynthType(const int scope); static bool isVapourSynthComplete(const QString &vsCorePath, QFile *&vpsExeFile, QFile *&vpsDllFile); static bool checkVapourSynth(const QString &vspipePath); }; diff --git a/src/version.h b/src/version.h index dd8bd61..8fb2778 100644 --- a/src/version.h +++ b/src/version.h @@ -26,7 +26,7 @@ #define VER_X264_MAJOR 2 #define VER_X264_MINOR 9 #define VER_X264_PATCH 1 -#define VER_X264_BUILD 1170 +#define VER_X264_BUILD 1172 #define VER_X264_PORTABLE_EDITION (0) diff --git a/x264_launcher_MSVC2019.sln b/x264_launcher_MSVC2019.sln index a9ce995..6172963 100644 --- a/x264_launcher_MSVC2019.sln +++ b/x264_launcher_MSVC2019.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27130.2036 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29102.190 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "x264_launcher", "x264_launcher_MSVC2019.vcxproj", "{563D953B-CBC3-4C75-AFC2-5BD87531C332}" ProjectSection(ProjectDependencies) = postProject