OSDN Git Service

Reorganized global functions: The file "Global.h" was split into multiple file in...
authorLoRd_MuldeR <mulder2@gmx.de>
Sun, 3 Nov 2013 22:43:21 +0000 (23:43 +0100)
committerLoRd_MuldeR <mulder2@gmx.de>
Sun, 3 Nov 2013 22:43:21 +0000 (23:43 +0100)
17 files changed:
LameXP_VS2013.vcxproj
LameXP_VS2013.vcxproj.filters
etc/Translation/Blank.ts
etc/Translation/LameXP_PL.ts
etc/Translation/LameXP_SV.ts
src/Config.h
src/Global.h
src/Global_EntryPoint.cpp [new file with mode: 0644]
src/Global_IPC.cpp [new file with mode: 0644]
src/Global_Tools.cpp [new file with mode: 0644]
src/Global_Utils.cpp [new file with mode: 0644]
src/Global_Version.cpp [new file with mode: 0644]
src/Global_Win32.cpp [moved from src/Global.cpp with 56% similarity]
src/JobObject.cpp
src/JobObject.h
src/Main.cpp
src/Thread_Initialization.cpp

index 461e5bd..7e3f652 100644 (file)
@@ -327,7 +327,12 @@ del "$(TargetDir)imageformats\q???d4.dll"
     <ClCompile Include="src\Filter_Resample.cpp" />
     <ClCompile Include="src\Filter_ToneAdjust.cpp" />
     <ClCompile Include="src\Genres.cpp" />
-    <ClCompile Include="src\Global.cpp" />
+    <ClCompile Include="src\Global_EntryPoint.cpp" />
+    <ClCompile Include="src\Global_IPC.cpp" />
+    <ClCompile Include="src\Global_Utils.cpp" />
+    <ClCompile Include="src\Global_Version.cpp" />
+    <ClCompile Include="src\Global_Win32.cpp" />
+    <ClCompile Include="src\Global_Tools.cpp" />
     <ClCompile Include="src\JobObject.cpp" />
     <ClCompile Include="src\LockedFile.cpp" />
     <ClCompile Include="src\Main.cpp" />
index 927a1fe..863d7a9 100644 (file)
@@ -1,9 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup>
-    <ClCompile Include="src\Global.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
     <ClCompile Include="src\Main.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
     <ClCompile Include="tmp\QRC_Tools_Encd_D.cpp">
       <Filter>Generated Files\QRC</Filter>
     </ClCompile>
+    <ClCompile Include="src\Global_Tools.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="src\Global_Win32.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="src\Global_IPC.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="src\Global_EntryPoint.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="src\Global_Version.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="src\Global_Utils.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="src\Config.h">
index 7e7c3c0..a4162ab 100644 (file)
 <context>
     <name>QApplication</name>
     <message>
-        <location filename="../../src/Global.cpp" line="1415"/>
+        <location filename="../../src/Global_Win32.cpp" line="994"/>
         <source>Executable &apos;%1&apos; doesn&apos;t support Windows compatibility mode.</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../src/Global.cpp" line="1357"/>
+        <location filename="../../src/Global_Win32.cpp" line="936"/>
         <source>Executable &apos;%1&apos; requires Qt v%2, but found Qt v%3.</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../src/Global.cpp" line="1362"/>
+        <location filename="../../src/Global_Win32.cpp" line="941"/>
         <source>Executable &apos;%1&apos; was built for Qt &apos;%2&apos;, but found Qt &apos;%3&apos;.</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../src/Global.cpp" line="1374"/>
+        <location filename="../../src/Global_Win32.cpp" line="953"/>
         <source>Executable &apos;%1&apos; requires Windows XP or later.</source>
         <translation type="unfinished"></translation>
     </message>
index 86e4588..05a90c6 100644 (file)
 <context>
     <name>QApplication</name>
     <message>
-        <location filename="../../src/Global.cpp" line="1415"/>
+        <location filename="../../src/Global_Win32.cpp" line="994"/>
         <source>Executable &apos;%1&apos; doesn&apos;t support Windows compatibility mode.</source>
         <translation type="unfinished">Plik wykonywalny &apos;%1&apos; nie działa w trybie kompatybilności z Windows.</translation>
     </message>
     <message>
-        <location filename="../../src/Global.cpp" line="1357"/>
+        <location filename="../../src/Global_Win32.cpp" line="936"/>
         <source>Executable &apos;%1&apos; requires Qt v%2, but found Qt v%3.</source>
         <translation type="unfinished">Plik wykonywalny &apos;%1&apos; wymaga Qt v%2, znaleziono jednak Qt v%3.</translation>
     </message>
     <message>
-        <location filename="../../src/Global.cpp" line="1362"/>
+        <location filename="../../src/Global_Win32.cpp" line="941"/>
         <source>Executable &apos;%1&apos; was built for Qt &apos;%2&apos;, but found Qt &apos;%3&apos;.</source>
         <translation type="unfinished">Plik wykonywalny &quot;%1&quot; został skompilowany dla Qt &quot;%2&quot;, znaleziono &quot;%3&quot;.</translation>
     </message>
     <message>
-        <location filename="../../src/Global.cpp" line="1374"/>
+        <location filename="../../src/Global_Win32.cpp" line="953"/>
         <source>Executable &apos;%1&apos; requires Windows XP or later.</source>
         <translation type="unfinished"></translation>
     </message>
index d64a69a..82346cd 100644 (file)
 <context>
     <name>QApplication</name>
     <message>
-        <location filename="../../src/Global.cpp" line="1415"/>
+        <location filename="../../src/Global_Win32.cpp" line="994"/>
         <source>Executable &apos;%1&apos; doesn&apos;t support Windows compatibility mode.</source>
         <translation>EXE-filen &apos;%1&apos; stöder inte Windows kompatibilitetsläge.</translation>
     </message>
     <message>
-        <location filename="../../src/Global.cpp" line="1357"/>
+        <location filename="../../src/Global_Win32.cpp" line="936"/>
         <source>Executable &apos;%1&apos; requires Qt v%2, but found Qt v%3.</source>
         <translation>EXE-filen &apos;%1&apos; kräver Qt v%2, du har Qt v%3.</translation>
     </message>
     <message>
-        <location filename="../../src/Global.cpp" line="1362"/>
+        <location filename="../../src/Global_Win32.cpp" line="941"/>
         <source>Executable &apos;%1&apos; was built for Qt &apos;%2&apos;, but found Qt &apos;%3&apos;.</source>
         <translation>EXE-filen &apos;%1&apos; är byggd för Qt &apos;%2&apos;, du har Qt &apos;%3&apos;.</translation>
     </message>
     <message>
-        <location filename="../../src/Global.cpp" line="1374"/>
+        <location filename="../../src/Global_Win32.cpp" line="953"/>
         <source>Executable &apos;%1&apos; requires Windows XP or later.</source>
         <translation type="unfinished"></translation>
     </message>
index 4af7be9..108cf6c 100644 (file)
@@ -35,7 +35,7 @@
 #define VER_LAMEXP_MINOR_LO                                    9
 #define VER_LAMEXP_TYPE                                                Alpha
 #define VER_LAMEXP_PATCH                                       7
-#define VER_LAMEXP_BUILD                                       1450
+#define VER_LAMEXP_BUILD                                       1454
 #define VER_LAMEXP_CONFG                                       1348
 
 ///////////////////////////////////////////////////////////////////////////////
index 018b2a6..bebdf30 100644 (file)
 
 #pragma once
 
-//Target version
-#include "Targetver.h"
-
-//inlcude C standard library
 #define _CRT_RAND_S
-#include <stdio.h>
-#include <tchar.h>
-
-//Visual Leaks Detector
-#include <vld.h>
+#include <cstdlib>
 
-//Declarations
+//Forward declarations
 class QString;
 class QStringList;
 class QDate;
@@ -44,7 +36,15 @@ class QProcess;
 class LockedFile;
 enum QtMsgType;
 
-//Types definitions
+//Variables
+extern const char* LAMEXP_DEFAULT_LANGID;
+extern const char* LAMEXP_DEFAULT_TRANSLATION;
+
+///////////////////////////////////////////////////////////////////////////////
+// TYPE DEFINITIONS
+///////////////////////////////////////////////////////////////////////////////
+
+//CPU features
 typedef struct
 {
        int family;
@@ -125,119 +125,123 @@ typedef enum
 }
 lamexp_network_t;
 
-//LameXP version info
-unsigned int lamexp_version_major(void);
-unsigned int lamexp_version_minor(void);
-unsigned int lamexp_version_build(void);
-unsigned int lamexp_version_confg(void);
-const QDate &lamexp_version_date(void);
-const char *lamexp_version_time(void);
-const char *lamexp_version_release(void);
-bool lamexp_version_demo(void);
-const char *lamexp_version_compiler(void);
-const char *lamexp_version_arch(void);
-QDate lamexp_version_expires(void);
-unsigned int lamexp_toolver_neroaac(void);
-unsigned int lamexp_toolver_fhgaacenc(void);
-unsigned int lamexp_toolver_qaacenc(void);
-unsigned int lamexp_toolver_coreaudio(void);
-const char *lamexp_website_url(void);
-const char *lamexp_mulders_url(void);
-const char *lamexp_support_url(void);
-const lamexp_os_version_t &lamexp_get_os_version(void);
-bool lamexp_detect_wine(void);
+///////////////////////////////////////////////////////////////////////////////
+// GLOBAL FUNCTIONS
+///////////////////////////////////////////////////////////////////////////////
 
-//Public functions
-void lamexp_init_console(const QStringList &argv);
-bool lamexp_init_qt(int argc, char* argv[]);
-int lamexp_init_ipc(void);
-void lamexp_invalid_param_handler(const wchar_t*, const wchar_t*, const wchar_t*, unsigned int, uintptr_t);
-void lamexp_message_handler(QtMsgType type, const char *msg);
-void lamexp_register_tool(const QString &toolName, LockedFile *file, unsigned int version = 0, const QString *tag = NULL);
-bool lamexp_check_tool(const QString &toolName);
-const QString lamexp_lookup_tool(const QString &toolName);
-unsigned int lamexp_tool_version(const QString &toolName, QString *tag = NULL);
-void lamexp_finalization(void);
-QString lamexp_rand_str(const bool bLong = false);
-const QString &lamexp_temp_folder2(void);
-void lamexp_ipc_read(unsigned int *command, char* message, size_t buffSize);
-void lamexp_ipc_send(unsigned int command, const char* message);
-lamexp_cpu_t lamexp_detect_cpu_features(const QStringList &argv);
-bool lamexp_portable_mode(void);
-bool lamexp_shutdown_computer(const QString &message, const unsigned long timeout = 30, const bool forceShutdown = true, const bool hibernate = false);
-bool lamexp_is_hibernation_supported(void);
 QIcon lamexp_app_icon(const QDate *date = NULL, const QTime *time = NULL);
+bool lamexp_append_sysmenu(const QWidget *win, const unsigned int identifier, const QString &text);
 const QStringList &lamexp_arguments(void);
-
-//Translation support
-QStringList lamexp_query_translations(void);
-bool lamexp_translation_register(const QString &langId, const QString &qmFile, const QString &langName, unsigned int &systemId, unsigned int &country);
-QString lamexp_translation_name(const QString &language);
-unsigned int lamexp_translation_sysid(const QString &langId);
-unsigned int lamexp_translation_country(const QString &langId);
-bool lamexp_install_translator_from_file(const QString &qmFile);
-bool lamexp_install_translator(const QString &language);
 QStringList lamexp_available_codepages(bool noAliases = true);
-extern const char* LAMEXP_DEFAULT_LANGID;
-extern const char* LAMEXP_DEFAULT_TRANSLATION;
-
-//Auxiliary functions
-bool lamexp_clean_folder(const QString &folderPath);
-const QString lamexp_version2string(const QString &pattern, unsigned int version, const QString &defaultText, const QString *tag = NULL);
-const QString &lamexp_known_folder(lamexp_known_folder_t folder_id);
-unsigned __int64 lamexp_free_diskspace(const QString &path, bool *ok = NULL);
-bool lamexp_remove_file(const QString &filename);
-bool lamexp_themes_enabled(void);
+bool lamexp_beep(int beepType);
 void lamexp_blink_window(QWidget *poWindow, unsigned int count = 10, unsigned int delay = 150);
+bool lamexp_bring_process_to_front(const unsigned long pid);
+bool lamexp_bring_to_front(const QWidget *win);
+bool lamexp_broadcast(int eventType, bool onlyToVisible);
+bool lamexp_change_process_priority(const int priority);
+bool lamexp_change_process_priority(void *hProcess, const int priority);
+bool lamexp_change_process_priority(const QProcess *proc, const int priority);
+bool lamexp_check_escape_state(void);
+bool lamexp_check_sysmenu_msg(void *message, const unsigned int identifier);
+bool lamexp_check_tool(const QString &toolName);
 const QString lamexp_clean_filename(const QString &str);
 const QString lamexp_clean_filepath(const QString &str);
-void lamexp_seed_rand(void);
-unsigned int lamexp_rand(void);
+void lamexp_clean_all_tools(void);
+void lamexp_clean_all_translations(void);
+bool lamexp_clean_folder(const QString &folderPath);
 QDate lamexp_current_date_safe(void);
-void lamexp_sleep(const unsigned int delay);
-bool lamexp_beep(int beepType);
-bool lamexp_play_sound(const unsigned short uiSoundIdx, const bool bAsync, const wchar_t *alias = NULL);
-bool lamexp_play_sound_file(const QString &library, const unsigned short uiSoundIdx, const bool bAsync);
+unsigned __int64 lamexp_current_file_time(void);
+void lamexp_dbg_dbg_output_string(const char* format, ...);
+unsigned long lamexp_dbg_private_bytes(void);
+lamexp_cpu_t lamexp_detect_cpu_features(const QStringList &argv);
+bool lamexp_detect_wine(void);
+bool lamexp_enable_close_button(const QWidget *win, const bool bEnable = true);
 bool lamexp_exec_shell(const QWidget *win, const QString &url, const bool explore = false);
 bool lamexp_exec_shell(const QWidget *win, const QString &url, const QString &parameters, const QString &directory, const bool explore = false);
-__int64 lamexp_perfcounter_frequ(void);
-__int64 lamexp_perfcounter_value(void);
-bool lamexp_append_sysmenu(const QWidget *win, const unsigned int identifier, const QString &text);
-bool lamexp_update_sysmenu(const QWidget *win, const unsigned int identifier, const QString &text);
-bool lamexp_check_sysmenu_msg(void *message, const unsigned int identifier);
-bool lamexp_enable_close_button(const QWidget *win, const bool bEnable = true);
-bool lamexp_check_escape_state(void);
-bool lamexp_change_process_priority(const int priority);
-bool lamexp_change_process_priority(const QProcess *proc, const int priority);
-bool lamexp_change_process_priority(void *hProcess, const int priority);
-bool lamexp_bring_to_front(const QWidget *win);
-bool lamexp_bring_process_to_front(const unsigned long pid);
-int lamexp_network_status(void);
-unsigned long lamexp_process_id(const QProcess *proc);
-unsigned __int64 lamexp_current_file_time(void);
+void lamexp_fatal_exit(const wchar_t* exitMessage, const wchar_t* errorBoxMessage = NULL);
+void lamexp_finalization(void);
+unsigned __int64 lamexp_free_diskspace(const QString &path, bool *ok = NULL);
+const lamexp_os_version_t &lamexp_get_os_version(void);
+void lamexp_init_console(const QStringList &argv);
+void lamexp_init_error_handlers(void);
+int lamexp_init_ipc(void);
+void lamexp_init_process(QProcess &process, const QString &wokringDir);
+bool lamexp_init_qt(int argc, char* argv[]);
+bool lamexp_install_translator(const QString &language);
+bool lamexp_install_translator_from_file(const QString &qmFile);
+void lamexp_invalid_param_handler(const wchar_t*, const wchar_t*, const wchar_t*, unsigned int, uintptr_t);
+void lamexp_ipc_exit(void);
+void lamexp_ipc_read(unsigned int *command, char* message, size_t buffSize);
+void lamexp_ipc_send(unsigned int command, const char* message);
+bool lamexp_is_hibernation_supported(void);
+const QString &lamexp_known_folder(lamexp_known_folder_t folder_id);
+const QString lamexp_lookup_tool(const QString &toolName);
+void lamexp_message_handler(QtMsgType type, const char *msg);
+const char *lamexp_mulders_url(void);
 void lamexp_natural_string_sort(QStringList &list, const bool bIgnoreCase);
+int lamexp_network_status(void);
 bool lamexp_open_media_file(const QString &mediaFilePath);
 QString lamexp_path_to_short(const QString &longPath);
-void lamexp_init_process(QProcess &process, const QString &wokringDir);
-void lamexp_fatal_exit(const wchar_t* exitMessage, const wchar_t* errorBoxMessage = NULL);
-
+__int64 lamexp_perfcounter_frequ(void);
+__int64 lamexp_perfcounter_value(void);
+bool lamexp_play_sound(const unsigned short uiSoundIdx, const bool bAsync, const wchar_t *alias = NULL);
+bool lamexp_play_sound_file(const QString &library, const unsigned short uiSoundIdx, const bool bAsync);
+bool lamexp_portable_mode(void);
+unsigned long lamexp_process_id(const QProcess *proc);
+QStringList lamexp_query_translations(void);
+unsigned int lamexp_rand(void);
+QString lamexp_rand_str(const bool bLong = false);
+void lamexp_register_tool(const QString &toolName, LockedFile *file, unsigned int version = 0, const QString *tag = NULL);
+bool lamexp_remove_file(const QString &filename);
+void lamexp_seed_rand(void);
+bool lamexp_shutdown_computer(const QString &message, const unsigned long timeout = 30, const bool forceShutdown = true, const bool hibernate = false);
+void lamexp_sleep(const unsigned int delay);
+const char *lamexp_support_url(void);
+const QString &lamexp_temp_folder2(void);
+void lamexp_temp_folder_clear(void);
+bool lamexp_themes_enabled(void);
+unsigned int lamexp_tool_version(const QString &toolName, QString *tag = NULL);
+unsigned int lamexp_toolver_coreaudio(void);
+unsigned int lamexp_toolver_fhgaacenc(void);
+unsigned int lamexp_toolver_neroaac(void);
+unsigned int lamexp_toolver_qaacenc(void);
+unsigned int lamexp_translation_country(const QString &langId);
+bool lamexp_translation_init(void);
+QString lamexp_translation_name(const QString &language);
+bool lamexp_translation_register(const QString &langId, const QString &qmFile, const QString &langName, unsigned int &systemId, unsigned int &country);
+unsigned int lamexp_translation_sysid(const QString &langId);
+bool lamexp_update_sysmenu(const QWidget *win, const unsigned int identifier, const QString &text);
+const QString lamexp_version2string(const QString &pattern, unsigned int version, const QString &defaultText, const QString *tag = NULL);
+const char *lamexp_version_arch(void);
+unsigned int lamexp_version_build(void);
+const char *lamexp_version_compiler(void);
+unsigned int lamexp_version_confg(void);
+const QDate &lamexp_version_date(void);
+bool lamexp_version_demo(void);
+QDate lamexp_version_expires(void);
+unsigned int lamexp_version_major(void);
+unsigned int lamexp_version_minor(void);
+const char *lamexp_version_release(void);
+const char *lamexp_version_time(void);
+const char *lamexp_website_url(void);
 
-//Debug-only functions
-unsigned long lamexp_dbg_private_bytes(void);
+///////////////////////////////////////////////////////////////////////////////
+// HELPER MACROS
+///////////////////////////////////////////////////////////////////////////////
 
-//Helper macros
+#define LAMEXP_BOOL2STR(X) ((X) ? "1" : "0")
+#define LAMEXP_COMPILER_WARNING(TXT) __pragma(message(__FILE__ "(" LAMEXP_MAKE_STRING(__LINE__) ") : warning: " TXT))
+#define LAMEXP_CLOSE(HANDLE) do { if(HANDLE != NULL && HANDLE != INVALID_HANDLE_VALUE) { CloseHandle(HANDLE); HANDLE = NULL; } } while(0)
 #define LAMEXP_DELETE(PTR) do { if(PTR) { delete PTR; PTR = NULL; } } while(0)
 #define LAMEXP_DELETE_ARRAY(PTR) do { if(PTR) { delete [] PTR; PTR = NULL; } } while(0)
-#define LAMEXP_SAFE_FREE(PTR) do { if(PTR) { free((void*) PTR); PTR = NULL; } } while(0)
-#define LAMEXP_CLOSE(HANDLE) do { if(HANDLE != NULL && HANDLE != INVALID_HANDLE_VALUE) { CloseHandle(HANDLE); HANDLE = NULL; } } while(0)
-#define QWCHAR(STR) (reinterpret_cast<const wchar_t*>((STR).utf16()))
-#define WCHAR2QSTR(STR) (QString::fromUtf16(reinterpret_cast<const unsigned short*>((STR))))
-#define QUTF8(STR) ((STR).toUtf8().constData())
-#define LAMEXP_BOOL2STR(X) ((X) ? "1" : "0")
 #define LAMEXP_MAKE_STRING_EX(X) #X
 #define LAMEXP_MAKE_STRING(X) LAMEXP_MAKE_STRING_EX(X)
-#define LAMEXP_COMPILER_WARNING(TXT) __pragma(message(__FILE__ "(" LAMEXP_MAKE_STRING(__LINE__) ") : warning: " TXT))
+#define LAMEXP_SAFE_FREE(PTR) do { if(PTR) { free((void*) PTR); PTR = NULL; } } while(0)
+#define LAMEXP_ZERO_MEMORY(X) memset(&(X), 0, sizeof((X)))
 #define NOBR(STR) (QString("<nobr>%1</nobr>").arg((STR)).replace("-", "&minus;"))
+#define QUTF8(STR) ((STR).toUtf8().constData())
+#define QWCHAR(STR) (reinterpret_cast<const wchar_t*>((STR).utf16()))
+#define WCHAR2QSTR(STR) (QString::fromUtf16(reinterpret_cast<const unsigned short*>((STR))))
 
 //Check for debug build
 #if defined(_DEBUG) && defined(QT_DEBUG) && !defined(NDEBUG) && !defined(QT_NO_DEBUG)
@@ -248,30 +252,6 @@ unsigned long lamexp_dbg_private_bytes(void);
        #error Inconsistent debug defines detected!
 #endif
 
-//Memory check
-#if LAMEXP_DEBUG
-       #define LAMEXP_MEMORY_CHECK(FUNC, RETV,  ...) do \
-       { \
-               SIZE_T _privateBytesBefore = lamexp_dbg_private_bytes(); \
-               RETV = FUNC(__VA_ARGS__); \
-               SIZE_T _privateBytesLeak = (lamexp_dbg_private_bytes() - _privateBytesBefore) / 1024; \
-               if(_privateBytesLeak > 0) { \
-                       char _buffer[128]; \
-                       _snprintf_s(_buffer, 128, _TRUNCATE, "Memory leak: Lost %u KiloBytes of PrivateUsage memory.\n", _privateBytesLeak); \
-                       OutputDebugStringA("----------\n"); \
-                       OutputDebugStringA(_buffer); \
-                       OutputDebugStringA("----------\n"); \
-               } \
-       } \
-       while(0)
-#else
-       #define LAMEXP_MEMORY_CHECK(FUNC, RETV,  ...) do \
-       { \
-               RETV = __noop(__VA_ARGS__); \
-       } \
-       while(0)
-#endif
-
 //Check for CPU-compatibility options
 #if !defined(_M_X64) && defined(_MSC_VER) && defined(_M_IX86_FP)
        #if (_M_IX86_FP != 0)
@@ -292,3 +272,23 @@ while(0)
        throw std::runtime_error(_error_msg); \
 } \
 while(0)
+
+//Memory check
+#if LAMEXP_DEBUG
+       #define LAMEXP_MEMORY_CHECK(FUNC, RETV,  ...) do \
+       { \
+               size_t _privateBytesBefore = lamexp_dbg_private_bytes(); \
+               RETV = FUNC(__VA_ARGS__); \
+               size_t _privateBytesLeak = (lamexp_dbg_private_bytes() - _privateBytesBefore) / 1024; \
+               if(_privateBytesLeak > 0) { \
+                       lamexp_dbg_dbg_output_string("\nMemory leak: Lost %u KiloBytes of PrivateUsage memory!\n\n", _privateBytesLeak); \
+               } \
+       } \
+       while(0)
+#else
+       #define LAMEXP_MEMORY_CHECK(FUNC, RETV,  ...) do \
+       { \
+               RETV = __noop(__VA_ARGS__); \
+       } \
+       while(0)
+#endif
diff --git a/src/Global_EntryPoint.cpp b/src/Global_EntryPoint.cpp
new file mode 100644 (file)
index 0000000..2990523
--- /dev/null
@@ -0,0 +1,79 @@
+///////////////////////////////////////////////////////////////////////////////
+// LameXP - Audio Encoder Front-End
+// Copyright (C) 2004-2013 LoRd_MuldeR <MuldeR2@GMX.de>
+//
+// 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, but always including the *additional*
+// restrictions defined in the "License.txt" file.
+//
+// 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 "Global.h"
+
+///////////////////////////////////////////////////////////////////////////////
+// GLOBAL FUNCTIONS
+///////////////////////////////////////////////////////////////////////////////
+
+static size_t lamexp_entry_check(void);
+static size_t g_lamexp_entry_check_result = lamexp_entry_check();
+static size_t g_lamexp_entry_check_flag = 0x789E09B2;
+
+/*
+ * Entry point checks
+ */
+static size_t lamexp_entry_check(void)
+{
+       volatile size_t retVal = 0xA199B5AF;
+       if(g_lamexp_entry_check_flag != 0x8761F64D)
+       {
+               lamexp_fatal_exit(L"Application initialization has failed, take care!");
+       }
+       return retVal;
+}
+
+/*
+ * Application entry point (runs before static initializers)
+ */
+extern "C"
+{
+       int WinMainCRTStartup(void);
+
+       void _lamexp_global_init_win32(void);
+       void _lamexp_global_init_versn(void);
+       void _lamexp_global_init_tools(void);
+       void _lamexp_global_init_ipcom(void);
+       void _lamexp_global_init_utils(void);
+
+       int lamexp_entry_point(void)
+       {
+               if(g_lamexp_entry_check_flag != 0x789E09B2)
+               {
+                       lamexp_fatal_exit(L"Application initialization has failed, take care!");
+               }
+
+               //Call global initialization functions
+               _lamexp_global_init_win32();
+               _lamexp_global_init_versn();
+               _lamexp_global_init_tools();
+               _lamexp_global_init_ipcom();
+               _lamexp_global_init_utils();
+
+               //Make sure we will pass the check
+               g_lamexp_entry_check_flag = (~g_lamexp_entry_check_flag);
+
+               //Now initialize the C Runtime library!
+               return WinMainCRTStartup();
+       }
+}
diff --git a/src/Global_IPC.cpp b/src/Global_IPC.cpp
new file mode 100644 (file)
index 0000000..5a5737d
--- /dev/null
@@ -0,0 +1,278 @@
+///////////////////////////////////////////////////////////////////////////////
+// LameXP - Audio Encoder Front-End
+// Copyright (C) 2004-2013 LoRd_MuldeR <MuldeR2@GMX.de>
+//
+// 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, but always including the *additional*
+// restrictions defined in the "License.txt" file.
+//
+// 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 "Global.h"
+
+//Qt includes
+#include <QSharedMemory>
+#include <QSystemSemaphore>
+#include <QWriteLocker>
+
+///////////////////////////////////////////////////////////////////////////////
+// TYPES
+///////////////////////////////////////////////////////////////////////////////
+
+static const size_t g_lamexp_ipc_slots = 128;
+
+typedef struct
+{
+       unsigned int command;
+       unsigned int reserved_1;
+       unsigned int reserved_2;
+       char parameter[4096];
+}
+lamexp_ipc_data_t;
+
+typedef struct
+{
+       unsigned int pos_write;
+       unsigned int pos_read;
+       lamexp_ipc_data_t data[g_lamexp_ipc_slots];
+}
+lamexp_ipc_t;
+
+///////////////////////////////////////////////////////////////////////////////
+// GLOBAL VARS
+///////////////////////////////////////////////////////////////////////////////
+
+//Shared memory
+static const struct
+{
+       char *sharedmem;
+       char *semaphore_read;
+       char *semaphore_read_mutex;
+       char *semaphore_write;
+       char *semaphore_write_mutex;
+}
+g_lamexp_ipc_uuid =
+{
+       "{21A68A42-6923-43bb-9CF6-64BF151942EE}",
+       "{7A605549-F58C-4d78-B4E5-06EFC34F405B}",
+       "{60AA8D04-F6B8-497d-81EB-0F600F4A65B5}",
+       "{726061D5-1615-4B82-871C-75FD93458E46}",
+       "{1A616023-AA6A-4519-8AF3-F7736E899977}"
+};
+static struct
+{
+       QSharedMemory *sharedmem;
+       QSystemSemaphore *semaphore_read;
+       QSystemSemaphore *semaphore_read_mutex;
+       QSystemSemaphore *semaphore_write;
+       QSystemSemaphore *semaphore_write_mutex;
+       QReadWriteLock lock;
+}
+g_lamexp_ipc_ptr;
+
+///////////////////////////////////////////////////////////////////////////////
+// GLOBAL FUNCTIONS
+///////////////////////////////////////////////////////////////////////////////
+
+/*
+ * Initialize IPC
+ */
+int lamexp_init_ipc(void)
+{
+       QWriteLocker writeLock(&g_lamexp_ipc_ptr.lock);
+       
+       if(g_lamexp_ipc_ptr.sharedmem && g_lamexp_ipc_ptr.semaphore_read && g_lamexp_ipc_ptr.semaphore_write && g_lamexp_ipc_ptr.semaphore_read_mutex && g_lamexp_ipc_ptr.semaphore_write_mutex)
+       {
+               return 0;
+       }
+
+       g_lamexp_ipc_ptr.semaphore_read = new QSystemSemaphore(QString(g_lamexp_ipc_uuid.semaphore_read), 0);
+       g_lamexp_ipc_ptr.semaphore_write = new QSystemSemaphore(QString(g_lamexp_ipc_uuid.semaphore_write), 0);
+       g_lamexp_ipc_ptr.semaphore_read_mutex = new QSystemSemaphore(QString(g_lamexp_ipc_uuid.semaphore_read_mutex), 0);
+       g_lamexp_ipc_ptr.semaphore_write_mutex = new QSystemSemaphore(QString(g_lamexp_ipc_uuid.semaphore_write_mutex), 0);
+
+       if(g_lamexp_ipc_ptr.semaphore_read->error() != QSystemSemaphore::NoError)
+       {
+               QString errorMessage = g_lamexp_ipc_ptr.semaphore_read->errorString();
+               LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_read);
+               LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_write);
+               LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_read_mutex);
+               LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_write_mutex);
+               qFatal("Failed to create system smaphore: %s", QUTF8(errorMessage));
+               return -1;
+       }
+       if(g_lamexp_ipc_ptr.semaphore_write->error() != QSystemSemaphore::NoError)
+       {
+               QString errorMessage = g_lamexp_ipc_ptr.semaphore_write->errorString();
+               LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_read);
+               LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_write);
+               LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_read_mutex);
+               LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_write_mutex);
+               qFatal("Failed to create system smaphore: %s", QUTF8(errorMessage));
+               return -1;
+       }
+       if(g_lamexp_ipc_ptr.semaphore_read_mutex->error() != QSystemSemaphore::NoError)
+       {
+               QString errorMessage = g_lamexp_ipc_ptr.semaphore_read_mutex->errorString();
+               LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_read);
+               LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_write);
+               LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_read_mutex);
+               LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_write_mutex);
+               qFatal("Failed to create system smaphore: %s", QUTF8(errorMessage));
+               return -1;
+       }
+       if(g_lamexp_ipc_ptr.semaphore_write_mutex->error() != QSystemSemaphore::NoError)
+       {
+               QString errorMessage = g_lamexp_ipc_ptr.semaphore_write_mutex->errorString();
+               LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_read);
+               LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_write);
+               LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_read_mutex);
+               LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_write_mutex);
+               qFatal("Failed to create system smaphore: %s", QUTF8(errorMessage));
+               return -1;
+       }
+
+       g_lamexp_ipc_ptr.sharedmem = new QSharedMemory(QString(g_lamexp_ipc_uuid.sharedmem), NULL);
+       
+       if(!g_lamexp_ipc_ptr.sharedmem->create(sizeof(lamexp_ipc_t)))
+       {
+               if(g_lamexp_ipc_ptr.sharedmem->error() == QSharedMemory::AlreadyExists)
+               {
+                       g_lamexp_ipc_ptr.sharedmem->attach();
+                       if(g_lamexp_ipc_ptr.sharedmem->error() == QSharedMemory::NoError)
+                       {
+                               return 1;
+                       }
+                       else
+                       {
+                               QString errorMessage = g_lamexp_ipc_ptr.sharedmem->errorString();
+                               LAMEXP_DELETE(g_lamexp_ipc_ptr.sharedmem);
+                               qFatal("Failed to attach to shared memory: %s", QUTF8(errorMessage));
+                               return -1;
+                       }
+               }
+               else
+               {
+                       QString errorMessage = g_lamexp_ipc_ptr.sharedmem->errorString();
+                       LAMEXP_DELETE(g_lamexp_ipc_ptr.sharedmem);
+                       qFatal("Failed to create shared memory: %s", QUTF8(errorMessage));
+                       return -1;
+               }
+       }
+
+       memset(g_lamexp_ipc_ptr.sharedmem->data(), 0, sizeof(lamexp_ipc_t));
+       g_lamexp_ipc_ptr.semaphore_write->release(g_lamexp_ipc_slots);
+       g_lamexp_ipc_ptr.semaphore_read_mutex->release();
+       g_lamexp_ipc_ptr.semaphore_write_mutex->release();
+
+       return 0;
+}
+
+/*
+ * IPC send message
+ */
+void lamexp_ipc_send(unsigned int command, const char* message)
+{
+       QReadLocker readLock(&g_lamexp_ipc_ptr.lock);
+
+       if(!g_lamexp_ipc_ptr.sharedmem || !g_lamexp_ipc_ptr.semaphore_read || !g_lamexp_ipc_ptr.semaphore_write || !g_lamexp_ipc_ptr.semaphore_read_mutex || !g_lamexp_ipc_ptr.semaphore_write_mutex)
+       {
+               THROW("Shared memory for IPC not initialized yet.");
+       }
+
+       lamexp_ipc_data_t ipc_data;
+       memset(&ipc_data, 0, sizeof(lamexp_ipc_data_t));
+       ipc_data.command = command;
+       
+       if(message)
+       {
+               strncpy_s(ipc_data.parameter, 4096, message, _TRUNCATE);
+       }
+
+       if(g_lamexp_ipc_ptr.semaphore_write->acquire())
+       {
+               if(g_lamexp_ipc_ptr.semaphore_write_mutex->acquire())
+               {
+                       lamexp_ipc_t *ptr = reinterpret_cast<lamexp_ipc_t*>(g_lamexp_ipc_ptr.sharedmem->data());
+                       memcpy(&ptr->data[ptr->pos_write], &ipc_data, sizeof(lamexp_ipc_data_t));
+                       ptr->pos_write = (ptr->pos_write + 1) % g_lamexp_ipc_slots;
+                       g_lamexp_ipc_ptr.semaphore_read->release();
+                       g_lamexp_ipc_ptr.semaphore_write_mutex->release();
+               }
+       }
+}
+
+/*
+ * IPC read message
+ */
+void lamexp_ipc_read(unsigned int *command, char* message, size_t buffSize)
+{
+       QReadLocker readLock(&g_lamexp_ipc_ptr.lock);
+       
+       *command = 0;
+       message[0] = '\0';
+       
+       if(!g_lamexp_ipc_ptr.sharedmem || !g_lamexp_ipc_ptr.semaphore_read || !g_lamexp_ipc_ptr.semaphore_write || !g_lamexp_ipc_ptr.semaphore_read_mutex || !g_lamexp_ipc_ptr.semaphore_write_mutex)
+       {
+               THROW("Shared memory for IPC not initialized yet.");
+       }
+
+       lamexp_ipc_data_t ipc_data;
+       memset(&ipc_data, 0, sizeof(lamexp_ipc_data_t));
+
+       if(g_lamexp_ipc_ptr.semaphore_read->acquire())
+       {
+               if(g_lamexp_ipc_ptr.semaphore_read_mutex->acquire())
+               {
+                       lamexp_ipc_t *ptr = reinterpret_cast<lamexp_ipc_t*>(g_lamexp_ipc_ptr.sharedmem->data());
+                       memcpy(&ipc_data, &ptr->data[ptr->pos_read], sizeof(lamexp_ipc_data_t));
+                       ptr->pos_read = (ptr->pos_read + 1) % g_lamexp_ipc_slots;
+                       g_lamexp_ipc_ptr.semaphore_write->release();
+                       g_lamexp_ipc_ptr.semaphore_read_mutex->release();
+
+                       if(!(ipc_data.reserved_1 || ipc_data.reserved_2))
+                       {
+                               *command = ipc_data.command;
+                               strncpy_s(message, buffSize, ipc_data.parameter, _TRUNCATE);
+                       }
+                       else
+                       {
+                               qWarning("Malformed IPC message, will be ignored");
+                       }
+               }
+       }
+}
+
+/*
+ * Exit and clean-up IPC
+ */
+void lamexp_ipc_exit(void)
+{
+       if(g_lamexp_ipc_ptr.sharedmem) g_lamexp_ipc_ptr.sharedmem->detach();
+       LAMEXP_DELETE(g_lamexp_ipc_ptr.sharedmem);
+       LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_read);
+       LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_write);
+       LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_read_mutex);
+       LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_write_mutex);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// INITIALIZATION
+///////////////////////////////////////////////////////////////////////////////
+
+extern "C" void _lamexp_global_init_ipcom(void)
+{
+       LAMEXP_ZERO_MEMORY(g_lamexp_ipc_ptr);
+}
diff --git a/src/Global_Tools.cpp b/src/Global_Tools.cpp
new file mode 100644 (file)
index 0000000..0c9f5dd
--- /dev/null
@@ -0,0 +1,398 @@
+///////////////////////////////////////////////////////////////////////////////
+// LameXP - Audio Encoder Front-End
+// Copyright (C) 2004-2013 LoRd_MuldeR <MuldeR2@GMX.de>
+//
+// 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, but always including the *additional*
+// restrictions defined in the "License.txt" file.
+//
+// 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 "Global.h"
+
+//Qt includes
+#include <QApplication>
+#include <QMap>
+#include <QReadWriteLock>
+#include <QReadLocker>
+#include <QWriteLocker>
+#include <QString>
+#include <QStringList>
+#include <QTranslator>
+#include <QFileInfo>
+
+//LameXP includes
+#include "LockedFile.h"
+
+///////////////////////////////////////////////////////////////////////////////
+// GLOBAL VARS
+///////////////////////////////////////////////////////////////////////////////
+
+//Tools
+static struct
+{
+       QMap<QString, LockedFile*> *registry;
+       QMap<QString, unsigned int> *versions;
+       QMap<QString, QString> *tags;
+       QReadWriteLock lock;
+}
+g_lamexp_tools;
+
+//Supported languages
+static struct
+{
+       QMap<QString, QString> *files;
+       QMap<QString, QString> *names;
+       QMap<QString, unsigned int> *sysid;
+       QMap<QString, unsigned int> *cntry;
+       QReadWriteLock lock;
+}
+g_lamexp_translation;
+
+//Translator
+static struct
+{
+       QTranslator *instance;
+       QReadWriteLock lock;
+}
+g_lamexp_currentTranslator;
+
+///////////////////////////////////////////////////////////////////////////////
+// GLOBAL FUNCTIONS
+///////////////////////////////////////////////////////////////////////////////
+
+/*
+ * Register tool
+ */
+void lamexp_register_tool(const QString &toolName, LockedFile *file, unsigned int version, const QString *tag)
+{
+       QWriteLocker writeLock(&g_lamexp_tools.lock);
+       
+       if(!g_lamexp_tools.registry) g_lamexp_tools.registry = new QMap<QString, LockedFile*>();
+       if(!g_lamexp_tools.versions) g_lamexp_tools.versions = new QMap<QString, unsigned int>();
+       if(!g_lamexp_tools.tags) g_lamexp_tools.tags = new QMap<QString, QString>();
+
+       if(g_lamexp_tools.registry->contains(toolName.toLower()))
+       {
+               THROW("lamexp_register_tool: Tool is already registered!");
+       }
+
+       g_lamexp_tools.registry->insert(toolName.toLower(), file);
+       g_lamexp_tools.versions->insert(toolName.toLower(), version);
+       g_lamexp_tools.tags->insert(toolName.toLower(), (tag) ? (*tag) : QString());
+}
+
+/*
+ * Check for tool
+ */
+bool lamexp_check_tool(const QString &toolName)
+{
+       QReadLocker readLock(&g_lamexp_tools.lock);
+       return (g_lamexp_tools.registry) ? g_lamexp_tools.registry->contains(toolName.toLower()) : false;
+}
+
+/*
+ * Lookup tool path
+ */
+const QString lamexp_lookup_tool(const QString &toolName)
+{
+       QReadLocker readLock(&g_lamexp_tools.lock);
+
+       if(g_lamexp_tools.registry)
+       {
+               if(g_lamexp_tools.registry->contains(toolName.toLower()))
+               {
+                       return g_lamexp_tools.registry->value(toolName.toLower())->filePath();
+               }
+               else
+               {
+                       return QString();
+               }
+       }
+       else
+       {
+               return QString();
+       }
+}
+
+/*
+ * Lookup tool version
+ */
+unsigned int lamexp_tool_version(const QString &toolName, QString *tag)
+{
+       QReadLocker readLock(&g_lamexp_tools.lock);
+       if(tag) tag->clear();
+
+       if(g_lamexp_tools.versions)
+       {
+               if(g_lamexp_tools.versions->contains(toolName.toLower()))
+               {
+                       if(tag)
+                       {
+                               if(g_lamexp_tools.tags->contains(toolName.toLower())) *tag = g_lamexp_tools.tags->value(toolName.toLower());
+                       }
+                       return g_lamexp_tools.versions->value(toolName.toLower());
+               }
+               else
+               {
+                       return UINT_MAX;
+               }
+       }
+       else
+       {
+               return UINT_MAX;
+       }
+}
+
+/*
+ * Version number to human-readable string
+ */
+const QString lamexp_version2string(const QString &pattern, unsigned int version, const QString &defaultText, const QString *tag)
+{
+       if(version == UINT_MAX)
+       {
+               return defaultText;
+       }
+       
+       QString result = pattern;
+       int digits = result.count("?", Qt::CaseInsensitive);
+       
+       if(digits < 1)
+       {
+               return result;
+       }
+       
+       int pos = 0;
+       QString versionStr = QString().sprintf(QString().sprintf("%%0%du", digits).toLatin1().constData(), version);
+       int index = result.indexOf("?", Qt::CaseInsensitive);
+       
+       while(index >= 0 && pos < versionStr.length())
+       {
+               result[index] = versionStr[pos++];
+               index = result.indexOf("?", Qt::CaseInsensitive);
+       }
+
+       if(tag)
+       {
+               result.replace(QChar('#'), *tag, Qt::CaseInsensitive);
+       }
+
+       return result;
+}
+
+/*
+ * Free all registered tools (final clean-up)
+ */
+void lamexp_clean_all_tools(void)
+{
+       if(g_lamexp_tools.registry)
+       {
+               QStringList keys = g_lamexp_tools.registry->keys();
+               for(int i = 0; i < keys.count(); i++)
+               {
+                       LockedFile *lf = g_lamexp_tools.registry->take(keys.at(i));
+                       LAMEXP_DELETE(lf);
+               }
+               g_lamexp_tools.registry->clear();
+               g_lamexp_tools.versions->clear();
+               g_lamexp_tools.tags->clear();
+       }
+
+       LAMEXP_DELETE(g_lamexp_tools.registry);
+       LAMEXP_DELETE(g_lamexp_tools.versions);
+       LAMEXP_DELETE(g_lamexp_tools.tags);
+}
+
+/*
+ * Initialize translations and add default language
+ */
+bool lamexp_translation_init(void)
+{
+       QWriteLocker writeLockTranslations(&g_lamexp_translation.lock);
+
+       if((!g_lamexp_translation.files) && (!g_lamexp_translation.names))
+       {
+               g_lamexp_translation.files = new QMap<QString, QString>();
+               g_lamexp_translation.names = new QMap<QString, QString>();
+               g_lamexp_translation.files->insert(LAMEXP_DEFAULT_LANGID, "");
+               g_lamexp_translation.names->insert(LAMEXP_DEFAULT_LANGID, "English");
+               return true;
+       }
+       else
+       {
+               qWarning("[lamexp_translation_init] Error: Already initialized!");
+               return false;
+       }
+}
+
+/*
+ * Register a new translation
+ */
+bool lamexp_translation_register(const QString &langId, const QString &qmFile, const QString &langName, unsigned int &systemId, unsigned int &country)
+{
+       QWriteLocker writeLockTranslations(&g_lamexp_translation.lock);
+
+       if(qmFile.isEmpty() || langName.isEmpty() || systemId < 1)
+       {
+               return false;
+       }
+
+       if(!g_lamexp_translation.files) g_lamexp_translation.files = new QMap<QString, QString>();
+       if(!g_lamexp_translation.names) g_lamexp_translation.names = new QMap<QString, QString>();
+       if(!g_lamexp_translation.sysid) g_lamexp_translation.sysid = new QMap<QString, unsigned int>();
+       if(!g_lamexp_translation.cntry) g_lamexp_translation.cntry = new QMap<QString, unsigned int>();
+
+       g_lamexp_translation.files->insert(langId, qmFile);
+       g_lamexp_translation.names->insert(langId, langName);
+       g_lamexp_translation.sysid->insert(langId, systemId);
+       g_lamexp_translation.cntry->insert(langId, country);
+
+       return true;
+}
+
+/*
+ * Get list of all translations
+ */
+QStringList lamexp_query_translations(void)
+{
+       QReadLocker readLockTranslations(&g_lamexp_translation.lock);
+       return (g_lamexp_translation.files) ? g_lamexp_translation.files->keys() : QStringList();
+}
+
+/*
+ * Get translation name
+ */
+QString lamexp_translation_name(const QString &langId)
+{
+       QReadLocker readLockTranslations(&g_lamexp_translation.lock);
+       return (g_lamexp_translation.names) ? g_lamexp_translation.names->value(langId.toLower(), QString()) : QString();
+}
+
+/*
+ * Get translation system id
+ */
+unsigned int lamexp_translation_sysid(const QString &langId)
+{
+       QReadLocker readLockTranslations(&g_lamexp_translation.lock);
+       return (g_lamexp_translation.sysid) ? g_lamexp_translation.sysid->value(langId.toLower(), 0) : 0;
+}
+
+/*
+ * Get translation script id
+ */
+unsigned int lamexp_translation_country(const QString &langId)
+{
+       QReadLocker readLockTranslations(&g_lamexp_translation.lock);
+       return (g_lamexp_translation.cntry) ? g_lamexp_translation.cntry->value(langId.toLower(), 0) : 0;
+}
+
+/*
+ * Install a new translator
+ */
+bool lamexp_install_translator(const QString &langId)
+{
+       bool success = false;
+       const QString qmFileToPath(":/localization/%1");
+
+       if(langId.isEmpty() || langId.toLower().compare(LAMEXP_DEFAULT_LANGID) == 0)
+       {
+               success = lamexp_install_translator_from_file(qmFileToPath.arg(LAMEXP_DEFAULT_TRANSLATION));
+       }
+       else
+       {
+               QReadLocker readLock(&g_lamexp_translation.lock);
+               QString qmFile = (g_lamexp_translation.files) ? g_lamexp_translation.files->value(langId.toLower(), QString()) : QString();
+               readLock.unlock();
+
+               if(!qmFile.isEmpty())
+               {
+                       success = lamexp_install_translator_from_file(qmFileToPath.arg(qmFile));
+               }
+               else
+               {
+                       qWarning("Translation '%s' not available!", langId.toLatin1().constData());
+               }
+       }
+
+       return success;
+}
+
+/*
+ * Install a new translator from file
+ */
+bool lamexp_install_translator_from_file(const QString &qmFile)
+{
+       QWriteLocker writeLock(&g_lamexp_currentTranslator.lock);
+       bool success = false;
+
+       if(!g_lamexp_currentTranslator.instance)
+       {
+               g_lamexp_currentTranslator.instance = new QTranslator();
+       }
+
+       if(!qmFile.isEmpty())
+       {
+               QString qmPath = QFileInfo(qmFile).canonicalFilePath();
+               QApplication::removeTranslator(g_lamexp_currentTranslator.instance);
+               if(success = g_lamexp_currentTranslator.instance->load(qmPath))
+               {
+                       QApplication::installTranslator(g_lamexp_currentTranslator.instance);
+               }
+               else
+               {
+                       qWarning("Failed to load translation:\n\"%s\"", qmPath.toLatin1().constData());
+               }
+       }
+       else
+       {
+               QApplication::removeTranslator(g_lamexp_currentTranslator.instance);
+               success = true;
+       }
+
+       return success;
+}
+
+/*
+ * Free all registered translations (final clean-up)
+ */
+void lamexp_clean_all_translations(void)
+{
+       QWriteLocker writeLockTranslator(&g_lamexp_currentTranslator.lock);
+
+       if(g_lamexp_currentTranslator.instance)
+       {
+               QApplication::removeTranslator(g_lamexp_currentTranslator.instance);
+               LAMEXP_DELETE(g_lamexp_currentTranslator.instance);
+       }
+       
+       writeLockTranslator.unlock();
+       QWriteLocker writeLockTranslations(&g_lamexp_translation.lock);
+
+       LAMEXP_DELETE(g_lamexp_translation.files);
+       LAMEXP_DELETE(g_lamexp_translation.names);
+       LAMEXP_DELETE(g_lamexp_translation.cntry);
+       LAMEXP_DELETE(g_lamexp_translation.sysid);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// INITIALIZATION
+///////////////////////////////////////////////////////////////////////////////
+
+extern "C" void _lamexp_global_init_tools(void)
+{
+       LAMEXP_ZERO_MEMORY(g_lamexp_tools);
+       LAMEXP_ZERO_MEMORY(g_lamexp_currentTranslator);
+       LAMEXP_ZERO_MEMORY(g_lamexp_translation);
+}
diff --git a/src/Global_Utils.cpp b/src/Global_Utils.cpp
new file mode 100644 (file)
index 0000000..970e1cb
--- /dev/null
@@ -0,0 +1,585 @@
+///////////////////////////////////////////////////////////////////////////////
+// LameXP - Audio Encoder Front-End
+// Copyright (C) 2004-2013 LoRd_MuldeR <MuldeR2@GMX.de>
+//
+// 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, but always including the *additional*
+// restrictions defined in the "License.txt" file.
+//
+// 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 "Global.h"
+
+//Qt includes
+#include <QApplication>
+#include <QDate>
+#include <QDir>
+#include <QFileInfo>
+#include <QIcon>
+#include <QMutex>
+#include <QProcessEnvironment>
+#include <QReadWriteLock>
+#include <QTextCodec>
+#include <QUuid>
+#include <QWidget>
+
+//Natural sort
+#include "strnatcmp.h"
+
+//CRT includes
+#include <time.h>
+#include <process.h>
+
+///////////////////////////////////////////////////////////////////////////////
+// GLOBAL VARS
+///////////////////////////////////////////////////////////////////////////////
+
+//%TEMP% folder
+static struct
+{
+       QString *path;
+       QReadWriteLock lock;
+}
+g_lamexp_temp_folder;
+
+///////////////////////////////////////////////////////////////////////////////
+// GLOBAL FUNCTIONS
+///////////////////////////////////////////////////////////////////////////////
+
+/*
+ * Get a random string
+ */
+QString lamexp_rand_str(const bool bLong)
+{
+       const QUuid uuid = QUuid::createUuid().toString();
+
+       const unsigned int u1 = uuid.data1;
+       const unsigned int u2 = (((unsigned int)(uuid.data2)) << 16) | ((unsigned int)(uuid.data3));
+       const unsigned int u3 = (((unsigned int)(uuid.data4[0])) << 24) | (((unsigned int)(uuid.data4[1])) << 16) | (((unsigned int)(uuid.data4[2])) << 8) | ((unsigned int)(uuid.data4[3]));
+       const unsigned int u4 = (((unsigned int)(uuid.data4[4])) << 24) | (((unsigned int)(uuid.data4[5])) << 16) | (((unsigned int)(uuid.data4[6])) << 8) | ((unsigned int)(uuid.data4[7]));
+
+       return bLong ? QString().sprintf("%08x%08x%08x%08x", u1, u2, u3, u4) : QString().sprintf("%08x%08x", (u1 ^ u2), (u3 ^ u4));
+}
+
+/*
+ * Try to initialize the folder (with *write* access)
+ */
+static QString lamexp_try_init_folder(const QString &folderPath)
+{
+       bool success = false;
+
+       const QFileInfo folderInfo(folderPath);
+       const QDir folderDir(folderInfo.absoluteFilePath());
+
+       //Create folder, if it does *not* exist yet
+       if(!folderDir.exists())
+       {
+               folderDir.mkpath(".");
+       }
+
+       //Make sure folder exists now *and* is writable
+       if(folderDir.exists())
+       {
+               QFile testFile(folderDir.absoluteFilePath(QString("~%1.tmp").arg(lamexp_rand_str())));
+               if(testFile.open(QIODevice::ReadWrite))
+               {
+                       const QByteArray testData = QByteArray("Lorem ipsum dolor sit amet, consectetur, adipisci velit!");
+                       if(testFile.write(testData) >= strlen(testData))
+                       {
+                               success = true;
+                               testFile.remove();
+                       }
+                       testFile.close();
+               }
+       }
+
+       return (success ? folderDir.canonicalPath() : QString());
+}
+
+/*
+ * Initialize LameXP temp folder
+ */
+#define INIT_TEMP_FOLDER(OUT,TMP) do \
+{ \
+       (OUT) = lamexp_try_init_folder(QString("%1/%2").arg((TMP), lamexp_rand_str())); \
+} \
+while(0)
+
+/*
+ * Get LameXP temp folder
+ */
+const QString &lamexp_temp_folder2(void)
+{
+       QReadLocker readLock(&g_lamexp_temp_folder.lock);
+
+       //Already initialized?
+       if(g_lamexp_temp_folder.path && (!g_lamexp_temp_folder.path->isEmpty()))
+       {
+               if(QDir(*g_lamexp_temp_folder.path).exists())
+               {
+                       return *g_lamexp_temp_folder.path;
+               }
+       }
+
+       //Obtain the write lock to initilaize
+       readLock.unlock();
+       QWriteLocker writeLock(&g_lamexp_temp_folder.lock);
+       
+       //Still uninitilaized?
+       if(g_lamexp_temp_folder.path && (!g_lamexp_temp_folder.path->isEmpty()))
+       {
+               if(QDir(*g_lamexp_temp_folder.path).exists())
+               {
+                       return *g_lamexp_temp_folder.path;
+               }
+       }
+
+       //Create the string, if not done yet
+       if(!g_lamexp_temp_folder.path)
+       {
+               g_lamexp_temp_folder.path = new QString();
+       }
+       
+       g_lamexp_temp_folder.path->clear();
+
+       //Try the %TMP% or %TEMP% directory first
+       QString tempPath = lamexp_try_init_folder(QDir::temp().absolutePath());
+       if(!tempPath.isEmpty())
+       {
+               INIT_TEMP_FOLDER(*g_lamexp_temp_folder.path, tempPath);
+       }
+
+       //Otherwise create TEMP folder in %LOCALAPPDATA%
+       if(g_lamexp_temp_folder.path->isEmpty())
+       {
+               tempPath = lamexp_try_init_folder(QString("%1/Temp").arg(lamexp_known_folder(lamexp_folder_localappdata)));
+               if(!tempPath.isEmpty())
+               {
+                       INIT_TEMP_FOLDER(*g_lamexp_temp_folder.path, tempPath);
+               }
+       }
+
+       //Failed to create TEMP folder?
+       if(g_lamexp_temp_folder.path->isEmpty())
+       {
+               qFatal("Temporary directory could not be initialized !!!");
+       }
+       
+       return *g_lamexp_temp_folder.path;
+}
+
+/*
+ * Clear LameXP temp folder cache
+ */
+void lamexp_temp_folder_clear(void)
+{
+       QWriteLocker writeLock(&g_lamexp_temp_folder.lock);
+       LAMEXP_DELETE(g_lamexp_temp_folder.path);
+}
+
+/*
+ * Setup QPorcess object
+ */
+void lamexp_init_process(QProcess &process, const QString &wokringDir)
+{
+       //Environment variable names
+       static const char *const s_envvar_names[] =
+       {
+               "WGETRC", "SYSTEM_WGETRC", "HTTP_PROXY", "FTP_PROXY", "NO_PROXY", "GNUPGHOME", "LC_ALL", "LC_COLLATE", "LC_CTYPE", "LC_MESSAGES", "LC_MONETARY", "LC_NUMERIC", "LC_TIME", "LANG", NULL
+       };
+
+       const QString tempDir = QDir::toNativeSeparators(lamexp_temp_folder2());
+
+       QProcessEnvironment env = process.processEnvironment();
+       if(env.isEmpty()) env = QProcessEnvironment::systemEnvironment();
+
+       //Setup TEMP directory
+       env.insert("TEMP", tempDir);
+       env.insert("TMP", tempDir);
+       env.insert("TMPDIR", tempDir);
+       env.insert("HOME", tempDir);
+       env.insert("USERPROFILE", tempDir);
+       env.insert("HOMEPATH", tempDir);
+
+       //Setup PATH variable
+       const QString path = env.value("PATH", QString());
+       env.insert("PATH", path.isEmpty() ? tempDir : QString("%1;%2").arg(tempDir, path));
+
+       //Clean a number of enviroment variables that might affect our tools
+       for(size_t i = 0; s_envvar_names[i]; i++)
+       {
+               env.remove(QString::fromLatin1(s_envvar_names[i]));
+               env.remove(QString::fromLatin1(s_envvar_names[i]).toLower());
+       }
+       
+       process.setWorkingDirectory(wokringDir);
+       process.setProcessChannelMode(QProcess::MergedChannels);
+       process.setReadChannel(QProcess::StandardOutput);
+       process.setProcessEnvironment(env);
+}
+
+/*
+ * Natural Order String Comparison - the 'lessThan' helper function
+ */
+static bool lamexp_natural_string_sort_helper(const QString &str1, const QString &str2)
+{
+       return (strnatcmp(QWCHAR(str1), QWCHAR(str2)) < 0);
+}
+
+/*
+ * Natural Order String Comparison - the 'lessThan' helper function *with* case folding
+ */
+static bool lamexp_natural_string_sort_helper_fold_case(const QString &str1, const QString &str2)
+{
+       return (strnatcasecmp(QWCHAR(str1), QWCHAR(str2)) < 0);
+}
+
+/*
+ * Natural Order String Comparison - the main sorting function
+ */
+void lamexp_natural_string_sort(QStringList &list, const bool bIgnoreCase)
+{
+       qSort(list.begin(), list.end(), bIgnoreCase ? lamexp_natural_string_sort_helper_fold_case : lamexp_natural_string_sort_helper);
+}
+
+/*
+ * Remove forbidden characters from a filename
+ */
+const QString lamexp_clean_filename(const QString &str)
+{
+       QString newStr(str);
+       QRegExp rx("\"(.+)\"");
+       rx.setMinimal(true);
+
+       newStr.replace("\\", "-");
+       newStr.replace(" / ", ", ");
+       newStr.replace("/", ",");
+       newStr.replace(":", "-");
+       newStr.replace("*", "x");
+       newStr.replace("?", "");
+       newStr.replace("<", "[");
+       newStr.replace(">", "]");
+       newStr.replace("|", "!");
+       newStr.replace(rx, "`\\1´");
+       newStr.replace("\"", "'");
+       
+       return newStr.simplified();
+}
+
+/*
+ * Remove forbidden characters from a file path
+ */
+const QString lamexp_clean_filepath(const QString &str)
+{
+       QStringList parts = QString(str).replace("\\", "/").split("/");
+
+       for(int i = 0; i < parts.count(); i++)
+       {
+               parts[i] = lamexp_clean_filename(parts[i]);
+       }
+
+       return parts.join("/");
+}
+
+/*
+ * Get a list of all available Qt Text Codecs
+ */
+QStringList lamexp_available_codepages(bool noAliases)
+{
+       QStringList codecList;
+       
+       QList<QByteArray> availableCodecs = QTextCodec::availableCodecs();
+       while(!availableCodecs.isEmpty())
+       {
+               QByteArray current = availableCodecs.takeFirst();
+               if(!(current.startsWith("system") || current.startsWith("System")))
+               {
+                       codecList << QString::fromLatin1(current.constData(), current.size());
+                       if(noAliases)
+                       {
+                               if(QTextCodec *currentCodec = QTextCodec::codecForName(current.constData()))
+                               {
+                                       
+                                       QList<QByteArray> aliases = currentCodec->aliases();
+                                       while(!aliases.isEmpty()) availableCodecs.removeAll(aliases.takeFirst());
+                               }
+                       }
+               }
+       }
+
+       return codecList;
+}
+
+/*
+ * Robert Jenkins' 96 bit Mix Function
+ * Source: http://www.concentric.net/~Ttwang/tech/inthash.htm
+ */
+static unsigned int lamexp_mix(const unsigned int x, const unsigned int y, const unsigned int z)
+{
+       unsigned int a = x;
+       unsigned int b = y;
+       unsigned int c = z;
+       
+       a=a-b;  a=a-c;  a=a^(c >> 13);
+       b=b-c;  b=b-a;  b=b^(a << 8); 
+       c=c-a;  c=c-b;  c=c^(b >> 13);
+       a=a-b;  a=a-c;  a=a^(c >> 12);
+       b=b-c;  b=b-a;  b=b^(a << 16);
+       c=c-a;  c=c-b;  c=c^(b >> 5);
+       a=a-b;  a=a-c;  a=a^(c >> 3);
+       b=b-c;  b=b-a;  b=b^(a << 10);
+       c=c-a;  c=c-b;  c=c^(b >> 15);
+
+       return c;
+}
+
+/*
+ * Seeds the random number generator
+ * Note: Altough rand_s() doesn't need a seed, this must be called pripr to lamexp_rand(), just to to be sure!
+ */
+void lamexp_seed_rand(void)
+{
+       qsrand(lamexp_mix(clock(), time(NULL), _getpid()));
+}
+
+/*
+ * Returns a randum number
+ * Note: This function uses rand_s() if available, but falls back to qrand() otherwise
+ */
+unsigned int lamexp_rand(void)
+{
+       quint32 rnd = 0;
+
+       if(rand_s(&rnd) == 0)
+       {
+               return rnd;
+       }
+
+       for(size_t i = 0; i < sizeof(unsigned int); i++)
+       {
+               rnd = (rnd << 8) ^ qrand();
+       }
+
+       return rnd;
+}
+
+/*
+ * Make a window blink (to draw user's attention)
+ */
+void lamexp_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<int>(ceil(maxOpac - minOpac) / delOpac);
+               const int sleep = static_cast<int>(floor(static_cast<double>(delay) / static_cast<double>(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();
+                               lamexp_sleep(sleep);
+                       }
+
+                       for(double x = minOpac; x <= maxOpac; x += delOpac)
+                       {
+                               poWindow->setWindowOpacity(x);
+                               QApplication::processEvents();
+                               lamexp_sleep(sleep);
+                       }
+               }
+
+               poWindow->setWindowOpacity(opacity);
+               QApplication::processEvents();
+               blinkMutex.unlock();
+       }
+       catch(...)
+       {
+               blinkMutex.unlock();
+               qWarning("Exception error while blinking!");
+       }
+}
+
+/*
+ * Clean folder
+ */
+bool lamexp_clean_folder(const QString &folderPath)
+{
+       QDir tempFolder(folderPath);
+       if(tempFolder.exists())
+       {
+               QFileInfoList entryList = tempFolder.entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot);
+
+               for(int i = 0; i < entryList.count(); i++)
+               {
+                       if(entryList.at(i).isDir())
+                       {
+                               lamexp_clean_folder(entryList.at(i).canonicalFilePath());
+                       }
+                       else
+                       {
+                               for(int j = 0; j < 3; j++)
+                               {
+                                       if(lamexp_remove_file(entryList.at(i).canonicalFilePath()))
+                                       {
+                                               break;
+                                       }
+                               }
+                       }
+               }
+               return tempFolder.rmdir(".");
+       }
+       return true;
+}
+
+/*
+ * Computus according to H. Lichtenberg
+ */
+static bool lamexp_computus(const QDate &date)
+{
+       int X = date.year();
+       int A = X % 19;
+       int K = X / 100;
+       int M = 15 + (3*K + 3) / 4 - (8*K + 13) / 25;
+       int D = (19*A + M) % 30;
+       int S = 2 - (3*K + 3) / 4;
+       int R = D / 29 + (D / 28 - D / 29) * (A / 11);
+       int OG = 21 + D - R;
+       int SZ = 7 - (X + X / 4 + S) % 7;
+       int OE = 7 - (OG - SZ) % 7;
+       int OS = (OG + OE);
+
+       if(OS > 31)
+       {
+               return (date.month() == 4) && (date.day() == (OS - 31));
+       }
+       else
+       {
+               return (date.month() == 3) && (date.day() == OS);
+       }
+}
+
+/*
+ * Check for Thanksgiving
+ */
+static bool lamexp_thanksgiving(const QDate &date)
+{
+       int day = 0;
+
+       switch(QDate(date.year(), 11, 1).dayOfWeek())
+       {
+               case 1: day = 25; break; 
+               case 2: day = 24; break; 
+               case 3: day = 23; break; 
+               case 4: day = 22; break; 
+               case 5: day = 28; break; 
+               case 6: day = 27; break; 
+               case 7: day = 26; break;
+       }
+
+       return (date.month() == 11) && (date.day() == day);
+}
+
+/*
+ * Initialize app icon
+ */
+QIcon lamexp_app_icon(const QDate *date, const QTime *time)
+{
+       QDate currentDate = (date) ? QDate(*date) : QDate::currentDate();
+       QTime currentTime = (time) ? QTime(*time) : QTime::currentTime();
+       
+       if(lamexp_thanksgiving(currentDate))
+       {
+               return QIcon(":/MainIcon6.png");
+       }
+       else if(((currentDate.month() == 12) && (currentDate.day() == 31) && (currentTime.hour() >= 20)) || ((currentDate.month() == 1) && (currentDate.day() == 1)  && (currentTime.hour() <= 19)))
+       {
+               return QIcon(":/MainIcon5.png");
+       }
+       else if(((currentDate.month() == 10) && (currentDate.day() == 31) && (currentTime.hour() >= 12)) || ((currentDate.month() == 11) && (currentDate.day() == 1)  && (currentTime.hour() <= 11)))
+       {
+               return QIcon(":/MainIcon4.png");
+       }
+       else if((currentDate.month() == 12) && (currentDate.day() >= 24) && (currentDate.day() <= 26))
+       {
+               return QIcon(":/MainIcon3.png");
+       }
+       else if(lamexp_computus(currentDate))
+       {
+               return QIcon(":/MainIcon2.png");
+       }
+       else
+       {
+               return QIcon(":/MainIcon1.png");
+       }
+}
+
+/*
+ * Broadcast event to all windows
+ */
+bool lamexp_broadcast(int eventType, bool onlyToVisible)
+{
+       if(QApplication *app = dynamic_cast<QApplication*>(QApplication::instance()))
+       {
+               qDebug("Broadcasting %d", eventType);
+               
+               bool allOk = true;
+               QEvent poEvent(static_cast<QEvent::Type>(eventType));
+               QWidgetList list = app->topLevelWidgets();
+
+               while(!list.isEmpty())
+               {
+                       QWidget *widget = list.takeFirst();
+                       if(!onlyToVisible || widget->isVisible())
+                       {
+                               if(!app->sendEvent(widget, &poEvent))
+                               {
+                                       allOk = false;
+                               }
+                       }
+               }
+
+               qDebug("Broadcast %d done (%s)", eventType, (allOk ? "OK" : "Stopped"));
+               return allOk;
+       }
+       else
+       {
+               qWarning("Broadcast failed, could not get QApplication instance!");
+               return false;
+       }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// INITIALIZATION
+///////////////////////////////////////////////////////////////////////////////
+
+extern "C" void _lamexp_global_init_utils(void)
+{
+       LAMEXP_ZERO_MEMORY(g_lamexp_temp_folder);
+}
diff --git a/src/Global_Version.cpp b/src/Global_Version.cpp
new file mode 100644 (file)
index 0000000..f5aeaf8
--- /dev/null
@@ -0,0 +1,327 @@
+///////////////////////////////////////////////////////////////////////////////
+// LameXP - Audio Encoder Front-End
+// Copyright (C) 2004-2013 LoRd_MuldeR <MuldeR2@GMX.de>
+//
+// 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, but always including the *additional*
+// restrictions defined in the "License.txt" file.
+//
+// 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 "Global.h"
+
+//LameXP includes
+#define LAMEXP_INC_CONFIG
+#include "Resource.h"
+#include "Config.h"
+
+//Qt includes
+#include <QApplication>
+#include <QDate>
+#include <QFileInfo>
+#include <QReadWriteLock>
+
+///////////////////////////////////////////////////////////////////////////////
+// GLOBAL VARS
+///////////////////////////////////////////////////////////////////////////////
+
+//Build version
+static const struct
+{
+       unsigned int ver_major;
+       unsigned int ver_minor;
+       unsigned int ver_build;
+       unsigned int ver_confg;
+       char *ver_release_name;
+}
+g_lamexp_version =
+{
+       VER_LAMEXP_MAJOR,
+       (10 * VER_LAMEXP_MINOR_HI) + VER_LAMEXP_MINOR_LO,
+       VER_LAMEXP_BUILD,
+       VER_LAMEXP_CONFG,
+       VER_LAMEXP_RNAME,
+};
+
+//Portable Mode
+static struct
+{
+       bool bInitialized;
+       bool bPortableModeEnabled;
+       QReadWriteLock lock;
+}
+g_lamexp_portable;
+
+//Build date
+static QDate g_lamexp_version_date;
+static const char *g_lamexp_months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
+static const char *g_lamexp_version_raw_date = __DATE__;
+static const char *g_lamexp_version_raw_time = __TIME__;
+
+//Official web-site URL
+static const char *g_lamexp_website_url = "http://lamexp.sourceforge.net/";
+static const char *g_lamexp_support_url = "http://forum.doom9.org/showthread.php?t=157726";
+static const char *g_lamexp_mulders_url = "http://muldersoft.com/";
+
+//Tool versions (expected versions!)
+static const unsigned int g_lamexp_toolver_neroaac = VER_LAMEXP_TOOL_NEROAAC;
+static const unsigned int g_lamexp_toolver_fhgaacenc = VER_LAMEXP_TOOL_FHGAACENC;
+static const unsigned int g_lamexp_toolver_qaacenc = VER_LAMEXP_TOOL_QAAC;
+static const unsigned int g_lamexp_toolver_coreaudio = VER_LAMEXP_TOOL_COREAUDIO;
+
+///////////////////////////////////////////////////////////////////////////////
+// COMPILER INFO
+///////////////////////////////////////////////////////////////////////////////
+
+/*
+ * Disclaimer: Parts of the following code were borrowed from MPC-HC project: http://mpc-hc.sf.net/
+ */
+
+//Compiler detection
+#if defined(__INTEL_COMPILER)
+       #if (__INTEL_COMPILER >= 1300)
+               static const char *g_lamexp_version_compiler = "ICL 13." LAMEXP_MAKE_STR(__INTEL_COMPILER_BUILD_DATE);
+       #elif (__INTEL_COMPILER >= 1200)
+               static const char *g_lamexp_version_compiler = "ICL 12." LAMEXP_MAKE_STR(__INTEL_COMPILER_BUILD_DATE);
+       #elif (__INTEL_COMPILER >= 1100)
+               static const char *g_lamexp_version_compiler = "ICL 11.x";
+       #elif (__INTEL_COMPILER >= 1000)
+               static const char *g_lamexp_version_compiler = "ICL 10.x";
+       #else
+               #error Compiler is not supported!
+       #endif
+#elif defined(_MSC_VER)
+       #if (_MSC_VER == 1800)
+               #if (_MSC_FULL_VER < 180021005)
+                       static const char *g_lamexp_version_compiler = "MSVC 2013-Beta";
+               #elif (_MSC_FULL_VER == 180021005)
+                       static const char *g_lamexp_version_compiler = "MSVC 2013";
+               #else
+                       #error Compiler version is not supported yet!
+               #endif
+       #elif (_MSC_VER == 1700)
+               #if (_MSC_FULL_VER < 170050727)
+                       static const char *g_lamexp_version_compiler = "MSVC 2012-Beta";
+               #elif (_MSC_FULL_VER < 170051020)
+                       static const char *g_lamexp_version_compiler = "MSVC 2012";
+               #elif (_MSC_FULL_VER < 170051106)
+                       static const char *g_lamexp_version_compiler = "MSVC 2012.1-CTP";
+               #elif (_MSC_FULL_VER < 170060315)
+                       static const char *g_lamexp_version_compiler = "MSVC 2012.1";
+               #elif (_MSC_FULL_VER < 170060610)
+                       static const char *g_lamexp_version_compiler = "MSVC 2012.2";
+               #elif (_MSC_FULL_VER == 170060610)
+                       static const char *g_lamexp_version_compiler = "MSVC 2012.3";
+               #else
+                       #error Compiler version is not supported yet!
+               #endif
+       #elif (_MSC_VER == 1600)
+               #if (_MSC_FULL_VER < 160040219)
+                       static const char *g_lamexp_version_compiler = "MSVC 2010";
+               #elif (_MSC_FULL_VER == 160040219)
+                       static const char *g_lamexp_version_compiler = "MSVC 2010-SP1";
+               #else
+                       #error Compiler version is not supported yet!
+               #endif
+       #elif (_MSC_VER == 1500)
+               #if (_MSC_FULL_VER >= 150030729)
+                       static const char *g_lamexp_version_compiler = "MSVC 2008-SP1";
+               #else
+                       static const char *g_lamexp_version_compiler = "MSVC 2008";
+               #endif
+       #else
+               #error Compiler is not supported!
+       #endif
+
+       // Note: /arch:SSE and /arch:SSE2 are only available for the x86 platform
+       #if !defined(_M_X64) && defined(_M_IX86_FP)
+               #if (_M_IX86_FP == 1)
+                       LAMEXP_COMPILER_WARNING("SSE instruction set is enabled!")
+               #elif (_M_IX86_FP == 2)
+                       LAMEXP_COMPILER_WARNING("SSE2 (or higher) instruction set is enabled!")
+               #endif
+       #endif
+#else
+       #error Compiler is not supported!
+#endif
+
+//Architecture detection
+#if defined(_M_X64)
+       static const char *g_lamexp_version_arch = "x64";
+#elif defined(_M_IX86)
+       static const char *g_lamexp_version_arch = "x86";
+#else
+       #error Architecture is not supported!
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// GLOBAL FUNCTIONS
+///////////////////////////////////////////////////////////////////////////////
+
+/*
+ * Version getters
+ */
+unsigned int lamexp_version_major(void)     { return g_lamexp_version.ver_major; }
+unsigned int lamexp_version_minor(void)     { return g_lamexp_version.ver_minor; }
+unsigned int lamexp_version_build(void)     { return g_lamexp_version.ver_build; }
+unsigned int lamexp_version_confg(void)     { return g_lamexp_version.ver_confg; }
+const char *lamexp_version_release(void)    { return g_lamexp_version.ver_release_name; }
+const char *lamexp_version_time(void)       { return g_lamexp_version_raw_time; }
+const char *lamexp_version_compiler(void)   { return g_lamexp_version_compiler; }
+const char *lamexp_version_arch(void)       { return g_lamexp_version_arch; }
+unsigned int lamexp_toolver_neroaac(void)   { return g_lamexp_toolver_neroaac; }
+unsigned int lamexp_toolver_fhgaacenc(void) { return g_lamexp_toolver_fhgaacenc; }
+unsigned int lamexp_toolver_qaacenc(void)   { return g_lamexp_toolver_qaacenc; }
+unsigned int lamexp_toolver_coreaudio(void) { return g_lamexp_toolver_coreaudio; }
+
+/*
+ * URL getters
+ */
+const char *lamexp_website_url(void) { return g_lamexp_website_url; }
+const char *lamexp_mulders_url(void) { return g_lamexp_mulders_url; }
+const char *lamexp_support_url(void) { return g_lamexp_support_url; }
+
+/*
+ * Check for Demo (pre-release) version
+ */
+bool lamexp_version_demo(void)
+{
+       char buffer[128];
+       bool releaseVersion = false;
+       if(!strncpy_s(buffer, 128, g_lamexp_version.ver_release_name, _TRUNCATE))
+       {
+               char *context, *prefix = strtok_s(buffer, "-,; ", &context);
+               if(prefix)
+               {
+                       releaseVersion = (!_stricmp(prefix, "Final")) || (!_stricmp(prefix, "Hotfix"));
+               }
+       }
+       return (!releaseVersion);
+}
+
+/*
+ * Calculate expiration date
+ */
+QDate lamexp_version_expires(void)
+{
+       return lamexp_version_date().addDays(LAMEXP_DEBUG ? 7 : 30);
+}
+
+/*
+ * Convert month string to integer value
+ */
+static int lamexp_month2int(const char *str)
+{
+       int ret = 0;
+
+       for(int j = 0; j < 12; j++)
+       {
+               if(!_strcmpi(str, g_lamexp_months[j]))
+               {
+                       ret = j+1;
+                       break;
+               }
+       }
+
+       return ret;
+}
+
+/*
+ * Get build date date
+ */
+const QDate &lamexp_version_date(void)
+{
+       //Format of __DATE__ is defined as: "MMM DD YYYY"
+       if(!g_lamexp_version_date.isValid())
+       {
+               int date[3] = {0, 0, 0};
+               char temp_m[4], temp_d[3], temp_y[5];
+
+               temp_m[0] = g_lamexp_version_raw_date[0x0];
+               temp_m[1] = g_lamexp_version_raw_date[0x1];
+               temp_m[2] = g_lamexp_version_raw_date[0x2];
+               temp_m[3] = 0x00;
+
+               temp_d[0] = g_lamexp_version_raw_date[0x4];
+               temp_d[1] = g_lamexp_version_raw_date[0x5];
+               temp_d[2] = 0x00;
+
+               temp_y[0] = g_lamexp_version_raw_date[0x7];
+               temp_y[1] = g_lamexp_version_raw_date[0x8];
+               temp_y[2] = g_lamexp_version_raw_date[0x9];
+               temp_y[3] = g_lamexp_version_raw_date[0xA];
+               temp_y[4] = 0x00;
+               
+               date[0] = atoi(temp_y);
+               date[1] = lamexp_month2int(temp_m);
+               date[2] = atoi(temp_d);
+
+               if((date[0] > 0) && (date[1] > 0) && (date[2] > 0))
+               {
+
+                       g_lamexp_version_date = QDate(date[0], date[1], date[2]);
+               }
+               else
+               {
+                       THROW("Internal error: Date format could not be recognized!");
+               }
+       }
+
+       return g_lamexp_version_date;
+}
+
+/*
+ * Check for LameXP "portable" mode
+ */
+bool lamexp_portable_mode(void)
+{
+       QReadLocker readLock(&g_lamexp_portable.lock);
+
+       if(g_lamexp_portable.bInitialized)
+       {
+               return g_lamexp_portable.bPortableModeEnabled;
+       }
+       
+       readLock.unlock();
+       QWriteLocker writeLock(&g_lamexp_portable.lock);
+
+       if(!g_lamexp_portable.bInitialized)
+       {
+               if(VER_LAMEXP_PORTABLE_EDITION)
+               {
+                       qWarning("LameXP portable edition!\n");
+                       g_lamexp_portable.bPortableModeEnabled = true;
+               }
+               else
+               {
+                       QString baseName = QFileInfo(QApplication::applicationFilePath()).completeBaseName();
+                       int idx1 = baseName.indexOf("lamexp", 0, Qt::CaseInsensitive);
+                       int idx2 = baseName.lastIndexOf("portable", -1, Qt::CaseInsensitive);
+                       g_lamexp_portable.bPortableModeEnabled = (idx1 >= 0) && (idx2 >= 0) && (idx1 < idx2);
+               }
+               g_lamexp_portable.bInitialized = true;
+       }
+       
+       return g_lamexp_portable.bPortableModeEnabled;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// INITIALIZATION
+///////////////////////////////////////////////////////////////////////////////
+
+extern "C" void _lamexp_global_init_versn(void)
+{
+       LAMEXP_ZERO_MEMORY(g_lamexp_portable);
+}
similarity index 56%
rename from src/Global.cpp
rename to src/Global_Win32.cpp
index 99415c8..cfd6c25 100644 (file)
 
 #include "Global.h"
 
+//Target version
+#include "Targetver.h"
+
+//Visual Leaks Detector
+#include <vld.h>
+
 //Windows includes
 #define NOMINMAX
 #define WIN32_LEAN_AND_MEAN
 #include <MMSystem.h>
 #include <ShellAPI.h>
 #include <SensAPI.h>
+#include <Objbase.h>
+#include <PowrProf.h>
+#include <Psapi.h>
 
 //Qt includes
 #include <QApplication>
-#include <QMessageBox>
-#include <QDir>
-#include <QUuid>
-#include <QMap>
 #include <QDate>
+#include <QDir>
+#include <QEvent>
 #include <QIcon>
-#include <QPlastiqueStyle>
 #include <QImageReader>
-#include <QSharedMemory>
-#include <QSysInfo>
-#include <QStringList>
-#include <QSystemSemaphore>
-#include <QMutex>
-#include <QTextCodec>
 #include <QLibrary>
-#include <QRegExp>
-#include <QResource>
-#include <QTranslator>
-#include <QEventLoop>
-#include <QTimer>
 #include <QLibraryInfo>
-#include <QEvent>
-#include <QReadWriteLock>
-#include <QReadLocker>
-#include <QWriteLocker>
+#include <QMap>
+#include <QMessageBox>
+#include <QMutex>
+#include <QPlastiqueStyle>
 #include <QProcess>
+#include <QReadWriteLock>
+#include <QRegExp>
+#include <QSysInfo>
+#include <QTextCodec>
+#include <QTimer>
+#include <QTranslator>
+#include <QUuid>
 
 //LameXP includes
 #define LAMEXP_INC_CONFIG
 #include "Resource.h"
 #include "Config.h"
-#include "LockedFile.h"
-#include "strnatcmp.h"
 
 //CRT includes
+#include <cstdio>
 #include <iostream>
 #include <fstream>
 #include <io.h>
 #include <fcntl.h>
 #include <intrin.h>
-#include <math.h>
-#include <time.h>
+#include <cmath>
+#include <ctime>
 #include <process.h>
 
-//Shell API
-#include <Shellapi.h>
-
-//COM includes
-#include <Objbase.h>
-#include <PowrProf.h>
-
-//Process API
-#include <Psapi.h>
-
 //Initialize static Qt plugins
 #ifdef QT_NODLL
 #if QT_VERSION < QT_VERSION_CHECK(5,0,0)
@@ -97,9 +88,10 @@ Q_IMPORT_PLUGIN(QICOPlugin)
 #endif
 #endif
 
-#define LAMEXP_ZERO_MEMORY(X) SecureZeroMemory(&X, sizeof(X))
+///////////////////////////////////////////////////////////////////////////////
+// HELPER MACROS
+///////////////////////////////////////////////////////////////////////////////
 
-//Helper macros
 #define _LAMEXP_MAKE_STR(STR) #STR
 #define LAMEXP_MAKE_STR(STR) _LAMEXP_MAKE_STR(STR)
 
@@ -126,70 +118,12 @@ while(0)
 while(0)
 
 ///////////////////////////////////////////////////////////////////////////////
-// TYPES
-///////////////////////////////////////////////////////////////////////////////
-
-static const size_t g_lamexp_ipc_slots = 128;
-
-typedef struct
-{
-       unsigned int command;
-       unsigned int reserved_1;
-       unsigned int reserved_2;
-       char parameter[4096];
-}
-lamexp_ipc_data_t;
-
-typedef struct
-{
-       unsigned int pos_write;
-       unsigned int pos_read;
-       lamexp_ipc_data_t data[g_lamexp_ipc_slots];
-}
-lamexp_ipc_t;
-
-///////////////////////////////////////////////////////////////////////////////
 // GLOBAL VARS
 ///////////////////////////////////////////////////////////////////////////////
 
-//Build version
-static const struct
-{
-       unsigned int ver_major;
-       unsigned int ver_minor;
-       unsigned int ver_build;
-       unsigned int ver_confg;
-       char *ver_release_name;
-}
-g_lamexp_version =
-{
-       VER_LAMEXP_MAJOR,
-       (10 * VER_LAMEXP_MINOR_HI) + VER_LAMEXP_MINOR_LO,
-       VER_LAMEXP_BUILD,
-       VER_LAMEXP_CONFG,
-       VER_LAMEXP_RNAME,
-};
-
-//Build date
-static QDate g_lamexp_version_date;
-static const char *g_lamexp_months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
-static const char *g_lamexp_version_raw_date = __DATE__;
-static const char *g_lamexp_version_raw_time = __TIME__;
-
 //Console attached flag
 static bool g_lamexp_console_attached = false;
 
-//Official web-site URL
-static const char *g_lamexp_website_url = "http://lamexp.sourceforge.net/";
-static const char *g_lamexp_support_url = "http://forum.doom9.org/showthread.php?t=157726";
-static const char *g_lamexp_mulders_url = "http://muldersoft.com/";
-
-//Tool versions (expected versions!)
-static const unsigned int g_lamexp_toolver_neroaac = VER_LAMEXP_TOOL_NEROAAC;
-static const unsigned int g_lamexp_toolver_fhgaacenc = VER_LAMEXP_TOOL_FHGAACENC;
-static const unsigned int g_lamexp_toolver_qaacenc = VER_LAMEXP_TOOL_QAAC;
-static const unsigned int g_lamexp_toolver_coreaudio = VER_LAMEXP_TOOL_COREAUDIO;
-
 //Special folders
 static struct
 {
@@ -198,43 +132,6 @@ static struct
 }
 g_lamexp_known_folder;
 
-//%TEMP% folder
-static struct
-{
-       QString *path;
-       QReadWriteLock lock;
-}
-g_lamexp_temp_folder;
-
-//Tools
-static struct
-{
-       QMap<QString, LockedFile*> *registry;
-       QMap<QString, unsigned int> *versions;
-       QMap<QString, QString> *tags;
-       QReadWriteLock lock;
-}
-g_lamexp_tools;
-
-//Languages
-static struct
-{
-       QMap<QString, QString> *files;
-       QMap<QString, QString> *names;
-       QMap<QString, unsigned int> *sysid;
-       QMap<QString, unsigned int> *cntry;
-       QReadWriteLock lock;
-}
-g_lamexp_translation;
-
-//Translator
-static struct
-{
-       QTranslator *instance;
-       QReadWriteLock lock;
-}
-g_lamexp_currentTranslator;
-
 //CLI Arguments
 static struct
 {
@@ -252,14 +149,14 @@ static struct
 }
 g_lamexp_os_version;
 
-//Portable Mode
+//Wine detection
 static struct
 {
        bool bInitialized;
-       bool bPortableModeEnabled;
+       bool bIsWine;
        QReadWriteLock lock;
 }
-g_lamexp_portable;
+g_lamexp_wine;
 
 //Win32 Theme support
 static struct
@@ -270,34 +167,6 @@ static struct
 }
 g_lamexp_themes_enabled;
 
-//Shared memory
-static const struct
-{
-       char *sharedmem;
-       char *semaphore_read;
-       char *semaphore_read_mutex;
-       char *semaphore_write;
-       char *semaphore_write_mutex;
-}
-g_lamexp_ipc_uuid =
-{
-       "{21A68A42-6923-43bb-9CF6-64BF151942EE}",
-       "{7A605549-F58C-4d78-B4E5-06EFC34F405B}",
-       "{60AA8D04-F6B8-497d-81EB-0F600F4A65B5}",
-       "{726061D5-1615-4B82-871C-75FD93458E46}",
-       "{1A616023-AA6A-4519-8AF3-F7736E899977}"
-};
-static struct
-{
-       QSharedMemory *sharedmem;
-       QSystemSemaphore *semaphore_read;
-       QSystemSemaphore *semaphore_read_mutex;
-       QSystemSemaphore *semaphore_write;
-       QSystemSemaphore *semaphore_write_mutex;
-       QReadWriteLock lock;
-}
-g_lamexp_ipc_ptr;
-
 //Image formats
 static const char *g_lamexp_imageformats[] = {"bmp", "png", "jpg", "gif", "ico", "xpm", NULL}; //"svg"
 
@@ -327,206 +196,12 @@ const lamexp_os_version_t lamexp_winver_win81 = {6,3};
 static const char *GURU_MEDITATION = "\n\nGURU MEDITATION !!!\n\n";
 
 ///////////////////////////////////////////////////////////////////////////////
-// COMPILER INFO
-///////////////////////////////////////////////////////////////////////////////
-
-/*
- * Disclaimer: Parts of the following code were borrowed from MPC-HC project: http://mpc-hc.sf.net/
- */
-
-//Compiler detection
-#if defined(__INTEL_COMPILER)
-       #if (__INTEL_COMPILER >= 1300)
-               static const char *g_lamexp_version_compiler = "ICL 13." LAMEXP_MAKE_STR(__INTEL_COMPILER_BUILD_DATE);
-       #elif (__INTEL_COMPILER >= 1200)
-               static const char *g_lamexp_version_compiler = "ICL 12." LAMEXP_MAKE_STR(__INTEL_COMPILER_BUILD_DATE);
-       #elif (__INTEL_COMPILER >= 1100)
-               static const char *g_lamexp_version_compiler = "ICL 11.x";
-       #elif (__INTEL_COMPILER >= 1000)
-               static const char *g_lamexp_version_compiler = "ICL 10.x";
-       #else
-               #error Compiler is not supported!
-       #endif
-#elif defined(_MSC_VER)
-       #if (_MSC_VER == 1800)
-               #if (_MSC_FULL_VER < 180021005)
-                       static const char *g_lamexp_version_compiler = "MSVC 2013-Beta";
-               #elif (_MSC_FULL_VER == 180021005)
-                       static const char *g_lamexp_version_compiler = "MSVC 2013";
-               #else
-                       #error Compiler version is not supported yet!
-               #endif
-       #elif (_MSC_VER == 1700)
-               #if (_MSC_FULL_VER < 170050727)
-                       static const char *g_lamexp_version_compiler = "MSVC 2012-Beta";
-               #elif (_MSC_FULL_VER < 170051020)
-                       static const char *g_lamexp_version_compiler = "MSVC 2012";
-               #elif (_MSC_FULL_VER < 170051106)
-                       static const char *g_lamexp_version_compiler = "MSVC 2012.1-CTP";
-               #elif (_MSC_FULL_VER < 170060315)
-                       static const char *g_lamexp_version_compiler = "MSVC 2012.1";
-               #elif (_MSC_FULL_VER < 170060610)
-                       static const char *g_lamexp_version_compiler = "MSVC 2012.2";
-               #elif (_MSC_FULL_VER == 170060610)
-                       static const char *g_lamexp_version_compiler = "MSVC 2012.3";
-               #else
-                       #error Compiler version is not supported yet!
-               #endif
-       #elif (_MSC_VER == 1600)
-               #if (_MSC_FULL_VER < 160040219)
-                       static const char *g_lamexp_version_compiler = "MSVC 2010";
-               #elif (_MSC_FULL_VER == 160040219)
-                       static const char *g_lamexp_version_compiler = "MSVC 2010-SP1";
-               #else
-                       #error Compiler version is not supported yet!
-               #endif
-       #elif (_MSC_VER == 1500)
-               #if (_MSC_FULL_VER >= 150030729)
-                       static const char *g_lamexp_version_compiler = "MSVC 2008-SP1";
-               #else
-                       static const char *g_lamexp_version_compiler = "MSVC 2008";
-               #endif
-       #else
-               #error Compiler is not supported!
-       #endif
-
-       // Note: /arch:SSE and /arch:SSE2 are only available for the x86 platform
-       #if !defined(_M_X64) && defined(_M_IX86_FP)
-               #if (_M_IX86_FP == 1)
-                       LAMEXP_COMPILER_WARNING("SSE instruction set is enabled!")
-               #elif (_M_IX86_FP == 2)
-                       LAMEXP_COMPILER_WARNING("SSE2 (or higher) instruction set is enabled!")
-               #endif
-       #endif
-#else
-       #error Compiler is not supported!
-#endif
-
-//Architecture detection
-#if defined(_M_X64)
-       static const char *g_lamexp_version_arch = "x64";
-#elif defined(_M_IX86)
-       static const char *g_lamexp_version_arch = "x86";
-#else
-       #error Architecture is not supported!
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
 // GLOBAL FUNCTIONS
 ///////////////////////////////////////////////////////////////////////////////
 
 /*
- * Version getters
- */
-unsigned int lamexp_version_major(void) { return g_lamexp_version.ver_major; }
-unsigned int lamexp_version_minor(void) { return g_lamexp_version.ver_minor; }
-unsigned int lamexp_version_build(void) { return g_lamexp_version.ver_build; }
-unsigned int lamexp_version_confg(void) { return g_lamexp_version.ver_confg; }
-const char *lamexp_version_release(void) { return g_lamexp_version.ver_release_name; }
-const char *lamexp_version_time(void) { return g_lamexp_version_raw_time; }
-const char *lamexp_version_compiler(void) { return g_lamexp_version_compiler; }
-const char *lamexp_version_arch(void) { return g_lamexp_version_arch; }
-unsigned int lamexp_toolver_neroaac(void) { return g_lamexp_toolver_neroaac; }
-unsigned int lamexp_toolver_fhgaacenc(void) { return g_lamexp_toolver_fhgaacenc; }
-unsigned int lamexp_toolver_qaacenc(void) { return g_lamexp_toolver_qaacenc; }
-unsigned int lamexp_toolver_coreaudio(void) { return g_lamexp_toolver_coreaudio; }
-
-/*
- * URL getters
- */
-const char *lamexp_website_url(void) { return g_lamexp_website_url; }
-const char *lamexp_mulders_url(void) { return g_lamexp_mulders_url; }
-const char *lamexp_support_url(void) { return g_lamexp_support_url; }
-
-/*
- * Check for Demo (pre-release) version
- */
-bool lamexp_version_demo(void)
-{
-       char buffer[128];
-       bool releaseVersion = false;
-       if(!strncpy_s(buffer, 128, g_lamexp_version.ver_release_name, _TRUNCATE))
-       {
-               char *context, *prefix = strtok_s(buffer, "-,; ", &context);
-               if(prefix)
-               {
-                       releaseVersion = (!_stricmp(prefix, "Final")) || (!_stricmp(prefix, "Hotfix"));
-               }
-       }
-       return (!releaseVersion);
-}
-
-/*
- * Calculate expiration date
- */
-QDate lamexp_version_expires(void)
-{
-       return lamexp_version_date().addDays(LAMEXP_DEBUG ? 7 : 30);
-}
-
-/*
- * Convert month string to integer value
- */
-static int lamexp_month2int(const char *str)
-{
-       int ret = 0;
-
-       for(int j = 0; j < 12; j++)
-       {
-               if(!_strcmpi(str, g_lamexp_months[j]))
-               {
-                       ret = j+1;
-                       break;
-               }
-       }
-
-       return ret;
-}
-
-/*
- * Get build date date
+ * Verify a specific Windows version
  */
-const QDate &lamexp_version_date(void)
-{
-       //Format of __DATE__ is defined as: "MMM DD YYYY"
-       if(!g_lamexp_version_date.isValid())
-       {
-               int date[3] = {0, 0, 0};
-               char temp_m[4], temp_d[3], temp_y[5];
-
-               temp_m[0] = g_lamexp_version_raw_date[0x0];
-               temp_m[1] = g_lamexp_version_raw_date[0x1];
-               temp_m[2] = g_lamexp_version_raw_date[0x2];
-               temp_m[3] = 0x00;
-
-               temp_d[0] = g_lamexp_version_raw_date[0x4];
-               temp_d[1] = g_lamexp_version_raw_date[0x5];
-               temp_d[2] = 0x00;
-
-               temp_y[0] = g_lamexp_version_raw_date[0x7];
-               temp_y[1] = g_lamexp_version_raw_date[0x8];
-               temp_y[2] = g_lamexp_version_raw_date[0x9];
-               temp_y[3] = g_lamexp_version_raw_date[0xA];
-               temp_y[4] = 0x00;
-               
-               date[0] = atoi(temp_y);
-               date[1] = lamexp_month2int(temp_m);
-               date[2] = atoi(temp_d);
-
-               if((date[0] > 0) && (date[1] > 0) && (date[2] > 0))
-               {
-
-                       g_lamexp_version_date = QDate(date[0], date[1], date[2]);
-               }
-               else
-               {
-                       THROW("Internal error: Date format could not be recognized!");
-               }
-       }
-
-       return g_lamexp_version_date;
-}
-
 static bool lamexp_verify_os_version(const DWORD major, const DWORD minor)
 {
        OSVERSIONINFOEXW osvi;
@@ -662,31 +337,31 @@ const lamexp_os_version_t &lamexp_get_os_version(void)
  */
 bool lamexp_detect_wine(void)
 {
-       static bool isWine = false;
-       static bool isWine_initialized = false;
+       QReadLocker readLock(&g_lamexp_wine.lock);
+
+       //Already initialized?
+       if(g_lamexp_wine.bInitialized)
+       {
+               return g_lamexp_wine.bIsWine;
+       }
+       
+       readLock.unlock();
+       QWriteLocker writeLock(&g_lamexp_wine.lock);
 
-       if(!isWine_initialized)
+       if(!g_lamexp_wine.bInitialized)
        {
+               g_lamexp_wine.bIsWine = false;
                QLibrary ntdll("ntdll.dll");
                if(ntdll.load())
                {
-                       if(ntdll.resolve("wine_nt_to_unix_file_name") != NULL) isWine = true;
-                       if(ntdll.resolve("wine_get_version") != NULL) isWine = true;
+                       if(ntdll.resolve("wine_nt_to_unix_file_name") != NULL) g_lamexp_wine.bIsWine = true;
+                       if(ntdll.resolve("wine_get_version") != NULL) g_lamexp_wine.bIsWine = true;
                        ntdll.unload();
                }
-               isWine_initialized = true;
+               g_lamexp_wine.bInitialized = true;
        }
 
-       return isWine;
-}
-
-/*
- * Global exception handler
- */
-LONG WINAPI lamexp_exception_handler(__in struct _EXCEPTION_POINTERS *ExceptionInfo)
-{
-       lamexp_fatal_exit(L"Unhandeled exception handler invoked, application will exit!");
-       return LONG_MAX;
+       return g_lamexp_wine.bIsWine;
 }
 
 /*
@@ -865,6 +540,27 @@ void lamexp_message_handler(QtMsgType type, const char *msg)
        }
 }
 
+
+/*
+ * Global exception handler
+ */
+static LONG WINAPI lamexp_exception_handler(__in struct _EXCEPTION_POINTERS *ExceptionInfo)
+{
+       lamexp_fatal_exit(L"Unhandeled exception handler invoked, application will exit!");
+       return LONG_MAX;
+}
+
+/*
+ * Initialize error handlers
+ */
+void lamexp_init_error_handlers(void)
+{
+       SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
+       SetUnhandledExceptionFilter(lamexp_exception_handler);
+       SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
+       _set_invalid_parameter_handler(lamexp_invalid_param_handler);
+}
+
 /*
  * Initialize the console
  */
@@ -1110,123 +806,6 @@ static HANDLE lamexp_debug_thread_init()
 }
 
 /*
- * Computus according to H. Lichtenberg
- */
-static bool lamexp_computus(const QDate &date)
-{
-       int X = date.year();
-       int A = X % 19;
-       int K = X / 100;
-       int M = 15 + (3*K + 3) / 4 - (8*K + 13) / 25;
-       int D = (19*A + M) % 30;
-       int S = 2 - (3*K + 3) / 4;
-       int R = D / 29 + (D / 28 - D / 29) * (A / 11);
-       int OG = 21 + D - R;
-       int SZ = 7 - (X + X / 4 + S) % 7;
-       int OE = 7 - (OG - SZ) % 7;
-       int OS = (OG + OE);
-
-       if(OS > 31)
-       {
-               return (date.month() == 4) && (date.day() == (OS - 31));
-       }
-       else
-       {
-               return (date.month() == 3) && (date.day() == OS);
-       }
-}
-
-/*
- * Check for Thanksgiving
- */
-static bool lamexp_thanksgiving(const QDate &date)
-{
-       int day = 0;
-
-       switch(QDate(date.year(), 11, 1).dayOfWeek())
-       {
-               case 1: day = 25; break; 
-               case 2: day = 24; break; 
-               case 3: day = 23; break; 
-               case 4: day = 22; break; 
-               case 5: day = 28; break; 
-               case 6: day = 27; break; 
-               case 7: day = 26; break;
-       }
-
-       return (date.month() == 11) && (date.day() == day);
-}
-
-/*
- * Initialize app icon
- */
-QIcon lamexp_app_icon(const QDate *date, const QTime *time)
-{
-       QDate currentDate = (date) ? QDate(*date) : QDate::currentDate();
-       QTime currentTime = (time) ? QTime(*time) : QTime::currentTime();
-       
-       if(lamexp_thanksgiving(currentDate))
-       {
-               return QIcon(":/MainIcon6.png");
-       }
-       else if(((currentDate.month() == 12) && (currentDate.day() == 31) && (currentTime.hour() >= 20)) || ((currentDate.month() == 1) && (currentDate.day() == 1)  && (currentTime.hour() <= 19)))
-       {
-               return QIcon(":/MainIcon5.png");
-       }
-       else if(((currentDate.month() == 10) && (currentDate.day() == 31) && (currentTime.hour() >= 12)) || ((currentDate.month() == 11) && (currentDate.day() == 1)  && (currentTime.hour() <= 11)))
-       {
-               return QIcon(":/MainIcon4.png");
-       }
-       else if((currentDate.month() == 12) && (currentDate.day() >= 24) && (currentDate.day() <= 26))
-       {
-               return QIcon(":/MainIcon3.png");
-       }
-       else if(lamexp_computus(currentDate))
-       {
-               return QIcon(":/MainIcon2.png");
-       }
-       else
-       {
-               return QIcon(":/MainIcon1.png");
-       }
-}
-
-/*
- * Broadcast event to all windows
- */
-static bool lamexp_broadcast(int eventType, bool onlyToVisible)
-{
-       if(QApplication *app = dynamic_cast<QApplication*>(QApplication::instance()))
-       {
-               qDebug("Broadcasting %d", eventType);
-               
-               bool allOk = true;
-               QEvent poEvent(static_cast<QEvent::Type>(eventType));
-               QWidgetList list = app->topLevelWidgets();
-
-               while(!list.isEmpty())
-               {
-                       QWidget *widget = list.takeFirst();
-                       if(!onlyToVisible || widget->isVisible())
-                       {
-                               if(!app->sendEvent(widget, &poEvent))
-                               {
-                                       allOk = false;
-                               }
-                       }
-               }
-
-               qDebug("Broadcast %d done (%s)", eventType, (allOk ? "OK" : "Stopped"));
-               return allOk;
-       }
-       else
-       {
-               qWarning("Broadcast failed, could not get QApplication instance!");
-               return false;
-       }
-}
-
-/*
  * Qt event filter
  */
 static bool lamexp_event_filter(void *message, long *result)
@@ -1452,13 +1031,8 @@ bool lamexp_init_qt(int argc, char* argv[])
                }
        }
        
-       //Add default translations
-       QWriteLocker writeLockTranslations(&g_lamexp_translation.lock);
-       if(!g_lamexp_translation.files) g_lamexp_translation.files = new QMap<QString, QString>();
-       if(!g_lamexp_translation.names) g_lamexp_translation.names = new QMap<QString, QString>();
-       g_lamexp_translation.files->insert(LAMEXP_DEFAULT_LANGID, "");
-       g_lamexp_translation.names->insert(LAMEXP_DEFAULT_LANGID, "English");
-       writeLockTranslations.unlock();
+       //Add the default translations
+       lamexp_translation_init();
 
        //Check for process elevation
        if((!lamexp_check_elevation()) && (!lamexp_detect_wine()))
@@ -1481,7 +1055,8 @@ bool lamexp_init_qt(int argc, char* argv[])
                if(kernel32.load())
                {
                        SetConsoleIconFun SetConsoleIconPtr = (SetConsoleIconFun) kernel32.resolve("SetConsoleIcon");
-                       if(SetConsoleIconPtr != NULL) SetConsoleIconPtr(QIcon(":/icons/sound.png").pixmap(16, 16).toWinHICON());
+                       QPixmap pixmap = QIcon(":/icons/sound.png").pixmap(16, 16);
+                       if((SetConsoleIconPtr != NULL) && (!pixmap.isNull())) SetConsoleIconPtr(pixmap.toWinHICON());
                        kernel32.unload();
                }
        }
@@ -1492,630 +1067,25 @@ bool lamexp_init_qt(int argc, char* argv[])
        return true;
 }
 
-/*
- * Initialize IPC
- */
-int lamexp_init_ipc(void)
+const QStringList &lamexp_arguments(void)
 {
-       QWriteLocker writeLock(&g_lamexp_ipc_ptr.lock);
-       
-       if(g_lamexp_ipc_ptr.sharedmem && g_lamexp_ipc_ptr.semaphore_read && g_lamexp_ipc_ptr.semaphore_write && g_lamexp_ipc_ptr.semaphore_read_mutex && g_lamexp_ipc_ptr.semaphore_write_mutex)
+       QReadLocker readLock(&g_lamexp_argv.lock);
+
+       if(!g_lamexp_argv.list)
        {
-               return 0;
-       }
+               readLock.unlock();
+               QWriteLocker writeLock(&g_lamexp_argv.lock);
 
-       g_lamexp_ipc_ptr.semaphore_read = new QSystemSemaphore(QString(g_lamexp_ipc_uuid.semaphore_read), 0);
-       g_lamexp_ipc_ptr.semaphore_write = new QSystemSemaphore(QString(g_lamexp_ipc_uuid.semaphore_write), 0);
-       g_lamexp_ipc_ptr.semaphore_read_mutex = new QSystemSemaphore(QString(g_lamexp_ipc_uuid.semaphore_read_mutex), 0);
-       g_lamexp_ipc_ptr.semaphore_write_mutex = new QSystemSemaphore(QString(g_lamexp_ipc_uuid.semaphore_write_mutex), 0);
+               g_lamexp_argv.list = new QStringList;
 
-       if(g_lamexp_ipc_ptr.semaphore_read->error() != QSystemSemaphore::NoError)
-       {
-               QString errorMessage = g_lamexp_ipc_ptr.semaphore_read->errorString();
-               LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_read);
-               LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_write);
-               LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_read_mutex);
-               LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_write_mutex);
-               qFatal("Failed to create system smaphore: %s", QUTF8(errorMessage));
-               return -1;
-       }
-       if(g_lamexp_ipc_ptr.semaphore_write->error() != QSystemSemaphore::NoError)
-       {
-               QString errorMessage = g_lamexp_ipc_ptr.semaphore_write->errorString();
-               LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_read);
-               LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_write);
-               LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_read_mutex);
-               LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_write_mutex);
-               qFatal("Failed to create system smaphore: %s", QUTF8(errorMessage));
-               return -1;
-       }
-       if(g_lamexp_ipc_ptr.semaphore_read_mutex->error() != QSystemSemaphore::NoError)
-       {
-               QString errorMessage = g_lamexp_ipc_ptr.semaphore_read_mutex->errorString();
-               LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_read);
-               LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_write);
-               LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_read_mutex);
-               LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_write_mutex);
-               qFatal("Failed to create system smaphore: %s", QUTF8(errorMessage));
-               return -1;
-       }
-       if(g_lamexp_ipc_ptr.semaphore_write_mutex->error() != QSystemSemaphore::NoError)
-       {
-               QString errorMessage = g_lamexp_ipc_ptr.semaphore_write_mutex->errorString();
-               LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_read);
-               LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_write);
-               LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_read_mutex);
-               LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_write_mutex);
-               qFatal("Failed to create system smaphore: %s", QUTF8(errorMessage));
-               return -1;
-       }
+               int nArgs = 0;
+               LPWSTR *szArglist = CommandLineToArgvW(GetCommandLineW(), &nArgs);
 
-       g_lamexp_ipc_ptr.sharedmem = new QSharedMemory(QString(g_lamexp_ipc_uuid.sharedmem), NULL);
-       
-       if(!g_lamexp_ipc_ptr.sharedmem->create(sizeof(lamexp_ipc_t)))
-       {
-               if(g_lamexp_ipc_ptr.sharedmem->error() == QSharedMemory::AlreadyExists)
+               if(NULL != szArglist)
                {
-                       g_lamexp_ipc_ptr.sharedmem->attach();
-                       if(g_lamexp_ipc_ptr.sharedmem->error() == QSharedMemory::NoError)
-                       {
-                               return 1;
-                       }
-                       else
+                       for(int i = 0; i < nArgs; i++)
                        {
-                               QString errorMessage = g_lamexp_ipc_ptr.sharedmem->errorString();
-                               LAMEXP_DELETE(g_lamexp_ipc_ptr.sharedmem);
-                               qFatal("Failed to attach to shared memory: %s", QUTF8(errorMessage));
-                               return -1;
-                       }
-               }
-               else
-               {
-                       QString errorMessage = g_lamexp_ipc_ptr.sharedmem->errorString();
-                       LAMEXP_DELETE(g_lamexp_ipc_ptr.sharedmem);
-                       qFatal("Failed to create shared memory: %s", QUTF8(errorMessage));
-                       return -1;
-               }
-       }
-
-       memset(g_lamexp_ipc_ptr.sharedmem->data(), 0, sizeof(lamexp_ipc_t));
-       g_lamexp_ipc_ptr.semaphore_write->release(g_lamexp_ipc_slots);
-       g_lamexp_ipc_ptr.semaphore_read_mutex->release();
-       g_lamexp_ipc_ptr.semaphore_write_mutex->release();
-
-       return 0;
-}
-
-/*
- * IPC send message
- */
-void lamexp_ipc_send(unsigned int command, const char* message)
-{
-       QReadLocker readLock(&g_lamexp_ipc_ptr.lock);
-
-       if(!g_lamexp_ipc_ptr.sharedmem || !g_lamexp_ipc_ptr.semaphore_read || !g_lamexp_ipc_ptr.semaphore_write || !g_lamexp_ipc_ptr.semaphore_read_mutex || !g_lamexp_ipc_ptr.semaphore_write_mutex)
-       {
-               THROW("Shared memory for IPC not initialized yet.");
-       }
-
-       lamexp_ipc_data_t ipc_data;
-       memset(&ipc_data, 0, sizeof(lamexp_ipc_data_t));
-       ipc_data.command = command;
-       
-       if(message)
-       {
-               strncpy_s(ipc_data.parameter, 4096, message, _TRUNCATE);
-       }
-
-       if(g_lamexp_ipc_ptr.semaphore_write->acquire())
-       {
-               if(g_lamexp_ipc_ptr.semaphore_write_mutex->acquire())
-               {
-                       lamexp_ipc_t *ptr = reinterpret_cast<lamexp_ipc_t*>(g_lamexp_ipc_ptr.sharedmem->data());
-                       memcpy(&ptr->data[ptr->pos_write], &ipc_data, sizeof(lamexp_ipc_data_t));
-                       ptr->pos_write = (ptr->pos_write + 1) % g_lamexp_ipc_slots;
-                       g_lamexp_ipc_ptr.semaphore_read->release();
-                       g_lamexp_ipc_ptr.semaphore_write_mutex->release();
-               }
-       }
-}
-
-/*
- * IPC read message
- */
-void lamexp_ipc_read(unsigned int *command, char* message, size_t buffSize)
-{
-       QReadLocker readLock(&g_lamexp_ipc_ptr.lock);
-       
-       *command = 0;
-       message[0] = '\0';
-       
-       if(!g_lamexp_ipc_ptr.sharedmem || !g_lamexp_ipc_ptr.semaphore_read || !g_lamexp_ipc_ptr.semaphore_write || !g_lamexp_ipc_ptr.semaphore_read_mutex || !g_lamexp_ipc_ptr.semaphore_write_mutex)
-       {
-               THROW("Shared memory for IPC not initialized yet.");
-       }
-
-       lamexp_ipc_data_t ipc_data;
-       memset(&ipc_data, 0, sizeof(lamexp_ipc_data_t));
-
-       if(g_lamexp_ipc_ptr.semaphore_read->acquire())
-       {
-               if(g_lamexp_ipc_ptr.semaphore_read_mutex->acquire())
-               {
-                       lamexp_ipc_t *ptr = reinterpret_cast<lamexp_ipc_t*>(g_lamexp_ipc_ptr.sharedmem->data());
-                       memcpy(&ipc_data, &ptr->data[ptr->pos_read], sizeof(lamexp_ipc_data_t));
-                       ptr->pos_read = (ptr->pos_read + 1) % g_lamexp_ipc_slots;
-                       g_lamexp_ipc_ptr.semaphore_write->release();
-                       g_lamexp_ipc_ptr.semaphore_read_mutex->release();
-
-                       if(!(ipc_data.reserved_1 || ipc_data.reserved_2))
-                       {
-                               *command = ipc_data.command;
-                               strncpy_s(message, buffSize, ipc_data.parameter, _TRUNCATE);
-                       }
-                       else
-                       {
-                               qWarning("Malformed IPC message, will be ignored");
-                       }
-               }
-       }
-}
-
-/*
- * Check for LameXP "portable" mode
- */
-bool lamexp_portable_mode(void)
-{
-       QReadLocker readLock(&g_lamexp_portable.lock);
-
-       if(g_lamexp_portable.bInitialized)
-       {
-               return g_lamexp_portable.bPortableModeEnabled;
-       }
-       
-       readLock.unlock();
-       QWriteLocker writeLock(&g_lamexp_portable.lock);
-
-       if(!g_lamexp_portable.bInitialized)
-       {
-               if(VER_LAMEXP_PORTABLE_EDITION)
-               {
-                       qWarning("LameXP portable edition!\n");
-                       g_lamexp_portable.bPortableModeEnabled = true;
-               }
-               else
-               {
-                       QString baseName = QFileInfo(QApplication::applicationFilePath()).completeBaseName();
-                       int idx1 = baseName.indexOf("lamexp", 0, Qt::CaseInsensitive);
-                       int idx2 = baseName.lastIndexOf("portable", -1, Qt::CaseInsensitive);
-                       g_lamexp_portable.bPortableModeEnabled = (idx1 >= 0) && (idx2 >= 0) && (idx1 < idx2);
-               }
-               g_lamexp_portable.bInitialized = true;
-       }
-       
-       return g_lamexp_portable.bPortableModeEnabled;
-}
-
-/*
- * Get a random string
- */
-QString lamexp_rand_str(const bool bLong)
-{
-       const QUuid uuid = QUuid::createUuid().toString();
-
-       const unsigned int u1 = uuid.data1;
-       const unsigned int u2 = (((unsigned int)(uuid.data2)) << 16) | ((unsigned int)(uuid.data3));
-       const unsigned int u3 = (((unsigned int)(uuid.data4[0])) << 24) | (((unsigned int)(uuid.data4[1])) << 16) | (((unsigned int)(uuid.data4[2])) << 8) | ((unsigned int)(uuid.data4[3]));
-       const unsigned int u4 = (((unsigned int)(uuid.data4[4])) << 24) | (((unsigned int)(uuid.data4[5])) << 16) | (((unsigned int)(uuid.data4[6])) << 8) | ((unsigned int)(uuid.data4[7]));
-
-       return bLong ? QString().sprintf("%08x%08x%08x%08x", u1, u2, u3, u4) : QString().sprintf("%08x%08x", (u1 ^ u2), (u3 ^ u4));
-}
-
-
-/*
- * Try to initialize the folder (with *write* access)
- */
-static QString lamexp_try_init_folder(const QString &folderPath)
-{
-       bool success = false;
-
-       const QFileInfo folderInfo(folderPath);
-       const QDir folderDir(folderInfo.absoluteFilePath());
-
-       //Create folder, if it does *not* exist yet
-       if(!folderDir.exists())
-       {
-               folderDir.mkpath(".");
-       }
-
-       //Make sure folder exists now *and* is writable
-       if(folderDir.exists())
-       {
-               QFile testFile(folderDir.absoluteFilePath(QString("~%1.tmp").arg(lamexp_rand_str())));
-               if(testFile.open(QIODevice::ReadWrite))
-               {
-                       const QByteArray testData = QByteArray("Lorem ipsum dolor sit amet, consectetur, adipisci velit!");
-                       if(testFile.write(testData) >= strlen(testData))
-                       {
-                               success = true;
-                               testFile.remove();
-                       }
-                       testFile.close();
-               }
-       }
-
-       return (success ? folderDir.canonicalPath() : QString());
-}
-
-/*
- * Initialize LameXP temp folder
- */
-#define INIT_TEMP_FOLDER(OUT,TMP) do \
-{ \
-       (OUT) = lamexp_try_init_folder(QString("%1/%2").arg((TMP), lamexp_rand_str())); \
-} \
-while(0)
-
-/*
- * Get LameXP temp folder
- */
-const QString &lamexp_temp_folder2(void)
-{
-       QReadLocker readLock(&g_lamexp_temp_folder.lock);
-
-       //Already initialized?
-       if(g_lamexp_temp_folder.path && (!g_lamexp_temp_folder.path->isEmpty()))
-       {
-               if(QDir(*g_lamexp_temp_folder.path).exists())
-               {
-                       return *g_lamexp_temp_folder.path;
-               }
-       }
-
-       //Obtain the write lock to initilaize
-       readLock.unlock();
-       QWriteLocker writeLock(&g_lamexp_temp_folder.lock);
-       
-       //Still uninitilaized?
-       if(g_lamexp_temp_folder.path && (!g_lamexp_temp_folder.path->isEmpty()))
-       {
-               if(QDir(*g_lamexp_temp_folder.path).exists())
-               {
-                       return *g_lamexp_temp_folder.path;
-               }
-       }
-
-       //Create the string, if not done yet
-       if(!g_lamexp_temp_folder.path)
-       {
-               g_lamexp_temp_folder.path = new QString();
-       }
-       
-       g_lamexp_temp_folder.path->clear();
-
-       //Try the %TMP% or %TEMP% directory first
-       QString tempPath = lamexp_try_init_folder(QDir::temp().absolutePath());
-       if(!tempPath.isEmpty())
-       {
-               INIT_TEMP_FOLDER(*g_lamexp_temp_folder.path, tempPath);
-       }
-
-       //Otherwise create TEMP folder in %LOCALAPPDATA%
-       if(g_lamexp_temp_folder.path->isEmpty())
-       {
-               tempPath = lamexp_try_init_folder(QString("%1/Temp").arg(lamexp_known_folder(lamexp_folder_localappdata)));
-               if(!tempPath.isEmpty())
-               {
-                       INIT_TEMP_FOLDER(*g_lamexp_temp_folder.path, tempPath);
-               }
-       }
-
-       //Failed to create TEMP folder?
-       if(g_lamexp_temp_folder.path->isEmpty())
-       {
-               qFatal("Temporary directory could not be initialized !!!");
-       }
-       
-       return *g_lamexp_temp_folder.path;
-}
-
-/*
- * Clean folder
- */
-bool lamexp_clean_folder(const QString &folderPath)
-{
-       QDir tempFolder(folderPath);
-       if(tempFolder.exists())
-       {
-               QFileInfoList entryList = tempFolder.entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot);
-
-               for(int i = 0; i < entryList.count(); i++)
-               {
-                       if(entryList.at(i).isDir())
-                       {
-                               lamexp_clean_folder(entryList.at(i).canonicalFilePath());
-                       }
-                       else
-                       {
-                               for(int j = 0; j < 3; j++)
-                               {
-                                       if(lamexp_remove_file(entryList.at(i).canonicalFilePath()))
-                                       {
-                                               break;
-                                       }
-                               }
-                       }
-               }
-               return tempFolder.rmdir(".");
-       }
-       return true;
-}
-
-/*
- * Register tool
- */
-void lamexp_register_tool(const QString &toolName, LockedFile *file, unsigned int version, const QString *tag)
-{
-       QWriteLocker writeLock(&g_lamexp_tools.lock);
-       
-       if(!g_lamexp_tools.registry) g_lamexp_tools.registry = new QMap<QString, LockedFile*>();
-       if(!g_lamexp_tools.versions) g_lamexp_tools.versions = new QMap<QString, unsigned int>();
-       if(!g_lamexp_tools.tags) g_lamexp_tools.tags = new QMap<QString, QString>();
-
-       if(g_lamexp_tools.registry->contains(toolName.toLower()))
-       {
-               THROW("lamexp_register_tool: Tool is already registered!");
-       }
-
-       g_lamexp_tools.registry->insert(toolName.toLower(), file);
-       g_lamexp_tools.versions->insert(toolName.toLower(), version);
-       g_lamexp_tools.tags->insert(toolName.toLower(), (tag) ? (*tag) : QString());
-}
-
-/*
- * Check for tool
- */
-bool lamexp_check_tool(const QString &toolName)
-{
-       QReadLocker readLock(&g_lamexp_tools.lock);
-       return (g_lamexp_tools.registry) ? g_lamexp_tools.registry->contains(toolName.toLower()) : false;
-}
-
-/*
- * Lookup tool path
- */
-const QString lamexp_lookup_tool(const QString &toolName)
-{
-       QReadLocker readLock(&g_lamexp_tools.lock);
-
-       if(g_lamexp_tools.registry)
-       {
-               if(g_lamexp_tools.registry->contains(toolName.toLower()))
-               {
-                       return g_lamexp_tools.registry->value(toolName.toLower())->filePath();
-               }
-               else
-               {
-                       return QString();
-               }
-       }
-       else
-       {
-               return QString();
-       }
-}
-
-/*
- * Lookup tool version
- */
-unsigned int lamexp_tool_version(const QString &toolName, QString *tag)
-{
-       QReadLocker readLock(&g_lamexp_tools.lock);
-       if(tag) tag->clear();
-
-       if(g_lamexp_tools.versions)
-       {
-               if(g_lamexp_tools.versions->contains(toolName.toLower()))
-               {
-                       if(tag)
-                       {
-                               if(g_lamexp_tools.tags->contains(toolName.toLower())) *tag = g_lamexp_tools.tags->value(toolName.toLower());
-                       }
-                       return g_lamexp_tools.versions->value(toolName.toLower());
-               }
-               else
-               {
-                       return UINT_MAX;
-               }
-       }
-       else
-       {
-               return UINT_MAX;
-       }
-}
-
-/*
- * Version number to human-readable string
- */
-const QString lamexp_version2string(const QString &pattern, unsigned int version, const QString &defaultText, const QString *tag)
-{
-       if(version == UINT_MAX)
-       {
-               return defaultText;
-       }
-       
-       QString result = pattern;
-       int digits = result.count("?", Qt::CaseInsensitive);
-       
-       if(digits < 1)
-       {
-               return result;
-       }
-       
-       int pos = 0;
-       QString versionStr = QString().sprintf(QString().sprintf("%%0%du", digits).toLatin1().constData(), version);
-       int index = result.indexOf("?", Qt::CaseInsensitive);
-       
-       while(index >= 0 && pos < versionStr.length())
-       {
-               result[index] = versionStr[pos++];
-               index = result.indexOf("?", Qt::CaseInsensitive);
-       }
-
-       if(tag)
-       {
-               result.replace(QChar('#'), *tag, Qt::CaseInsensitive);
-       }
-
-       return result;
-}
-
-/*
- * Register a new translation
- */
-bool lamexp_translation_register(const QString &langId, const QString &qmFile, const QString &langName, unsigned int &systemId, unsigned int &country)
-{
-       QWriteLocker writeLockTranslations(&g_lamexp_translation.lock);
-
-       if(qmFile.isEmpty() || langName.isEmpty() || systemId < 1)
-       {
-               return false;
-       }
-
-       if(!g_lamexp_translation.files) g_lamexp_translation.files = new QMap<QString, QString>();
-       if(!g_lamexp_translation.names) g_lamexp_translation.names = new QMap<QString, QString>();
-       if(!g_lamexp_translation.sysid) g_lamexp_translation.sysid = new QMap<QString, unsigned int>();
-       if(!g_lamexp_translation.cntry) g_lamexp_translation.cntry = new QMap<QString, unsigned int>();
-
-       g_lamexp_translation.files->insert(langId, qmFile);
-       g_lamexp_translation.names->insert(langId, langName);
-       g_lamexp_translation.sysid->insert(langId, systemId);
-       g_lamexp_translation.cntry->insert(langId, country);
-
-       return true;
-}
-
-/*
- * Get list of all translations
- */
-QStringList lamexp_query_translations(void)
-{
-       QReadLocker readLockTranslations(&g_lamexp_translation.lock);
-       return (g_lamexp_translation.files) ? g_lamexp_translation.files->keys() : QStringList();
-}
-
-/*
- * Get translation name
- */
-QString lamexp_translation_name(const QString &langId)
-{
-       QReadLocker readLockTranslations(&g_lamexp_translation.lock);
-       return (g_lamexp_translation.names) ? g_lamexp_translation.names->value(langId.toLower(), QString()) : QString();
-}
-
-/*
- * Get translation system id
- */
-unsigned int lamexp_translation_sysid(const QString &langId)
-{
-       QReadLocker readLockTranslations(&g_lamexp_translation.lock);
-       return (g_lamexp_translation.sysid) ? g_lamexp_translation.sysid->value(langId.toLower(), 0) : 0;
-}
-
-/*
- * Get translation script id
- */
-unsigned int lamexp_translation_country(const QString &langId)
-{
-       QReadLocker readLockTranslations(&g_lamexp_translation.lock);
-       return (g_lamexp_translation.cntry) ? g_lamexp_translation.cntry->value(langId.toLower(), 0) : 0;
-}
-
-/*
- * Install a new translator
- */
-bool lamexp_install_translator(const QString &langId)
-{
-       bool success = false;
-       const QString qmFileToPath(":/localization/%1");
-
-       if(langId.isEmpty() || langId.toLower().compare(LAMEXP_DEFAULT_LANGID) == 0)
-       {
-               success = lamexp_install_translator_from_file(qmFileToPath.arg(LAMEXP_DEFAULT_TRANSLATION));
-       }
-       else
-       {
-               QReadLocker readLock(&g_lamexp_translation.lock);
-               QString qmFile = (g_lamexp_translation.files) ? g_lamexp_translation.files->value(langId.toLower(), QString()) : QString();
-               readLock.unlock();
-
-               if(!qmFile.isEmpty())
-               {
-                       success = lamexp_install_translator_from_file(qmFileToPath.arg(qmFile));
-               }
-               else
-               {
-                       qWarning("Translation '%s' not available!", langId.toLatin1().constData());
-               }
-       }
-
-       return success;
-}
-
-/*
- * Install a new translator from file
- */
-bool lamexp_install_translator_from_file(const QString &qmFile)
-{
-       QWriteLocker writeLock(&g_lamexp_currentTranslator.lock);
-       bool success = false;
-
-       if(!g_lamexp_currentTranslator.instance)
-       {
-               g_lamexp_currentTranslator.instance = new QTranslator();
-       }
-
-       if(!qmFile.isEmpty())
-       {
-               QString qmPath = QFileInfo(qmFile).canonicalFilePath();
-               QApplication::removeTranslator(g_lamexp_currentTranslator.instance);
-               if(success = g_lamexp_currentTranslator.instance->load(qmPath))
-               {
-                       QApplication::installTranslator(g_lamexp_currentTranslator.instance);
-               }
-               else
-               {
-                       qWarning("Failed to load translation:\n\"%s\"", qmPath.toLatin1().constData());
-               }
-       }
-       else
-       {
-               QApplication::removeTranslator(g_lamexp_currentTranslator.instance);
-               success = true;
-       }
-
-       return success;
-}
-
-const QStringList &lamexp_arguments(void)
-{
-       QReadLocker readLock(&g_lamexp_argv.lock);
-
-       if(!g_lamexp_argv.list)
-       {
-               readLock.unlock();
-               QWriteLocker writeLock(&g_lamexp_argv.lock);
-
-               g_lamexp_argv.list = new QStringList;
-
-               int nArgs = 0;
-               LPWSTR *szArglist = CommandLineToArgvW(GetCommandLineW(), &nArgs);
-
-               if(NULL != szArglist)
-               {
-                       for(int i = 0; i < nArgs; i++)
-                       {
-                               (*g_lamexp_argv.list) << WCHAR2QSTR(szArglist[i]);
+                               (*g_lamexp_argv.list) << WCHAR2QSTR(szArglist[i]);
                        }
                        LocalFree(szArglist);
                }
@@ -2406,178 +1376,6 @@ bool lamexp_shutdown_computer(const QString &message, const unsigned long timeou
 }
 
 /*
- * Make a window blink (to draw user's attention)
- */
-void lamexp_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<int>(ceil(maxOpac - minOpac) / delOpac);
-               const int sleep = static_cast<int>(floor(static_cast<double>(delay) / static_cast<double>(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!");
-       }
-}
-
-/*
- * Remove forbidden characters from a filename
- */
-const QString lamexp_clean_filename(const QString &str)
-{
-       QString newStr(str);
-       QRegExp rx("\"(.+)\"");
-       rx.setMinimal(true);
-
-       newStr.replace("\\", "-");
-       newStr.replace(" / ", ", ");
-       newStr.replace("/", ",");
-       newStr.replace(":", "-");
-       newStr.replace("*", "x");
-       newStr.replace("?", "");
-       newStr.replace("<", "[");
-       newStr.replace(">", "]");
-       newStr.replace("|", "!");
-       newStr.replace(rx, "`\\1´");
-       newStr.replace("\"", "'");
-       
-       return newStr.simplified();
-}
-
-/*
- * Remove forbidden characters from a file path
- */
-const QString lamexp_clean_filepath(const QString &str)
-{
-       QStringList parts = QString(str).replace("\\", "/").split("/");
-
-       for(int i = 0; i < parts.count(); i++)
-       {
-               parts[i] = lamexp_clean_filename(parts[i]);
-       }
-
-       return parts.join("/");
-}
-
-/*
- * Get a list of all available Qt Text Codecs
- */
-QStringList lamexp_available_codepages(bool noAliases)
-{
-       QStringList codecList;
-       
-       QList<QByteArray> availableCodecs = QTextCodec::availableCodecs();
-       while(!availableCodecs.isEmpty())
-       {
-               QByteArray current = availableCodecs.takeFirst();
-               if(!(current.startsWith("system") || current.startsWith("System")))
-               {
-                       codecList << QString::fromLatin1(current.constData(), current.size());
-                       if(noAliases)
-                       {
-                               if(QTextCodec *currentCodec = QTextCodec::codecForName(current.constData()))
-                               {
-                                       
-                                       QList<QByteArray> aliases = currentCodec->aliases();
-                                       while(!aliases.isEmpty()) availableCodecs.removeAll(aliases.takeFirst());
-                               }
-                       }
-               }
-       }
-
-       return codecList;
-}
-
-/*
- * Robert Jenkins' 96 bit Mix Function
- * Source: http://www.concentric.net/~Ttwang/tech/inthash.htm
- */
-static unsigned int lamexp_mix(const unsigned int x, const unsigned int y, const unsigned int z)
-{
-       unsigned int a = x;
-       unsigned int b = y;
-       unsigned int c = z;
-       
-       a=a-b;  a=a-c;  a=a^(c >> 13);
-       b=b-c;  b=b-a;  b=b^(a << 8); 
-       c=c-a;  c=c-b;  c=c^(b >> 13);
-       a=a-b;  a=a-c;  a=a^(c >> 12);
-       b=b-c;  b=b-a;  b=b^(a << 16);
-       c=c-a;  c=c-b;  c=c^(b >> 5);
-       a=a-b;  a=a-c;  a=a^(c >> 3);
-       b=b-c;  b=b-a;  b=b^(a << 10);
-       c=c-a;  c=c-b;  c=c^(b >> 15);
-
-       return c;
-}
-
-/*
- * Seeds the random number generator
- * Note: Altough rand_s() doesn't need a seed, this must be called pripr to lamexp_rand(), just to to be sure!
- */
-void lamexp_seed_rand(void)
-{
-       qsrand(lamexp_mix(clock(), time(NULL), _getpid()));
-}
-
-/*
- * Returns a randum number
- * Note: This function uses rand_s() if available, but falls back to qrand() otherwise
- */
-unsigned int lamexp_rand(void)
-{
-       quint32 rnd = 0;
-
-       if(rand_s(&rnd) == 0)
-       {
-               return rnd;
-       }
-
-       for(size_t i = 0; i < sizeof(unsigned int); i++)
-       {
-               rnd = (rnd << 8) ^ qrand();
-       }
-
-       return rnd;
-}
-
-/*
  * Determines the current date, resistant against certain manipulations
  */
 QDate lamexp_current_date_safe(void)
@@ -2640,31 +1438,6 @@ QDate lamexp_current_date_safe(void)
        return (currentDate >= processDate) ? currentDate : processDate;
 }
 
-
-/*
- * Natural Order String Comparison - the 'lessThan' helper function
- */
-static bool lamexp_natural_string_sort_helper(const QString &str1, const QString &str2)
-{
-       return (strnatcmp(QWCHAR(str1), QWCHAR(str2)) < 0);
-}
-
-/*
- * Natural Order String Comparison - the 'lessThan' helper function *with* case folding
- */
-static bool lamexp_natural_string_sort_helper_fold_case(const QString &str1, const QString &str2)
-{
-       return (strnatcasecmp(QWCHAR(str1), QWCHAR(str2)) < 0);
-}
-
-/*
- * Natural Order String Comparison - the main sorting function
- */
-void lamexp_natural_string_sort(QStringList &list, const bool bIgnoreCase)
-{
-       qSort(list.begin(), list.end(), bIgnoreCase ? lamexp_natural_string_sort_helper_fold_case : lamexp_natural_string_sort_helper);
-}
-
 /*
  * Suspend calling thread for N milliseconds
  */
@@ -3053,101 +1826,6 @@ bool lamexp_open_media_file(const QString &mediaFilePath)
 }
 
 /*
- * Setup QPorcess object
- */
-void lamexp_init_process(QProcess &process, const QString &wokringDir)
-{
-       //Environment variable names
-       static const char *const s_envvar_names[] =
-       {
-               "WGETRC", "SYSTEM_WGETRC", "HTTP_PROXY", "FTP_PROXY", "NO_PROXY", "GNUPGHOME", "LC_ALL", "LC_COLLATE", "LC_CTYPE", "LC_MESSAGES", "LC_MONETARY", "LC_NUMERIC", "LC_TIME", "LANG", NULL
-       };
-
-       const QString tempDir = QDir::toNativeSeparators(lamexp_temp_folder2());
-
-       QProcessEnvironment env = process.processEnvironment();
-       if(env.isEmpty()) env = QProcessEnvironment::systemEnvironment();
-
-       //Setup TEMP directory
-       env.insert("TEMP", tempDir);
-       env.insert("TMP", tempDir);
-       env.insert("TMPDIR", tempDir);
-       env.insert("HOME", tempDir);
-       env.insert("USERPROFILE", tempDir);
-       env.insert("HOMEPATH", tempDir);
-
-       //Setup PATH variable
-       const QString path = env.value("PATH", QString());
-       env.insert("PATH", path.isEmpty() ? tempDir : QString("%1;%2").arg(tempDir, path));
-
-       //Clean a number of enviroment variables that might affect our tools
-       for(size_t i = 0; s_envvar_names[i]; i++)
-       {
-               env.remove(QString::fromLatin1(s_envvar_names[i]));
-               env.remove(QString::fromLatin1(s_envvar_names[i]).toLower());
-       }
-       
-       process.setWorkingDirectory(wokringDir);
-       process.setProcessChannelMode(QProcess::MergedChannels);
-       process.setReadChannel(QProcess::StandardOutput);
-       process.setProcessEnvironment(env);
-}
-
-/*
- * Entry point checks
- */
-static DWORD lamexp_entry_check(void);
-static DWORD g_lamexp_entry_check_result = lamexp_entry_check();
-static DWORD g_lamexp_entry_check_flag = 0x789E09B2;
-static DWORD lamexp_entry_check(void)
-{
-       volatile DWORD retVal = 0xA199B5AF;
-       if(g_lamexp_entry_check_flag != 0x8761F64D)
-       {
-               lamexp_fatal_exit(L"Application initialization has failed, take care!");
-       }
-       return retVal;
-}
-
-/*
- * Application entry point (runs before static initializers)
- */
-extern "C"
-{
-       int WinMainCRTStartup(void);
-       
-       int lamexp_entry_point(void)
-       {
-               if((!LAMEXP_DEBUG) && lamexp_check_for_debugger())
-               {
-                       lamexp_fatal_exit(L"Not a debug build. Please unload debugger and try again!");
-               }
-               if(g_lamexp_entry_check_flag != 0x789E09B2)
-               {
-                       lamexp_fatal_exit(L"Application initialization has failed, take care!");
-               }
-
-               //Zero *before* constructors are called
-               LAMEXP_ZERO_MEMORY(g_lamexp_argv);
-               LAMEXP_ZERO_MEMORY(g_lamexp_tools);
-               LAMEXP_ZERO_MEMORY(g_lamexp_currentTranslator);
-               LAMEXP_ZERO_MEMORY(g_lamexp_translation);
-               LAMEXP_ZERO_MEMORY(g_lamexp_known_folder);
-               LAMEXP_ZERO_MEMORY(g_lamexp_temp_folder);
-               LAMEXP_ZERO_MEMORY(g_lamexp_ipc_ptr);
-               LAMEXP_ZERO_MEMORY(g_lamexp_os_version);
-               LAMEXP_ZERO_MEMORY(g_lamexp_themes_enabled);
-               LAMEXP_ZERO_MEMORY(g_lamexp_portable);
-
-               //Make sure we will pass the check
-               g_lamexp_entry_check_flag = ~g_lamexp_entry_check_flag;
-
-               //Now initialize the C Runtime library!
-               return WinMainCRTStartup();
-       }
-}
-
-/*
  * Fatal application exit
  */
 #pragma intrinsic(_InterlockedExchange)
@@ -3180,25 +1858,6 @@ void lamexp_fatal_exit(const wchar_t* exitMessage, const wchar_t* errorBoxMessag
 }
 
 /*
- * Free all registered tools (final clean-up)
- */
-void lamexp_clean_all_tools(void)
-{
-       if(g_lamexp_tools.registry)
-       {
-               QStringList keys = g_lamexp_tools.registry->keys();
-               for(int i = 0; i < keys.count(); i++)
-               {
-                       LockedFile *lf = g_lamexp_tools.registry->take(keys.at(i));
-                       LAMEXP_DELETE(lf);
-               }
-               g_lamexp_tools.registry->clear();
-               g_lamexp_tools.versions->clear();
-               g_lamexp_tools.tags->clear();
-       }
-}
-
-/*
  * Finalization function (final clean-up)
  */
 void lamexp_finalization(void)
@@ -3206,63 +1865,41 @@ void lamexp_finalization(void)
        qDebug("lamexp_finalization()");
        
        //Free all tools
-       if(g_lamexp_tools.registry)
-       {
-               lamexp_clean_all_tools();
-               LAMEXP_DELETE(g_lamexp_tools.registry);
-               LAMEXP_DELETE(g_lamexp_tools.versions);
-               LAMEXP_DELETE(g_lamexp_tools.tags);
-       }
+       lamexp_clean_all_tools();
        
        //Delete temporary files
-       if(g_lamexp_temp_folder.path)
+       const QString &tempFolder = lamexp_temp_folder2();
+       if(!tempFolder.isEmpty())
        {
-               if(!g_lamexp_temp_folder.path->isEmpty())
+               bool success = false;
+               for(int i = 0; i < 100; i++)
                {
-                       bool success = false;
-                       for(int i = 0; i < 100; i++)
-                       {
-                               if(lamexp_clean_folder(*g_lamexp_temp_folder.path))
-                               {
-                                       success = true;
-                                       break;
-                               }
-                               lamexp_sleep(100);
-                       }
-                       if(!success)
+                       if(lamexp_clean_folder(tempFolder))
                        {
-                               MessageBoxW(NULL, L"Sorry, LameXP was unable to clean up all temporary files. Some residual files in your TEMP directory may require manual deletion!", L"LameXP", MB_ICONEXCLAMATION|MB_TOPMOST);
-                               lamexp_exec_shell(NULL, *g_lamexp_temp_folder.path, QString(), QString(), true);
+                               success = true;
+                               break;
                        }
+                       lamexp_sleep(100);
+               }
+               if(!success)
+               {
+                       MessageBoxW(NULL, L"Sorry, LameXP was unable to clean up all temporary files. Some residual files in your TEMP directory may require manual deletion!", L"LameXP", MB_ICONEXCLAMATION|MB_TOPMOST);
+                       lamexp_exec_shell(NULL, tempFolder, QString(), QString(), true);
                }
-               LAMEXP_DELETE(g_lamexp_temp_folder.path);
        }
 
        //Clear folder cache
        LAMEXP_DELETE(g_lamexp_known_folder.knownFolders);
 
        //Clear languages
-       if(g_lamexp_currentTranslator.instance)
-       {
-               QApplication::removeTranslator(g_lamexp_currentTranslator.instance);
-               LAMEXP_DELETE(g_lamexp_currentTranslator.instance);
-       }
-       LAMEXP_DELETE(g_lamexp_translation.files);
-       LAMEXP_DELETE(g_lamexp_translation.names);
-       LAMEXP_DELETE(g_lamexp_translation.cntry);
-       LAMEXP_DELETE(g_lamexp_translation.sysid);
+       lamexp_clean_all_translations();
 
        //Destroy Qt application object
        QApplication *application = dynamic_cast<QApplication*>(QApplication::instance());
        LAMEXP_DELETE(application);
 
        //Detach from shared memory
-       if(g_lamexp_ipc_ptr.sharedmem) g_lamexp_ipc_ptr.sharedmem->detach();
-       LAMEXP_DELETE(g_lamexp_ipc_ptr.sharedmem);
-       LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_read);
-       LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_write);
-       LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_read_mutex);
-       LAMEXP_DELETE(g_lamexp_ipc_ptr.semaphore_write_mutex);
+       lamexp_ipc_exit();
 
        //Free STDOUT and STDERR buffers
        if(g_lamexp_console_attached)
@@ -3288,6 +1925,9 @@ void lamexp_finalization(void)
 
        //Free CLI Arguments
        LAMEXP_DELETE(g_lamexp_argv.list);
+
+       //Free TEMP folder
+       lamexp_temp_folder_clear();
 }
 
 /*
@@ -3310,3 +1950,39 @@ unsigned long lamexp_dbg_private_bytes(void)
        THROW("Cannot call this function in a non-debug build!");
 #endif //LAMEXP_DEBUG
 }
+
+/*
+ * Output string to debugger [debug only]
+ */
+void lamexp_dbg_dbg_output_string(const char* format, ...)
+{
+#if LAMEXP_DEBUG
+       char buffer[256];
+       va_list args;
+       va_start (args, format);
+       vsnprintf_s(buffer, 256, _TRUNCATE, format, args);
+       OutputDebugStringA(buffer);
+       va_end(args);
+#else
+       THROW("Cannot call this function in a non-debug build!");
+#endif //LAMEXP_DEBUG
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// INITIALIZATION
+///////////////////////////////////////////////////////////////////////////////
+
+extern "C" void _lamexp_global_init_win32(void)
+{
+       if((!LAMEXP_DEBUG) && lamexp_check_for_debugger())
+       {
+               lamexp_fatal_exit(L"Not a debug build. Please unload debugger and try again!");
+       }
+
+       //Zero *before* constructors are called
+       LAMEXP_ZERO_MEMORY(g_lamexp_argv);
+       LAMEXP_ZERO_MEMORY(g_lamexp_known_folder);
+       LAMEXP_ZERO_MEMORY(g_lamexp_os_version);
+       LAMEXP_ZERO_MEMORY(g_lamexp_wine);
+       LAMEXP_ZERO_MEMORY(g_lamexp_themes_enabled);
+}
index 292c573..0f51da0 100644 (file)
@@ -72,15 +72,53 @@ JobObject::~JobObject(void)
 
 bool JobObject::addProcessToJob(const QProcess *proc)
 {
+       if(!m_hJobObject)
+       {
+               qWarning("Cannot assign process to job: No job bject available!");
+               return false;
+       }
+
+       if(Q_PID pid = proc->pid())
+       {
+               DWORD exitCode;
+               if(!GetExitCodeProcess(pid->hProcess, &exitCode))
+               {
+                       qWarning("Cannot assign process to job: Failed to query process status!");
+                       return false;
+               }
+
+               if(exitCode != STILL_ACTIVE)
+               {
+                       qWarning("Cannot assign process to job: Process is not running anymore!");
+                       return false;
+               }
+
+               if(!AssignProcessToJobObject(m_hJobObject, pid->hProcess))
+               {
+                       qWarning("Failed to assign process to job object!");
+                       return false;
+               }
+
+               return true;
+       }
+       else
+       {
+               qWarning("Cannot assign process to job: Process handle not available!");
+               return false;
+       }
+}
+
+bool JobObject::terminateJob(unsigned int exitCode)
+{
        if(m_hJobObject)
        {
-               if(AssignProcessToJobObject(m_hJobObject, proc->pid()->hProcess))
+               if(TerminateJobObject(m_hJobObject, exitCode))
                {
                        return true;
                }
                else
                {
-                       qWarning("Failed to assign process to job object!");
+                       qWarning("Failed to terminate job object!");
                        return false;
                }
        }
index 5f73ab2..9d1bf60 100644 (file)
@@ -31,6 +31,7 @@ public:
        ~JobObject(void);
 
        bool addProcessToJob(const QProcess *proc);
+       bool terminateJob(unsigned int exitCode);
 
 private:
        void *m_hJobObject;
index 6ed798d..46e88e9 100644 (file)
 #include <QMutex>
 #include <QDir>
 
-//Windows includes
-#define NOMINMAX
-#define WIN32_LEAN_AND_MEAN
-#include <Windows.h>
-
-//Forward declaration
-LONG WINAPI lamexp_exception_handler(__in struct _EXCEPTION_POINTERS *ExceptionInfo);
-
 ///////////////////////////////////////////////////////////////////////////////
 // Main function
 ///////////////////////////////////////////////////////////////////////////////
@@ -58,9 +50,6 @@ static int lamexp_main(int argc, char* argv[])
        int iShutdown = shutdownFlag_None;
        bool bAccepted = true;
 
-       //Increase "main" thread priority
-       SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
-
        //Get CLI arguments
        const QStringList &arguments = lamexp_arguments();
 
@@ -272,16 +261,14 @@ int main(int argc, char* argv[])
        {
                __try
                {
-                       SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
-                       SetUnhandledExceptionFilter(lamexp_exception_handler);
-                       _set_invalid_parameter_handler(lamexp_invalid_param_handler);
+                       lamexp_init_error_handlers();
                        return _main(argc, argv);
                }
                __except(1)
                {
                        fflush(stdout);
                        fflush(stderr);
-                       fprintf(stderr, "\nGURU MEDITATION !!!\n\nUnhandeled structured exception error! [code: 0x%X]\n", GetExceptionCode());
+                       fprintf(stderr, "\nGURU MEDITATION !!!\n\nUnhandeled structured exception error!\n");
                        lamexp_fatal_exit(L"Unhandeled structured exception error, application will exit!");
                }
        }
index 0912e27..a3e03a9 100644 (file)
@@ -221,7 +221,6 @@ InitializationThread::InitializationThread(const lamexp_cpu_t *cpuFeatures)
 
 #ifdef ENABLE_BENCHMARK
 #define DO_INIT_FUNCT runBenchmark
-void lamexp_clean_all_tools(void);
 #else //ENABLE_BENCHMARK
 #define DO_INIT_FUNCT doInit
 #endif //ENABLE_BENCHMARK
@@ -314,7 +313,7 @@ double InitializationThread::doInit(const size_t threadCount)
 
        QThreadPool *pool = new QThreadPool();
        pool->setMaxThreadCount((threadCount > 0) ? threadCount : qBound(2U, cores2threads(m_cpuFeatures.count), EXPECTED_TOOL_COUNT));
-       //qWarning("Using %u threads for extraction.", pool->maxThreadCount());
+       /* qWarning("Using %u threads for extraction.", pool->maxThreadCount()); */
 
        LockedFile::selfTest();
        ExtractorTask::clearFlags();