OSDN Git Service

Update MediaInfo binaries to v0.7.53 (2012-01-24), compiled with ICL 12.1.6 and MSVC...
[lamexp/LameXP.git] / src / Tool_Abstract.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // LameXP - Audio Encoder Front-End
3 // Copyright (C) 2004-2012 LoRd_MuldeR <MuldeR2@GMX.de>
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License along
16 // with this program; if not, write to the Free Software Foundation, Inc.,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 //
19 // http://www.gnu.org/licenses/gpl-2.0.txt
20 ///////////////////////////////////////////////////////////////////////////////
21
22 #include "Tool_Abstract.h"
23
24 #include "Global.h"
25
26 #include <QProcess>
27 #include <QMutex>
28 #include <QMutexLocker>
29 #include <QLibrary>
30 #include <QProcessEnvironment>
31 #include <QDir>
32
33 /*
34  * Win32 API definitions
35  */
36 typedef HANDLE (WINAPI *CreateJobObjectFun)(__in_opt LPSECURITY_ATTRIBUTES lpJobAttributes, __in_opt LPCSTR lpName);
37 typedef BOOL (WINAPI *SetInformationJobObjectFun)(__in HANDLE hJob, __in JOBOBJECTINFOCLASS JobObjectInformationClass, __in_bcount(cbJobObjectInformationLength) LPVOID lpJobObjectInformation, __in DWORD cbJobObjectInformationLength);
38 typedef BOOL (WINAPI *AssignProcessToJobObjectFun)(__in HANDLE hJob, __in HANDLE hProcess);
39
40 /*
41  * Static vars
42  */
43 QMutex *AbstractTool::m_mutex_startProcess = NULL;
44 HANDLE AbstractTool::m_handle_jobObject = NULL;
45
46 /*
47  * Constructor
48  */
49 AbstractTool::AbstractTool(void)
50 {
51         static CreateJobObjectFun CreateJobObjectPtr = NULL;
52         static SetInformationJobObjectFun SetInformationJobObjectPtr = NULL;
53
54         if(!m_mutex_startProcess)
55         {
56                 m_mutex_startProcess = new QMutex();
57         }
58
59         if(!m_handle_jobObject)
60         {
61                 if(!CreateJobObjectPtr || !SetInformationJobObjectPtr)
62                 {
63                         QLibrary Kernel32Lib("kernel32.dll");
64                         CreateJobObjectPtr = (CreateJobObjectFun) Kernel32Lib.resolve("CreateJobObjectA");
65                         SetInformationJobObjectPtr = (SetInformationJobObjectFun) Kernel32Lib.resolve("SetInformationJobObject");
66                 }
67                 if(CreateJobObjectPtr && SetInformationJobObjectPtr)
68                 {
69                         m_handle_jobObject = CreateJobObjectPtr(NULL, NULL);
70                         if(m_handle_jobObject == INVALID_HANDLE_VALUE)
71                         {
72                                 m_handle_jobObject = NULL;
73                         }
74                         if(m_handle_jobObject)
75                         {
76                                 JOBOBJECT_EXTENDED_LIMIT_INFORMATION jobExtendedLimitInfo;
77                                 memset(&jobExtendedLimitInfo, 0, sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
78                                 jobExtendedLimitInfo.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE | JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION;
79                                 SetInformationJobObjectPtr(m_handle_jobObject, JobObjectExtendedLimitInformation, &jobExtendedLimitInfo, sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
80                         }
81                 }
82         }
83
84         m_firstLaunch = true;
85 }
86
87 /*
88  * Destructor
89  */
90 AbstractTool::~AbstractTool(void)
91 {
92 }
93
94 /*
95  * Initialize and launch process object
96  */
97 bool AbstractTool::startProcess(QProcess &process, const QString &program, const QStringList &args)
98 {
99         static AssignProcessToJobObjectFun AssignProcessToJobObjectPtr = NULL;
100         
101         QMutexLocker lock(m_mutex_startProcess);
102         emit messageLogged(commandline2string(program, args) + "\n");
103
104         QProcessEnvironment env = process.processEnvironment();
105         if(env.isEmpty()) env = QProcessEnvironment::systemEnvironment();
106         env.insert("TEMP", QDir::toNativeSeparators(lamexp_temp_folder2()));
107         env.insert("TMP", QDir::toNativeSeparators(lamexp_temp_folder2()));
108         process.setProcessEnvironment(env);
109         
110         if(!AssignProcessToJobObjectPtr)
111         {
112                 QLibrary Kernel32Lib("kernel32.dll");
113                 AssignProcessToJobObjectPtr = (AssignProcessToJobObjectFun) Kernel32Lib.resolve("AssignProcessToJobObject");
114         }
115         
116         process.setProcessChannelMode(QProcess::MergedChannels);
117         process.setReadChannel(QProcess::StandardOutput);
118         process.start(program, args);
119         
120         if(process.waitForStarted())
121         {
122                 
123                 if(AssignProcessToJobObjectPtr)
124                 {
125                         AssignProcessToJobObjectPtr(m_handle_jobObject, process.pid()->hProcess);
126                 }
127                 if(!SetPriorityClass(process.pid()->hProcess, BELOW_NORMAL_PRIORITY_CLASS))
128                 {
129                         SetPriorityClass(process.pid()->hProcess, IDLE_PRIORITY_CLASS);
130                 }
131                 
132                 lock.unlock();
133                 
134                 if(m_firstLaunch)
135                 {
136                         emit statusUpdated(0);
137                         m_firstLaunch = false;
138                 }
139                 
140                 return true;
141         }
142
143         emit messageLogged("Process creation has failed :-(");
144         QString errorMsg= process.errorString().trimmed();
145         if(!errorMsg.isEmpty()) emit messageLogged(errorMsg);
146
147         process.kill();
148         process.waitForFinished(-1);
149         return false;
150 }
151
152 /*
153  * Convert program arguments to single string
154  */
155 QString AbstractTool::commandline2string(const QString &program, const QStringList &arguments)
156 {
157         QString commandline = (program.contains(' ') ? QString("\"%1\"").arg(program) : program);
158         
159         for(int i = 0; i < arguments.count(); i++)
160         {
161                 commandline += (arguments.at(i).contains(' ') ? QString(" \"%1\"").arg(arguments.at(i)) : QString(" %1").arg(arguments.at(i)));
162         }
163
164         return commandline;
165 }
166
167 /*
168  * Convert long path to short path
169  */
170 QString AbstractTool::pathToShort(const QString &longPath)
171 {
172         QString shortPath;
173         DWORD buffSize = GetShortPathNameW(reinterpret_cast<const wchar_t*>(longPath.utf16()), NULL, NULL);
174         
175         if(buffSize > 0)
176         {
177                 wchar_t *buffer = new wchar_t[buffSize];
178                 DWORD result = GetShortPathNameW(reinterpret_cast<const wchar_t*>(longPath.utf16()), buffer, buffSize);
179
180                 if(result > 0 && result < buffSize)
181                 {
182                         shortPath = QString::fromUtf16(reinterpret_cast<const unsigned short*>(buffer));
183                 }
184
185                 delete[] buffer;
186         }
187
188         return (shortPath.isEmpty() ? longPath : shortPath);
189 }
190