Various improvements to Avisynth and VapourSynth detection code. Refactored common code into a shared base class.

This commit is contained in:
LoRd_MuldeR 2019-05-07 21:13:22 +02:00
parent 798c41f7f8
commit 8955a9edd7
11 changed files with 192 additions and 125 deletions

View File

@ -25,9 +25,7 @@
#include <QLibrary> #include <QLibrary>
#include <QEventLoop> #include <QEventLoop>
#include <QTimer> #include <QTimer>
#include <QMutexLocker>
#include <QApplication> #include <QApplication>
#include <QProcess>
#include <QDir> #include <QDir>
//Internal //Internal
@ -97,7 +95,7 @@ bool AvisynthCheckThread::detect(SysinfoModel *sysinfo)
connect(&thread, SIGNAL(terminated()), &loop, SLOT(quit())); connect(&thread, SIGNAL(terminated()), &loop, SLOT(quit()));
thread.start(); thread.start();
QTimer::singleShot(15000, &loop, SLOT(quit())); QTimer::singleShot(30000, &loop, SLOT(quit()));
qDebug("Avisynth thread has been created, please wait..."); qDebug("Avisynth thread has been created, please wait...");
loop.exec(QEventLoop::ExcludeUserInputEvents); loop.exec(QEventLoop::ExcludeUserInputEvents);
@ -225,9 +223,6 @@ bool AvisynthCheckThread::checkAvisynth(QString &basePath, const SysinfoModel *c
{ {
qDebug("Avisynth %s-Bit support is being tested.", x64 ? "64" : "32"); qDebug("Avisynth %s-Bit support is being tested.", x64 ? "64" : "32");
QProcess process;
QStringList output;
//Look for "portable" Avisynth version //Look for "portable" Avisynth version
static const char *const ARCH_DIR[] = { "x64", "x86" }; static const char *const ARCH_DIR[] = { "x64", "x86" };
const QLatin1String archSuffix = QLatin1String(ARCH_DIR[x64 ? 1 : 0]); const QLatin1String archSuffix = QLatin1String(ARCH_DIR[x64 ? 1 : 0]);
@ -245,56 +240,15 @@ bool AvisynthCheckThread::checkAvisynth(QString &basePath, const SysinfoModel *c
} }
} }
//Get extra paths
QStringList avisynthExtraPaths;
if (!basePath.isEmpty())
{
avisynthExtraPaths << QString("%1/%2").arg(basePath, archSuffix);
}
//Setup process object //Setup process object
MUtils::init_process(process, QDir::tempPath(), true, basePath.isEmpty() ? NULL : &(QStringList() << QString("%1/%2").arg(basePath, archSuffix))); const QStringList output = runProcess(AVS_CHECK_BINARY(sysinfo, x64), QStringList(), &avisynthExtraPaths);
//Try to start VSPIPE.EXE
process.start(AVS_CHECK_BINARY(sysinfo, x64), QStringList());
if(!process.waitForStarted())
{
qWarning("Failed to launch AVS_CHECK.EXE -> %s", process.errorString().toUtf8().constData());
return false;
}
//Wait for process to finish
while(process.state() != QProcess::NotRunning)
{
if(process.waitForReadyRead(12000))
{
while(process.canReadLine())
{
output << QString::fromUtf8(process.readLine()).simplified();
}
continue;
}
if(process.state() != QProcess::NotRunning)
{
qWarning("AVS_CHECK.EXE process encountered a deadlock -> aborting now!");
break;
}
}
//Make sure VSPIPE.EXE has terminated!
process.waitForFinished(2500);
if(process.state() != QProcess::NotRunning)
{
qWarning("AVS_CHECK.EXE process still running, going to kill it!");
process.kill();
process.waitForFinished(-1);
}
//Read pending lines
while(process.canReadLine())
{
output << QString::fromUtf8(process.readLine()).simplified();
}
//Check exit code
if(process.exitCode() != 0)
{
qWarning("AVS_CHECK.EXE failed with code 0x%08X -> disable Avisynth support!", process.exitCode());
return false;
}
//Init regular expressions //Init regular expressions
QRegExp avsLogo("Avisynth\\s+Checker\\s+(x86|x64)"); QRegExp avsLogo("Avisynth\\s+Checker\\s+(x86|x64)");

View File

@ -21,14 +21,14 @@
#pragma once #pragma once
#include <QThread> #include "thread_startup.h"
#include <QMutex> #include <QMutex>
class QLibrary;
class SysinfoModel; class SysinfoModel;
class QFile; class QFile;
class AvisynthCheckThread : public QThread class AvisynthCheckThread : public StarupThread
{ {
Q_OBJECT Q_OBJECT

101
src/thread_startup.cpp Normal file
View File

@ -0,0 +1,101 @@
///////////////////////////////////////////////////////////////////////////////
// Simple x264 Launcher
// Copyright (C) 2004-2019 LoRd_MuldeR <MuldeR2@GMX.de>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// http://www.gnu.org/licenses/gpl-2.0.txt
///////////////////////////////////////////////////////////////////////////////
#include "thread_startup.h"
//MUtils
#include <MUtils/Global.h>
//Qt
#include <QDir>
#include <QElapsedTimer>
#include <QProcess>
QStringList StarupThread::runProcess(const QString &exePath, const QStringList &arguments, const QStringList *const extraPaths)
{
QProcess process;
//Get file name
const QString fileName = QFileInfo(exePath).fileName().toUpper();
//Setup process object
MUtils::init_process(process, QDir::tempPath(), true, extraPaths);
//Try to start process
process.start(exePath, arguments);
if (!process.waitForStarted())
{
qWarning("Failed to launch %s -> %s", MUTILS_UTF8(fileName), MUTILS_UTF8(process.errorString()));
return QStringList();
}
//Start the timer
QElapsedTimer timer;
timer.start();
//Wait until process has finished
QStringList processOutput;
while (process.state() != QProcess::NotRunning)
{
process.waitForReadyRead(1250);
while (process.canReadLine())
{
const QString line = QString::fromUtf8(process.readLine()).simplified();
if (!line.isEmpty())
{
processOutput << line;
}
}
if (timer.hasExpired(15000))
{
qWarning("%s process encountered a deadlock -> aborting now!", MUTILS_UTF8(fileName));
break;
}
}
//Make sure process has terminated!
process.waitForFinished(1250);
if (process.state() != QProcess::NotRunning)
{
qWarning("%s process still running, going to kill it!", MUTILS_UTF8(fileName));
process.kill();
process.waitForFinished(-1);
}
//Read pending lines
while (process.bytesAvailable() > 0)
{
const QString line = QString::fromUtf8(process.readLine()).simplified();
if (!line.isEmpty())
{
processOutput << line;
}
}
//Check exit code
if (process.exitCode() != 0)
{
qWarning("%s failed with code 0x%08X -> discarding all output!", MUTILS_UTF8(fileName), process.exitCode());
return QStringList();
}
return processOutput;
}

34
src/thread_startup.h Normal file
View File

@ -0,0 +1,34 @@
///////////////////////////////////////////////////////////////////////////////
// Simple x264 Launcher
// Copyright (C) 2004-2019 LoRd_MuldeR <MuldeR2@GMX.de>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// http://www.gnu.org/licenses/gpl-2.0.txt
///////////////////////////////////////////////////////////////////////////////
#pragma once
//Qt
#include <QThread>
#include <QStringList>
class StarupThread : public QThread
{
Q_OBJECT
protected:
static QStringList runProcess(const QString &exePath, const QStringList &args, const QStringList *const extraPaths = NULL);
};

View File

@ -29,10 +29,8 @@
#include <QLibrary> #include <QLibrary>
#include <QEventLoop> #include <QEventLoop>
#include <QTimer> #include <QTimer>
#include <QMutexLocker>
#include <QApplication> #include <QApplication>
#include <QDir> #include <QDir>
#include <QProcess>
//Internal //Internal
#include "global.h" #include "global.h"
@ -86,7 +84,7 @@ bool VapourSynthCheckThread::detect(SysinfoModel *sysinfo)
connect(&thread, SIGNAL(terminated()), &loop, SLOT(quit())); connect(&thread, SIGNAL(terminated()), &loop, SLOT(quit()));
thread.start(); thread.start();
QTimer::singleShot(15000, &loop, SLOT(quit())); QTimer::singleShot(30000, &loop, SLOT(quit()));
qDebug("VapourSynth thread has been created, please wait..."); qDebug("VapourSynth thread has been created, please wait...");
loop.exec(QEventLoop::ExcludeUserInputEvents); loop.exec(QEventLoop::ExcludeUserInputEvents);
@ -336,61 +334,8 @@ bool VapourSynthCheckThread::isVapourSynthComplete(const QString &vsCorePath, QF
bool VapourSynthCheckThread::checkVapourSynth(const QString &vspipePath) bool VapourSynthCheckThread::checkVapourSynth(const QString &vspipePath)
{ {
QProcess process; //Try to run VSPIPE.EXE
QStringList output; const QStringList output = runProcess(vspipePath, QStringList() << "--version");
//Setup process object
process.setWorkingDirectory(QDir::tempPath());
process.setProcessChannelMode(QProcess::MergedChannels);
process.setReadChannel(QProcess::StandardOutput);
//Try to start VSPIPE.EXE
process.start(vspipePath, QStringList() << "--version");
if(!process.waitForStarted())
{
qWarning("Failed to launch VSPIPE.EXE -> %s", process.errorString().toUtf8().constData());
return false;
}
//Wait for process to finish
while(process.state() != QProcess::NotRunning)
{
if(process.waitForReadyRead(12000))
{
while(process.canReadLine())
{
output << QString::fromUtf8(process.readLine()).simplified();
}
continue;
}
if(process.state() != QProcess::NotRunning)
{
qWarning("VSPIPE.EXE process encountered a deadlock -> aborting now!");
break;
}
}
//Make sure VSPIPE.EXE has terminated!
process.waitForFinished(2500);
if(process.state() != QProcess::NotRunning)
{
qWarning("VSPIPE.EXE process still running, going to kill it!");
process.kill();
process.waitForFinished(-1);
}
//Read pending lines
while(process.canReadLine())
{
output << QString::fromUtf8(process.readLine()).simplified();
}
//Check exit code
if(process.exitCode() != 0)
{
qWarning("VSPIPE.EXE failed with code 0x%08X -> disable Vapousynth support!", process.exitCode());
return false;
}
//Init regular expressions //Init regular expressions
QRegExp vpsLogo("VapourSynth\\s+Video\\s+Processing\\s+Library"); QRegExp vpsLogo("VapourSynth\\s+Video\\s+Processing\\s+Library");

View File

@ -21,15 +21,15 @@
#pragma once #pragma once
#include "thread_startup.h"
//Qt //Qt
#include <QThread>
#include <QMutex> #include <QMutex>
class QLibrary;
class QFile; class QFile;
class SysinfoModel; class SysinfoModel;
class VapourSynthCheckThread : public QThread class VapourSynthCheckThread : public StarupThread
{ {
Q_OBJECT Q_OBJECT

View File

@ -26,7 +26,7 @@
#define VER_X264_MAJOR 2 #define VER_X264_MAJOR 2
#define VER_X264_MINOR 9 #define VER_X264_MINOR 9
#define VER_X264_PATCH 0 #define VER_X264_PATCH 0
#define VER_X264_BUILD 1146 #define VER_X264_BUILD 1154
#define VER_X264_PORTABLE_EDITION (0) #define VER_X264_PORTABLE_EDITION (0)

14
x264_launcher.props Normal file
View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros">
<XPDeprecationWarning>false</XPDeprecationWarning>
</PropertyGroup>
<PropertyGroup />
<ItemDefinitionGroup />
<ItemGroup>
<BuildMacro Include="XPDeprecationWarning">
<Value>$(XPDeprecationWarning)</Value>
</BuildMacro>
</ItemGroup>
</Project>

View File

@ -36,9 +36,11 @@
</ImportGroup> </ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="x264_launcher.props" />
</ImportGroup> </ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="x264_launcher.props" />
</ImportGroup> </ImportGroup>
<PropertyGroup Label="UserMacros" /> <PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
@ -262,7 +264,6 @@ copy /Y "$(ProjectDir)\..\Prerequisites\Qt4\$(PlatformToolset)\Shared\plugins\im
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)tmp\$(ProjectName)\UIC_%(Filename).h;%(Outputs)</Outputs> <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)tmp\$(ProjectName)\UIC_%(Filename).h;%(Outputs)</Outputs>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)tmp\$(ProjectName)\UIC_%(Filename).h;%(Outputs)</Outputs> <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)tmp\$(ProjectName)\UIC_%(Filename).h;%(Outputs)</Outputs>
</CustomBuild> </CustomBuild>
<None Include="ReadMe.txt" />
<CustomBuild Include="res\resources.qrc"> <CustomBuild Include="res\resources.qrc">
<FileType>Document</FileType> <FileType>Document</FileType>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">"$(QTDIR)\bin\rcc.exe" -o "$(SolutionDir)tmp\$(ProjectName)\QRC_%(Filename).cpp" -name "%(Filename)" "%(FullPath)"</Command> <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">"$(QTDIR)\bin\rcc.exe" -o "$(SolutionDir)tmp\$(ProjectName)\QRC_%(Filename).cpp" -name "%(Filename)" "%(FullPath)"</Command>
@ -304,6 +305,14 @@ copy /Y "$(ProjectDir)\..\Prerequisites\Qt4\$(PlatformToolset)\Shared\plugins\im
<ClInclude Include="src\model_clipInfo.h" /> <ClInclude Include="src\model_clipInfo.h" />
<ClInclude Include="src\source_factory.h" /> <ClInclude Include="src\source_factory.h" />
<ClInclude Include="src\string_validator.h" /> <ClInclude Include="src\string_validator.h" />
<CustomBuild Include="src\thread_startup.h">
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">"$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\$(ProjectName)\MOC_%(Filename).cpp" "%(FullPath)"</Command>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">"$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\$(ProjectName)\MOC_%(Filename).cpp" "%(FullPath)"</Command>
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">MOC "$(SolutionDir)tmp\$(ProjectName)\MOC_%(Filename).cpp"</Message>
<Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">MOC "$(SolutionDir)tmp\$(ProjectName)\MOC_%(Filename).cpp"</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)tmp\$(ProjectName)\MOC_%(Filename).cpp;%(Outputs)</Outputs>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)tmp\$(ProjectName)\MOC_%(Filename).cpp;%(Outputs)</Outputs>
</CustomBuild>
<ClInclude Include="tmp\x264_launcher\UIC_win_about.h" /> <ClInclude Include="tmp\x264_launcher\UIC_win_about.h" />
<ClInclude Include="tmp\x264_launcher\UIC_win_addJob.h" /> <ClInclude Include="tmp\x264_launcher\UIC_win_addJob.h" />
<ClInclude Include="tmp\x264_launcher\UIC_win_editor.h" /> <ClInclude Include="tmp\x264_launcher\UIC_win_editor.h" />
@ -470,6 +479,7 @@ copy /Y "$(ProjectDir)\..\Prerequisites\Qt4\$(PlatformToolset)\Shared\plugins\im
<ClCompile Include="src\main.cpp" /> <ClCompile Include="src\main.cpp" />
<ClCompile Include="src\thread_ipc_recv.cpp" /> <ClCompile Include="src\thread_ipc_recv.cpp" />
<ClCompile Include="src\thread_ipc_send.cpp" /> <ClCompile Include="src\thread_ipc_send.cpp" />
<ClCompile Include="src\thread_startup.cpp" />
<ClCompile Include="src\thread_vapoursynth.cpp" /> <ClCompile Include="src\thread_vapoursynth.cpp" />
<ClCompile Include="src\tool_abstract.cpp" /> <ClCompile Include="src\tool_abstract.cpp" />
<ClCompile Include="src\win_about.cpp" /> <ClCompile Include="src\win_about.cpp" />
@ -488,6 +498,7 @@ copy /Y "$(ProjectDir)\..\Prerequisites\Qt4\$(PlatformToolset)\Shared\plugins\im
<ClCompile Include="tmp\x264_launcher\MOC_thread_encode.cpp" /> <ClCompile Include="tmp\x264_launcher\MOC_thread_encode.cpp" />
<ClCompile Include="tmp\x264_launcher\MOC_thread_ipc_recv.cpp" /> <ClCompile Include="tmp\x264_launcher\MOC_thread_ipc_recv.cpp" />
<ClCompile Include="tmp\x264_launcher\MOC_thread_ipc_send.cpp" /> <ClCompile Include="tmp\x264_launcher\MOC_thread_ipc_send.cpp" />
<ClCompile Include="tmp\x264_launcher\MOC_thread_startup.cpp" />
<ClCompile Include="tmp\x264_launcher\MOC_thread_vapoursynth.cpp" /> <ClCompile Include="tmp\x264_launcher\MOC_thread_vapoursynth.cpp" />
<ClCompile Include="tmp\x264_launcher\MOC_tool_abstract.cpp" /> <ClCompile Include="tmp\x264_launcher\MOC_tool_abstract.cpp" />
<ClCompile Include="tmp\x264_launcher\MOC_win_about.cpp" /> <ClCompile Include="tmp\x264_launcher\MOC_win_about.cpp" />

View File

@ -24,7 +24,6 @@
</Filter> </Filter>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="ReadMe.txt" />
<None Include="res\icons\movie.ico"> <None Include="res\icons\movie.ico">
<Filter>Resource Files</Filter> <Filter>Resource Files</Filter>
</None> </None>
@ -120,6 +119,9 @@
<ClInclude Include="src\encoder_nvencc.h"> <ClInclude Include="src\encoder_nvencc.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="src\thread_startup.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="src\main.cpp"> <ClCompile Include="src\main.cpp">
@ -284,6 +286,12 @@
<ClCompile Include="src\encoder_nvencc.cpp"> <ClCompile Include="src\encoder_nvencc.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="src\thread_startup.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="tmp\x264_launcher\MOC_thread_startup.cpp">
<Filter>Generated Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<CustomBuild Include="src\win_main.h"> <CustomBuild Include="src\win_main.h">

View File

@ -145,9 +145,9 @@ REM ///////////////////////////////////////////////////////////////////////////
REM /////////////////////////////////////////////////////////////////////////// REM ///////////////////////////////////////////////////////////////////////////
REM // Compress REM // Compress
REM /////////////////////////////////////////////////////////////////////////// REM ///////////////////////////////////////////////////////////////////////////
"%~dp0\..\Prerequisites\UPX\upx.exe" --best "%PACK_PATH%\x264_launcher.exe" :: "%~dp0\..\Prerequisites\UPX\upx.exe" --best "%PACK_PATH%\x264_launcher.exe"
"%~dp0\..\Prerequisites\UPX\upx.exe" --best "%PACK_PATH%\MUtils32-1.dll" :: "%~dp0\..\Prerequisites\UPX\upx.exe" --best "%PACK_PATH%\MUtils32-1.dll"
"%~dp0\..\Prerequisites\UPX\upx.exe" --best "%PACK_PATH%\Qt*.dll" :: "%~dp0\..\Prerequisites\UPX\upx.exe" --best "%PACK_PATH%\Qt*.dll"
REM /////////////////////////////////////////////////////////////////////////// REM ///////////////////////////////////////////////////////////////////////////
REM // Attributes REM // Attributes