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 / Thread_Initialization.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 "Thread_Initialization.h"
23
24 #include "LockedFile.h"
25 #include "Tools.h"
26
27 #include <QFileInfo>
28 #include <QCoreApplication>
29 #include <QProcess>
30 #include <QMap>
31 #include <QDir>
32 #include <QLibrary>
33 #include <QResource>
34 #include <QTime>
35 #include <QTextStream>
36
37 /* helper macros */
38 #define PRINT_CPU_TYPE(X) case X: qDebug("Selected CPU is: " #X)
39 static const double g_allowedExtractDelay = 10.0;
40
41 ////////////////////////////////////////////////////////////
42 // Constructor
43 ////////////////////////////////////////////////////////////
44
45 InitializationThread::InitializationThread(const lamexp_cpu_t *cpuFeatures)
46 {
47         m_bSuccess = false;
48         memset(&m_cpuFeatures, 0, sizeof(lamexp_cpu_t));
49         m_slowIndicator = false;
50         
51         if(cpuFeatures)
52         {
53                 memcpy(&m_cpuFeatures, cpuFeatures, sizeof(lamexp_cpu_t));
54         }
55 }
56
57 ////////////////////////////////////////////////////////////
58 // Thread Main
59 ////////////////////////////////////////////////////////////
60
61 void InitializationThread::run()
62 {
63         m_bSuccess = false;
64         bool bCustom = false;
65         delay();
66
67         //CPU type selection
68         unsigned int cpuSupport = 0;
69         if(m_cpuFeatures.sse && m_cpuFeatures.sse2 && m_cpuFeatures.intel)
70         {
71                 cpuSupport = m_cpuFeatures.x64 ? CPU_TYPE_X64_SSE : CPU_TYPE_X86_SSE;
72         }
73         else
74         {
75                 cpuSupport = m_cpuFeatures.x64 ? CPU_TYPE_X64_GEN : CPU_TYPE_X86_GEN;
76         }
77
78         //Hack to disable x64 on the Windows 8 Developer Preview (not required anymore)
79         //if(cpuSupport & CPU_TYPE_X64_ALL)
80         //{
81         //      DWORD osVerNo = lamexp_get_os_version();
82         //      if((HIWORD(osVerNo) == 6) && (LOWORD(osVerNo) == 2))
83         //      {
84         //              qWarning("Windows 8 (x64) developer preview detected. Going to disable all x64 support!\n");
85         //              cpuSupport = (cpuSupport == CPU_TYPE_X64_SSE) ? CPU_TYPE_X86_SSE : CPU_TYPE_X86_GEN;
86         //      }
87         //}
88
89         //Print selected CPU type
90         switch(cpuSupport)
91         {
92                 PRINT_CPU_TYPE(CPU_TYPE_X86_GEN); break;
93                 PRINT_CPU_TYPE(CPU_TYPE_X86_SSE); break;
94                 PRINT_CPU_TYPE(CPU_TYPE_X64_GEN); break;
95                 PRINT_CPU_TYPE(CPU_TYPE_X64_SSE); break;
96                 default: throw "CPU support undefined!";
97         }
98
99         //Allocate maps
100         QMap<QString, QString> mapChecksum;
101         QMap<QString, unsigned int> mapVersion;
102         QMap<QString, unsigned int> mapCpuType;
103
104         //Init properties
105         for(int i = 0; i < INT_MAX; i++)
106         {
107                 if(!g_lamexp_tools[i].pcName && !g_lamexp_tools[i].pcHash && !g_lamexp_tools[i].uiVersion)
108                 {
109                         break;
110                 }
111                 else if(g_lamexp_tools[i].pcName && g_lamexp_tools[i].pcHash && g_lamexp_tools[i].uiVersion)
112                 {
113                         const QString currentTool = QString::fromLatin1(g_lamexp_tools[i].pcName);
114                         mapChecksum.insert(currentTool, QString::fromLatin1(g_lamexp_tools[i].pcHash));
115                         mapCpuType.insert(currentTool, g_lamexp_tools[i].uiCpuType);
116                         mapVersion.insert(currentTool, g_lamexp_tools[i].uiVersion);
117                 }
118                 else
119                 {
120                         qFatal("Inconsistent checksum data detected. Take care!");
121                 }
122         }
123
124         QDir toolsDir(":/tools/");
125         QList<QFileInfo> toolsList = toolsDir.entryInfoList(QStringList("*.*"), QDir::Files, QDir::Name);
126         QDir appDir = QDir(QCoreApplication::applicationDirPath()).canonicalPath();
127
128         QTime timer;
129         timer.start();
130         
131         //Extract all files
132         while(!toolsList.isEmpty())
133         {
134                 try
135                 {
136                         QFileInfo currentTool = toolsList.takeFirst();
137                         QString toolName = currentTool.fileName().toLower();
138                         QString toolShortName = QString("%1.%2").arg(currentTool.baseName().toLower(), currentTool.suffix().toLower());
139                         
140                         QByteArray toolHash = mapChecksum.take(toolName).toLatin1();
141                         unsigned int toolCpuType = mapCpuType.take(toolName);
142                         unsigned int toolVersion = mapVersion.take(toolName);
143                         
144                         if(toolHash.size() != 72)
145                         {
146                                 throw "The required checksum is missing, take care!";
147                         }
148                         
149                         if(toolCpuType & cpuSupport)
150                         {
151                                 QFileInfo customTool(QString("%1/tools/%2/%3").arg(appDir.canonicalPath(), QString::number(lamexp_version_build()), toolShortName));
152                                 if(customTool.exists() && customTool.isFile())
153                                 {
154                                         bCustom = true;
155                                         qDebug("Setting up file: %s <- %s", toolShortName.toLatin1().constData(), appDir.relativeFilePath(customTool.canonicalFilePath()).toLatin1().constData());
156                                         LockedFile *lockedFile = new LockedFile(customTool.canonicalFilePath());
157                                         lamexp_register_tool(toolShortName, lockedFile, UINT_MAX);
158                                 }
159                                 else
160                                 {
161                                         qDebug("Extracting file: %s -> %s", toolName.toLatin1().constData(),  toolShortName.toLatin1().constData());
162                                         LockedFile *lockedFile = new LockedFile(QString(":/tools/%1").arg(toolName), QString("%1/tool_%2").arg(lamexp_temp_folder2(), toolShortName), toolHash);
163                                         lamexp_register_tool(toolShortName, lockedFile, toolVersion);
164                                 }
165                         }
166                 }
167                 catch(char *errorMsg)
168                 {
169                         qFatal("At least one of the required tools could not be initialized:\n%s", errorMsg);
170                         return;
171                 }
172         }
173         
174         //Make sure all files were extracted
175         if(!mapChecksum.isEmpty())
176         {
177                 qFatal("At least one required tool could not be found:\n%s", toolsDir.filePath(mapChecksum.keys().first()).toLatin1().constData());
178                 return;
179         }
180         
181         qDebug("All extracted.\n");
182
183         //Clean-up
184         mapChecksum.clear();
185         mapVersion.clear();
186         mapCpuType.clear();
187         
188         //Using any custom tools?
189         if(bCustom)
190         {
191                 qWarning("Warning: Using custom tools, you might encounter unexpected problems!\n");
192         }
193
194         //Check delay
195         double delayExtract = static_cast<double>(timer.elapsed()) / 1000.0;
196         if(delayExtract > g_allowedExtractDelay)
197         {
198                 m_slowIndicator = true;
199                 qWarning("Extracting tools took %.3f seconds -> probably slow realtime virus scanner.", delayExtract);
200                 qWarning("Please report performance problems to your anti-virus developer !!!\n");
201         }
202
203         //Register all translations
204         initTranslations();
205
206         //Look for AAC encoders
207         initNeroAac();
208         initFhgAac();
209         initQAac();
210
211         delay();
212         m_bSuccess = true;
213 }
214
215 ////////////////////////////////////////////////////////////
216 // PUBLIC FUNCTIONS
217 ////////////////////////////////////////////////////////////
218
219 void InitializationThread::delay(void)
220 {
221         const char *temp = "|/-\\";
222         printf("Thread is doing something important... ?\b", temp[4]);
223
224         for(int i = 0; i < 20; i++)
225         {
226                 printf("%c\b", temp[i%4]);
227                 msleep(25);
228         }
229
230         printf("Done\n\n");
231 }
232
233 void InitializationThread::initTranslations(void)
234 {
235         //Search for language files
236         QStringList qmFiles = QDir(":/localization").entryList(QStringList() << "LameXP_??.qm", QDir::Files, QDir::Name);
237
238         //Make sure we found at least one translation
239         if(qmFiles.count() < 1)
240         {
241                 qFatal("Could not find any translation files!");
242                 return;
243         }
244
245         //Add all available translations
246         while(!qmFiles.isEmpty())
247         {
248                 QString langId, langName;
249                 unsigned int systemId = 0, country = 0;
250                 QString qmFile = qmFiles.takeFirst();
251                 
252                 QRegExp langIdExp("LameXP_(\\w\\w)\\.qm", Qt::CaseInsensitive);
253                 if(langIdExp.indexIn(qmFile) >= 0)
254                 {
255                         langId = langIdExp.cap(1).toLower();
256                         QResource langRes = QResource(QString(":/localization/%1.txt").arg(qmFile));
257                         if(langRes.isValid() && langRes.size() > 0)
258                         {
259                                 QByteArray data = QByteArray::fromRawData(reinterpret_cast<const char*>(langRes.data()), langRes.size());
260                                 QTextStream stream(&data, QIODevice::ReadOnly);
261                                 stream.setAutoDetectUnicode(false); stream.setCodec("UTF-8");
262                                 while(!stream.atEnd())
263                                 {
264                                         QStringList langInfo = stream.readLine().simplified().split(",", QString::SkipEmptyParts);
265                                         if(langInfo.count() == 3)
266                                         {
267                                                 systemId = langInfo.at(0).trimmed().toUInt();
268                                                 country  = langInfo.at(1).trimmed().toUInt();
269                                                 langName = langInfo.at(2).trimmed();
270                                                 break;
271                                         }
272                                 }
273                         }
274                 }
275
276                 if(!(langId.isEmpty() || langName.isEmpty() || systemId == 0))
277                 {
278                         if(lamexp_translation_register(langId, qmFile, langName, systemId, country))
279                         {
280                                 qDebug("Registering translation: %s = %s (%u) [%u]", qmFile.toUtf8().constData(), langName.toUtf8().constData(), systemId, country);
281                         }
282                         else
283                         {
284                                 qWarning("Failed to register: %s", qmFile.toLatin1().constData());
285                         }
286                 }
287         }
288
289         qDebug("All registered.\n");
290 }
291
292 void InitializationThread::initNeroAac(void)
293 {
294         const QString appPath = QDir(QCoreApplication::applicationDirPath()).canonicalPath();
295         
296         QFileInfo neroFileInfo[3];
297         neroFileInfo[0] = QFileInfo(QString("%1/neroAacEnc.exe").arg(appPath));
298         neroFileInfo[1] = QFileInfo(QString("%1/neroAacDec.exe").arg(appPath));
299         neroFileInfo[2] = QFileInfo(QString("%1/neroAacTag.exe").arg(appPath));
300         
301         bool neroFilesFound = true;
302         for(int i = 0; i < 3; i++)      { if(!neroFileInfo[i].exists()) neroFilesFound = false; }
303
304         //Lock the Nero binaries
305         if(!neroFilesFound)
306         {
307                 qDebug("Nero encoder binaries not found -> AAC encoding support will be disabled!\n");
308                 return;
309         }
310
311         qDebug("Found Nero AAC encoder binary:\n%s\n", neroFileInfo[0].canonicalFilePath().toUtf8().constData());
312
313         LockedFile *neroBin[3];
314         for(int i = 0; i < 3; i++) neroBin[i] = NULL;
315
316         try
317         {
318                 for(int i = 0; i < 3; i++)
319                 {
320                         neroBin[i] = new LockedFile(neroFileInfo[i].canonicalFilePath());
321                 }
322         }
323         catch(...)
324         {
325                 for(int i = 0; i < 3; i++) LAMEXP_DELETE(neroBin[i]);
326                 qWarning("Failed to get excluive lock to Nero encoder binary -> AAC encoding support will be disabled!");
327                 return;
328         }
329
330         QProcess process;
331         process.setProcessChannelMode(QProcess::MergedChannels);
332         process.setReadChannel(QProcess::StandardOutput);
333         process.start(neroFileInfo[0].canonicalFilePath(), QStringList() << "-help");
334
335         if(!process.waitForStarted())
336         {
337                 qWarning("Nero process failed to create!");
338                 qWarning("Error message: \"%s\"\n", process.errorString().toLatin1().constData());
339                 process.kill();
340                 process.waitForFinished(-1);
341                 for(int i = 0; i < 3; i++) LAMEXP_DELETE(neroBin[i]);
342                 return;
343         }
344
345         unsigned int neroVersion = 0;
346
347         while(process.state() != QProcess::NotRunning)
348         {
349                 if(!process.waitForReadyRead())
350                 {
351                         if(process.state() == QProcess::Running)
352                         {
353                                 qWarning("Nero process time out -> killing!");
354                                 process.kill();
355                                 process.waitForFinished(-1);
356                                 for(int i = 0; i < 3; i++) LAMEXP_DELETE(neroBin[i]);
357                                 return;
358                         }
359                 }
360
361                 while(process.canReadLine())
362                 {
363                         QString line = QString::fromUtf8(process.readLine().constData()).simplified();
364                         QStringList tokens = line.split(" ", QString::SkipEmptyParts, Qt::CaseInsensitive);
365                         int index1 = tokens.indexOf("Package");
366                         int index2 = tokens.indexOf("version:");
367                         if(index1 >= 0 && index2 >= 0 && index1 + 1 == index2 && index2 < tokens.count() - 1)
368                         {
369                                 QStringList versionTokens = tokens.at(index2 + 1).split(".", QString::SkipEmptyParts, Qt::CaseInsensitive);
370                                 if(versionTokens.count() == 4)
371                                 {
372                                         neroVersion = 0;
373                                         neroVersion += qMin(9, qMax(0, versionTokens.at(3).toInt()));
374                                         neroVersion += qMin(9, qMax(0, versionTokens.at(2).toInt())) * 10;
375                                         neroVersion += qMin(9, qMax(0, versionTokens.at(1).toInt())) * 100;
376                                         neroVersion += qMin(9, qMax(0, versionTokens.at(0).toInt())) * 1000;
377                                 }
378                         }
379                 }
380         }
381
382         if(!(neroVersion > 0))
383         {
384                 qWarning("Nero AAC version could not be determined -> AAC encoding support will be disabled!");
385                 for(int i = 0; i < 3; i++) LAMEXP_DELETE(neroBin[i]);
386                 return;
387         }
388         
389         for(int i = 0; i < 3; i++)
390         {
391                 lamexp_register_tool(neroFileInfo[i].fileName(), neroBin[i], neroVersion);
392         }
393 }
394
395 void InitializationThread::initFhgAac(void)
396 {
397         const QString appPath = QDir(QCoreApplication::applicationDirPath()).canonicalPath();
398         
399         QFileInfo fhgFileInfo[4];
400         fhgFileInfo[0] = QFileInfo(QString("%1/fhgaacenc.exe").arg(appPath));
401         fhgFileInfo[1] = QFileInfo(QString("%1/enc_fhgaac.dll").arg(appPath));
402         fhgFileInfo[2] = QFileInfo(QString("%1/nsutil.dll").arg(appPath));
403         fhgFileInfo[3] = QFileInfo(QString("%1/libmp4v2.dll").arg(appPath));
404         
405         bool fhgFilesFound = true;
406         for(int i = 0; i < 4; i++)      { if(!fhgFileInfo[i].exists()) fhgFilesFound = false; }
407
408         //Lock the FhgAacEnc binaries
409         if(!fhgFilesFound)
410         {
411                 qDebug("FhgAacEnc binaries not found -> FhgAacEnc support will be disabled!\n");
412                 return;
413         }
414
415         qDebug("Found FhgAacEnc cli_exe:\n%s\n", fhgFileInfo[0].canonicalFilePath().toUtf8().constData());
416         qDebug("Found FhgAacEnc enc_dll:\n%s\n", fhgFileInfo[1].canonicalFilePath().toUtf8().constData());
417
418         LockedFile *fhgBin[4];
419         for(int i = 0; i < 4; i++) fhgBin[i] = NULL;
420
421         try
422         {
423                 for(int i = 0; i < 4; i++)
424                 {
425                         fhgBin[i] = new LockedFile(fhgFileInfo[i].canonicalFilePath());
426                 }
427         }
428         catch(...)
429         {
430                 for(int i = 0; i < 4; i++) LAMEXP_DELETE(fhgBin[i]);
431                 qWarning("Failed to get excluive lock to FhgAacEnc binary -> FhgAacEnc support will be disabled!");
432                 return;
433         }
434
435         QProcess process;
436         process.setProcessChannelMode(QProcess::MergedChannels);
437         process.setReadChannel(QProcess::StandardOutput);
438         process.start(fhgFileInfo[0].canonicalFilePath(), QStringList() << "--version");
439
440         if(!process.waitForStarted())
441         {
442                 qWarning("FhgAacEnc process failed to create!");
443                 qWarning("Error message: \"%s\"\n", process.errorString().toLatin1().constData());
444                 process.kill();
445                 process.waitForFinished(-1);
446                 for(int i = 0; i < 4; i++) LAMEXP_DELETE(fhgBin[i]);
447                 return;
448         }
449
450         QRegExp fhgAacEncSig("fhgaacenc version (\\d+) by tmkk", Qt::CaseInsensitive);
451         unsigned int fhgVersion = 0;
452
453         while(process.state() != QProcess::NotRunning)
454         {
455                 process.waitForReadyRead();
456                 if(!process.bytesAvailable() && process.state() == QProcess::Running)
457                 {
458                         qWarning("FhgAacEnc process time out -> killing!");
459                         process.kill();
460                         process.waitForFinished(-1);
461                         for(int i = 0; i < 4; i++) LAMEXP_DELETE(fhgBin[i]);
462                         return;
463                 }
464                 while(process.bytesAvailable() > 0)
465                 {
466                         QString line = QString::fromUtf8(process.readLine().constData()).simplified();
467                         if(fhgAacEncSig.lastIndexIn(line) >= 0)
468                         {
469                                 bool ok = false;
470                                 unsigned int temp = fhgAacEncSig.cap(1).toUInt(&ok);
471                                 if(ok) fhgVersion = temp;
472                         }
473                 }
474         }
475
476         if(!(fhgVersion > 0))
477         {
478                 qWarning("FhgAacEnc version couldn't be determined -> FhgAacEnc support will be disabled!");
479                 for(int i = 0; i < 4; i++) LAMEXP_DELETE(fhgBin[i]);
480                 return;
481         }
482         else if(fhgVersion < lamexp_toolver_fhgaacenc())
483         {
484                 qWarning("FhgAacEnc version is too much outdated -> FhgAacEnc support will be disabled!");
485                 for(int i = 0; i < 4; i++) LAMEXP_DELETE(fhgBin[i]);
486                 return;
487         }
488         
489         for(int i = 0; i < 4; i++)
490         {
491                 lamexp_register_tool(fhgFileInfo[i].fileName(), fhgBin[i], fhgVersion);
492         }
493 }
494
495 void InitializationThread::initQAac(void)
496 {
497         const QString appPath = QDir(QCoreApplication::applicationDirPath()).canonicalPath();
498
499         QFileInfo qaacFileInfo[2];
500         qaacFileInfo[0] = QFileInfo(QString("%1/qaac.exe").arg(appPath));
501         qaacFileInfo[1] = QFileInfo(QString("%1/libsoxrate.dll").arg(appPath));
502         
503         bool qaacFilesFound = true;
504         for(int i = 0; i < 2; i++)      { if(!qaacFileInfo[i].exists()) qaacFilesFound = false; }
505
506         //Lock the QAAC binaries
507         if(!qaacFilesFound)
508         {
509                 qDebug("QAAC binaries not found -> QAAC support will be disabled!\n");
510                 return;
511         }
512
513         qDebug("Found QAAC encoder:\n%s\n", qaacFileInfo[0].canonicalFilePath().toUtf8().constData());
514
515         LockedFile *qaacBin[2];
516         for(int i = 0; i < 2; i++) qaacBin[i] = NULL;
517
518         try
519         {
520                 for(int i = 0; i < 2; i++)
521                 {
522                         qaacBin[i] = new LockedFile(qaacFileInfo[i].canonicalFilePath());
523                 }
524         }
525         catch(...)
526         {
527                 for(int i = 0; i < 2; i++) LAMEXP_DELETE(qaacBin[i]);
528                 qWarning("Failed to get excluive lock to QAAC binary -> QAAC support will be disabled!");
529                 return;
530         }
531
532         QProcess process;
533         process.setProcessChannelMode(QProcess::MergedChannels);
534         process.setReadChannel(QProcess::StandardOutput);
535         process.start(qaacFileInfo[0].canonicalFilePath(), QStringList() << "--check");
536
537         if(!process.waitForStarted())
538         {
539                 qWarning("QAAC process failed to create!");
540                 qWarning("Error message: \"%s\"\n", process.errorString().toLatin1().constData());
541                 process.kill();
542                 process.waitForFinished(-1);
543                 for(int i = 0; i < 2; i++) LAMEXP_DELETE(qaacBin[i]);
544                 return;
545         }
546
547         QRegExp qaacEncSig("qaac (\\d)\\.(\\d)(\\d)", Qt::CaseInsensitive);
548         QRegExp coreEncSig("CoreAudioToolbox (\\d)\\.(\\d)\\.(\\d)\\.(\\d)", Qt::CaseInsensitive);
549         unsigned int qaacVersion = 0;
550         unsigned int coreVersion = 0;
551
552         while(process.state() != QProcess::NotRunning)
553         {
554                 process.waitForReadyRead();
555                 if(!process.bytesAvailable() && process.state() == QProcess::Running)
556                 {
557                         qWarning("QAAC process time out -> killing!");
558                         process.kill();
559                         process.waitForFinished(-1);
560                 for(int i = 0; i < 2; i++) LAMEXP_DELETE(qaacBin[i]);
561                         return;
562                 }
563                 while(process.bytesAvailable() > 0)
564                 {
565                         QString line = QString::fromUtf8(process.readLine().constData()).simplified();
566                         if(qaacEncSig.lastIndexIn(line) >= 0)
567                         {
568                                 unsigned int tmp[3] = {0, 0, 0};
569                                 bool ok[3] = {false, false, false};
570                                 tmp[0] = qaacEncSig.cap(1).toUInt(&ok[0]);
571                                 tmp[1] = qaacEncSig.cap(2).toUInt(&ok[1]);
572                                 tmp[2] = qaacEncSig.cap(3).toUInt(&ok[2]);
573                                 if(ok[0] && ok[1] && ok[2])
574                                 {
575                                         qaacVersion = (qBound(0U, tmp[0], 9U) * 100) + (qBound(0U, tmp[1], 9U) * 10) + qBound(0U, tmp[2], 9U);
576                                 }
577                         }
578                         if(coreEncSig.lastIndexIn(line) >= 0)
579                         {
580                                 unsigned int tmp[4] = {0, 0, 0, 0};
581                                 bool ok[4] = {false, false, false, false};
582                                 tmp[0] = coreEncSig.cap(1).toUInt(&ok[0]);
583                                 tmp[1] = coreEncSig.cap(2).toUInt(&ok[1]);
584                                 tmp[2] = coreEncSig.cap(3).toUInt(&ok[2]);
585                                 tmp[3] = coreEncSig.cap(4).toUInt(&ok[3]);
586                                 if(ok[0] && ok[1] && ok[2] && ok[3])
587                                 {
588                                         coreVersion = (qBound(0U, tmp[0], 9U) * 1000) + (qBound(0U, tmp[1], 9U) * 100) + (qBound(0U, tmp[2], 9U) * 10) + qBound(0U, tmp[3], 9U);
589                                 }
590                         }
591                 }
592         }
593
594         //qDebug("qaac %d, CoreAudioToolbox %d", qaacVersion, coreVersion);
595
596         if(!(qaacVersion > 0))
597         {
598                 qWarning("QAAC version couldn't be determined -> QAAC support will be disabled!");
599                 for(int i = 0; i < 2; i++) LAMEXP_DELETE(qaacBin[i]);
600                 return;
601         }
602         else if(qaacVersion < lamexp_toolver_qaacenc())
603         {
604                 qWarning("QAAC version is too much outdated (%s) -> QAAC support will be disabled!", lamexp_version2string("v?.??", qaacVersion, "N/A").toLatin1().constData());
605                 for(int i = 0; i < 2; i++) LAMEXP_DELETE(qaacBin[i]);
606                 return;
607         }
608
609         if(!(coreVersion > 0))
610         {
611                 qWarning("CoreAudioToolbox version couldn't be determined -> QAAC support will be disabled!");
612                 for(int i = 0; i < 2; i++) LAMEXP_DELETE(qaacBin[i]);
613                 return;
614         }
615         else if(coreVersion < lamexp_toolver_coreaudio())
616         {
617                 qWarning("CoreAudioToolbox version is too much outdated (%s) -> QAAC support will be disabled!", lamexp_version2string("v?.?.?.?", coreVersion, "N/A").toLatin1().constData());
618                 for(int i = 0; i < 2; i++) LAMEXP_DELETE(qaacBin[i]);
619                 return;
620         }
621
622         lamexp_register_tool(qaacFileInfo[0].fileName(), qaacBin[0], qaacVersion);
623         lamexp_register_tool(qaacFileInfo[1].fileName(), qaacBin[1], qaacVersion);
624 }
625
626 void InitializationThread::selfTest(void)
627 {
628         const unsigned int cpu[4] = {CPU_TYPE_X86_GEN, CPU_TYPE_X86_SSE, CPU_TYPE_X64_GEN, CPU_TYPE_X64_SSE};
629
630         for(size_t k = 0; k < 4; k++)
631         {
632                 qDebug("[TEST]");
633                 switch(cpu[k])
634                 {
635                         PRINT_CPU_TYPE(CPU_TYPE_X86_GEN); break;
636                         PRINT_CPU_TYPE(CPU_TYPE_X86_SSE); break;
637                         PRINT_CPU_TYPE(CPU_TYPE_X64_GEN); break;
638                         PRINT_CPU_TYPE(CPU_TYPE_X64_SSE); break;
639                         default: throw "CPU support undefined!";
640                 }
641                 int n = 0;
642                 for(int i = 0; i < INT_MAX; i++)
643                 {
644                         if(!g_lamexp_tools[i].pcName && !g_lamexp_tools[i].pcHash && !g_lamexp_tools[i].uiVersion)
645                         {
646                                 break;
647                         }
648                         if(g_lamexp_tools[i].uiCpuType & cpu[k])
649                         {
650                                 qDebug("%02i -> %s", ++n, g_lamexp_tools[i].pcName);
651                         }
652                 }
653                 if(n != 25)
654                 {
655                         qFatal("Tool count mismatch !!!");
656                 }
657                 qDebug("Done.\n");
658         }
659 }
660
661 ////////////////////////////////////////////////////////////
662 // EVENTS
663 ////////////////////////////////////////////////////////////
664
665 /*NONE*/