1 ///////////////////////////////////////////////////////////////////////////////
2 // LameXP - Audio Encoder Front-End
3 // Copyright (C) 2004-2011 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 "Thread_Initialization.h"
25 #include "LockedFile.h"
28 #include <QCoreApplication>
38 ////////////////////////////////////////////////////////////
40 ////////////////////////////////////////////////////////////
46 unsigned int uiVersion
;
50 {"3b41f85dde8d4a5a0f4cd5f461099d0db24610ba", "alac.exe", UINT_MAX
},
51 {"fb74ac8b73ad8cba2c3b4e6e61f23401d630dc22", "elevator.exe", UINT_MAX
},
52 {"3c647950bccfcc75d0746c0772e7115684be4dc5", "faad.exe", UINT_MAX
},
53 {"d33cd86f04bd4067e244d2804466583c7b90a4e2", "flac.exe", 121},
54 {"9328a50e89b54ec065637496d9681a7e3eebf915", "gpgv.exe", 1411},
55 {"d837bf6ee4dab557d8b02d46c75a24e58980fffa", "gpgv.gpg", UINT_MAX
},
56 {"143fc001a2f6c56fe1b9e6f8a2eb2b53b9e1e504", "lame.exe", 39910},
57 {"a4e929cfaa42fa2e61a3d0c6434c77a06d45aef3", "mac.exe", 406},
58 {"ec235c6404caa31e7975e9bbf9ba59599258ae1d", "mediainfo_i386.exe", 741},
59 {"72d7efdcafc2dee3b534f27ab6e01916d02ba470", "mediainfo_x64.exe", 741},
60 {"55c293a80475f7aeccf449ac9487a4626e5139cb", "mpcdec.exe", UINT_MAX
},
61 {"6b6913a54cac08b22d5b468aaed83550fc9ae5b4", "mpg123.exe", 1131},
62 {"8dd7138714c3bcb39f5a3213413addba13d06f1e", "oggdec.exe", UINT_MAX
},
63 {"ecd15abe103184aca96e406f5f1c82c6fb2e665d", "oggenc2_i386.exe", 287},
64 {"ffe0fbd73352396dc3752ac9d484dbfc754a226d", "oggenc2_sse2.exe", 287},
65 {"a8c50872e544a55495a824426e9378984f2ae01d", "oggenc2_x64.exe", 287},
66 {"cd95369051f96b9ca3a997658771c5ea52bc874d", "selfdelete.exe", UINT_MAX
},
67 {"ffeaa70bd6321185eafcb067ab2dc441650038bf", "shorten.exe", UINT_MAX
},
68 {"2d08c3586f9cf99f2e4c89ac54eeb595f63aef61", "sox.exe", 1431},
69 {"346ce516281c97e92e1b8957ddeca52edcf2d056", "speexdec.exe", UINT_MAX
},
70 {"8a74b767cfe88bf88c068fdae0de02d65589d25e", "takc.exe", UINT_MAX
},
71 {"d6e0de1e7a2d9dee10d06ae0b6b4f93b63205920", "ttaenc.exe", 341},
72 {"8c842eef65248b46fa6cb9a9e5714f575672d999", "valdec.exe", 31},
73 {"8159f4e824b3e343ece95ba6dbb5e16da9c4866e", "volumax.exe", UINT_MAX
},
74 {"62e2805d1b2eb2a4d86a5ca6e6ea58010d05d2a7", "wget.exe", UINT_MAX
},
75 {"a7e8aad52213e339ad985829722f35eab62be182", "wupdate.exe", UINT_MAX
},
76 {"b7d14b3540d24df13119a55d97623a61412de6e3", "wvunpack.exe", 4601},
80 ////////////////////////////////////////////////////////////
82 ////////////////////////////////////////////////////////////
84 InitializationThread::InitializationThread(void)
89 ////////////////////////////////////////////////////////////
91 ////////////////////////////////////////////////////////////
93 void InitializationThread::run()
98 QMap
<QString
, QString
> checksum
;
99 QMap
<QString
, unsigned int> version
;
102 for(int i
= 0; i
< INT_MAX
; i
++)
104 if(!g_lamexp_tools
[i
].pcName
&& !g_lamexp_tools
[i
].pcHash
&& !g_lamexp_tools
[i
].uiVersion
)
108 else if(g_lamexp_tools
[i
].pcName
&& g_lamexp_tools
[i
].pcHash
&& g_lamexp_tools
[i
].uiVersion
)
110 const QString currentTool
= QString::fromLatin1(g_lamexp_tools
[i
].pcName
);
111 checksum
.insert(currentTool
, QString::fromLatin1(g_lamexp_tools
[i
].pcHash
));
112 version
.insert(currentTool
, g_lamexp_tools
[i
].uiVersion
);
116 qFatal("Inconsistent checksum data detected. Take care!");
120 QDir
toolsDir(":/tools/");
121 QList
<QFileInfo
> toolsList
= toolsDir
.entryInfoList(QStringList("*.*"), QDir::Files
, QDir::Name
);
127 for(int i
= 0; i
< toolsList
.count(); i
++)
131 QString toolName
= toolsList
.at(i
).fileName().toLower();
132 qDebug("Extracting file: %s", toolName
.toLatin1().constData());
133 QByteArray toolHash
= checksum
.take(toolName
).toLatin1();
134 unsigned int toolVersion
= version
.take(toolName
);
135 if(toolHash
.size() != 40)
137 throw "The required checksum is missing, take care!";
139 LockedFile
*lockedFile
= new LockedFile(QString(":/tools/%1").arg(toolName
), QString(lamexp_temp_folder()).append(QString("/tool_%1").arg(toolName
)), toolHash
);
140 lamexp_register_tool(toolName
, lockedFile
, toolVersion
);
142 catch(char *errorMsg
)
144 qFatal("At least one required tool could not be extracted:\n%s", errorMsg
);
149 if(!checksum
.isEmpty())
151 qFatal("At least one required tool could not be found:\n%s", toolsDir
.filePath(checksum
.keys().first()).toLatin1().constData());
155 qDebug("All extracted.\n");
158 double delayExtract
= static_cast<double>(timer
.elapsed()) / 1000.0;
159 if(delayExtract
> 8.0)
161 qWarning("Extracting tools took %.3f seconds -> probably slow realtime virus scanner.", delayExtract
);
162 qWarning("Please report performance problems to your anti-virus developer !!!\n");
165 //Register all translations
168 //Look for Nero encoder
171 //Look for WMA File decoder
178 ////////////////////////////////////////////////////////////
180 ////////////////////////////////////////////////////////////
182 void InitializationThread::delay(void)
184 const char *temp
= "|/-\\";
185 printf("Thread is doing something important... ?\b", temp
[4]);
187 for(int i
= 0; i
< 20; i
++)
189 printf("%c\b", temp
[i
%4]);
196 void InitializationThread::initTranslations(void)
198 //Search for language files
199 QStringList qmFiles
= QDir(":/localization").entryList(QStringList() << "LameXP_??.qm", QDir::Files
, QDir::Name
);
201 //Make sure we found at least one translation
202 if(qmFiles
.count() < 1)
204 qFatal("Could not find any translation files!");
208 //Add all available translations
209 while(!qmFiles
.isEmpty())
211 QString langId
, langName
;
212 unsigned int systemId
= 0;
213 QString qmFile
= qmFiles
.takeFirst();
215 QRegExp
langIdExp("LameXP_(\\w\\w)\\.qm", Qt::CaseInsensitive
);
216 if(langIdExp
.indexIn(qmFile
) >= 0)
218 langId
= langIdExp
.cap(1).toLower();
221 QResource langRes
= (QString(":/localization/%1.txt").arg(qmFile
));
222 if(langRes
.isValid() && langRes
.size() > 0)
224 QStringList langInfo
= QString::fromUtf8(reinterpret_cast<const char*>(langRes
.data()), langRes
.size()).simplified().split(",", QString::SkipEmptyParts
);
225 if(langInfo
.count() == 2)
227 systemId
= langInfo
.at(0).toUInt();
228 langName
= langInfo
.at(1);
232 if(lamexp_translation_register(langId
, qmFile
, langName
, systemId
))
234 qDebug("Registering translation: %s = %s (%u)", qmFile
.toLatin1().constData(), langName
.toLatin1().constData(), systemId
);
238 qWarning("Failed to register: %s", qmFile
.toLatin1().constData());
242 qDebug("All registered.\n");
245 void InitializationThread::initNeroAac(void)
247 QFileInfo neroFileInfo
[3];
248 neroFileInfo
[0] = QFileInfo(QString("%1/neroAacEnc.exe").arg(QCoreApplication::applicationDirPath()));
249 neroFileInfo
[1] = QFileInfo(QString("%1/neroAacDec.exe").arg(QCoreApplication::applicationDirPath()));
250 neroFileInfo
[2] = QFileInfo(QString("%1/neroAacTag.exe").arg(QCoreApplication::applicationDirPath()));
252 bool neroFilesFound
= true;
253 for(int i
= 0; i
< 3; i
++) { if(!neroFileInfo
[i
].exists()) neroFilesFound
= false; }
255 //Lock the Nero binaries
258 qDebug("Nero encoder binaries not found -> AAC encoding support will be disabled!\n");
262 qDebug("Found Nero AAC encoder binary:\n%s\n", neroFileInfo
[0].canonicalFilePath().toUtf8().constData());
264 LockedFile
*neroBin
[3];
265 for(int i
= 0; i
< 3; i
++) neroBin
[i
] = NULL
;
269 for(int i
= 0; i
< 3; i
++)
271 neroBin
[i
] = new LockedFile(neroFileInfo
[i
].canonicalFilePath());
276 for(int i
= 0; i
< 3; i
++) LAMEXP_DELETE(neroBin
[i
]);
277 qWarning("Failed to get excluive lock to Nero encoder binary -> AAC encoding support will be disabled!");
282 process
.setProcessChannelMode(QProcess::MergedChannels
);
283 process
.setReadChannel(QProcess::StandardOutput
);
284 process
.start(neroFileInfo
[0].canonicalFilePath(), QStringList() << "-help");
286 if(!process
.waitForStarted())
288 qWarning("Nero process failed to create!");
289 qWarning("Error message: \"%s\"\n", process
.errorString().toLatin1().constData());
291 process
.waitForFinished(-1);
292 for(int i
= 0; i
< 3; i
++) LAMEXP_DELETE(neroBin
[i
]);
296 unsigned int neroVersion
= 0;
298 while(process
.state() != QProcess::NotRunning
)
300 if(!process
.waitForReadyRead())
302 if(process
.state() == QProcess::Running
)
304 qWarning("Nero process time out -> killing!");
306 process
.waitForFinished(-1);
307 for(int i
= 0; i
< 3; i
++) LAMEXP_DELETE(neroBin
[i
]);
312 while(process
.canReadLine())
314 QString line
= QString::fromUtf8(process
.readLine().constData()).simplified();
315 QStringList tokens
= line
.split(" ", QString::SkipEmptyParts
, Qt::CaseInsensitive
);
316 int index1
= tokens
.indexOf("Package");
317 int index2
= tokens
.indexOf("version:");
318 if(index1
>= 0 && index2
>= 0 && index1
+ 1 == index2
&& index2
< tokens
.count() - 1)
320 QStringList versionTokens
= tokens
.at(index2
+ 1).split(".", QString::SkipEmptyParts
, Qt::CaseInsensitive
);
321 if(versionTokens
.count() == 4)
324 neroVersion
+= min(9, max(0, versionTokens
.at(3).toInt()));
325 neroVersion
+= min(9, max(0, versionTokens
.at(2).toInt())) * 10;
326 neroVersion
+= min(9, max(0, versionTokens
.at(1).toInt())) * 100;
327 neroVersion
+= min(9, max(0, versionTokens
.at(0).toInt())) * 1000;
333 if(!(neroVersion
> 0))
335 qWarning("Nero AAC version could not be determined -> AAC encoding support will be disabled!");
336 for(int i
= 0; i
< 3; i
++) LAMEXP_DELETE(neroBin
[i
]);
340 for(int i
= 0; i
< 3; i
++)
342 lamexp_register_tool(neroFileInfo
[i
].fileName(), neroBin
[i
], neroVersion
);
347 void InitializationThread::initWmaDec(void)
349 static const char* wmaDecoderComponentPath
= "NCH Software/Components/wmawav/wmawav.exe";
351 LockedFile
*wmaFileBin
= NULL
;
352 QFileInfo wmaFileInfo
= QFileInfo(QString("%1/%2").arg(lamexp_known_folder(lamexp_folder_programfiles
), wmaDecoderComponentPath
));
354 if(!wmaFileInfo
.exists())
356 qDebug("WMA File Decoder not found -> WMA decoding support will be disabled!\n");
362 wmaFileBin
= new LockedFile(wmaFileInfo
.canonicalFilePath());
366 qWarning("Failed to get excluive lock to WMA File Decoder binary -> WMA decoding support will be disabled!");
371 process
.setProcessChannelMode(QProcess::MergedChannels
);
372 process
.setReadChannel(QProcess::StandardOutput
);
373 process
.start(wmaFileInfo
.canonicalFilePath(), QStringList());
375 if(!process
.waitForStarted())
377 qWarning("WmaWav process failed to create!");
378 qWarning("Error message: \"%s\"\n", process
.errorString().toLatin1().constData());
380 process
.waitForFinished(-1);
384 bool b_wmaWavFound
= false;
386 while(process
.state() != QProcess::NotRunning
)
388 if(!process
.waitForReadyRead())
390 if(process
.state() == QProcess::Running
)
392 qWarning("WmaWav process time out -> killing!");
394 process
.waitForFinished(-1);
398 while(process
.canReadLine())
400 QString line
= QString::fromUtf8(process
.readLine().constData()).simplified();
401 if(line
.contains("Usage: wmatowav.exe WMAFileSpec WAVFileSpec", Qt::CaseInsensitive
))
403 b_wmaWavFound
= true;
410 qWarning("WmaWav could not be identified -> WMA decoding support will be disabled!\n");
411 LAMEXP_DELETE(wmaFileBin
);
415 qDebug("Found WMA File Decoder binary:\n%s\n", wmaFileInfo
.canonicalFilePath().toUtf8().constData());
419 lamexp_register_tool(wmaFileInfo
.fileName(), wmaFileBin
);
423 ////////////////////////////////////////////////////////////
425 ////////////////////////////////////////////////////////////