diff --git a/gui/MainWindow.ui b/gui/MainWindow.ui index 1bfba613..679524b1 100644 --- a/gui/MainWindow.ui +++ b/gui/MainWindow.ui @@ -7,7 +7,7 @@ 0 0 676 - 550 + 459 @@ -503,7 +503,7 @@ - Automatically generate playlist (.m3u) + Automatically generate playlist file (.m3u) true @@ -545,70 +545,284 @@ - - - - - true + + + + + + 0 + 75 + - - QFrame::StyledPanel + + + 50 + false + - - QFrame::Sunken - - - - - - :/images/Construction.gif - - - Qt::AlignCenter + + Encoder / Format + + + + + + + Lame MP3 + + + true + + + + + + + Ogg Vorbis + + + + + + + Nero AAC + + + + + + + Wave (PCM) + + + + + + + FLAC + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 10 + 20 + + + + + + + - - - - Qt::Horizontal - - + + + - 40 - 20 + 0 + 75 - - - - - - Qt::Horizontal + + + 50 + false + - + + Rate Control Method + + + + + + + + Quality-based (VBR) + + + true + + + + + + + Average Bitrate (ABR) + + + + + + + Constant Bitrate (CBR) + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 10 + 20 + + + + + + + + + + + + - 40 - 20 + 0 + 100 - - - - - - Qt::Vertical + + + 50 + false + - - - 20 - 40 - + + Quality / Bitrate - + + + + + + + 4 + + + 50 + + + 24 + + + true + + + Qt::Horizontal + + + false + + + QSlider::TicksBelow + + + 5 + + + + + + + Minimum + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + Maximum + + + Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing + + + + + + + (VALUE) + + + Qt::AlignHCenter|Qt::AlignTop + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 8 + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 10 + 20 + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 10 + 20 + + + + + + + + - - + + Qt::Vertical @@ -637,6 +851,9 @@ + + ForbiddenCursor + QFrame::StyledPanel @@ -647,7 +864,7 @@ - :/images/Construction.gif + :/images/Cogwheels.png Qt::AlignCenter @@ -1052,6 +1269,26 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/res/Images.qrc b/res/Images.qrc index 4a8c71cd..1a75d719 100644 --- a/res/Images.qrc +++ b/res/Images.qrc @@ -3,12 +3,13 @@ images/Busy.gif images/HeaderIcon_MetaInfo.png - images/Label.png - images/Loading.gif - images/Logo.png - images/Splash.png - images/Thumb.png + images/Label.png + images/Loading.gif + images/Logo.png + images/Splash.png + images/Thumb.png images/Construction.gif + images/Cogwheels.png images/Qt.svg diff --git a/res/images/Cogwheels.png b/res/images/Cogwheels.png new file mode 100644 index 00000000..5590ab8f Binary files /dev/null and b/res/images/Cogwheels.png differ diff --git a/src/Dialog_About.cpp b/src/Dialog_About.cpp index 9c57d79b..e07788e4 100644 --- a/src/Dialog_About.cpp +++ b/src/Dialog_About.cpp @@ -36,6 +36,13 @@ //Helper macros #define LINK(URL) QString("%2").arg(URL).arg(URL) +//Constants +const char *AboutDialog::neroAacUrl = "http://www.nero.com/eng/technologies-aac-codec.html"; + +//////////////////////////////////////////////////////////// +// Constructor +//////////////////////////////////////////////////////////// + AboutDialog::AboutDialog(QWidget *parent) : QMessageBox(parent) { @@ -83,6 +90,10 @@ AboutDialog::~AboutDialog(void) { } +//////////////////////////////////////////////////////////// +// Public Functions +//////////////////////////////////////////////////////////// + int AboutDialog::exec() { PlaySound(MAKEINTRESOURCE(IDR_WAVE_ABOUT), GetModuleHandle(NULL), SND_RESOURCE | SND_ASYNC); @@ -105,30 +116,32 @@ int AboutDialog::exec() return 0; } +//////////////////////////////////////////////////////////// +// Private Functions +//////////////////////////////////////////////////////////// + void AboutDialog::showMoreAbout() { - const QString li("
  • "); - QString moreAboutText; moreAboutText += "

    The following third-party software is used in LameXP:

    "; - moreAboutText += "
      "; - moreAboutText += li + "LAME - OpenSource mp3 Encoder
      "; + moreAboutText += "
        "; + moreAboutText += "
      • LAME - OpenSource mp3 Encoder
        "; moreAboutText += "Released under the terms of the GNU Leser General Public License.
        "; moreAboutText += LINK("http://lame.sourceforge.net/"); moreAboutText += "
        "; - moreAboutText += li + "OggEnc - Ogg Vorbis Encoder"; + moreAboutText += "
      • OggEnc - Ogg Vorbis Encoder"; moreAboutText += "
        Completely open and patent-free audio encoding technology.
        "; moreAboutText += LINK("http://www.vorbis.com/"); moreAboutText += "
        "; - moreAboutText += li + "Nero AAC reference MPEG-4 Encoder
        "; + moreAboutText += "
      • Nero AAC reference MPEG-4 Encoder
        "; moreAboutText += "Freeware state-of-the-art HE-AAC encoder with 2-Pass support.
        "; moreAboutText += "(Available from vendor web-site as free download)
        "; - moreAboutText += LINK("http://www.nero.com/eng/technologies-aac-codec.html/"); + moreAboutText += LINK(neroAacUrl); moreAboutText += "
        "; - moreAboutText += li + "MediaInfo - Media File Analysis Tool
        "; + moreAboutText += "
      • MediaInfo - Media File Analysis Tool
        "; moreAboutText += "Released under the terms of the GNU Leser General Public License.
        "; moreAboutText += LINK("http://mediainfo.sourceforge.net/"); - moreAboutText += "
      "; + moreAboutText += "
    "; QMessageBox *moreAboutBox = new QMessageBox(dynamic_cast(this->parent())); moreAboutBox->setText(moreAboutText); diff --git a/src/Dialog_About.h b/src/Dialog_About.h index adfe5363..f597d60f 100644 --- a/src/Dialog_About.h +++ b/src/Dialog_About.h @@ -30,6 +30,7 @@ public: public slots: int exec(); + static const char *neroAacUrl; private: void AboutDialog::showMoreAbout(); diff --git a/src/Dialog_MainWindow.cpp b/src/Dialog_MainWindow.cpp index 34c12b5e..13ad56b5 100644 --- a/src/Dialog_MainWindow.cpp +++ b/src/Dialog_MainWindow.cpp @@ -56,9 +56,8 @@ if(m_banner->isVisible() || m_delayedFileTimer->isActive()) \ { \ MessageBeep(MB_ICONEXCLAMATION); \ return; \ -} \ - -#define LINK(X) "" +} +#define LINK(URL) QString("%2").arg(URL).arg(URL) //////////////////////////////////////////////////////////// // Constructor @@ -129,6 +128,11 @@ MainWindow::MainWindow(QWidget *parent) connect(buttonEditMeta, SIGNAL(clicked()), this, SLOT(editMetaButtonClicked())); connect(buttonClearMeta, SIGNAL(clicked()), this, SLOT(clearMetaButtonClicked())); + //Setup "Compression" tab + sliderBitrate->setValue(24); + connect(sliderBitrate, SIGNAL(valueChanged(int)), this, SLOT(updateBitrate(int))); + updateBitrate(sliderBitrate->value()); + //Activate file menu actions connect(actionOpenFolder, SIGNAL(triggered()), this, SLOT(openFolderActionActivated())); @@ -265,6 +269,23 @@ void MainWindow::windowShown(void) { QStringList arguments = QApplication::arguments(); + //Check for AAC support + if(lamexp_check_tool("neroAacEnc.exe") && lamexp_check_tool("neroAacDec.exe") && lamexp_check_tool("neroAacTag.exe")) + { + radioButtonEncoderAAC->setEnabled(true); + } + else + { + 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 += "" + LINK(AboutDialog::neroAacUrl) + "
    "; + QMessageBox::information(this, "AAC Support Disabled", messageText); + radioButtonEncoderAAC->setEnabled(false); + } + + //Add files from the command-line for(int i = 0; i < arguments.count() - 1; i++) { if(!arguments[i].compare("--add", Qt::CaseInsensitive)) @@ -659,3 +680,11 @@ void MainWindow::handleDelayedFiles(void) addFiles(selectedFiles); } + +/* + * Update bitrate + */ +void MainWindow::updateBitrate(int value) +{ + labelBitrate->setText(QString("%1 kbps").arg(value * 8)); +} diff --git a/src/Dialog_MainWindow.h b/src/Dialog_MainWindow.h index af40ec63..ba14f3a9 100644 --- a/src/Dialog_MainWindow.h +++ b/src/Dialog_MainWindow.h @@ -66,6 +66,7 @@ private slots: void handleDelayedFiles(void); void editMetaButtonClicked(void); void clearMetaButtonClicked(void); + void updateBitrate(int value); protected: void showEvent(QShowEvent *event); diff --git a/src/Global.cpp b/src/Global.cpp index b46715db..d9ea178d 100644 --- a/src/Global.cpp +++ b/src/Global.cpp @@ -285,8 +285,10 @@ int lamexp_init_ipc(void) return 0; } - g_lamexp_semaphore_read_ptr = new QSystemSemaphore(g_lamexp_semaphore_read_uuid, 0); - g_lamexp_semaphore_write_ptr = new QSystemSemaphore(g_lamexp_semaphore_write_uuid, 0); + const QString versionTag = QString().sprintf("@%d.%02d.%04d", lamexp_version_major(), lamexp_version_minor(), lamexp_version_build()); + + g_lamexp_semaphore_read_ptr = new QSystemSemaphore(QString(g_lamexp_semaphore_read_uuid).append(versionTag), 0); + g_lamexp_semaphore_write_ptr = new QSystemSemaphore(QString(g_lamexp_semaphore_write_uuid).append(versionTag), 0); if(g_lamexp_semaphore_read_ptr->error() != QSystemSemaphore::NoError) { @@ -305,7 +307,7 @@ int lamexp_init_ipc(void) return -1; } - g_lamexp_sharedmem_ptr = new QSharedMemory(g_lamexp_sharedmem_uuid, NULL); + g_lamexp_sharedmem_ptr = new QSharedMemory(QString(g_lamexp_sharedmem_uuid).append(versionTag), NULL); if(!g_lamexp_sharedmem_ptr->create(sizeof(lamexp_ipc_t))) { @@ -495,20 +497,28 @@ void lamexp_finalization(void) */ void lamexp_register_tool(const QString &toolName, LockedFile *file) { - if(g_lamexp_tool_registry.contains(toolName)) + if(g_lamexp_tool_registry.contains(toolName.toLower())) { throw "lamexp_register_tool: Tool is already registered!"; } - g_lamexp_tool_registry.insert(toolName, file); + g_lamexp_tool_registry.insert(toolName.toLower(), file); } /* - * Register tool + * Check for tool + */ +bool lamexp_check_tool(const QString &toolName) +{ + return g_lamexp_tool_registry.contains(toolName.toLower()); +} + +/* + * Lookup tool */ const QString lamexp_lookup_tool(const QString &toolName) { - if(g_lamexp_tool_registry.contains(toolName)) + if(g_lamexp_tool_registry.contains(toolName.toLower())) { return g_lamexp_tool_registry.value(toolName)->filePath(); } diff --git a/src/Global.h b/src/Global.h index b2163223..0e03f37c 100644 --- a/src/Global.h +++ b/src/Global.h @@ -49,6 +49,7 @@ 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); +bool lamexp_check_tool(const QString &toolName); const QString lamexp_lookup_tool(const QString &toolName); void lamexp_finalization(void); const QString &lamexp_temp_folder(void); diff --git a/src/LockedFile.cpp b/src/LockedFile.cpp index ce1c1650..1206d0b9 100644 --- a/src/LockedFile.cpp +++ b/src/LockedFile.cpp @@ -44,16 +44,16 @@ LockedFile::LockedFile(const QString &resourcePath, const QString &outPath, cons if(outFile.write(reinterpret_cast(resource.data()), resource.size()) != resource.size()) { QFile::remove(QFileInfo(outFile).absoluteFilePath()); - char error_msg[256]; - strcpy_s(error_msg, 256, QString("File '%1' could not be written!").arg(QFileInfo(outFile).fileName()).toUtf8().constData()); + char error_msg[512]; + strcpy_s(error_msg, 512, QString("File '%1' could not be written!").arg(QFileInfo(outFile).fileName()).toUtf8().constData()); throw error_msg; } outFile.close(); } else { - char error_msg[256]; - strcpy_s(error_msg, 256, QString("File '%1' could not be created!").arg(QFileInfo(outFile).fileName()).toUtf8().constData()); + char error_msg[512]; + strcpy_s(error_msg, 512, QString("File '%1' could not be created!").arg(QFileInfo(outFile).fileName()).toUtf8().constData()); throw error_msg; } @@ -63,8 +63,8 @@ LockedFile::LockedFile(const QString &resourcePath, const QString &outPath, cons if(m_fileHandle == INVALID_HANDLE_VALUE) { QFile::remove(QFileInfo(outFile).absoluteFilePath()); - char error_msg[256]; - strcpy_s(error_msg, 256, QString("File '%1' could not be locked!").arg(QFileInfo(outFile).fileName()).toLatin1().constData()); + char error_msg[512]; + strcpy_s(error_msg, 512, QString("File '%1' could not be locked!").arg(QFileInfo(outFile).fileName()).toLatin1().constData()); throw error_msg; } @@ -82,8 +82,31 @@ LockedFile::LockedFile(const QString &resourcePath, const QString &outPath, cons qWarning("\nFile checksum error:\n Expected = %040s\n Detected = %040s\n", expectedHash.constData(), fileHash.result().toHex().constData()); LAMEXP_CLOSE(m_fileHandle); QFile::remove(QFileInfo(outFile).absoluteFilePath()); + char error_msg[512]; + strcpy_s(error_msg, 512, QString("File '%1' is corruputed, take care!").arg(QFileInfo(outFile).fileName()).toLatin1().constData()); + throw error_msg; + } +} + +LockedFile::LockedFile(const QString &filePath) +{ + m_fileHandle = NULL; + QFileInfo existingFile(filePath); + + if(!existingFile.exists()) + { char error_msg[256]; - strcpy_s(error_msg, 256, QString("File '%1' is corruputed, take care!").arg(QFileInfo(outFile).fileName()).toLatin1().constData()); + strcpy_s(error_msg, 256, QString("File '%1' does not exist!").arg(existingFile.fileName()).toLatin1().constData()); + throw error_msg; + } + + //Now lock the file + m_fileHandle = CreateFileW(QWCHAR(QDir::toNativeSeparators(filePath)), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL); + + if(m_fileHandle == INVALID_HANDLE_VALUE) + { + char error_msg[256]; + strcpy_s(error_msg, 256, QString("File '%1' could not be locked!").arg(existingFile.fileName()).toLatin1().constData()); throw error_msg; } } diff --git a/src/LockedFile.h b/src/LockedFile.h index 17064499..b0bf28f0 100644 --- a/src/LockedFile.h +++ b/src/LockedFile.h @@ -27,6 +27,7 @@ class LockedFile { public: LockedFile(const QString &resourcePath, const QString &outPath, const QByteArray &expectedHash = QByteArray()); + LockedFile(const QString &filePath); ~LockedFile(void); const QString &filePath(); diff --git a/src/Thread_Initialization.cpp b/src/Thread_Initialization.cpp index 241febfe..57911550 100644 --- a/src/Thread_Initialization.cpp +++ b/src/Thread_Initialization.cpp @@ -24,6 +24,9 @@ #include "Global.h" #include "LockedFile.h" +#include +#include + //////////////////////////////////////////////////////////// // TOOLS //////////////////////////////////////////////////////////// @@ -43,7 +46,6 @@ static const struct lamexp_tool_t g_lamexp_tools[] = {"e613a1b56a2187edb4cdf3628a5a3e60de2e8cbc", "lame.exe"}, {"775b260b3f64101beaeb317b74746f9bccdab842", "MAC.exe"}, {"e770eaa5f2449d0fd6b3f3c02a1f574fc4370b5e", "mediainfo_icl11.exe"}, -// {"6f57f93b597f143453c6a30ee0bc9d161afe2e4b", "mediainfo_msvc9.exe"}, {"55c293a80475f7aeccf449ac9487a4626e5139cb", "mpcdec.exe"}, {"8bbf4a3fffe2ff143eb5ba2cf82ca16d676e865d", "mpg123.exe"}, {"437a1b193727c3dbdd557b9a58659d1ce7fbec51", "oggdec.exe"}, @@ -114,6 +116,37 @@ void InitializationThread::run() } qDebug("All extracted.\n"); + + //Look for Nero encoder + QFileInfo neroFileInfo[3]; + neroFileInfo[0] = QFileInfo(QString("%1/neroAacEnc.exe").arg(QCoreApplication::applicationDirPath())); + neroFileInfo[1] = QFileInfo(QString("%1/neroAacDec.exe").arg(QCoreApplication::applicationDirPath())); + neroFileInfo[2] = QFileInfo(QString("%1/neroAacTag.exe").arg(QCoreApplication::applicationDirPath())); + + bool neroFilesFound = true; + 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 + { + qDebug("Nero encoder binaries not found -> AAC encoding support will be disabled!\n"); + } delay(); m_bSuccess = true;