2013-08-07 15:34:02 +02:00
///////////////////////////////////////////////////////////////////////////////
// Simple x264 Launcher
2019-05-02 12:47:47 +02:00
// Copyright (C) 2004-2019 LoRd_MuldeR <MuldeR2@GMX.de>
2013-08-07 15:34:02 +02:00
//
// 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_vapoursynth.h"
2015-02-02 22:11:06 +01:00
//Mutils
# include <MUtils/OSSupport.h>
2016-03-11 19:08:29 +01:00
# include <MUtils/Registry.h>
2015-02-02 22:11:06 +01:00
//Qt
2013-08-07 15:34:02 +02:00
# include <QLibrary>
# include <QEventLoop>
# include <QTimer>
# include <QApplication>
# include <QDir>
2015-02-27 19:05:18 +01:00
//Internal
2013-08-07 15:34:02 +02:00
# include "global.h"
2015-03-01 22:00:05 +01:00
# include "model_sysinfo.h"
2013-08-07 15:34:02 +02:00
2015-02-27 19:05:18 +01:00
//CRT
# include <cassert>
2016-09-27 21:04:35 +02:00
//Const
static const bool ENABLE_PORTABLE_VPS = true ;
2015-03-01 22:00:05 +01:00
//Static
2013-08-07 15:34:02 +02:00
QMutex VapourSynthCheckThread : : m_vpsLock ;
2015-02-27 19:05:18 +01:00
QScopedPointer < QFile > VapourSynthCheckThread : : m_vpsExePath [ 2 ] ;
QScopedPointer < QFile > VapourSynthCheckThread : : m_vpsDllPath [ 2 ] ;
2013-08-07 15:34:02 +02:00
2013-11-08 17:39:16 +01:00
# define VALID_DIR(STR) ((!(STR).isEmpty()) && QDir((STR)).exists())
2015-03-01 22:00:05 +01:00
# define BOOLIFY(X) ((X) ? '1' : '0')
2016-09-27 21:04:35 +02:00
# define VPS_BITNESS(X) (((X) + 1U) * 32U)
2013-11-08 17:39:16 +01:00
static inline QString & cleanDir ( QString & path )
{
if ( ! path . isEmpty ( ) )
{
path = QDir : : fromNativeSeparators ( path ) ;
while ( path . endsWith ( ' / ' ) )
{
path . chop ( 1 ) ;
}
}
return path ;
}
2013-08-07 15:34:02 +02:00
//-------------------------------------
// External API
//-------------------------------------
2015-03-01 22:00:05 +01:00
bool VapourSynthCheckThread : : detect ( SysinfoModel * sysinfo )
2013-08-07 15:34:02 +02:00
{
2015-03-01 22:00:05 +01:00
sysinfo - > clearVapourSynth ( ) ;
sysinfo - > clearVPSPath ( ) ;
2013-08-07 15:34:02 +02:00
QMutexLocker lock ( & m_vpsLock ) ;
QEventLoop loop ;
VapourSynthCheckThread thread ;
QApplication : : setOverrideCursor ( QCursor ( Qt : : WaitCursor ) ) ;
connect ( & thread , SIGNAL ( finished ( ) ) , & loop , SLOT ( quit ( ) ) ) ;
connect ( & thread , SIGNAL ( terminated ( ) ) , & loop , SLOT ( quit ( ) ) ) ;
thread . start ( ) ;
2019-05-07 21:13:22 +02:00
QTimer : : singleShot ( 30000 , & loop , SLOT ( quit ( ) ) ) ;
2013-08-07 15:34:02 +02:00
qDebug ( " VapourSynth thread has been created, please wait... " ) ;
loop . exec ( QEventLoop : : ExcludeUserInputEvents ) ;
qDebug ( " VapourSynth thread finished. " ) ;
QApplication : : restoreOverrideCursor ( ) ;
if ( ! thread . wait ( 1000 ) )
{
qWarning ( " VapourSynth thread encountered timeout -> probably deadlock! " ) ;
thread . terminate ( ) ;
thread . wait ( ) ;
2015-03-01 22:00:05 +01:00
return false ;
2013-08-07 15:34:02 +02:00
}
if ( thread . getException ( ) )
{
qWarning ( " VapourSynth thread encountered an exception !!! " ) ;
2015-03-01 22:00:05 +01:00
return false ;
2013-08-07 15:34:02 +02:00
}
2015-03-01 22:00:05 +01:00
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
2013-08-07 15:34:02 +02:00
{
2015-03-01 22:00:05 +01:00
qWarning ( " VapourSynth could not be found -> VapourSynth support disabled! " ) ;
2013-08-07 15:34:02 +02:00
}
2015-03-01 22:00:05 +01:00
return true ;
2013-08-07 15:34:02 +02:00
}
//-------------------------------------
// Thread class
//-------------------------------------
VapourSynthCheckThread : : VapourSynthCheckThread ( void )
{
2015-02-28 17:12:35 +01:00
m_success & = 0 ;
2013-08-07 15:34:02 +02:00
m_exception = false ;
m_vpsPath . clear ( ) ;
}
VapourSynthCheckThread : : ~ VapourSynthCheckThread ( void )
{
}
void VapourSynthCheckThread : : run ( void )
{
2015-02-28 17:12:35 +01:00
m_success & = 0 ;
2015-02-27 19:05:18 +01:00
m_exception = false ;
2015-02-28 17:12:35 +01:00
m_vpsPath . clear ( ) ;
2015-02-27 19:05:18 +01:00
2015-02-28 17:12:35 +01:00
detectVapourSynthPath1 ( m_success , m_vpsPath , & m_exception ) ;
2013-08-07 15:34:02 +02:00
}
2015-03-01 22:00:05 +01:00
void VapourSynthCheckThread : : detectVapourSynthPath1 ( int & success , QString & path , volatile bool * exception )
2013-08-07 15:34:02 +02:00
{
__try
{
2015-02-28 17:12:35 +01:00
return detectVapourSynthPath2 ( success , path , exception ) ;
2013-08-07 15:34:02 +02:00
}
__except ( 1 )
{
* exception = true ;
qWarning ( " Unhandled exception error in VapourSynth thread !!! " ) ;
}
}
2015-03-01 22:00:05 +01:00
void VapourSynthCheckThread : : detectVapourSynthPath2 ( int & success , QString & path , volatile bool * exception )
2013-08-07 15:34:02 +02:00
{
try
{
2015-02-28 17:12:35 +01:00
return detectVapourSynthPath3 ( success , path ) ;
2013-08-07 15:34:02 +02:00
}
catch ( . . . )
{
* exception = true ;
qWarning ( " VapourSynth initializdation raised an C++ exception! " ) ;
}
}
2015-03-01 22:00:05 +01:00
void VapourSynthCheckThread : : detectVapourSynthPath3 ( int & success , QString & path )
2013-08-07 15:34:02 +02:00
{
2015-02-28 17:12:35 +01:00
success & = 0 ;
2013-08-07 15:34:02 +02:00
path . clear ( ) ;
2016-09-27 21:04:35 +02:00
static const char * VPS_CORE_DIR [ ] =
{
" core32 " ,
" core64 " ,
NULL
} ;
static const int VPS_BIT_FLAG [ ] =
{
VAPOURSYNTH_X86 ,
VAPOURSYNTH_X64 ,
NULL
} ;
2013-11-08 17:39:16 +01:00
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
} ;
2016-03-11 19:08:29 +01:00
static const MUtils : : Registry : : reg_scope_t REG_SCOPE [ 3 ] =
{
MUtils : : Registry : : scope_default ,
MUtils : : Registry : : scope_wow_x32 ,
MUtils : : Registry : : scope_wow_x64
} ;
2013-11-08 17:39:16 +01:00
QString vapoursynthPath ;
2016-09-27 21:04:35 +02:00
//Look for "portable" VapourSynth version
if ( ENABLE_PORTABLE_VPS )
{
const QString vpsPortableDir = QString ( " %1/extra/VapourSynth " ) . arg ( QCoreApplication : : applicationDirPath ( ) ) ;
if ( VALID_DIR ( vpsPortableDir ) )
{
for ( size_t i = 0 ; VPS_CORE_DIR [ i ] ; i + + )
{
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 ;
}
}
}
}
//Read VapourSynth path from registry
if ( vapoursynthPath . isEmpty ( ) )
2013-11-08 17:39:16 +01:00
{
2016-09-27 21:04:35 +02:00
for ( size_t i = 0 ; VPS_REG_KEYS [ i ] ; i + + )
2013-11-08 17:39:16 +01:00
{
2016-09-27 21:04:35 +02:00
for ( size_t j = 0 ; VPS_REG_NAME [ j ] ; j + + )
2016-03-11 19:08:29 +01:00
{
2016-09-27 21:04:35 +02:00
for ( size_t k = 0 ; k < 3 ; k + + )
2016-03-11 19:08:29 +01:00
{
2016-10-21 12:00:33 +02:00
if ( MUtils : : Registry : : reg_key_exists ( MUtils : : Registry : : root_machine , QString : : fromLatin1 ( VPS_REG_KEYS [ i ] ) , REG_SCOPE [ k ] ) )
2016-03-11 19:08:29 +01:00
{
2016-10-21 12:00:33 +02:00
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 ] ) )
2016-09-27 21:04:35 +02:00
{
2016-10-21 12:00:33 +02:00
temp = cleanDir ( temp ) ;
if ( VALID_DIR ( temp ) )
{
vapoursynthPath = temp ;
break ;
}
2016-09-27 21:04:35 +02:00
}
2016-03-11 19:08:29 +01:00
}
}
2016-09-27 21:04:35 +02:00
if ( ! vapoursynthPath . isEmpty ( ) )
{
break ;
}
2016-03-11 19:08:29 +01:00
}
if ( ! vapoursynthPath . isEmpty ( ) )
{
break ;
}
}
2013-11-08 17:39:16 +01:00
}
2013-08-07 15:34:02 +02:00
2016-09-27 21:04:35 +02:00
//Make sure VapourSynth directory does exist
if ( vapoursynthPath . isEmpty ( ) )
2013-08-07 15:34:02 +02:00
{
2014-05-05 15:07:31 +02:00
qWarning ( " VapourSynth install path not found -> disable VapouSynth support! " ) ;
2015-02-28 17:12:35 +01:00
return ;
2013-08-07 15:34:02 +02:00
}
2016-09-27 21:04:35 +02:00
//Validate the VapourSynth installation now!
qDebug ( " VapourSynth Dir: %s " , vapoursynthPath . toUtf8 ( ) . constData ( ) ) ;
for ( size_t i = 0 ; VPS_CORE_DIR [ i ] ; i + + )
2015-02-27 19:05:18 +01:00
{
2016-09-27 21:04:35 +02:00
QFile * vpsExeFile , * vpsDllFile ;
if ( isVapourSynthComplete ( QString ( " %1/%2 " ) . arg ( vapoursynthPath , QString : : fromLatin1 ( VPS_CORE_DIR [ i ] ) ) , vpsExeFile , vpsDllFile ) )
2015-02-27 19:05:18 +01:00
{
2016-09-27 21:04:35 +02:00
if ( vpsExeFile & & checkVapourSynth ( vpsExeFile - > fileName ( ) ) )
{
success | = VPS_BIT_FLAG [ i ] ;
qDebug ( " VapourSynth %u-Bit edition found! " , VPS_BITNESS ( i ) ) ;
m_vpsExePath [ i ] . reset ( vpsExeFile ) ;
m_vpsDllPath [ i ] . reset ( vpsDllFile ) ;
}
else
{
qWarning ( " VapourSynth %u-Bit edition was found, but version check has failed! " , VPS_BITNESS ( i ) ) ;
}
2015-02-27 19:05:18 +01:00
}
else
{
2016-09-27 21:04:35 +02:00
qDebug ( " VapourSynth %u-Bit edition *not* found! " , VPS_BITNESS ( i ) ) ;
2015-02-27 19:05:18 +01:00
}
}
2014-05-05 15:07:31 +02:00
//Return VapourSynth path
if ( success )
{
path = vapoursynthPath ;
}
}
2015-02-27 19:05:18 +01:00
bool VapourSynthCheckThread : : isVapourSynthComplete ( const QString & vsCorePath , QFile * & vpsExeFile , QFile * & vpsDllFile )
{
bool complete = false ;
vpsExeFile = vpsDllFile = NULL ;
QFileInfo vpsExeInfo ( QString ( " %1/vspipe.exe " ) . arg ( vsCorePath ) ) ;
QFileInfo vpsDllInfo ( QString ( " %1/vapoursynth.dll " ) . arg ( vsCorePath ) ) ;
qDebug ( " VapourSynth EXE: %s " , vpsExeInfo . absoluteFilePath ( ) . toUtf8 ( ) . constData ( ) ) ;
qDebug ( " VapourSynth DLL: %s " , vpsDllInfo . absoluteFilePath ( ) . toUtf8 ( ) . constData ( ) ) ;
if ( vpsExeInfo . exists ( ) & & vpsDllInfo . exists ( ) )
{
vpsExeFile = new QFile ( vpsExeInfo . canonicalFilePath ( ) ) ;
vpsDllFile = new QFile ( vpsDllInfo . canonicalFilePath ( ) ) ;
if ( vpsExeFile - > open ( QIODevice : : ReadOnly ) & & vpsDllFile - > open ( QIODevice : : ReadOnly ) )
{
complete = MUtils : : OS : : is_executable_file ( vpsExeFile - > fileName ( ) ) ;
}
}
if ( ! complete )
{
MUTILS_DELETE ( vpsExeFile ) ;
MUTILS_DELETE ( vpsDllFile ) ;
}
return complete ;
}
bool VapourSynthCheckThread : : checkVapourSynth ( const QString & vspipePath )
2014-05-05 15:07:31 +02:00
{
2019-05-07 21:13:22 +02:00
//Try to run VSPIPE.EXE
const QStringList output = runProcess ( vspipePath , QStringList ( ) < < " --version " ) ;
2014-05-05 15:07:31 +02:00
//Init regular expressions
QRegExp vpsLogo ( " VapourSynth \\ s+Video \\ s+Processing \\ s+Library " ) ;
//Check for version info
2014-05-06 00:22:18 +02:00
bool vapoursynthLogo = false ;
2014-05-05 15:07:31 +02:00
for ( QStringList : : ConstIterator iter = output . constBegin ( ) ; iter ! = output . constEnd ( ) ; iter + + )
{
if ( vpsLogo . lastIndexIn ( * iter ) > = 0 )
{
vapoursynthLogo = true ;
2014-05-06 00:22:18 +02:00
break ;
2014-05-05 15:07:31 +02:00
}
}
//Minimum required version found?
2014-05-06 00:22:18 +02:00
if ( vapoursynthLogo )
2014-05-05 15:07:31 +02:00
{
2015-02-27 19:05:18 +01:00
qDebug ( " VapourSynth version was detected successfully. " ) ;
2014-05-05 15:07:31 +02:00
return true ;
}
//Failed to determine version
2015-02-27 19:05:18 +01:00
qWarning ( " Failed to determine VapourSynth version! " ) ;
2014-05-05 15:07:31 +02:00
return false ;
2013-08-07 15:34:02 +02:00
}