diff --git a/src/global.cpp b/src/global.cpp index 8d53819..ce26a92 100644 --- a/src/global.cpp +++ b/src/global.cpp @@ -20,6 +20,7 @@ /////////////////////////////////////////////////////////////////////////////// #include "global.h" +#include "targetver.h" #include "version.h" //Windows includes @@ -29,6 +30,15 @@ #include #include +//C++ includes +#include +#include +#include +#include + +//VLD +#include + //Qt includes #include #include @@ -56,6 +66,7 @@ #include #include #include +#include //CRT includes #include @@ -1368,6 +1379,258 @@ bool x264_init_qt(int argc, char* argv[]) return true; } +/* + * Suspend or resume process + */ +bool x264_suspendProcess(const QProcess *proc, const bool suspend) +{ + if(Q_PID pid = proc->pid()) + { + if(suspend) + { + return (SuspendThread(pid->hThread) != ((DWORD) -1)); + } + else + { + return (ResumeThread(pid->hThread) != ((DWORD) -1)); + } + } + else + { + return false; + } +} + +/* + * Convert path to short/ANSI path + */ +QString x264_path2ansi(const QString &longPath) +{ + QString shortPath = longPath; + + DWORD buffSize = GetShortPathNameW(reinterpret_cast(longPath.utf16()), NULL, NULL); + + if(buffSize > 0) + { + wchar_t *buffer = new wchar_t[buffSize]; + DWORD result = GetShortPathNameW(reinterpret_cast(longPath.utf16()), buffer, buffSize); + + if((result > 0) && (result < buffSize)) + { + shortPath = QString::fromUtf16(reinterpret_cast(buffer), result); + } + + delete[] buffer; + buffer = NULL; + } + + return shortPath; +} + +/* + * Set the process priority class for current process + */ +bool x264_change_process_priority(const int priority) +{ + return x264_change_process_priority(GetCurrentProcess(), priority); +} + +/* + * Set the process priority class for specified process + */ +bool x264_change_process_priority(const QProcess *proc, const int priority) +{ + if(Q_PID qPid = proc->pid()) + { + return x264_change_process_priority(qPid->hProcess, priority); + } + else + { + return false; + } +} + +/* + * Set the process priority class for specified process + */ +bool x264_change_process_priority(void *hProcess, const int priority) +{ + bool ok = false; + + switch(qBound(-2, priority, 2)) + { + case 2: + ok = (SetPriorityClass(hProcess, HIGH_PRIORITY_CLASS) == TRUE); + break; + case 1: + if(!(ok = (SetPriorityClass(hProcess, ABOVE_NORMAL_PRIORITY_CLASS) == TRUE))) + { + ok = (SetPriorityClass(hProcess, HIGH_PRIORITY_CLASS) == TRUE); + } + break; + case 0: + ok = (SetPriorityClass(hProcess, NORMAL_PRIORITY_CLASS) == TRUE); + break; + case -1: + if(!(ok = (SetPriorityClass(hProcess, BELOW_NORMAL_PRIORITY_CLASS) == TRUE))) + { + ok = (SetPriorityClass(hProcess, IDLE_PRIORITY_CLASS) == TRUE); + } + break; + case -2: + ok = (SetPriorityClass(hProcess, IDLE_PRIORITY_CLASS) == TRUE); + break; + } + + return ok; +} + +/* + * Play a sound (from resources) + */ +bool x264_play_sound(const unsigned short uiSoundIdx, const bool bAsync, const wchar_t *alias) +{ + if(alias) + { + return PlaySound(alias, GetModuleHandle(NULL), (SND_ALIAS | (bAsync ? SND_ASYNC : SND_SYNC))) == TRUE; + } + else + { + return PlaySound(MAKEINTRESOURCE(uiSoundIdx), GetModuleHandle(NULL), (SND_RESOURCE | (bAsync ? SND_ASYNC : SND_SYNC))) == TRUE; + } +} + +/* + * Current process ID + */ +unsigned int x264_process_id(void) +{ + return GetCurrentProcessId(); +} + +/* + * Make a window blink (to draw user's attention) + */ +void x264_blink_window(QWidget *poWindow, unsigned int count, unsigned int delay) +{ + static QMutex blinkMutex; + + const double maxOpac = 1.0; + const double minOpac = 0.3; + const double delOpac = 0.1; + + if(!blinkMutex.tryLock()) + { + qWarning("Blinking is already in progress, skipping!"); + return; + } + + try + { + const int steps = static_cast(ceil(maxOpac - minOpac) / delOpac); + const int sleep = static_cast(floor(static_cast(delay) / static_cast(steps))); + const double opacity = poWindow->windowOpacity(); + + for(unsigned int i = 0; i < count; i++) + { + for(double x = maxOpac; x >= minOpac; x -= delOpac) + { + poWindow->setWindowOpacity(x); + QApplication::processEvents(); + Sleep(sleep); + } + + for(double x = minOpac; x <= maxOpac; x += delOpac) + { + poWindow->setWindowOpacity(x); + QApplication::processEvents(); + Sleep(sleep); + } + } + + poWindow->setWindowOpacity(opacity); + QApplication::processEvents(); + blinkMutex.unlock(); + } + catch(...) + { + blinkMutex.unlock(); + qWarning("Exception error while blinking!"); + } +} + +/* + * Bring the specifed window to the front + */ +bool x264_bring_to_front(const QWidget *win) +{ + const bool ret = (SetForegroundWindow(win->winId()) == TRUE); + SwitchToThisWindow(win->winId(), TRUE); + return ret; +} + +/* + * Check if file is a valid Win32/Win64 executable + */ +bool x264_is_executable(const QString &path) +{ + bool bIsExecutable = false; + DWORD binaryType; + if(GetBinaryType(QWCHAR(QDir::toNativeSeparators(path)), &binaryType)) + { + bIsExecutable = (binaryType == SCS_32BIT_BINARY || binaryType == SCS_64BIT_BINARY); + } + return bIsExecutable; +} + +/* + * Read value from registry + */ +QString x264_query_reg_string(const bool bUser, const QString &path, const QString &name) +{ + QString result; HKEY hKey = NULL; + if(RegOpenKey((bUser ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE), QWCHAR(path), &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, QWCHAR(name), NULL, &type, ((BYTE*)&data[0]), &size) == ERROR_SUCCESS) + { + if((type == REG_SZ) || (type == REG_EXPAND_SZ)) + { + result = WCHAR2QSTR(&data[0]); + } + } + RegCloseKey(hKey); + } + return result; +} + +/* + * Display the window's close button + */ +bool x264_enable_close_button(const QWidget *win, const bool bEnable) +{ + bool ok = false; + + if(HMENU hMenu = GetSystemMenu(win->winId(), FALSE)) + { + ok = (EnableMenuItem(hMenu, SC_CLOSE, MF_BYCOMMAND | (bEnable ? MF_ENABLED : MF_GRAYED)) == TRUE); + } + + return ok; +} + +bool x264_beep(int beepType) +{ + switch(beepType) + { + case x264_beep_info: return MessageBeep(MB_ICONASTERISK) == TRUE; break; + case x264_beep_warning: return MessageBeep(MB_ICONEXCLAMATION) == TRUE; break; + case x264_beep_error: return MessageBeep(MB_ICONHAND) == TRUE; break; + default: return false; + } +} + /* * Shutdown the computer */ @@ -1534,7 +1797,7 @@ static const HANDLE g_debug_thread = X264_DEBUG ? NULL : x264_debug_thread_init( /* * Get number private bytes [debug only] */ -SIZE_T x264_dbg_private_bytes(void) +size_t x264_dbg_private_bytes(void) { #if X264_DEBUG PROCESS_MEMORY_COUNTERS_EX memoryCounters; diff --git a/src/global.h b/src/global.h index 20740c8..3090bf6 100644 --- a/src/global.h +++ b/src/global.h @@ -21,20 +21,7 @@ #pragma once -#include "targetver.h" - -//C++ includes -#include -#include -#include -#include - -//Win32 includes -#define WIN32_LEAN_AND_MEAN -#include - -//VLD -#include +#include //Debug build #if defined(_DEBUG) && defined(QT_DEBUG) && !defined(NDEBUG) && !defined(QT_NO_DEBUG) @@ -84,6 +71,7 @@ class QTime; class QIcon; class QWidget; class LockedFile; +class QProcess; enum QtMsgType; //Types definitions @@ -123,6 +111,15 @@ typedef struct _x264_os_version_t } x264_os_version_t; +//Beep types +typedef enum +{ + x264_beep_info = 0, + x264_beep_warning = 1, + x264_beep_error = 2 +} +x264_beep_t; + //Known Windows versions extern const x264_os_version_t x264_winver_win2k; extern const x264_os_version_t x264_winver_winxp; @@ -133,8 +130,6 @@ extern const x264_os_version_t x264_winver_win80; extern const x264_os_version_t x264_winver_win81; //Functions -LONG WINAPI x264_exception_handler(__in struct _EXCEPTION_POINTERS *ExceptionInfo); -void x264_invalid_param_handler(const wchar_t*, const wchar_t*, const wchar_t*, unsigned int, uintptr_t); void x264_message_handler(QtMsgType type, const char *msg); unsigned int x264_version_major(void); unsigned int x264_version_minor(void); @@ -153,5 +148,18 @@ bool x264_shutdown_computer(const QString &message, const unsigned long timeout, void x264_fatal_exit(const wchar_t* exitMessage, const wchar_t* errorBoxMessage = NULL); void x264_sleep(const unsigned int delay); const QStringList &x264_arguments(void); -SIZE_T x264_dbg_private_bytes(void); +bool x264_suspendProcess(const QProcess *proc, const bool suspend); +size_t x264_dbg_private_bytes(void); void x264_finalization(void); +QString x264_path2ansi(const QString &longPath); +bool x264_change_process_priority(const int priority); +bool x264_change_process_priority(const QProcess *proc, const int priority); +bool x264_change_process_priority(void *hProcess, const int priority); +bool x264_play_sound(const unsigned short uiSoundIdx, const bool bAsync, const wchar_t *alias = NULL); +unsigned int x264_process_id(void); +bool x264_enable_close_button(const QWidget *win, const bool bEnable); +void x264_blink_window(QWidget *poWindow, unsigned int count, unsigned int delay); +bool x264_bring_to_front(const QWidget *win); +bool x264_is_executable(const QString &path); +QString x264_query_reg_string(const bool bUser, const QString &path, const QString &name); +bool x264_beep(int beepType); diff --git a/src/main.cpp b/src/main.cpp index 03c6c7e..d12ced3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -28,6 +28,11 @@ #include #include +//Windows includes +#define NOMINMAX +#define WIN32_LEAN_AND_MEAN +#include + /////////////////////////////////////////////////////////////////////////////// // Main function /////////////////////////////////////////////////////////////////////////////// @@ -105,6 +110,9 @@ static int x264_main(int argc, char* argv[]) // Applicaton entry point /////////////////////////////////////////////////////////////////////////////// +LONG WINAPI x264_exception_handler(__in struct _EXCEPTION_POINTERS *ExceptionInfo); +void x264_invalid_param_handler(const wchar_t*, const wchar_t*, const wchar_t*, unsigned int, uintptr_t); + static int _main(int argc, char* argv[]) { if(X264_DEBUG) diff --git a/src/model_jobList.cpp b/src/model_jobList.cpp index ef675e4..9e3aa81 100644 --- a/src/model_jobList.cpp +++ b/src/model_jobList.cpp @@ -29,8 +29,6 @@ #include #include -#include - JobListModel::JobListModel(PreferencesModel *preferences) { m_preferences = preferences; @@ -493,13 +491,13 @@ void JobListModel::updateStatus(const QUuid &jobId, JobStatus newStatus) switch(newStatus) { case JobStatus_Completed: - PlaySound(MAKEINTRESOURCE(IDR_WAVE4), GetModuleHandle(NULL), SND_RESOURCE | SND_ASYNC); + x264_play_sound(IDR_WAVE4, true); break; case JobStatus_Aborted: - PlaySound(MAKEINTRESOURCE(IDR_WAVE5), GetModuleHandle(NULL), SND_RESOURCE | SND_ASYNC); + x264_play_sound(IDR_WAVE5, true); break; case JobStatus_Failed: - PlaySound(MAKEINTRESOURCE(IDR_WAVE6), GetModuleHandle(NULL), SND_RESOURCE | SND_ASYNC); + x264_play_sound(IDR_WAVE6, true); break; } } diff --git a/src/model_preferences.cpp b/src/model_preferences.cpp index aa5a828..152eeef 100644 --- a/src/model_preferences.cpp +++ b/src/model_preferences.cpp @@ -46,7 +46,7 @@ void PreferencesModel::initPreferences(PreferencesModel *preferences) preferences->m_useAvisyth64Bit = false; preferences->m_saveLogFiles = false; preferences->m_saveToSourcePath = false; - preferences->m_processPriority = X264_PRIORITY_BELOWNORMAL; + preferences->m_processPriority = -1; preferences->m_enableSounds = false; preferences->m_disableWarnings = false; } diff --git a/src/model_preferences.h b/src/model_preferences.h index f7ebd3e..9702ae5 100644 --- a/src/model_preferences.h +++ b/src/model_preferences.h @@ -26,15 +26,6 @@ class PreferencesModel public: PreferencesModel(void); - enum - { - X264_PRIORITY_ABOVENORMAL = 0, - X264_PRIORITY_NORMAL = 1, - X264_PRIORITY_BELOWNORMAL = 2, - X264_PRIORITY_IDLE = 3, - } - x264_priority_t; - //Getter bool autoRunNextJob(void) { return m_autoRunNextJob; } unsigned int maxRunningJobCount(void) { return m_maxRunningJobCount; } diff --git a/src/taskbar7.cpp b/src/taskbar7.cpp index 462625f..c58268d 100644 --- a/src/taskbar7.cpp +++ b/src/taskbar7.cpp @@ -25,8 +25,8 @@ #include #include -UINT WinSevenTaskbar::m_winMsg = 0; -ITaskbarList3 *WinSevenTaskbar::m_ptbl = NULL; +static UINT s_winMsg = 0; +static ITaskbarList3 *s_ptbl = NULL; WinSevenTaskbar::WinSevenTaskbar(void) { @@ -43,27 +43,27 @@ WinSevenTaskbar::~WinSevenTaskbar(void) void WinSevenTaskbar::init(void) { - m_winMsg = RegisterWindowMessageW(L"TaskbarButtonCreated"); - m_ptbl = NULL; + s_winMsg = RegisterWindowMessageW(L"TaskbarButtonCreated"); + s_ptbl = NULL; } void WinSevenTaskbar::uninit(void) { - if(m_ptbl) + if(s_ptbl) { - m_ptbl->Release(); - m_ptbl = NULL; + s_ptbl->Release(); + s_ptbl = NULL; } } -bool WinSevenTaskbar::handleWinEvent(MSG *message, long *result) +bool WinSevenTaskbar::handleWinEvent(void *message, long *result) { bool stopEvent = false; - if(message->message == m_winMsg) + if(((MSG*)message)->message == s_winMsg) { - if(!m_ptbl) createInterface(); - *result = (m_ptbl) ? S_OK : S_FALSE; + if(!s_ptbl) createInterface(); + *result = (s_ptbl) ? S_OK : S_FALSE; stopEvent = true; } @@ -72,7 +72,7 @@ bool WinSevenTaskbar::handleWinEvent(MSG *message, long *result) void WinSevenTaskbar::createInterface(void) { - if(!m_ptbl) + if(!s_ptbl) { ITaskbarList3 *ptbl = NULL; HRESULT hr = CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&ptbl)); @@ -82,7 +82,7 @@ void WinSevenTaskbar::createInterface(void) HRESULT hr2 = ptbl->HrInit(); if(SUCCEEDED(hr2)) { - m_ptbl = ptbl; + s_ptbl = ptbl; /*qDebug("ITaskbarList3::HrInit() succeeded.");*/ } else @@ -102,26 +102,26 @@ bool WinSevenTaskbar::setTaskbarState(QWidget *window, WinSevenTaskbarState stat { bool result = false; - if(m_ptbl && window) + if(s_ptbl && window) { HRESULT hr = HRESULT(-1); switch(state) { case WinSevenTaskbarNoState: - hr = m_ptbl->SetProgressState(window->winId(), TBPF_NOPROGRESS); + hr = s_ptbl->SetProgressState(window->winId(), TBPF_NOPROGRESS); break; case WinSevenTaskbarNormalState: - hr = m_ptbl->SetProgressState(window->winId(), TBPF_NORMAL); + hr = s_ptbl->SetProgressState(window->winId(), TBPF_NORMAL); break; case WinSevenTaskbarIndeterminateState: - hr = m_ptbl->SetProgressState(window->winId(), TBPF_INDETERMINATE); + hr = s_ptbl->SetProgressState(window->winId(), TBPF_INDETERMINATE); break; case WinSevenTaskbarErrorState: - hr = m_ptbl->SetProgressState(window->winId(), TBPF_ERROR); + hr = s_ptbl->SetProgressState(window->winId(), TBPF_ERROR); break; case WinSevenTaskbarPausedState: - hr = m_ptbl->SetProgressState(window->winId(), TBPF_PAUSED); + hr = s_ptbl->SetProgressState(window->winId(), TBPF_PAUSED); break; } @@ -133,17 +133,17 @@ bool WinSevenTaskbar::setTaskbarState(QWidget *window, WinSevenTaskbarState stat void WinSevenTaskbar::setTaskbarProgress(QWidget *window, unsigned __int64 currentValue, unsigned __int64 maximumValue) { - if(m_ptbl && window) + if(s_ptbl && window) { - m_ptbl->SetProgressValue(window->winId(), currentValue, maximumValue); + s_ptbl->SetProgressValue(window->winId(), currentValue, maximumValue); } } void WinSevenTaskbar::setOverlayIcon(QWidget *window, const QIcon *icon) { - if(m_ptbl && window) + if(s_ptbl && window) { - m_ptbl->SetOverlayIcon(window->winId(), (icon ? icon->pixmap(16,16).toWinHICON() : NULL), L"Simple x264 Launcher"); + s_ptbl->SetOverlayIcon(window->winId(), (icon ? icon->pixmap(16,16).toWinHICON() : NULL), L"Simple x264 Launcher"); } } diff --git a/src/taskbar7.h b/src/taskbar7.h index c84aa2e..1a86871 100644 --- a/src/taskbar7.h +++ b/src/taskbar7.h @@ -44,7 +44,7 @@ public: }; //Public interface - static bool handleWinEvent(MSG *message, long *result); + static bool handleWinEvent(void *message, long *result); static bool setTaskbarState(QWidget *window, WinSevenTaskbarState state); static void setTaskbarProgress(QWidget *window, unsigned __int64 currentValue, unsigned __int64 maximumValue); static void setOverlayIcon(QWidget *window, const QIcon *icon); @@ -53,7 +53,5 @@ public: static void uninit(void); private: - static ITaskbarList3 *m_ptbl; - static UINT m_winMsg; static void createInterface(void); }; diff --git a/src/thread_encode.cpp b/src/thread_encode.cpp index 949ab97..2b1a73b 100644 --- a/src/thread_encode.cpp +++ b/src/thread_encode.cpp @@ -24,6 +24,7 @@ #include "global.h" #include "model_options.h" #include "model_preferences.h" +#include "job_object.h" #include "version.h" #include @@ -121,7 +122,7 @@ EncodeThread::EncodeThread(const QString &sourceFileName, const QString &outputF m_skipVersionTest(skipVersionTest), m_processPriority(processPriroity), m_abortOnTimeout(abortOnTimeout), - m_handle_jobObject(NULL), + m_jobObject(new JobObject), m_semaphorePaused(0) { m_abort = false; @@ -131,12 +132,7 @@ EncodeThread::EncodeThread(const QString &sourceFileName, const QString &outputF EncodeThread::~EncodeThread(void) { X264_DELETE(m_options); - - if(m_handle_jobObject) - { - CloseHandle(m_handle_jobObject); - m_handle_jobObject = NULL; - } + X264_DELETE(m_jobObject); } /////////////////////////////////////////////////////////////////////////////// @@ -158,10 +154,10 @@ void EncodeThread::run(void) checkedRun(); #endif - if(m_handle_jobObject) + if(m_jobObject) { - TerminateJobObject(m_handle_jobObject, 42); - m_handle_jobObject = NULL; + m_jobObject->terminateJob(42); + X264_DELETE(m_jobObject); } } @@ -189,7 +185,7 @@ void EncodeThread::checkedRun(void) } catch(...) { - RaiseException(EXCEPTION_ACCESS_VIOLATION, 0, 0, NULL); + x264_fatal_exit(L"Unhandeled exception error in encode thread!"); } } @@ -369,7 +365,7 @@ bool EncodeThread::runEncodingPass(bool x264_x64, bool x264_10bit, bool avs2yuv_ { cmdLine_Input.append(splitParams(m_options->customAvs2YUV())); } - cmdLine_Input << pathToAnsi(QDir::toNativeSeparators(m_sourceFileName)); + cmdLine_Input << x264_path2ansi(QDir::toNativeSeparators(m_sourceFileName)); cmdLine_Input << "-"; log("Creating Avisynth process:"); if(!startProcess(processInput, AVS2_BINARY(m_binDir, avs2yuv_x64), cmdLine_Input, false)) @@ -378,7 +374,7 @@ bool EncodeThread::runEncodingPass(bool x264_x64, bool x264_10bit, bool avs2yuv_ } break; case INPUT_VAPOUR: - cmdLine_Input << pathToAnsi(QDir::toNativeSeparators(m_sourceFileName)); + cmdLine_Input << x264_path2ansi(QDir::toNativeSeparators(m_sourceFileName)); cmdLine_Input << "-" << "-y4m"; log("Creating Vapoursynth process:"); if(!startProcess(processInput, VPSP_BINARY(m_vpsDir), cmdLine_Input, false)) @@ -434,13 +430,13 @@ bool EncodeThread::runEncodingPass(bool x264_x64, bool x264_10bit, bool avs2yuv_ setStatus(JobStatus_Paused); log(tr("Job paused by user at %1, %2.").arg(QDate::currentDate().toString(Qt::ISODate), QTime::currentTime().toString( Qt::ISODate))); bool ok[2] = {false, false}; - Q_PID pid[2] = {processEncode.pid(), processInput.pid()}; - if(pid[0]) { ok[0] = (SuspendThread(pid[0]->hThread) != (DWORD)(-1)); } - if(pid[1]) { ok[1] = (SuspendThread(pid[1]->hThread) != (DWORD)(-1)); } + QProcess *proc[2] = { &processEncode, &processInput }; + ok[0] = x264_suspendProcess(proc[0], true); + ok[1] = x264_suspendProcess(proc[1], true); while(m_pause) m_semaphorePaused.tryAcquire(1, 5000); while(m_semaphorePaused.tryAcquire(1, 0)); - if(pid[0]) { if(ok[0]) ResumeThread(pid[0]->hThread); } - if(pid[1]) { if(ok[1]) ResumeThread(pid[1]->hThread); } + ok[0] = x264_suspendProcess(proc[0], false); + ok[1] = x264_suspendProcess(proc[1], false); if(!m_abort) setStatus(previousStatus); log(tr("Job resumed by user at %1, %2.").arg(QDate::currentDate().toString(Qt::ISODate), QTime::currentTime().toString( Qt::ISODate))); waitCounter = 0; @@ -995,7 +991,7 @@ bool EncodeThread::checkPropertiesAvisynth(bool x64, unsigned int &frames) } cmdLine << "-frames" << "1"; - cmdLine << pathToAnsi(QDir::toNativeSeparators(m_sourceFileName)) << "NUL"; + cmdLine << x264_path2ansi(QDir::toNativeSeparators(m_sourceFileName)) << "NUL"; log("Creating process:"); if(!startProcess(process, AVS2_BINARY(m_binDir, x64), cmdLine)) @@ -1155,7 +1151,7 @@ bool EncodeThread::checkPropertiesVapoursynth(/*const QString &vspipePath,*/ uns QProcess process; QStringList cmdLine; - cmdLine << pathToAnsi(QDir::toNativeSeparators(m_sourceFileName)); + cmdLine << x264_path2ansi(QDir::toNativeSeparators(m_sourceFileName)); cmdLine << "-" << "-info"; log("Creating process:"); @@ -1323,29 +1319,6 @@ void EncodeThread::setDetails(const QString &text) emit detailsChanged(m_jobId, text); } -QString EncodeThread::pathToAnsi(const QString &longPath) -{ - QString shortPath = longPath; - - DWORD buffSize = GetShortPathNameW(reinterpret_cast(longPath.utf16()), NULL, NULL); - - if(buffSize > 0) - { - wchar_t *buffer = new wchar_t[buffSize]; - DWORD result = GetShortPathNameW(reinterpret_cast(longPath.utf16()), buffer, buffSize); - - if((result > 0) && (result < buffSize)) - { - shortPath = QString::fromUtf16(reinterpret_cast(buffer), result); - } - - delete[] buffer; - buffer = NULL; - } - - return shortPath; -} - QString EncodeThread::stringToHash(const QString &string) { QByteArray result(10, char(0)); @@ -1369,23 +1342,6 @@ bool EncodeThread::startProcess(QProcess &process, const QString &program, const QMutexLocker lock(&m_mutex_startProcess); log(commandline2string(program, args) + "\n"); - //Create a new job object, if not done yet - if(!m_handle_jobObject) - { - m_handle_jobObject = CreateJobObject(NULL, NULL); - if(m_handle_jobObject == INVALID_HANDLE_VALUE) - { - m_handle_jobObject = NULL; - } - if(m_handle_jobObject) - { - JOBOBJECT_EXTENDED_LIMIT_INFORMATION jobExtendedLimitInfo; - memset(&jobExtendedLimitInfo, 0, sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION)); - jobExtendedLimitInfo.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE | JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION; - SetInformationJobObject(m_handle_jobObject, JobObjectExtendedLimitInformation, &jobExtendedLimitInfo, sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION)); - } - } - process.setWorkingDirectory(QDir::tempPath()); if(mergeChannels) @@ -1404,10 +1360,10 @@ bool EncodeThread::startProcess(QProcess &process, const QString &program, const if(process.waitForStarted()) { Q_PID pid = process.pid(); - if(pid != NULL) + if((pid != NULL) && (m_jobObject != NULL)) { - AssignProcessToJobObject(m_handle_jobObject, process.pid()->hProcess); - setPorcessPriority(process.pid()->hProcess, m_processPriority); + m_jobObject->addProcessToJob(&process); + x264_change_process_priority(&process, m_processPriority); } lock.unlock(); @@ -1512,28 +1468,3 @@ int EncodeThread::getInputType(const QString &fileExt) else if(fileExt.compare("py", Qt::CaseInsensitive) == 0) type = INPUT_VAPOUR; return type; } - -void EncodeThread::setPorcessPriority(void *processId, int priroity) -{ - switch(priroity) - { - case PreferencesModel::X264_PRIORITY_ABOVENORMAL: - if(!SetPriorityClass(processId, ABOVE_NORMAL_PRIORITY_CLASS)) - { - SetPriorityClass(processId, NORMAL_PRIORITY_CLASS); - } - break; - case PreferencesModel::X264_PRIORITY_NORMAL: - SetPriorityClass(processId, NORMAL_PRIORITY_CLASS); - break; - case PreferencesModel::X264_PRIORITY_BELOWNORMAL: - if(!SetPriorityClass(processId, BELOW_NORMAL_PRIORITY_CLASS)) - { - SetPriorityClass(processId, IDLE_PRIORITY_CLASS); - } - break; - case PreferencesModel::X264_PRIORITY_IDLE: - SetPriorityClass(processId, IDLE_PRIORITY_CLASS); - break; - } -} diff --git a/src/thread_encode.h b/src/thread_encode.h index 329b7d4..af5c6db 100644 --- a/src/thread_encode.h +++ b/src/thread_encode.h @@ -31,6 +31,7 @@ class OptionsModel; class QProcess; +class JobObject; class EncodeThread : public QThread { @@ -96,8 +97,8 @@ protected: //Synchronization QSemaphore m_semaphorePaused; - //Job handle - void *m_handle_jobObject; + //Job Object + JobObject *m_jobObject; //Internal status values JobStatus m_status; @@ -129,9 +130,7 @@ protected: //Static functions static QString commandline2string(const QString &program, const QStringList &arguments); static QString sizeToString(qint64 size); - static void setPorcessPriority(void *processId, int priroity); static int getInputType(const QString &fileExt); - static QString pathToAnsi(const QString &longPath); static QString stringToHash(const QString &string); signals: diff --git a/src/thread_ipc.cpp b/src/thread_ipc.cpp index a1b0a34..9923f6e 100644 --- a/src/thread_ipc.cpp +++ b/src/thread_ipc.cpp @@ -54,10 +54,10 @@ bool IPCThread::initialize(bool *firstInstance) { if((m_semaphore_r->error() == 0) && (m_semaphore_w->error() == 0) && (m_sharedMem->error() == 0)) { - if(m_sharedMem->create(sizeof(DWORD), QSharedMemory::ReadWrite)) + if(m_sharedMem->create(sizeof(size_t), QSharedMemory::ReadWrite)) { m_firstInstance = m_ipcReady = true; - memset(m_sharedMem->data(), 0, sizeof(DWORD)); + memset(m_sharedMem->data(), 0, sizeof(size_t)); } else { @@ -104,8 +104,8 @@ void IPCThread::run(void) if(!m_firstInstance) { m_semaphore_w->acquire(); - DWORD *pidPtr = reinterpret_cast(m_sharedMem->data()); - *pidPtr = GetCurrentProcessId(); + size_t *pidPtr = reinterpret_cast(m_sharedMem->data()); + *pidPtr = x264_process_id(); m_semaphore_r->release(); return; } @@ -122,7 +122,7 @@ void IPCThread::run(void) { break; } - const DWORD procId = *reinterpret_cast(m_sharedMem->constData()); + const size_t procId = *reinterpret_cast(m_sharedMem->constData()); m_semaphore_w->release(); emit instanceCreated(procId); } diff --git a/src/thread_ipc.h b/src/thread_ipc.h index eb5bf16..181ea36 100644 --- a/src/thread_ipc.h +++ b/src/thread_ipc.h @@ -39,7 +39,7 @@ public: bool initialize(bool *firstInstance = NULL); signals: - void instanceCreated(DWORD pid); + void instanceCreated(unsigned int pid); public slots: void start(Priority priority = InheritPriority); diff --git a/src/thread_vapoursynth.cpp b/src/thread_vapoursynth.cpp index f097d7b..02811db 100644 --- a/src/thread_vapoursynth.cpp +++ b/src/thread_vapoursynth.cpp @@ -178,33 +178,12 @@ bool VapourSynthCheckThread::detectVapourSynthPath3(QString &path) X264_DELETE(m_vpsDllPath); path.clear(); - static const wchar_t *VPS_REG_KEY = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\VapourSynth_is1"; + static const char *VPS_REG_KEY = "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) + QString vapoursynthPath = x264_query_reg_string(false, VPS_REG_KEY, "InstallLocation"); + if(vapoursynthPath.isEmpty()) { - 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!"); + qWarning("Vapoursynth install location entry not found -> not installed!"); } //Make sure that 'vapoursynth.dll' and 'vspipe.exe' are available @@ -217,11 +196,7 @@ bool VapourSynthCheckThread::detectVapourSynthPath3(QString &path) 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); - } + vapoursynthComplete = x264_is_executable(m_vpsExePath->fileName()); } if(!vapoursynthComplete) { diff --git a/src/version.h b/src/version.h index 7044eba..f6eef85 100644 --- a/src/version.h +++ b/src/version.h @@ -22,7 +22,7 @@ #define VER_X264_MAJOR 2 #define VER_X264_MINOR 2 #define VER_X264_PATCH 4 -#define VER_X264_BUILD 596 +#define VER_X264_BUILD 606 #define VER_X264_MINIMUM_REV 2363 #define VER_X264_CURRENT_API 140 diff --git a/src/win_help.cpp b/src/win_help.cpp index af64f58..9d2ed0b 100644 --- a/src/win_help.cpp +++ b/src/win_help.cpp @@ -96,7 +96,7 @@ void HelpDialog::closeEvent(QCloseEvent *e) if(m_process->state() != QProcess::NotRunning) { e->ignore(); - MessageBeep(MB_ICONWARNING); + x264_beep(x264_beep_warning); return; } diff --git a/src/win_main.cpp b/src/win_main.cpp index cbc0ed3..73cfab6 100644 --- a/src/win_main.cpp +++ b/src/win_main.cpp @@ -49,7 +49,7 @@ #include #include -#include +#include const char *home_url = "http://muldersoft.com/"; const char *update_url = "http://code.google.com/p/mulder/downloads/list"; @@ -59,7 +59,7 @@ const char *tpl_last = ""; #define SET_TEXT_COLOR(WIDGET,COLOR) { QPalette _palette = WIDGET->palette(); _palette.setColor(QPalette::WindowText, (COLOR)); _palette.setColor(QPalette::Text, (COLOR)); WIDGET->setPalette(_palette); } #define LINK(URL) "" URL "" -static int exceptionFilter(_EXCEPTION_RECORD *dst, _EXCEPTION_POINTERS *src) { memcpy(dst, src->ExceptionRecord, sizeof(_EXCEPTION_RECORD)); return EXCEPTION_EXECUTE_HANDLER; } +//static int exceptionFilter(_EXCEPTION_RECORD *dst, _EXCEPTION_POINTERS *src) { memcpy(dst, src->ExceptionRecord, sizeof(_EXCEPTION_RECORD)); return EXCEPTION_EXECUTE_HANDLER; } /////////////////////////////////////////////////////////////////////////////// // Constructor & Destructor @@ -104,7 +104,7 @@ MainWindow::MainWindow(const x264_cpu_t *const cpuFeatures) //Create IPC thread object m_ipcThread = new IPCThread(); - connect(m_ipcThread, SIGNAL(instanceCreated(DWORD)), this, SLOT(instanceCreated(DWORD)), Qt::QueuedConnection); + connect(m_ipcThread, SIGNAL(instanceCreated(unsigned int)), this, SLOT(instanceCreated(unsigned int)), Qt::QueuedConnection); //Freeze minimum size setMinimumSize(size()); @@ -467,7 +467,7 @@ void MainWindow::showAbout(void) forever { - MessageBeep(MB_ICONINFORMATION); + x264_beep(x264_beep_info); switch(aboutBox.exec()) { case 0: @@ -484,7 +484,7 @@ void MainWindow::showAbout(void) x264Box.setWindowTitle(tr("About x264")); x264Box.setText(text2.replace("-", "−")); x264Box.setEscapeButton(x264Box.addButton(tr("Close"), QMessageBox::NoRole)); - MessageBeep(MB_ICONINFORMATION); + x264_beep(x264_beep_info); x264Box.exec(); } break; @@ -502,7 +502,7 @@ void MainWindow::showAbout(void) x264Box.setWindowTitle(tr("About Avisynth")); x264Box.setText(text2.replace("-", "−")); x264Box.setEscapeButton(x264Box.addButton(tr("Close"), QMessageBox::NoRole)); - MessageBeep(MB_ICONINFORMATION); + x264_beep(x264_beep_info); x264Box.exec(); } break; @@ -520,7 +520,7 @@ void MainWindow::showAbout(void) x264Box.setWindowTitle(tr("About VapourSynth")); x264Box.setText(text2.replace("-", "−")); x264Box.setEscapeButton(x264Box.addButton(tr("Close"), QMessageBox::NoRole)); - MessageBeep(MB_ICONINFORMATION); + x264_beep(x264_beep_info); x264Box.exec(); } break; @@ -663,7 +663,7 @@ void MainWindow::shutdownComputer(void) QApplication::processEvents(QEventLoop::ExcludeUserInputEvents); QApplication::setOverrideCursor(Qt::WaitCursor); - PlaySound(MAKEINTRESOURCE(IDR_WAVE1), GetModuleHandle(NULL), SND_RESOURCE | SND_SYNC); + x264_play_sound(IDR_WAVE1, false); QApplication::restoreOverrideCursor(); QTimer timer; @@ -686,7 +686,7 @@ void MainWindow::shutdownComputer(void) progressDialog.setLabelText(text.arg(iTimeout-i)); if(iTimeout-i == 3) progressDialog.setCancelButton(NULL); QApplication::processEvents(); - PlaySound(MAKEINTRESOURCE((i < iTimeout) ? IDR_WAVE2 : IDR_WAVE3), GetModuleHandle(NULL), SND_RESOURCE | SND_SYNC); + x264_play_sound(((i < iTimeout) ? IDR_WAVE2 : IDR_WAVE3), false); } qWarning("Shutting down !!!"); @@ -732,13 +732,7 @@ void MainWindow::init(void) QFile *file = new QFile(QString("%1/toolset/%2").arg(m_appDir, current)); if(file->open(QIODevice::ReadOnly)) { - bool binaryTypeOkay = false; - DWORD binaryType; - if(GetBinaryType(QWCHAR(QDir::toNativeSeparators(file->fileName())), &binaryType)) - { - binaryTypeOkay = (binaryType == SCS_32BIT_BINARY || binaryType == SCS_64BIT_BINARY); - } - if(!binaryTypeOkay) + if(!x264_is_executable(file->fileName())) { QMessageBox::critical(this, tr("Invalid File!"), tr("At least on required tool is not a valid Win32 or Win64 binary:
%1

Please re-install the program in order to fix the problem!
").arg(QDir::toNativeSeparators(QString("%1/toolset/%2").arg(m_appDir, current))).replace("-", "−")); qFatal(QString("Binary is invalid: %1/toolset/%2").arg(m_appDir, current).toLatin1().constData()); @@ -925,7 +919,7 @@ void MainWindow::copyLogToClipboard(bool checked) if(LogFileModel *log = dynamic_cast(logView->model())) { log->copyToClipboard(); - MessageBeep(MB_ICONINFORMATION); + x264_beep(x264_beep_info); } } @@ -944,22 +938,14 @@ void MainWindow::handleDroppedFiles(void) qDebug("Leave from MainWindow::handleDroppedFiles!"); } -void MainWindow::instanceCreated(DWORD pid) +void MainWindow::instanceCreated(unsigned int pid) { qDebug("Notification from other instance (PID=0x%X) received!", pid); - FLASHWINFO flashWinInfo; - memset(&flashWinInfo, 0, sizeof(FLASHWINFO)); - flashWinInfo.cbSize = sizeof(FLASHWINFO); - flashWinInfo.hwnd = this->winId(); - flashWinInfo.dwFlags = FLASHW_ALL; - flashWinInfo.dwTimeout = 125; - flashWinInfo.uCount = 5; - - SwitchToThisWindow(this->winId(), TRUE); - SetForegroundWindow(this->winId()); - qApp->processEvents(); - FlashWindowEx(&flashWinInfo); + x264_blink_window(this, 5, 125); + x264_bring_to_front(this); + qApp->processEvents(QEventLoop::ExcludeUserInputEvents); + x264_blink_window(this, 5, 125); } /////////////////////////////////////////////////////////////////////////////// diff --git a/src/win_main.h b/src/win_main.h index f47e870..dce5105 100644 --- a/src/win_main.h +++ b/src/win_main.h @@ -90,7 +90,7 @@ private slots: void copyLogToClipboard(bool checked); void handleDroppedFiles(void); void init(void); - void instanceCreated(DWORD pid); + void instanceCreated(unsigned int pid); void jobSelected(const QModelIndex & current, const QModelIndex & previous); void jobChangedData(const QModelIndex &top, const QModelIndex &bottom); void jobLogExtended(const QModelIndex & parent, int start, int end); diff --git a/src/win_preferences.cpp b/src/win_preferences.cpp index 3821834..157b8db 100644 --- a/src/win_preferences.cpp +++ b/src/win_preferences.cpp @@ -45,12 +45,7 @@ PreferencesDialog::PreferencesDialog(QWidget *parent, PreferencesModel *preferen setupUi(this); setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint)); setFixedSize(minimumSize()); - - if(WId hWindow = this->winId()) - { - HMENU hMenu = GetSystemMenu(hWindow, 0); - EnableMenuItem(hMenu, SC_CLOSE, MF_BYCOMMAND | MF_GRAYED); - } + x264_enable_close_button(this, false); labelRunNextJob->installEventFilter(this); labelUse10BitEncoding->installEventFilter(this); @@ -86,7 +81,7 @@ void PreferencesDialog::showEvent(QShowEvent *event) UPDATE_CHECKBOX(checkUse10BitEncoding, m_preferences->use10BitEncoding(), true); spinBoxJobCount->setValue(m_preferences->maxRunningJobCount()); - comboBoxPriority->setCurrentIndex(qBound(0, m_preferences->processPriority(), comboBoxPriority->count()-1)); + comboBoxPriority->setCurrentIndex(qBound(0, m_preferences->processPriority() + 2, comboBoxPriority->count()-1)); checkUse64BitAvs2YUV->setEnabled(m_x64); labelUse64BitAvs2YUV->setEnabled(m_x64); @@ -134,7 +129,7 @@ void PreferencesDialog::done(int n) m_preferences->setSaveLogFiles(checkSaveLogFiles->isChecked()); m_preferences->setSaveToSourcePath(checkSaveToSourceFolder->isChecked()); m_preferences->setMaxRunningJobCount(spinBoxJobCount->value()); - m_preferences->setProcessPriority(comboBoxPriority->currentIndex()); + m_preferences->setProcessPriority(comboBoxPriority->currentIndex() - 2); m_preferences->setEnableSounds(checkEnableSounds->isChecked()); m_preferences->setDisableWarnings(checkDisableWarnings->isChecked()); diff --git a/x264_launcher_MSVC2013.vcxproj b/x264_launcher_MSVC2013.vcxproj index 31e9cd1..d5bf083 100644 --- a/x264_launcher_MSVC2013.vcxproj +++ b/x264_launcher_MSVC2013.vcxproj @@ -284,6 +284,7 @@ copy /Y "$(QTDIR)\plugins\imageformats\qgif4.dll" "$(TargetDir)\imageformats" $(SolutionDir)tmp\moc\moc_%(Filename).cpp;%(Outputs) $(SolutionDir)tmp\moc\moc_%(Filename).cpp;%(Outputs) + @@ -325,6 +326,7 @@ copy /Y "$(QTDIR)\plugins\imageformats\qgif4.dll" "$(TargetDir)\imageformats" + diff --git a/x264_launcher_MSVC2013.vcxproj.filters b/x264_launcher_MSVC2013.vcxproj.filters index 33fbd7f..27d436d 100644 --- a/x264_launcher_MSVC2013.vcxproj.filters +++ b/x264_launcher_MSVC2013.vcxproj.filters @@ -57,6 +57,9 @@ Header Files + + Header Files + @@ -149,6 +152,9 @@ Generated Files + + Source Files + diff --git a/z_build.bat b/z_build.bat index fe3cb2f..9504518 100644 --- a/z_build.bat +++ b/z_build.bat @@ -2,9 +2,9 @@ REM /////////////////////////////////////////////////////////////////////////// REM // Set Paths REM /////////////////////////////////////////////////////////////////////////// -set "MSVC_PATH=C:\Program Files\Microsoft Visual Studio 10.0\VC" +set "MSVC_PATH=C:\Program Files\Microsoft Visual Studio 12.0\VC" set "NSIS_PATH=C:\Program Files\NSIS\Unicode" -set "QTVC_PATH=C:\Qt\4.8.4" +set "QTVC_PATH=C:\Qt\4.8.5" set "UPX3_PATH=C:\Program Files\UPX" REM ############################################### @@ -60,9 +60,9 @@ REM /////////////////////////////////////////////////////////////////////////// echo --------------------------------------------------------------------- echo BEGIN BUILD echo --------------------------------------------------------------------- -MSBuild.exe /property:Configuration=release /target:clean "%~dp0\x264_launcher_MSVC2012.sln" +MSBuild.exe /property:Configuration=release /target:clean "%~dp0\x264_launcher_MSVC2013.sln" if not "%ERRORLEVEL%"=="0" goto BuildError -MSBuild.exe /property:Configuration=release /target:rebuild "%~dp0\x264_launcher_MSVC2012.sln" +MSBuild.exe /property:Configuration=release /target:rebuild "%~dp0\x264_launcher_MSVC2013.sln" if not "%ERRORLEVEL%"=="0" goto BuildError REM /////////////////////////////////////////////////////////////////////////// @@ -95,7 +95,7 @@ copy "%~dp0\*.txt" "%PACK_PATH%" REM /////////////////////////////////////////////////////////////////////////// REM // Copy dependencies REM /////////////////////////////////////////////////////////////////////////// -for %%i in (100, 110) do ( +for %%i in (100, 110, 120) do ( if exist "%MSVC_PATH%\redist\x86\Microsoft.VC%%i.CRT\*.dll" ( copy "%MSVC_PATH%\redist\x86\Microsoft.VC%%i.CRT\msvc?%%i.dll" "%PACK_PATH%" )