1 ///////////////////////////////////////////////////////////////////////////////
2 // Simple x264 Launcher
3 // Copyright (C) 2004-2015 LoRd_MuldeR <MuldeR2@GMX.de>
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License along
16 // with this program; if not, write to the Free Software Foundation, Inc.,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 // http://www.gnu.org/licenses/gpl-2.0.txt
20 ///////////////////////////////////////////////////////////////////////////////
22 #include "tool_abstract.h"
25 #include "model_options.h"
26 #include "model_preferences.h"
27 #include "model_sysinfo.h"
29 #include "job_object.h"
32 #include <QMutexLocker>
34 #include <QCryptographicHash>
36 QMutex AbstractTool::s_mutexStartProcess;
38 // ------------------------------------------------------------
39 // Constructor & Destructor
40 // ------------------------------------------------------------
42 AbstractTool::AbstractTool(JobObject *jobObject, const OptionsModel *options, const SysinfoModel *const sysinfo, const PreferencesModel *const preferences, JobStatus &jobStatus, volatile bool *abort, volatile bool *pause, QSemaphore *semaphorePause)
44 m_jobObject(jobObject),
47 m_preferences(preferences),
48 m_jobStatus(jobStatus),
51 m_semaphorePause(semaphorePause)
53 /*nothing to do here*/
56 // ------------------------------------------------------------
58 // ------------------------------------------------------------
60 unsigned int AbstractTool::checkVersion(bool &modified)
62 if(m_preferences->getSkipVersionTest())
64 log("Warning: Skipping the version check this time!");
65 return makeRevision(0xFFF0, 0xFFF0);
69 QList<QRegExp*> patterns;
72 //Init encoder-specific values
73 checkVersion_init(patterns, cmdLine);
75 log("Creating process:");
76 if(!startProcess(process, getBinaryPath(), cmdLine))
81 bool bTimeout = false;
82 bool bAborted = false;
84 unsigned int revision = UINT_MAX;
85 unsigned int coreVers = UINT_MAX;
88 while(process.state() != QProcess::NotRunning)
96 if(!process.waitForReadyRead())
98 if(process.state() == QProcess::Running)
101 qWarning("process timed out <-- killing!");
102 log("\nPROCESS TIMEOUT !!!");
107 PROCESS_PENDING_LINES(process, checkVersion_parseLine, patterns, coreVers, revision, modified);
110 if(!(bTimeout || bAborted))
112 PROCESS_PENDING_LINES(process, checkVersion_parseLine, patterns, coreVers, revision, modified);
115 process.waitForFinished();
116 if(process.state() != QProcess::NotRunning)
119 process.waitForFinished(-1);
122 while(!patterns.isEmpty())
124 QRegExp *pattern = patterns.takeFirst();
125 X264_DELETE(pattern);
128 if(bTimeout || bAborted || (!checkVersion_succeeded(process.exitCode())))
130 if(!(bTimeout || bAborted))
132 log(tr("\nPROCESS EXITED WITH ERROR CODE: %1").arg(QString::number(process.exitCode())));
137 if((revision == UINT_MAX) || (coreVers == UINT_MAX))
139 log(tr("\nFAILED TO DETERMINE VERSION INFO !!!"));
143 return makeRevision(coreVers, revision);
146 bool AbstractTool::checkVersion_succeeded(const int &exitCode)
148 return (exitCode == EXIT_SUCCESS);
151 // ------------------------------------------------------------
153 // ------------------------------------------------------------
155 bool AbstractTool::startProcess(QProcess &process, const QString &program, const QStringList &args, bool mergeChannels)
157 QMutexLocker lock(&s_mutexStartProcess);
158 log(commandline2string(program, args) + "\n");
160 process.setWorkingDirectory(QDir::tempPath());
164 process.setProcessChannelMode(QProcess::MergedChannels);
165 process.setReadChannel(QProcess::StandardOutput);
169 process.setProcessChannelMode(QProcess::SeparateChannels);
170 process.setReadChannel(QProcess::StandardError);
173 process.start(program, args);
175 if(process.waitForStarted())
177 m_jobObject->addProcessToJob(&process);
178 x264_change_process_priority(&process, m_preferences->getProcessPriority());
183 log("Process creation has failed :-(");
184 QString errorMsg= process.errorString().trimmed();
185 if(!errorMsg.isEmpty()) log(errorMsg);
188 process.waitForFinished(-1);
192 // ------------------------------------------------------------
194 // ------------------------------------------------------------
196 QString AbstractTool::commandline2string(const QString &program, const QStringList &arguments)
198 const QString nativeProgfram = QDir::toNativeSeparators(program);
199 QString commandline = (nativeProgfram.contains(' ') ? QString("\"%1\"").arg(nativeProgfram) : nativeProgfram);
201 for(int i = 0; i < arguments.count(); i++)
203 commandline += (arguments.at(i).contains(' ') ? QString(" \"%1\"").arg(arguments.at(i)) : QString(" %1").arg(arguments.at(i)));
209 QString AbstractTool::stringToHash(const QString &string)
211 QByteArray result(10, char(0));
212 const QByteArray hash = QCryptographicHash::hash(string.toUtf8(), QCryptographicHash::Sha1);
214 if((hash.size() == 20) && (result.size() == 10))
216 unsigned char *out = reinterpret_cast<unsigned char*>(result.data());
217 const unsigned char *in = reinterpret_cast<const unsigned char*>(hash.constData());
218 for(int i = 0; i < 10; i++)
220 out[i] = (in[i] ^ in[10+i]);
224 return QString::fromLatin1(result.toHex().constData());
227 unsigned int AbstractTool::makeRevision(const unsigned int &core, const unsigned int &build)
229 return ((core & 0x0000FFFF) << 16) | (build & 0x0000FFFF);
232 void AbstractTool::splitRevision(const unsigned int &revision, unsigned int &core, unsigned int &build)
234 core = (revision & 0xFFFF0000) >> 16;
235 build = (revision & 0x0000FFFF);