From 373e27b08886d736b0f760c2e05aef814f78e31e Mon Sep 17 00:00:00 2001 From: lordmulder Date: Fri, 12 Nov 2010 15:58:53 +0100 Subject: [PATCH] Detect Nero AAC encoder version at runtime and suggest update, if appropriate --- res/Icons.qrc | 2 + src/Config.h | 5 ++ src/Dialog_About.cpp | 81 ++++++++++++++----- src/Dialog_About.h | 3 +- src/Dialog_MainWindow.cpp | 21 ++++- src/Global.cpp | 53 +++++++++++- src/Global.h | 5 +- src/Thread_FileAnalyzer.cpp | 9 ++- src/Thread_Initialization.cpp | 147 ++++++++++++++++++++++++++-------- src/Thread_Initialization.h | 2 + 10 files changed, 270 insertions(+), 58 deletions(-) diff --git a/res/Icons.qrc b/res/Icons.qrc index 55439acf..01ca2f92 100644 --- a/res/Icons.qrc +++ b/res/Icons.qrc @@ -4,6 +4,7 @@ MainIcon.ico MainIcon.png icons/add.png + icons/accept.png icons/application_view_list.png icons/arrow_down.png icons/arrow_up.png @@ -39,6 +40,7 @@ icons/page_white_add.png icons/page_white_cd.png icons/play.png + icons/script_edit.png icons/sound.png icons/star.png icons/table_edit.png diff --git a/src/Config.h b/src/Config.h index 1b2be3ea..f91ba959 100644 --- a/src/Config.h +++ b/src/Config.h @@ -28,6 +28,11 @@ #define VER_LAMEXP_BUILD 11 #define VER_LAMEXP_SUFFIX TechPreview +/* + * Tools versions + */ +#define VER_LAMEXP_TOOL_NEROAAC 1540 + /* * Helper macros (aka: having fun with the C pre-processor) */ diff --git a/src/Dialog_About.cpp b/src/Dialog_About.cpp index e07788e4..6cecd53e 100644 --- a/src/Dialog_About.cpp +++ b/src/Dialog_About.cpp @@ -29,6 +29,8 @@ #include #include #include +#include +#include //Win32 includes #include @@ -43,7 +45,7 @@ const char *AboutDialog::neroAacUrl = "http://www.nero.com/eng/technologies-aac- // Constructor //////////////////////////////////////////////////////////// -AboutDialog::AboutDialog(QWidget *parent) +AboutDialog::AboutDialog(QWidget *parent, bool firstStart) : QMessageBox(parent) { QString aboutText; @@ -73,17 +75,36 @@ AboutDialog::AboutDialog(QWidget *parent) setIconPixmap(dynamic_cast(QApplication::instance())->windowIcon().pixmap(QSize(64,64))); setWindowTitle("About LameXP"); - QPushButton *firstButton = addButton("More About...", QMessageBox::AcceptRole); - firstButton->setIcon(QIcon(":/icons/information.png")); - firstButton->setMinimumWidth(120); + if(firstStart) + { + 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); - secondButton->setIcon(QIcon(":/images/Qt.svg")); - secondButton->setMinimumWidth(120); + QPushButton *secondButton = addButton("Accept License", QMessageBox::AcceptRole); + secondButton->setIcon(QIcon(":/icons/accept.png")); + secondButton->setMinimumWidth(120); - QPushButton *thirdButton = addButton("Discard", QMessageBox::AcceptRole); - thirdButton->setIcon(QIcon(":/icons/cross.png")); - thirdButton->setMinimumWidth(90); + QPushButton *thirdButton = addButton("Decline License", QMessageBox::AcceptRole); + thirdButton->setIcon(QIcon(":/icons/delete.png")); + 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) @@ -98,18 +119,38 @@ int AboutDialog::exec() { PlaySound(MAKEINTRESOURCE(IDR_WAVE_ABOUT), GetModuleHandle(NULL), SND_RESOURCE | SND_ASYNC); - while(1) + if(m_firstShow) { - switch(QMessageBox::exec()) + while(1) { - case 0: - showMoreAbout(); - break; - case 1: - QMessageBox::aboutQt(dynamic_cast(this->parent())); - break; - default: - return 0; + switch(QMessageBox::exec()) + { + case 0: + QDesktopServices::openUrl(QUrl("http://www.gnu.org/licenses/gpl-2.0.txt")); + break; + case 1: + return 1; + break; + default: + return -1; + } + } + } + else + { + while(1) + { + switch(QMessageBox::exec()) + { + case 0: + showMoreAbout(); + break; + case 1: + QMessageBox::aboutQt(dynamic_cast(this->parent())); + break; + default: + return 0; + } } } diff --git a/src/Dialog_About.h b/src/Dialog_About.h index f597d60f..976004d4 100644 --- a/src/Dialog_About.h +++ b/src/Dialog_About.h @@ -25,7 +25,7 @@ class AboutDialog : public QMessageBox { public: - AboutDialog(QWidget *parent = 0); + AboutDialog(QWidget *parent = 0, bool firstStart = false); ~AboutDialog(void); public slots: @@ -34,4 +34,5 @@ public slots: private: void AboutDialog::showMoreAbout(); + bool m_firstShow; }; diff --git a/src/Dialog_MainWindow.cpp b/src/Dialog_MainWindow.cpp index 13ad56b5..327ea4e3 100644 --- a/src/Dialog_MainWindow.cpp +++ b/src/Dialog_MainWindow.cpp @@ -269,9 +269,28 @@ void MainWindow::windowShown(void) { 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 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 += "LameXP detected that your version of the Nero AAC encoder is outdated!
"; + 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.

"; + messageText += "You can download the latest version of the Nero AAC encoder from the Nero website at:
"; + messageText += "" + LINK(AboutDialog::neroAacUrl) + "
"; + QMessageBox::information(this, "AAC Encoder Outdated", messageText); + } radioButtonEncoderAAC->setEnabled(true); } else @@ -279,7 +298,7 @@ void MainWindow::windowShown(void) QString messageText; messageText += "The Nero AAC encoder could not be found. AAC encoding support will be disabled.
"; messageText += "Please put 'neroAacEnc.exe', 'neroAacDec.exe' and 'neroAacTag.exe' into the LameXP directory!

"; - messageText += "You can download the Nero AAC encoder for free from the official Nero web-site at:
"; + messageText += "You can download the Nero AAC encoder for free from the official Nero website at:
"; messageText += "" + LINK(AboutDialog::neroAacUrl) + "
"; QMessageBox::information(this, "AAC Support Disabled", messageText); radioButtonEncoderAAC->setEnabled(false); diff --git a/src/Global.cpp b/src/Global.cpp index d9ea178d..24bded05 100644 --- a/src/Global.cpp +++ b/src/Global.cpp @@ -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_version_raw_date = __DATE__; +//Tool versions (expected) +static const unsigned int g_lamexp_toolver_neroaac = VER_LAMEXP_TOOL_NEROAAC; + //Special folders static QString g_lamexp_temp_folder; //Tools static QMap g_lamexp_tool_registry; +static QMap g_lamexp_tool_versions; //Shared memory 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_build(void) { return g_lamexp_version_build; } 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) { @@ -468,6 +473,7 @@ void lamexp_finalization(void) LAMEXP_DELETE(g_lamexp_tool_registry[keys.at(i)]); } g_lamexp_tool_registry.clear(); + g_lamexp_tool_versions.clear(); } //Delete temporary files @@ -495,7 +501,7 @@ void lamexp_finalization(void) /* * 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())) { @@ -503,6 +509,7 @@ void lamexp_register_tool(const QString &toolName, LockedFile *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())) { - return g_lamexp_tool_registry.value(toolName)->filePath(); + return g_lamexp_tool_registry.value(toolName.toLower())->filePath(); } 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] */ diff --git a/src/Global.h b/src/Global.h index 0e03f37c..48265c5b 100644 --- a/src/Global.h +++ b/src/Global.h @@ -43,14 +43,16 @@ unsigned int lamexp_version_build(void); const QDate &lamexp_version_date(void); const char *lamexp_version_release(void); bool lamexp_version_demo(void); +unsigned int lamexp_toolver_neroaac(void); //Public functions void lamexp_init_console(int argc, char* argv[]); bool lamexp_init_qt(int argc, char* argv[]); 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); const QString lamexp_lookup_tool(const QString &toolName); +unsigned int lamexp_tool_version(const QString &toolName); void lamexp_finalization(void); const QString &lamexp_temp_folder(void); 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 bool lamexp_clean_folder(const QString folderPath); +const QString lamexp_version2string(const QString &pattern, unsigned int version); //Debug-only functions SIZE_T lamexp_dbg_private_bytes(void); diff --git a/src/Thread_FileAnalyzer.cpp b/src/Thread_FileAnalyzer.cpp index e708dc12..dc19271e 100644 --- a/src/Thread_FileAnalyzer.cpp +++ b/src/Thread_FileAnalyzer.cpp @@ -112,7 +112,14 @@ const AudioFileModel FileAnalyzer::analyzeFile(const QString &filePath) process.setProcessChannelMode(QProcess::MergedChannels); process.setReadChannel(QProcess::StandardOutput); 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) { diff --git a/src/Thread_Initialization.cpp b/src/Thread_Initialization.cpp index 57911550..277a7bc1 100644 --- a/src/Thread_Initialization.cpp +++ b/src/Thread_Initialization.cpp @@ -26,6 +26,7 @@ #include #include +#include //////////////////////////////////////////////////////////// // TOOLS @@ -73,19 +74,9 @@ InitializationThread::InitializationThread(void) m_bSuccess = false; } -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"); -} +//////////////////////////////////////////////////////////// +// Thread Main +//////////////////////////////////////////////////////////// void InitializationThread::run() { @@ -118,6 +109,32 @@ void InitializationThread::run() qDebug("All extracted.\n"); //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]; neroFileInfo[0] = QFileInfo(QString("%1/neroAacEnc.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; } //Lock the Nero binaries - 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 + if(!neroFilesFound) { 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(); - m_bSuccess = true; + for(int i = 0; i < 3; i++) + { + lamexp_register_tool(neroFileInfo[i].fileName(), neroBin[i], neroVersion); + } } //////////////////////////////////////////////////////////// diff --git a/src/Thread_Initialization.h b/src/Thread_Initialization.h index 3962cf69..ea3a083c 100644 --- a/src/Thread_Initialization.h +++ b/src/Thread_Initialization.h @@ -38,5 +38,7 @@ public: private: void delay(void); + void initNeroAac(void); + bool m_bSuccess; };