/////////////////////////////////////////////////////////////////////////////// // Simple x264 Launcher // Copyright (C) 2004-2013 LoRd_MuldeR // // 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" #include #include #include #include #include #include #include "global.h" #include "avisynth_c.h" QMutex VapourSynthCheckThread::m_vpsLock; QFile *VapourSynthCheckThread::m_vpsExePath = NULL; QFile *VapourSynthCheckThread::m_vpsDllPath = NULL; QLibrary *VapourSynthCheckThread::m_vpsLib = NULL; //------------------------------------- // External API //------------------------------------- int VapourSynthCheckThread::detect(QString &path) { path.clear(); QMutexLocker lock(&m_vpsLock); QEventLoop loop; VapourSynthCheckThread thread; QTimer timer; QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); connect(&thread, SIGNAL(finished()), &loop, SLOT(quit())); connect(&thread, SIGNAL(terminated()), &loop, SLOT(quit())); connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit())); thread.start(); timer.start(8000); 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(); return -1; } if(thread.getException()) { qWarning("VapourSynth thread encountered an exception !!!"); return -1; } if(thread.getSuccess()) { path = thread.getPath(); qDebug("VapourSynth check completed successfully."); return 1; } qWarning("VapourSynth thread failed to detect installation!"); return 0; } void VapourSynthCheckThread::unload(void) { QMutexLocker lock(&m_vpsLock); if(m_vpsLib) { if(m_vpsLib->isLoaded()) { m_vpsLib->unload(); } } if(m_vpsExePath) { if (m_vpsExePath->isOpen()) { m_vpsExePath->close(); } } if(m_vpsDllPath) { if(m_vpsDllPath->isOpen()) { m_vpsDllPath->close(); } } X264_DELETE(m_vpsExePath); X264_DELETE(m_vpsDllPath); X264_DELETE(m_vpsLib); } //------------------------------------- // Thread class //------------------------------------- VapourSynthCheckThread::VapourSynthCheckThread(void) { m_success = false; m_exception = false; m_vpsPath.clear(); } VapourSynthCheckThread::~VapourSynthCheckThread(void) { } void VapourSynthCheckThread::run(void) { m_exception = m_success = false; m_success = detectVapourSynthPath1(m_vpsPath, &m_exception); } bool VapourSynthCheckThread::detectVapourSynthPath1(QString &path, volatile bool *exception) { __try { return detectVapourSynthPath2(path, exception); } __except(1) { *exception = true; qWarning("Unhandled exception error in VapourSynth thread !!!"); return false; } } bool VapourSynthCheckThread::detectVapourSynthPath2(QString &path, volatile bool *exception) { try { return detectVapourSynthPath3(path); } catch(...) { *exception = true; qWarning("VapourSynth initializdation raised an C++ exception!"); return false; } } bool VapourSynthCheckThread::detectVapourSynthPath3(QString &path) { bool success = false; X264_DELETE(m_vpsExePath); X264_DELETE(m_vpsDllPath); path.clear(); static const wchar_t *VPS_REG_KEY = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\VapourSynth_is1"; //Determine the VapourSynth install path from registry QString vapoursynthPath; HKEY hKey = NULL; if(RegOpenKey(HKEY_LOCAL_MACHINE, VPS_REG_KEY, &hKey) == ERROR_SUCCESS) { const size_t DATA_LEN = 2048; wchar_t data[DATA_LEN]; DWORD type = REG_NONE, size = sizeof(wchar_t) * DATA_LEN; if(RegQueryValueEx(hKey, L"InstallLocation", NULL, &type, ((BYTE*)&data[0]), &size) == ERROR_SUCCESS) { if((type == REG_SZ) || (type == REG_EXPAND_SZ)) { vapoursynthPath = QDir::fromNativeSeparators(QString::fromUtf16((const ushort*)&data[0])); while(vapoursynthPath.endsWith("/")) { vapoursynthPath.chop(1); } qDebug("Vapoursynth location: %s", vapoursynthPath.toUtf8().constData()); } } if(vapoursynthPath.isEmpty()) { qWarning("Vapoursynth install location entry not found -> not installed!"); } RegCloseKey(hKey); } else { qWarning("Vapoursynth registry key not found -> not installed!"); } //Make sure that 'vapoursynth.dll' and 'vspipe.exe' are available bool vapoursynthComplete = false; if(!vapoursynthPath.isEmpty()) { m_vpsExePath = new QFile(QString("%1/core/vspipe.exe").arg(vapoursynthPath)); m_vpsDllPath = new QFile(QString("%1/core/vapoursynth.dll").arg(vapoursynthPath)); qDebug("VapourSynth EXE: %s", m_vpsExePath->fileName().toUtf8().constData()); qDebug("VapourSynth DLL: %s", m_vpsDllPath->fileName().toUtf8().constData()); if(m_vpsExePath->open(QIODevice::ReadOnly) && m_vpsDllPath->open(QIODevice::ReadOnly)) { DWORD binaryType; if(GetBinaryType(QWCHAR(QDir::toNativeSeparators(m_vpsExePath->fileName())), &binaryType)) { vapoursynthComplete = (binaryType == SCS_32BIT_BINARY || binaryType == SCS_64BIT_BINARY); } } if(!vapoursynthComplete) { qWarning("VapourSynth installation incomplete -> disable Vapousynth support!"); } } //Make sure 'vsscript.dll' can be loaded successfully if(vapoursynthComplete) { if(!m_vpsLib) { m_vpsLib = new QLibrary("vsscript.dll"); } if(m_vpsLib->isLoaded() || m_vpsLib->load()) { static const char *VSSCRIPT_ENTRY = "_vsscript_init@0"; qDebug("VapourSynth scripting library loaded."); if(!(success = (m_vpsLib->resolve(VSSCRIPT_ENTRY) != NULL))) { qWarning("Entrypoint '%s' not found in VSSCRIPT.DLL !!!", VSSCRIPT_ENTRY); } } else { qWarning("Failed to load VSSCRIPT.DLL !!!"); } } //Return VapourSynth path if(success) { path = vapoursynthPath; } return success; }