2013-08-07 15:34:02 +02:00
///////////////////////////////////////////////////////////////////////////////
// Simple x264 Launcher
2021-12-08 00:03:40 +01:00
// Copyright (C) 2004-2021 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 <QEventLoop>
# include <QTimer>
# include <QApplication>
# include <QDir>
2019-07-22 14:19:18 +02:00
# include <QHash>
2019-08-06 20:47:59 +02:00
# include <QAbstractFileEngine.h>
2013-08-07 15:34:02 +02:00
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>
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
2019-07-22 14:19:18 +02:00
//Const
2019-08-06 20:47:59 +02:00
static const char * const VPS_DLL_NAME = " vapoursynth.dll " ;
static const char * const VPS_EXE_NAME = " vspipe.exe " ;
2019-08-13 19:58:29 +02:00
static const char * const VPS_REG_KEY1 = " SOFTWARE \\ VapourSynth " ;
static const char * const VPS_REG_KEY2 = " SOFTWARE \\ VapourSynth-32 " ;
2019-08-05 22:55:10 +02:00
static const char * const VPS_REG_NAME = " VapourSynthDLL " ;
2019-07-22 14:19:18 +02:00
//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
2019-08-13 19:58:29 +02:00
//EOL flags
# define REG_ROOT_EOL (MUtils::Registry::reg_root_t (-1))
2019-08-09 14:33:57 +02:00
# define REG_SCOPE_EOL (MUtils::Registry::reg_scope_t(-1))
2019-05-09 22:18:44 +02:00
2019-08-09 14:33:57 +02:00
//Auxilary functions
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
2013-08-07 15:34:02 +02:00
//-------------------------------------
// External API
//-------------------------------------
2019-07-22 14:19:18 +02:00
bool VapourSynthCheckThread : : detect ( SysinfoModel * sysinfo )
2013-08-07 15:34:02 +02:00
{
QMutexLocker lock ( & m_vpsLock ) ;
2019-07-22 14:19:18 +02:00
sysinfo - > clearVapourSynth ( ) ;
sysinfo - > clearVPS32Path ( ) ;
sysinfo - > clearVPS64Path ( ) ;
2013-08-07 15:34:02 +02:00
QEventLoop loop ;
VapourSynthCheckThread thread ;
QApplication : : setOverrideCursor ( QCursor ( Qt : : WaitCursor ) ) ;
connect ( & thread , SIGNAL ( finished ( ) ) , & loop , SLOT ( quit ( ) ) ) ;
connect ( & thread , SIGNAL ( terminated ( ) ) , & loop , SLOT ( quit ( ) ) ) ;
2019-07-22 14:19:18 +02:00
2013-08-07 15:34:02 +02:00
thread . start ( ) ;
2019-05-07 21:13:22 +02:00
QTimer : : singleShot ( 30000 , & loop , SLOT ( quit ( ) ) ) ;
2019-07-22 14:19:18 +02:00
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 ( ) ;
2019-07-22 14:19:18 +02:00
if ( ! thread . wait ( 1000 ) )
2013-08-07 15:34:02 +02:00
{
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
}
2019-07-22 14:19:18 +02:00
if ( thread . getException ( ) )
2013-08-07 15:34:02 +02:00
{
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
2019-07-22 19:25:29 +02:00
const int success = thread . getSuccess ( ) ;
if ( ! success )
2015-03-01 22:00:05 +01:00
{
2019-07-22 14:19:18 +02:00
qWarning ( " VapourSynth could not be found -> VapourSynth support disabled! " ) ;
2019-07-22 19:25:29 +02:00
return true ;
2015-03-01 22:00:05 +01:00
}
2019-07-22 14:19:18 +02:00
2019-07-22 19:25:29 +02:00
if ( success & VAPOURSYNTH_X86 )
2013-08-07 15:34:02 +02:00
{
2019-07-22 14:19:18 +02:00
sysinfo - > setVapourSynth ( SysinfoModel : : VapourSynth_X86 , true ) ;
sysinfo - > setVPS32Path ( thread . getPath32 ( ) ) ;
2013-08-07 15:34:02 +02:00
}
2019-07-22 19:25:29 +02:00
if ( success & VAPOURSYNTH_X64 )
2019-07-22 14:19:18 +02:00
{
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 ) ) ) ;
2015-03-01 22:00:05 +01:00
return true ;
2013-08-07 15:34:02 +02:00
}
//-------------------------------------
2019-05-09 22:18:44 +02:00
// Thread functions
2013-08-07 15:34:02 +02:00
//-------------------------------------
VapourSynthCheckThread : : VapourSynthCheckThread ( void )
{
2019-07-22 14:19:18 +02:00
m_vpsPath [ 0U ] . clear ( ) ;
m_vpsPath [ 1U ] . clear ( ) ;
2013-08-07 15:34:02 +02:00
}
VapourSynthCheckThread : : ~ VapourSynthCheckThread ( void )
{
}
void VapourSynthCheckThread : : run ( void )
{
2019-07-22 14:19:18 +02:00
m_vpsPath [ 0U ] . clear ( ) ;
m_vpsPath [ 1U ] . clear ( ) ;
2019-05-09 22:18:44 +02:00
StarupThread : : run ( ) ;
2013-08-07 15:34:02 +02:00
}
2019-05-09 22:18:44 +02:00
int VapourSynthCheckThread : : threadMain ( void )
2013-08-07 15:34:02 +02:00
{
2016-09-27 21:04:35 +02:00
static const int VPS_BIT_FLAG [ ] =
{
VAPOURSYNTH_X86 ,
VAPOURSYNTH_X64 ,
NULL
} ;
2019-08-13 19:58:29 +02:00
static const MUtils : : Registry : : reg_root_t REG_ROOTS [ ] =
2019-08-12 20:20:44 +02:00
{
2019-08-13 19:58:29 +02:00
MUtils : : Registry : : root_machine ,
MUtils : : Registry : : root_user ,
REG_ROOT_EOL
} ;
static const char * const REG_PATHS_HKLM [ ] =
{
VPS_REG_KEY1 ,
NULL
} ;
static const char * const REG_PATHS_HKCU [ ] =
{
VPS_REG_KEY1 ,
VPS_REG_KEY2 ,
2019-08-12 20:20:44 +02:00
NULL
} ;
2019-08-09 14:33:57 +02:00
static const MUtils : : Registry : : reg_scope_t REG_SCOPE_X86 [ ] =
{
MUtils : : Registry : : scope_default ,
REG_SCOPE_EOL
} ;
static const MUtils : : Registry : : reg_scope_t REG_SCOPE_X64 [ ] =
2016-03-11 19:08:29 +01:00
{
MUtils : : Registry : : scope_wow_x32 ,
2019-07-22 14:19:18 +02:00
MUtils : : Registry : : scope_wow_x64 ,
2019-08-09 14:33:57 +02:00
REG_SCOPE_EOL
2016-03-11 19:08:29 +01:00
} ;
2013-11-08 17:39:16 +01:00
2019-08-06 20:47:59 +02:00
QHash < int , QFileInfo > vpsDllInfo , vpsExeInfo ;
2019-05-09 22:18:44 +02:00
int flags = 0 ;
2016-09-27 21:04:35 +02:00
//Look for "portable" VapourSynth version
2019-07-22 14:19:18 +02:00
for ( size_t i = 0 ; i < 2U ; i + + )
2016-09-27 21:04:35 +02:00
{
2019-08-06 20:47:59 +02:00
const QDir vpsPortableDir ( QString ( " %1/extra/VapourSynth-%2 " ) . arg ( QCoreApplication : : applicationDirPath ( ) , QString : : number ( VPS_BITNESS ( i ) ) ) ) ;
if ( vpsPortableDir . exists ( ) )
2016-09-27 21:04:35 +02:00
{
2019-08-06 20:47:59 +02:00
const QFileInfo vpsPortableDll ( vpsPortableDir . absoluteFilePath ( VPS_DLL_NAME ) ) ;
const QFileInfo vpsPortableExe ( vpsPortableDir . absoluteFilePath ( VPS_EXE_NAME ) ) ;
if ( ( vpsPortableDll . exists ( ) & & vpsPortableDll . isFile ( ) ) | | ( vpsPortableExe . exists ( ) & & vpsPortableExe . isFile ( ) ) )
2016-09-27 21:04:35 +02:00
{
2019-08-06 20:47:59 +02:00
vpsDllInfo . insert ( VPS_BIT_FLAG [ i ] , vpsPortableDll ) ;
vpsExeInfo . insert ( VPS_BIT_FLAG [ i ] , vpsPortableExe ) ;
2016-09-27 21:04:35 +02:00
}
}
}
2019-08-06 20:47:59 +02:00
//Read VapourSynth path from registry
if ( vpsDllInfo . isEmpty ( ) & & vpsExeInfo . isEmpty ( ) )
2013-11-08 17:39:16 +01:00
{
2019-08-13 19:58:29 +02:00
for ( size_t i = 0 ; REG_ROOTS [ i ] ! = REG_ROOT_EOL ; i + + )
2019-08-12 20:20:44 +02:00
{
2019-08-13 19:58:29 +02:00
const char * const * const paths = ( REG_ROOTS [ i ] = = MUtils : : Registry : : root_machine ) ? REG_PATHS_HKLM : REG_PATHS_HKCU ;
const MUtils : : Registry : : reg_scope_t * const scopes = ( REG_ROOTS [ i ] = = MUtils : : Registry : : root_machine ) ? ( ( MUtils : : OS : : os_architecture ( ) = = MUtils : : OS : : ARCH_X64 ) ? REG_SCOPE_X64 : REG_SCOPE_X86 ) : REG_SCOPE_X86 ;
for ( size_t j = 0 ; paths [ j ] ; j + + )
2019-08-12 20:20:44 +02:00
{
2019-08-13 19:58:29 +02:00
for ( size_t k = 0 ; scopes [ k ] ! = REG_SCOPE_EOL ; k + + )
2019-08-12 20:20:44 +02:00
{
2019-08-13 19:58:29 +02:00
if ( MUtils : : Registry : : reg_key_exists ( REG_ROOTS [ i ] , QString : : fromLatin1 ( paths [ j ] ) , scopes [ k ] ) )
2019-08-12 20:20:44 +02:00
{
2019-08-13 19:58:29 +02:00
QString vpsRegDllPath ;
if ( MUtils : : Registry : : reg_value_read ( REG_ROOTS [ i ] , QString : : fromLatin1 ( paths [ j ] ) , QString : : fromLatin1 ( VPS_REG_NAME ) , vpsRegDllPath , scopes [ k ] ) )
2019-08-09 14:33:57 +02:00
{
2019-08-13 19:58:29 +02:00
QFileInfo vpsRegDllInfo ( QDir : : fromNativeSeparators ( vpsRegDllPath ) ) ;
vpsRegDllInfo . makeAbsolute ( ) ;
if ( vpsRegDllInfo . exists ( ) & & vpsRegDllInfo . isFile ( ) )
{
const int vpsArch = ( REG_ROOTS [ i ] = = MUtils : : Registry : : root_machine ) ? getVapourSynthType ( scopes [ k ] ) : ( ( j > 0U ) ? VAPOURSYNTH_X86 : VAPOURSYNTH_X64 ) ;
if ( ( ! vpsDllInfo . contains ( vpsArch ) ) | | ( ! vpsExeInfo . contains ( vpsArch ) ) )
{
vpsDllInfo . insert ( vpsArch , vpsRegDllInfo ) ;
vpsExeInfo . insert ( vpsArch , vpsRegDllInfo . absoluteDir ( ) . absoluteFilePath ( VPS_EXE_NAME ) ) ; /*derive VSPipe.EXE path from VapourSynth.DLL path!*/
}
}
2019-08-09 14:33:57 +02:00
}
2016-03-11 19:08:29 +01:00
}
}
}
}
2013-11-08 17:39:16 +01:00
}
2013-08-07 15:34:02 +02:00
2019-08-06 20:47:59 +02:00
//Abort, if VapourSynth was *not* found
if ( vpsDllInfo . isEmpty ( ) | | vpsExeInfo . 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! " ) ;
2019-05-09 22:18:44 +02:00
return 0 ;
2013-08-07 15:34:02 +02:00
}
2016-09-27 21:04:35 +02:00
//Validate the VapourSynth installation now!
2019-07-22 14:19:18 +02:00
for ( size_t i = 0 ; i < 2U ; i + + )
2015-02-27 19:05:18 +01:00
{
2019-08-09 14:33:57 +02:00
qDebug ( " VapourSynth %u-Bit support is being tested. " , VPS_BITNESS ( i ) ) ;
2019-08-06 20:47:59 +02:00
if ( vpsDllInfo . contains ( VPS_BIT_FLAG [ i ] ) & & vpsExeInfo . contains ( VPS_BIT_FLAG [ i ] ) )
2015-02-27 19:05:18 +01:00
{
2019-07-22 14:19:18 +02:00
QFile * vpsExeFile , * vpsDllFile ;
2019-08-06 20:47:59 +02:00
if ( isVapourSynthComplete ( vpsDllInfo [ VPS_BIT_FLAG [ i ] ] , vpsExeInfo [ VPS_BIT_FLAG [ i ] ] , vpsExeFile , vpsDllFile ) )
2016-09-27 21:04:35 +02:00
{
2019-08-06 20:47:59 +02:00
m_vpsExePath [ i ] . reset ( vpsExeFile ) ;
m_vpsDllPath [ i ] . reset ( vpsDllFile ) ;
if ( checkVapourSynth ( m_vpsExePath [ i ] - > fileEngine ( ) - > fileName ( QAbstractFileEngine : : CanonicalName ) ) )
2019-07-22 14:19:18 +02:00
{
qDebug ( " VapourSynth %u-Bit edition found! " , VPS_BITNESS ( i ) ) ;
2019-08-06 20:47:59 +02:00
m_vpsPath [ i ] = m_vpsExePath [ i ] - > fileEngine ( ) - > fileName ( QAbstractFileEngine : : CanonicalPathName ) ;
2019-07-22 14:19:18 +02:00
flags | = VPS_BIT_FLAG [ i ] ;
}
else
{
qWarning ( " VapourSynth %u-Bit edition was found, but version check has failed! " , VPS_BITNESS ( i ) ) ;
}
2016-09-27 21:04:35 +02:00
}
else
{
2019-07-22 14:19:18 +02:00
qWarning ( " VapourSynth %u-Bit edition was found, but appears to be incomplete! " , VPS_BITNESS ( i ) ) ;
2016-09-27 21:04:35 +02:00
}
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
2019-05-09 22:18:44 +02:00
return flags ;
2014-05-05 15:07:31 +02:00
}
2019-05-09 22:18:44 +02:00
//-------------------------------------
// Internal functions
//-------------------------------------
2019-07-22 14:19:18 +02:00
VapourSynthCheckThread : : VapourSynthFlags VapourSynthCheckThread : : getVapourSynthType ( const int scope )
{
2019-08-09 14:33:57 +02:00
if ( MUtils : : OS : : os_architecture ( ) = = MUtils : : OS : : ARCH_X64 )
2019-07-22 14:19:18 +02:00
{
2019-08-09 14:33:57 +02:00
switch ( scope )
{
2019-07-22 14:19:18 +02:00
case MUtils : : Registry : : scope_wow_x32 :
return VAPOURSYNTH_X86 ;
case MUtils : : Registry : : scope_wow_x64 :
return VAPOURSYNTH_X64 ;
default :
return VAPOURSYNTH_DEF ;
2019-08-09 14:33:57 +02:00
}
}
else
{
return VAPOURSYNTH_X86 ; /*ignore scope on 32-Bit OS*/
2019-07-22 14:19:18 +02:00
}
}
2019-08-06 20:47:59 +02:00
bool VapourSynthCheckThread : : isVapourSynthComplete ( const QFileInfo & vpsDllInfo , const QFileInfo & vpsExeInfo , QFile * & vpsExeFile , QFile * & vpsDllFile )
2015-02-27 19:05:18 +01:00
{
bool complete = false ;
vpsExeFile = vpsDllFile = NULL ;
qDebug ( " VapourSynth EXE: %s " , vpsExeInfo . absoluteFilePath ( ) . toUtf8 ( ) . constData ( ) ) ;
qDebug ( " VapourSynth DLL: %s " , vpsDllInfo . absoluteFilePath ( ) . toUtf8 ( ) . constData ( ) ) ;
2019-08-06 20:47:59 +02:00
if ( vpsDllInfo . exists ( ) & & vpsDllInfo . isFile ( ) & & vpsExeInfo . exists ( ) & & vpsExeInfo . isFile ( ) )
2015-02-27 19:05:18 +01:00
{
vpsExeFile = new QFile ( vpsExeInfo . canonicalFilePath ( ) ) ;
vpsDllFile = new QFile ( vpsDllInfo . canonicalFilePath ( ) ) ;
if ( vpsExeFile - > open ( QIODevice : : ReadOnly ) & & vpsDllFile - > open ( QIODevice : : ReadOnly ) )
{
2019-08-06 20:47:59 +02:00
complete = MUtils : : OS : : is_executable_file ( vpsExeFile - > fileEngine ( ) - > fileName ( QAbstractFileEngine : : CanonicalName ) ) ;
2015-02-27 19:05:18 +01:00
}
}
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
}