Detect Nero AAC encoder version at runtime and suggest update, if appropriate

This commit is contained in:
LoRd_MuldeR 2010-11-12 15:58:53 +01:00
parent cd83ebd5d6
commit 373e27b088
10 changed files with 270 additions and 58 deletions

View File

@ -4,6 +4,7 @@
<file>MainIcon.ico</file> <file>MainIcon.ico</file>
<file>MainIcon.png</file> <file>MainIcon.png</file>
<file>icons/add.png</file> <file>icons/add.png</file>
<file>icons/accept.png</file>
<file>icons/application_view_list.png</file> <file>icons/application_view_list.png</file>
<file>icons/arrow_down.png</file> <file>icons/arrow_down.png</file>
<file>icons/arrow_up.png</file> <file>icons/arrow_up.png</file>
@ -39,6 +40,7 @@
<file>icons/page_white_add.png</file> <file>icons/page_white_add.png</file>
<file>icons/page_white_cd.png</file> <file>icons/page_white_cd.png</file>
<file>icons/play.png</file> <file>icons/play.png</file>
<file>icons/script_edit.png</file>
<file>icons/sound.png</file> <file>icons/sound.png</file>
<file>icons/star.png</file> <file>icons/star.png</file>
<file>icons/table_edit.png</file> <file>icons/table_edit.png</file>

View File

@ -28,6 +28,11 @@
#define VER_LAMEXP_BUILD 11 #define VER_LAMEXP_BUILD 11
#define VER_LAMEXP_SUFFIX TechPreview #define VER_LAMEXP_SUFFIX TechPreview
/*
* Tools versions
*/
#define VER_LAMEXP_TOOL_NEROAAC 1540
/* /*
* Helper macros (aka: having fun with the C pre-processor) * Helper macros (aka: having fun with the C pre-processor)
*/ */

View File

@ -29,6 +29,8 @@
#include <QApplication> #include <QApplication>
#include <QIcon> #include <QIcon>
#include <QPushButton> #include <QPushButton>
#include <QDesktopServices>
#include <QUrl>
//Win32 includes //Win32 includes
#include <Windows.h> #include <Windows.h>
@ -43,7 +45,7 @@ const char *AboutDialog::neroAacUrl = "http://www.nero.com/eng/technologies-aac-
// Constructor // Constructor
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
AboutDialog::AboutDialog(QWidget *parent) AboutDialog::AboutDialog(QWidget *parent, bool firstStart)
: QMessageBox(parent) : QMessageBox(parent)
{ {
QString aboutText; QString aboutText;
@ -73,17 +75,36 @@ AboutDialog::AboutDialog(QWidget *parent)
setIconPixmap(dynamic_cast<QApplication*>(QApplication::instance())->windowIcon().pixmap(QSize(64,64))); setIconPixmap(dynamic_cast<QApplication*>(QApplication::instance())->windowIcon().pixmap(QSize(64,64)));
setWindowTitle("About LameXP"); setWindowTitle("About LameXP");
QPushButton *firstButton = addButton("More About...", QMessageBox::AcceptRole); if(firstStart)
firstButton->setIcon(QIcon(":/icons/information.png")); {
firstButton->setMinimumWidth(120); QPushButton *firstButton = addButton("Show License Text", QMessageBox::AcceptRole);
firstButton->setIcon(QIcon(":/icons/script_edit.png"));
firstButton->setMinimumWidth(135);
QPushButton *secondButton = addButton("About Qt...", QMessageBox::AcceptRole); QPushButton *secondButton = addButton("Accept License", QMessageBox::AcceptRole);
secondButton->setIcon(QIcon(":/images/Qt.svg")); secondButton->setIcon(QIcon(":/icons/accept.png"));
secondButton->setMinimumWidth(120); secondButton->setMinimumWidth(120);
QPushButton *thirdButton = addButton("Discard", QMessageBox::AcceptRole); QPushButton *thirdButton = addButton("Decline License", QMessageBox::AcceptRole);
thirdButton->setIcon(QIcon(":/icons/cross.png")); thirdButton->setIcon(QIcon(":/icons/delete.png"));
thirdButton->setMinimumWidth(90); thirdButton->setMinimumWidth(120);
}
else
{
QPushButton *firstButton = addButton("More About...", QMessageBox::AcceptRole);
firstButton->setIcon(QIcon(":/icons/information.png"));
firstButton->setMinimumWidth(120);
QPushButton *secondButton = addButton("About Qt...", QMessageBox::AcceptRole);
secondButton->setIcon(QIcon(":/images/Qt.svg"));
secondButton->setMinimumWidth(120);
QPushButton *thirdButton = addButton("Discard", QMessageBox::AcceptRole);
thirdButton->setIcon(QIcon(":/icons/cross.png"));
thirdButton->setMinimumWidth(90);
}
m_firstShow = firstStart;
} }
AboutDialog::~AboutDialog(void) AboutDialog::~AboutDialog(void)
@ -98,18 +119,38 @@ int AboutDialog::exec()
{ {
PlaySound(MAKEINTRESOURCE(IDR_WAVE_ABOUT), GetModuleHandle(NULL), SND_RESOURCE | SND_ASYNC); PlaySound(MAKEINTRESOURCE(IDR_WAVE_ABOUT), GetModuleHandle(NULL), SND_RESOURCE | SND_ASYNC);
while(1) if(m_firstShow)
{ {
switch(QMessageBox::exec()) while(1)
{ {
case 0: switch(QMessageBox::exec())
showMoreAbout(); {
break; case 0:
case 1: QDesktopServices::openUrl(QUrl("http://www.gnu.org/licenses/gpl-2.0.txt"));
QMessageBox::aboutQt(dynamic_cast<QWidget*>(this->parent())); break;
break; case 1:
default: return 1;
return 0; break;
default:
return -1;
}
}
}
else
{
while(1)
{
switch(QMessageBox::exec())
{
case 0:
showMoreAbout();
break;
case 1:
QMessageBox::aboutQt(dynamic_cast<QWidget*>(this->parent()));
break;
default:
return 0;
}
} }
} }

View File

@ -25,7 +25,7 @@
class AboutDialog : public QMessageBox class AboutDialog : public QMessageBox
{ {
public: public:
AboutDialog(QWidget *parent = 0); AboutDialog(QWidget *parent = 0, bool firstStart = false);
~AboutDialog(void); ~AboutDialog(void);
public slots: public slots:
@ -34,4 +34,5 @@ public slots:
private: private:
void AboutDialog::showMoreAbout(); void AboutDialog::showMoreAbout();
bool m_firstShow;
}; };

View File

@ -269,9 +269,28 @@ void MainWindow::windowShown(void)
{ {
QStringList arguments = QApplication::arguments(); QStringList arguments = QApplication::arguments();
AboutDialog *about = new AboutDialog(this, true);
int iAccepted = about->exec();
LAMEXP_DELETE(about);
if(iAccepted <= 0)
{
QApplication::quit();
return;
}
//Check for AAC support //Check for AAC support
if(lamexp_check_tool("neroAacEnc.exe") && lamexp_check_tool("neroAacDec.exe") && lamexp_check_tool("neroAacTag.exe")) if(lamexp_check_tool("neroAacEnc.exe") && lamexp_check_tool("neroAacDec.exe") && lamexp_check_tool("neroAacTag.exe"))
{ {
if(lamexp_tool_version("neroAacEnc.exe") < lamexp_toolver_neroaac())
{
QString messageText;
messageText += "<nobr>LameXP detected that your version of the Nero AAC encoder is outdated!<br>";
messageText += "The current version available is " + lamexp_version2string("?.?.?.?", lamexp_toolver_neroaac()) + " (or later), but you still have version " + lamexp_version2string("?.?.?.?", lamexp_tool_version("neroAacEnc.exe")) + " installed.<br><br>";
messageText += "You can download the latest version of the Nero AAC encoder from the Nero website at:<br>";
messageText += "<b>" + LINK(AboutDialog::neroAacUrl) + "</b><br></nobr>";
QMessageBox::information(this, "AAC Encoder Outdated", messageText);
}
radioButtonEncoderAAC->setEnabled(true); radioButtonEncoderAAC->setEnabled(true);
} }
else else
@ -279,7 +298,7 @@ void MainWindow::windowShown(void)
QString messageText; QString messageText;
messageText += "<nobr>The Nero AAC encoder could not be found. AAC encoding support will be disabled.<br>"; messageText += "<nobr>The Nero AAC encoder could not be found. AAC encoding support will be disabled.<br>";
messageText += "Please put 'neroAacEnc.exe', 'neroAacDec.exe' and 'neroAacTag.exe' into the LameXP directory!<br><br>"; messageText += "Please put 'neroAacEnc.exe', 'neroAacDec.exe' and 'neroAacTag.exe' into the LameXP directory!<br><br>";
messageText += "You can download the Nero AAC encoder for free from the official Nero web-site at:<br>"; messageText += "You can download the Nero AAC encoder for free from the official Nero website at:<br>";
messageText += "<b>" + LINK(AboutDialog::neroAacUrl) + "</b><br></nobr>"; messageText += "<b>" + LINK(AboutDialog::neroAacUrl) + "</b><br></nobr>";
QMessageBox::information(this, "AAC Support Disabled", messageText); QMessageBox::information(this, "AAC Support Disabled", messageText);
radioButtonEncoderAAC->setEnabled(false); radioButtonEncoderAAC->setEnabled(false);

View File

@ -85,11 +85,15 @@ 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_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_date = __DATE__;
//Tool versions (expected)
static const unsigned int g_lamexp_toolver_neroaac = VER_LAMEXP_TOOL_NEROAAC;
//Special folders //Special folders
static QString g_lamexp_temp_folder; static QString g_lamexp_temp_folder;
//Tools //Tools
static QMap<QString, LockedFile*> g_lamexp_tool_registry; static QMap<QString, LockedFile*> g_lamexp_tool_registry;
static QMap<QString, unsigned int> g_lamexp_tool_versions;
//Shared memory //Shared memory
static const char *g_lamexp_sharedmem_uuid = "{21A68A42-6923-43bb-9CF6-64BF151942EE}"; static const char *g_lamexp_sharedmem_uuid = "{21A68A42-6923-43bb-9CF6-64BF151942EE}";
@ -113,6 +117,7 @@ unsigned int lamexp_version_major(void) { return g_lamexp_version_major; }
unsigned int lamexp_version_minor(void) { return g_lamexp_version_minor; } unsigned int lamexp_version_minor(void) { return g_lamexp_version_minor; }
unsigned int lamexp_version_build(void) { return g_lamexp_version_build; } unsigned int lamexp_version_build(void) { return g_lamexp_version_build; }
const char *lamexp_version_release(void) { return g_lamexp_version_release; } const char *lamexp_version_release(void) { return g_lamexp_version_release; }
unsigned int lamexp_toolver_neroaac(void) { return g_lamexp_toolver_neroaac; }
bool lamexp_version_demo(void) bool lamexp_version_demo(void)
{ {
@ -468,6 +473,7 @@ void lamexp_finalization(void)
LAMEXP_DELETE(g_lamexp_tool_registry[keys.at(i)]); LAMEXP_DELETE(g_lamexp_tool_registry[keys.at(i)]);
} }
g_lamexp_tool_registry.clear(); g_lamexp_tool_registry.clear();
g_lamexp_tool_versions.clear();
} }
//Delete temporary files //Delete temporary files
@ -495,7 +501,7 @@ void lamexp_finalization(void)
/* /*
* Register tool * Register tool
*/ */
void lamexp_register_tool(const QString &toolName, LockedFile *file) void lamexp_register_tool(const QString &toolName, LockedFile *file, unsigned int version)
{ {
if(g_lamexp_tool_registry.contains(toolName.toLower())) if(g_lamexp_tool_registry.contains(toolName.toLower()))
{ {
@ -503,6 +509,7 @@ void lamexp_register_tool(const QString &toolName, LockedFile *file)
} }
g_lamexp_tool_registry.insert(toolName.toLower(), file); g_lamexp_tool_registry.insert(toolName.toLower(), file);
g_lamexp_tool_versions.insert(toolName.toLower(), version);
} }
/* /*
@ -520,7 +527,7 @@ const QString lamexp_lookup_tool(const QString &toolName)
{ {
if(g_lamexp_tool_registry.contains(toolName.toLower())) if(g_lamexp_tool_registry.contains(toolName.toLower()))
{ {
return g_lamexp_tool_registry.value(toolName)->filePath(); return g_lamexp_tool_registry.value(toolName.toLower())->filePath();
} }
else else
{ {
@ -528,6 +535,48 @@ const QString lamexp_lookup_tool(const QString &toolName)
} }
} }
/*
* Lookup tool
*/
unsigned int lamexp_tool_version(const QString &toolName)
{
if(g_lamexp_tool_versions.contains(toolName.toLower()))
{
return g_lamexp_tool_versions.value(toolName.toLower());
}
else
{
return UINT_MAX;
}
}
/*
* Version number to human-readable string
*/
const QString lamexp_version2string(const QString &pattern, unsigned int version)
{
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);
}
return result;
}
/* /*
* Get number private bytes [debug only] * Get number private bytes [debug only]
*/ */

View File

@ -43,14 +43,16 @@ unsigned int lamexp_version_build(void);
const QDate &lamexp_version_date(void); const QDate &lamexp_version_date(void);
const char *lamexp_version_release(void); const char *lamexp_version_release(void);
bool lamexp_version_demo(void); bool lamexp_version_demo(void);
unsigned int lamexp_toolver_neroaac(void);
//Public functions //Public functions
void lamexp_init_console(int argc, char* argv[]); void lamexp_init_console(int argc, char* argv[]);
bool lamexp_init_qt(int argc, char* argv[]); bool lamexp_init_qt(int argc, char* argv[]);
int lamexp_init_ipc(void); int lamexp_init_ipc(void);
void lamexp_register_tool(const QString &toolName, LockedFile *file); void lamexp_register_tool(const QString &toolName, LockedFile *file, unsigned int version = 0);
bool lamexp_check_tool(const QString &toolName); bool lamexp_check_tool(const QString &toolName);
const QString lamexp_lookup_tool(const QString &toolName); const QString lamexp_lookup_tool(const QString &toolName);
unsigned int lamexp_tool_version(const QString &toolName);
void lamexp_finalization(void); void lamexp_finalization(void);
const QString &lamexp_temp_folder(void); const QString &lamexp_temp_folder(void);
void lamexp_ipc_read(unsigned int *command, char* message, size_t buffSize); void lamexp_ipc_read(unsigned int *command, char* message, size_t buffSize);
@ -58,6 +60,7 @@ void lamexp_ipc_send(unsigned int command, const char* message);
//Auxiliary functions //Auxiliary functions
bool lamexp_clean_folder(const QString folderPath); bool lamexp_clean_folder(const QString folderPath);
const QString lamexp_version2string(const QString &pattern, unsigned int version);
//Debug-only functions //Debug-only functions
SIZE_T lamexp_dbg_private_bytes(void); SIZE_T lamexp_dbg_private_bytes(void);

View File

@ -112,7 +112,14 @@ const AudioFileModel FileAnalyzer::analyzeFile(const QString &filePath)
process.setProcessChannelMode(QProcess::MergedChannels); process.setProcessChannelMode(QProcess::MergedChannels);
process.setReadChannel(QProcess::StandardOutput); process.setReadChannel(QProcess::StandardOutput);
process.start(m_mediaInfoBin, QStringList() << QDir::toNativeSeparators(filePath)); process.start(m_mediaInfoBin, QStringList() << QDir::toNativeSeparators(filePath));
process.waitForStarted();
if(!process.waitForStarted())
{
qWarning("MediaInfo process failed to create!");
process.kill();
process.waitForFinished(-1);
return audioFile;
}
while(process.state() != QProcess::NotRunning) while(process.state() != QProcess::NotRunning)
{ {

View File

@ -26,6 +26,7 @@
#include <QFileInfo> #include <QFileInfo>
#include <QCoreApplication> #include <QCoreApplication>
#include <QProcess>
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// TOOLS // TOOLS
@ -73,19 +74,9 @@ InitializationThread::InitializationThread(void)
m_bSuccess = false; m_bSuccess = false;
} }
void InitializationThread::delay(void) ////////////////////////////////////////////////////////////
{ // Thread Main
const char *temp = "|/-\\"; ////////////////////////////////////////////////////////////
printf("Thread is doing something important... ?\b", temp[4]);
for(int i = 0; i < 20; i++)
{
printf("%c\b", temp[i%4]);
msleep(100);
}
printf("Done\n\n");
}
void InitializationThread::run() void InitializationThread::run()
{ {
@ -118,6 +109,32 @@ void InitializationThread::run()
qDebug("All extracted.\n"); qDebug("All extracted.\n");
//Look for Nero encoder //Look for Nero encoder
initNeroAac();
delay();
m_bSuccess = true;
}
////////////////////////////////////////////////////////////
// PUBLIC FUNCTIONS
////////////////////////////////////////////////////////////
void InitializationThread::delay(void)
{
const char *temp = "|/-\\";
printf("Thread is doing something important... ?\b", temp[4]);
for(int i = 0; i < 20; i++)
{
printf("%c\b", temp[i%4]);
msleep(100);
}
printf("Done\n\n");
}
void InitializationThread::initNeroAac(void)
{
QFileInfo neroFileInfo[3]; QFileInfo neroFileInfo[3];
neroFileInfo[0] = QFileInfo(QString("%1/neroAacEnc.exe").arg(QCoreApplication::applicationDirPath())); neroFileInfo[0] = QFileInfo(QString("%1/neroAacEnc.exe").arg(QCoreApplication::applicationDirPath()));
neroFileInfo[1] = QFileInfo(QString("%1/neroAacDec.exe").arg(QCoreApplication::applicationDirPath())); neroFileInfo[1] = QFileInfo(QString("%1/neroAacDec.exe").arg(QCoreApplication::applicationDirPath()));
@ -127,29 +144,95 @@ void InitializationThread::run()
for(int i = 0; i < 3; i++) { if(!neroFileInfo[i].exists()) neroFilesFound = false; } for(int i = 0; i < 3; i++) { if(!neroFileInfo[i].exists()) neroFilesFound = false; }
//Lock the Nero binaries //Lock the Nero binaries
if(neroFilesFound) if(!neroFilesFound)
{
qDebug("Found Nero AAC encoder binary:\n%s\n", neroFileInfo[0].absoluteFilePath().toUtf8().constData());
LockedFile *neroBin[3];
for(int i = 0; i < 3; i++) neroBin[i] = NULL;
try
{
for(int i = 0; i < 3; i++) { neroBin[i] = new LockedFile(neroFileInfo[i].absoluteFilePath()); }
for(int i = 0; i < 3; i++) { lamexp_register_tool(neroFileInfo[i].fileName(), neroBin[i]); }
}
catch(...)
{
for(int i = 0; i < 3; i++) LAMEXP_DELETE(neroBin[i]);
qWarning("Failed to lock Nero encoder binary -> AAC encoding support will be disabled!");
}
}
else
{ {
qDebug("Nero encoder binaries not found -> AAC encoding support will be disabled!\n"); qDebug("Nero encoder binaries not found -> AAC encoding support will be disabled!\n");
return;
}
qDebug("Found Nero AAC encoder binary:\n%s\n", neroFileInfo[0].absoluteFilePath().toUtf8().constData());
LockedFile *neroBin[3];
for(int i = 0; i < 3; i++) neroBin[i] = NULL;
try
{
for(int i = 0; i < 3; i++)
{
neroBin[i] = new LockedFile(neroFileInfo[i].absoluteFilePath());
}
}
catch(...)
{
for(int i = 0; i < 3; i++) LAMEXP_DELETE(neroBin[i]);
qWarning("Failed to lock Nero encoder binary -> AAC encoding support will be disabled!");
return;
}
QProcess process;
process.setProcessChannelMode(QProcess::MergedChannels);
process.setReadChannel(QProcess::StandardOutput);
process.start(neroFileInfo[0].absoluteFilePath());
if(!process.waitForStarted())
{
qWarning("Nero process failed to create!");
process.kill();
process.waitForFinished(-1);
for(int i = 0; i < 3; i++) LAMEXP_DELETE(neroBin[i]);
return;
}
unsigned int neroVersion = 0;
while(process.state() != QProcess::NotRunning)
{
if(!process.waitForReadyRead())
{
if(process.state() == QProcess::Running)
{
qWarning("Nero process time out -> killing!");
process.kill();
process.waitForFinished(-1);
for(int i = 0; i < 3; i++) LAMEXP_DELETE(neroBin[i]);
return;
}
}
QByteArray data = process.readLine();
while(!data.isEmpty())
{
QString line = QString::fromUtf8(data.constData()).simplified();
QStringList tokens = line.split(" ", QString::SkipEmptyParts, Qt::CaseInsensitive);
int index1 = tokens.indexOf("Package");
int index2 = tokens.indexOf("version:");
if(index1 >= 0 && index2 >= 0 && index1 + 1 == index2 && index2 < tokens.count() - 1)
{
QStringList versionTokens = tokens.at(index2 + 1).split(".", QString::SkipEmptyParts, Qt::CaseInsensitive);
if(versionTokens.count() == 4)
{
neroVersion = 0;
neroVersion += versionTokens.at(3).toInt();
neroVersion += versionTokens.at(2).toInt() * 10;
neroVersion += versionTokens.at(1).toInt() * 100;
neroVersion += versionTokens.at(0).toInt() * 1000;
}
}
data = process.readLine();
}
}
if(!(neroVersion > 0))
{
qWarning("Nero AAC version could not be determined!", neroVersion);
for(int i = 0; i < 3; i++) LAMEXP_DELETE(neroBin[i]);
return;
} }
delay(); for(int i = 0; i < 3; i++)
m_bSuccess = true; {
lamexp_register_tool(neroFileInfo[i].fileName(), neroBin[i], neroVersion);
}
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////

View File

@ -38,5 +38,7 @@ public:
private: private:
void delay(void); void delay(void);
void initNeroAac(void);
bool m_bSuccess; bool m_bSuccess;
}; };