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 <QEventLoop>
# include <QTimer>
# include <QApplication>
# include <QDir>
2019-07-22 14:19:18 +02:00
# include <QHash>
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
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
2019-05-09 22:18:44 +02:00
//-------------------------------------
// Auxilary functions
//-------------------------------------
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
2019-07-22 14:19:18 +02:00
static inline QString & cleanDir ( QString & path )
2013-11-08 17:39:16 +01:00
{
2019-07-22 14:19:18 +02:00
if ( ! path . isEmpty ( ) )
2013-11-08 17:39:16 +01:00
{
path = QDir : : fromNativeSeparators ( path ) ;
2019-07-22 14:19:18 +02:00
while ( path . endsWith ( ' / ' ) )
2013-11-08 17:39:16 +01:00
{
path . chop ( 1 ) ;
}
}
return path ;
}
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
} ;
2016-03-11 19:08:29 +01:00
static const MUtils : : Registry : : reg_scope_t REG_SCOPE [ 3 ] =
{
MUtils : : Registry : : scope_wow_x32 ,
2019-07-22 14:19:18 +02:00
MUtils : : Registry : : scope_wow_x64 ,
MUtils : : Registry : : scope_default
2016-03-11 19:08:29 +01:00
} ;
2013-11-08 17:39:16 +01:00
2019-07-22 14:19:18 +02:00
QHash < int , QString > vapoursynthPath ;
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-07-22 15:46:29 +02:00
const QString vpsPortableDir = QString ( " %1/extra/VapourSynth-%2 " ) . arg ( QCoreApplication : : applicationDirPath ( ) , QString : : number ( VPS_BITNESS ( i ) ) ) ;
2016-09-27 21:04:35 +02:00
if ( VALID_DIR ( vpsPortableDir ) )
{
2019-07-22 14:19:18 +02:00
const QFileInfo vpsPortableFile = QFileInfo ( QString ( " %1/vspipe.exe " ) . arg ( vpsPortableDir ) ) ;
if ( vpsPortableFile . exists ( ) & & vpsPortableFile . isFile ( ) )
2016-09-27 21:04:35 +02:00
{
2019-07-22 14:19:18 +02:00
vapoursynthPath . insert ( VPS_BIT_FLAG [ i ] , vpsPortableDir ) ;
2016-09-27 21:04:35 +02:00
}
}
}
2019-07-22 15:46:29 +02:00
//Read VapourSynth path from the registry
2016-09-27 21:04:35 +02:00
if ( vapoursynthPath . isEmpty ( ) )
2013-11-08 17:39:16 +01:00
{
2019-07-22 14:19:18 +02:00
for ( size_t i = 0 ; i < 3U ; i + + )
2013-11-08 17:39:16 +01:00
{
2019-07-22 14:19:18 +02:00
if ( MUtils : : Registry : : reg_key_exists ( MUtils : : Registry : : root_machine , QString : : fromLatin1 ( VPS_REG_KEYS ) , REG_SCOPE [ i ] ) )
2016-03-11 19:08:29 +01:00
{
2019-07-22 14:19:18 +02:00
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 ] ) )
2016-03-11 19:08:29 +01:00
{
2019-07-22 14:19:18 +02:00
if ( VALID_DIR ( vpsInstallPath ) )
2016-03-11 19:08:29 +01:00
{
2019-07-22 14:19:18 +02:00
const QString vpsCorePath = QString ( " %1/core " ) . arg ( cleanDir ( vpsInstallPath ) ) ;
if ( VALID_DIR ( vpsCorePath ) )
2016-09-27 21:04:35 +02:00
{
2019-07-22 14:19:18 +02:00
const int flag = getVapourSynthType ( REG_SCOPE [ i ] ) ;
if ( ! vapoursynthPath . contains ( flag ) )
2016-10-21 12:00:33 +02:00
{
2019-07-22 14:19:18 +02:00
vapoursynthPath . insert ( flag , vpsCorePath ) ;
2016-10-21 12:00:33 +02:00
}
2016-09-27 21:04:35 +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
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! " ) ;
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-07-22 14:19:18 +02:00
if ( vapoursynthPath . contains ( VPS_BIT_FLAG [ i ] ) )
2015-02-27 19:05:18 +01:00
{
2019-07-22 14:19:18 +02:00
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 ) )
2016-09-27 21:04:35 +02:00
{
2019-07-22 14:19:18 +02:00
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 ) ) ;
}
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 )
{
switch ( scope )
{
case MUtils : : Registry : : scope_wow_x32 :
return VAPOURSYNTH_X86 ;
case MUtils : : Registry : : scope_wow_x64 :
return VAPOURSYNTH_X64 ;
default :
return VAPOURSYNTH_DEF ;
}
}
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
}