1 ///////////////////////////////////////////////////////////////////////////////
2 // Simple x264 Launcher
3 // Copyright (C) 2004-2020 LoRd_MuldeR <MuldeR2@GMX.de>
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License along
16 // with this program; if not, write to the Free Software Foundation, Inc.,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 // http://www.gnu.org/licenses/gpl-2.0.txt
20 ///////////////////////////////////////////////////////////////////////////////
22 #include "thread_avisynth.h"
27 #include <QApplication>
32 #include "model_sysinfo.h"
35 #include <MUtils/Global.h>
36 #include <MUtils/OSSupport.h>
39 static const bool ENABLE_PORTABLE_AVS
= true;
42 QMutex
AvisynthCheckThread::m_avsLock
;
43 QScopedPointer
<QFile
> AvisynthCheckThread::m_avsDllPath
[2];
45 //-------------------------------------
47 //-------------------------------------
49 #define VALID_DIR(STR) ((!(STR).isEmpty()) && QDir((STR)).exists())
50 #define BOOLIFY(X) ((X) ? '1' : '0')
52 QString
AVS_CHECK_BINARY(const SysinfoModel
*sysinfo
, const bool& x64
)
54 return QString("%1/toolset/%2/avs_check_%2.exe").arg(sysinfo
->getAppPath(), (x64
? "x64": "x86"));
57 class Wow64RedirectionDisabler
60 Wow64RedirectionDisabler(void)
62 m_disabled
= MUtils::OS::wow64fsredir_disable(m_oldValue
);
64 ~Wow64RedirectionDisabler(void)
68 if(!MUtils::OS::wow64fsredir_revert(m_oldValue
))
70 qWarning("Failed to renable WOW64 filesystem redirection!");
79 //-------------------------------------
81 //-------------------------------------
83 bool AvisynthCheckThread::detect(SysinfoModel
*sysinfo
)
85 sysinfo
->clearAvisynth();
87 QMutexLocker
lock(&m_avsLock
);
90 AvisynthCheckThread
thread(sysinfo
);
92 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor
));
94 connect(&thread
, SIGNAL(finished()), &loop
, SLOT(quit()));
95 connect(&thread
, SIGNAL(terminated()), &loop
, SLOT(quit()));
98 QTimer::singleShot(30000, &loop
, SLOT(quit()));
100 qDebug("Avisynth thread has been created, please wait...");
101 loop
.exec(QEventLoop::ExcludeUserInputEvents
);
102 qDebug("Avisynth thread finished.");
104 QApplication::restoreOverrideCursor();
106 if(!thread
.wait(1000))
108 qWarning("Avisynth thread encountered timeout -> probably deadlock!");
114 if(thread
.getException())
116 qWarning("Avisynth thread encountered an exception !!!");
120 if(thread
.getSuccess())
122 sysinfo
->setAvisynth(SysinfoModel::Avisynth_X86
, thread
.getSuccess() & AVISYNTH_X86
);
123 sysinfo
->setAvisynth(SysinfoModel::Avisynth_X64
, thread
.getSuccess() & AVISYNTH_X64
);
124 sysinfo
->setAVSPath(thread
.getPath());
125 qDebug("Avisynth support is officially enabled now! [x86=%c, x64=%c]", BOOLIFY(sysinfo
->getAvisynth(SysinfoModel::Avisynth_X86
)), BOOLIFY(sysinfo
->getAvisynth(SysinfoModel::Avisynth_X64
)));
129 qWarning("Avisynth could not be found -> Avisynth support disabled!");
135 //-------------------------------------
137 //-------------------------------------
139 AvisynthCheckThread::AvisynthCheckThread(const SysinfoModel
*const sysinfo
)
146 AvisynthCheckThread::~AvisynthCheckThread(void)
150 void AvisynthCheckThread::run(void)
156 int AvisynthCheckThread::threadMain(void)
161 if(checkAvisynth(m_basePath
, m_sysinfo
, avsPath32
, false))
163 m_avsDllPath
[0].reset(avsPath32
);
164 flags
|= AVISYNTH_X86
;
165 qDebug("Avisynth 32-Bit edition found!");
169 qDebug("Avisynth 32-Bit edition *not* found!");
172 if(m_sysinfo
->getCPUFeatures(SysinfoModel::CPUFeatures_X64
))
175 if(checkAvisynth(m_basePath
, m_sysinfo
, avsPath64
, true))
177 m_avsDllPath
[1].reset(avsPath64
);
178 flags
|= AVISYNTH_X64
;
179 qDebug("Avisynth 64-Bit edition found!");
183 qDebug("Avisynth 64-Bit edition *not* found!");
188 qWarning("Skipping 64-Bit Avisynth check on non-x64 system!");
194 //-------------------------------------
195 // Internal functions
196 //-------------------------------------
198 bool AvisynthCheckThread::checkAvisynth(QString
&basePath
, const SysinfoModel
*const sysinfo
, QFile
*&path
, const bool &x64
)
200 qDebug("Avisynth %s-Bit support is being tested.", x64
? "64" : "32");
202 //Look for "portable" Avisynth version
203 static const char *const ARCH_DIR
[] = { "x64", "x86" };
204 const QLatin1String archSuffix
= QLatin1String(ARCH_DIR
[x64
? 1 : 0]);
205 if (ENABLE_PORTABLE_AVS
)
207 const QString avsPortableDir
= QString("%1/extra/Avisynth").arg(QCoreApplication::applicationDirPath());
208 if (VALID_DIR(avsPortableDir
))
210 QFileInfo
avsDllFile(QString("%1/%2/avisynth.dll").arg(avsPortableDir
, archSuffix
)), devilDllFile(QString("%1/%2/devil.dll").arg(avsPortableDir
, archSuffix
));
211 if (avsDllFile
.exists() && devilDllFile
.exists() && avsDllFile
.isFile() && devilDllFile
.isFile())
213 qWarning("Adding portable Avisynth to PATH environment variable: %s", MUTILS_UTF8(avsPortableDir
));
214 basePath
= avsPortableDir
;
220 QStringList avisynthExtraPaths
;
221 if (!basePath
.isEmpty())
223 avisynthExtraPaths
<< QString("%1/%2").arg(basePath
, archSuffix
);
226 //Setup process object
227 const QStringList output
= runProcess(AVS_CHECK_BINARY(sysinfo
, x64
), QStringList(), &avisynthExtraPaths
);
229 //Init regular expressions
230 QRegExp
avsLogo("Avisynth\\s+Checker\\s+(x86|x64)");
231 QRegExp
avsPath("Avisynth_DLLPath=(.+)");
232 QRegExp
avsVers("Avisynth_Version=(\\d+)\\.(\\d+)");
234 //Check for version info
235 bool avisynthLogo
= false;
236 quint32 avisynthVersion
[2] = { 0, 0 };
237 QString avisynthPath
;
238 for(QStringList::ConstIterator iter
= output
.constBegin(); iter
!= output
.constEnd(); iter
++)
242 if(avsPath
.indexIn(*iter
) >= 0)
244 avisynthPath
= avsPath
.cap(1).trimmed();
246 else if(avsVers
.indexIn(*iter
) >= 0)
249 if(MUtils::regexp_parse_uint32(avsVers
, temp
, 2))
251 avisynthVersion
[0] = temp
[0];
252 avisynthVersion
[1] = temp
[1];
258 if(avsLogo
.lastIndexIn(*iter
) >= 0)
265 //Minimum required version found?
266 if((avisynthVersion
[0] >= 2) && (avisynthVersion
[1] >= 50) && (!avisynthPath
.isEmpty()))
268 Wow64RedirectionDisabler disableWow64Redir
;
269 path
= new QFile(avisynthPath
);
270 if(!path
->open(QIODevice::ReadOnly
))
274 qDebug("Avisynth was detected successfully (current version: %u.%02u).", avisynthVersion
[0], avisynthVersion
[1]);
275 qDebug("Avisynth DLL path: %s", MUTILS_UTF8(avisynthPath
));
279 //Failed to determine version
280 qWarning("Failed to determine Avisynth version!");