diff --git a/gui/MainWindow.ui b/gui/MainWindow.ui index 33c9e5cd..112f830e 100644 --- a/gui/MainWindow.ui +++ b/gui/MainWindow.ui @@ -1346,6 +1346,8 @@ + + @@ -1620,5 +1622,21 @@ + + saveToSourceFolderCheckBox + toggled(bool) + generatePlaylistCheckBox + setDisabled(bool) + + + 70 + 79 + + + 70 + 79 + + + diff --git a/src/Config.h b/src/Config.h index 86ffafc3..b214dbb3 100644 --- a/src/Config.h +++ b/src/Config.h @@ -25,7 +25,7 @@ #define VER_LAMEXP_MAJOR 4 #define VER_LAMEXP_MINOR_HI 0 #define VER_LAMEXP_MINOR_LO 0 -#define VER_LAMEXP_BUILD 57 +#define VER_LAMEXP_BUILD 60 #define VER_LAMEXP_SUFFIX TechPreview /* diff --git a/src/Dialog_Processing.cpp b/src/Dialog_Processing.cpp index 6476cb0e..35571a07 100644 --- a/src/Dialog_Processing.cpp +++ b/src/Dialog_Processing.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include @@ -84,6 +85,8 @@ ProcessingDialog::ProcessingDialog(FileListModel *fileListModel, AudioFileModel view_log->verticalHeader()->hide(); view_log->horizontalHeader()->setResizeMode(QHeaderView::ResizeToContents); view_log->horizontalHeader()->setResizeMode(0, QHeaderView::Stretch); + connect(m_progressModel, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(progressModelChanged())); + connect(m_progressModel, SIGNAL(modelReset()), this, SLOT(progressModelChanged())); //Enque jobs if(fileListModel) @@ -97,6 +100,8 @@ ProcessingDialog::ProcessingDialog(FileListModel *fileListModel, AudioFileModel //Init other vars m_runningThreads = 0; m_currentFile = 0; + m_succeededFiles = 0; + m_failedFiles = 0; m_userAborted = false; } @@ -175,6 +180,8 @@ void ProcessingDialog::initEncoding(void) { m_runningThreads = 0; m_currentFile = 0; + m_succeededFiles = 0; + m_failedFiles = 0; m_userAborted = false; m_playList.clear(); @@ -228,20 +235,34 @@ void ProcessingDialog::doneEncoding(void) qDebug("Running jobs: %u", m_runningThreads); - if(!m_userAborted && m_settings->createPlaylist() && !m_settings->outputDir().isEmpty()) + if(!m_userAborted && m_settings->createPlaylist() && !m_settings->outputToSourceDir()) { - label_progress->setText("Creatig the play list, please wait..."); + label_progress->setText("Creatig the playlist file, please wait..."); QApplication::processEvents(); writePlayList(); } - label_progress->setText(m_userAborted ? "Process was aborted by the user!" : "Alle files completed successfully."); - m_progressIndicator->stop(); - + if(m_userAborted) + { + label_progress->setText("Process was aborted by the user!"); + } + else + { + if(m_failedFiles) + { + label_progress->setText(QString("Error: %1 of %2 files failed. See the log for details!").arg(QString::number(m_failedFiles), QString::number(m_failedFiles + m_succeededFiles))); + } + else + { + label_progress->setText("Alle files completed successfully."); + } + } + setCloseButtonEnabled(true); button_closeDialog->setEnabled(true); button_AbortProcess->setEnabled(false); + m_progressIndicator->stop(); progressBar->setValue(100); } @@ -249,8 +270,18 @@ void ProcessingDialog::processFinished(const QUuid &jobId, const QString &outFil { if(success) { + m_succeededFiles++; m_playList.append(outFileName); } + else + { + m_failedFiles++; + } +} + +void ProcessingDialog::progressModelChanged(void) +{ + view_log->scrollToBottom(); } //////////////////////////////////////////////////////////// @@ -281,8 +312,8 @@ void ProcessingDialog::startNextJob(void) default: throw "Unsupported encoder!"; } - - ProcessThread *thread = new ProcessThread(currentFile, m_settings->outputDir(), encoder); + + ProcessThread *thread = new ProcessThread(currentFile, (m_settings->outputToSourceDir() ? QFileInfo(currentFile.filePath()).absolutePath(): m_settings->outputDir()), encoder); m_threadList.append(thread); connect(thread, SIGNAL(finished()), this, SLOT(doneEncoding()), Qt::QueuedConnection); connect(thread, SIGNAL(processStateInitialized(QUuid,QString,QString,int)), m_progressModel, SLOT(addJob(QUuid,QString,QString,int)), Qt::QueuedConnection); @@ -322,6 +353,10 @@ void ProcessingDialog::writePlayList(void) } playList.close(); } + else + { + QMessageBox::warning(this, "Playlist creation failed", QString("The playlist file could not be created:
%1").arg(playListFile)); + } } AudioFileModel ProcessingDialog::updateMetaInfo(const AudioFileModel &audioFile) diff --git a/src/Dialog_Processing.h b/src/Dialog_Processing.h index fb352320..97aa9ab5 100644 --- a/src/Dialog_Processing.h +++ b/src/Dialog_Processing.h @@ -45,6 +45,7 @@ private slots: void doneEncoding(void); void abortEncoding(void); void processFinished(const QUuid &jobId, const QString &outFileName, bool success); + void progressModelChanged(void); protected: void showEvent(QShowEvent *event); @@ -66,5 +67,7 @@ private: QStringList m_playList; unsigned int m_runningThreads; unsigned int m_currentFile; + unsigned int m_succeededFiles; + unsigned int m_failedFiles; bool m_userAborted; }; diff --git a/src/Global.cpp b/src/Global.cpp index 992c7855..c9e8849e 100644 --- a/src/Global.cpp +++ b/src/Global.cpp @@ -208,6 +208,7 @@ void lamexp_message_handler(QtMsgType type, const char *msg) CONSOLE_SCREEN_BUFFER_INFO bufferInfo; GetConsoleScreenBufferInfo(hConsole, &bufferInfo); + SetConsoleOutputCP(CP_UTF8); switch(type) { @@ -216,17 +217,18 @@ void lamexp_message_handler(QtMsgType type, const char *msg) fflush(stdout); fflush(stderr); SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_INTENSITY); - fprintf(stderr, "\nCRITICAL ERROR !!!\n%s\n\n", msg); + fwprintf(stderr, L"\nCRITICAL ERROR !!!\n%S\n\n", msg); MessageBoxW(NULL, (wchar_t*) QString::fromUtf8(msg).utf16(), L"LameXP - CRITICAL ERROR", MB_ICONERROR | MB_TOPMOST | MB_TASKMODAL); break; case QtWarningMsg: SetConsoleTextAttribute(hConsole, FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY); - fprintf(stderr, "%s\n", msg); + fwprintf(stderr, L"%S\n", msg); fflush(stderr); + //MessageBoxW(NULL, (wchar_t*) QString::fromUtf8(msg).utf16(), NULL, MB_TOPMOST | MB_ICONWARNING); break; default: SetConsoleTextAttribute(hConsole, FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY); - fprintf(stderr, "%s\n", msg); + fwprintf(stderr, L"%S\n", msg); fflush(stderr); break; } diff --git a/src/Main.cpp b/src/Main.cpp index 30c3c8f7..062fa9e0 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -37,6 +37,7 @@ #include #include #include +#include /////////////////////////////////////////////////////////////////////////////// // Main function @@ -72,7 +73,7 @@ int lamexp_main(int argc, char* argv[]) //Initialize Qt lamexp_init_qt(argc, argv); - + //Check for expiration if(lamexp_version_demo()) { diff --git a/src/Model_Progress.cpp b/src/Model_Progress.cpp index 2b6dddc5..cc04b849 100644 --- a/src/Model_Progress.cpp +++ b/src/Model_Progress.cpp @@ -136,13 +136,14 @@ void ProgressModel::addJob(const QUuid &jobId, const QString &jobName, const QSt void ProgressModel::updateJob(const QUuid &jobId, const QString &newStatus, int newState) { - if(!m_jobList.contains(jobId)) + int row = m_jobList.indexOf(jobId); + + if(row < 0) { return; } - beginResetModel(); if(!newStatus.isEmpty()) m_jobStatus.insert(jobId, newStatus); if(newState >= 0) m_jobState.insert(jobId, newState); - endResetModel(); + emit dataChanged(index(row, 0), index(row, 1)); } diff --git a/src/Model_Settings.cpp b/src/Model_Settings.cpp index 4b272ae0..489717ba 100644 --- a/src/Model_Settings.cpp +++ b/src/Model_Settings.cpp @@ -29,23 +29,32 @@ #include #include +//Constants static const char *g_settingsId_versionNumber = "VersionNumber"; static const char *g_settingsId_licenseAccepted = "LicenseAccepted"; static const char *g_settingsId_interfaceStyle = "InterfaceStyle"; static const char *g_settingsId_compressionEncoder = "Compression/Encoder"; static const char *g_settingsId_compressionRCMode = "Compression/RCMode"; static const char *g_settingsId_compressionBitrate = "Compression/Bitrate"; -static const char *g_settingsId_outputDir = "OutputDirectory"; +static const char *g_settingsId_outputDir = "OutputDirectory/SelectedPath"; +static const char *g_settingsId_outputToSourceDir = "OutputDirectory/OutputToSourceFolder"; static const char *g_settingsId_writeMetaTags = "WriteMetaTags"; static const char *g_settingsId_createPlaylist = "AutoCreatePlaylist"; -#define MAKE_GETTER1(OPT,DEF) int SettingsModel::OPT(void) { return m_settings->value(g_settingsId_##OPT, DEF).toInt(); } -#define MAKE_SETTER1(OPT) void SettingsModel::OPT(int value) { m_settings->setValue(g_settingsId_##OPT, value); } -#define MAKE_GETTER2(OPT,DEF) QString SettingsModel::OPT(void) { return m_settings->value(g_settingsId_##OPT, DEF).toString().trimmed(); } -#define MAKE_SETTER2(OPT) void SettingsModel::OPT(const QString &value) { m_settings->setValue(g_settingsId_##OPT, value); } -#define MAKE_GETTER3(OPT,DEF) bool SettingsModel::OPT(void) { return m_settings->value(g_settingsId_##OPT, DEF).toBool(); } -#define MAKE_SETTER3(OPT) void SettingsModel::OPT(bool value) { m_settings->setValue(g_settingsId_##OPT, value); } +//Macros +#define MAKE_OPTION1(OPT,DEF) \ +int SettingsModel::OPT(void) { return m_settings->value(g_settingsId_##OPT, DEF).toInt(); } \ +void SettingsModel::OPT(int value) { m_settings->setValue(g_settingsId_##OPT, value); } +#define MAKE_OPTION2(OPT,DEF) \ +QString SettingsModel::OPT(void) { return m_settings->value(g_settingsId_##OPT, DEF).toString().trimmed(); } \ +void SettingsModel::OPT(const QString &value) { m_settings->setValue(g_settingsId_##OPT, value); } + +#define MAKE_OPTION3(OPT,DEF) \ +bool SettingsModel::OPT(void) { return m_settings->value(g_settingsId_##OPT, DEF).toBool(); } \ +void SettingsModel::OPT(bool value) { m_settings->setValue(g_settingsId_##OPT, value); } + +//LUT const int SettingsModel::mp3Bitrates[15] = {32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, -1}; //////////////////////////////////////////////////////////// @@ -98,26 +107,12 @@ void SettingsModel::validate(void) // Getter and Setter //////////////////////////////////////////////////////////// -MAKE_GETTER1(licenseAccepted, 0) -MAKE_SETTER1(licenseAccepted) - -MAKE_GETTER1(interfaceStyle, 0) -MAKE_SETTER1(interfaceStyle) - -MAKE_GETTER1(compressionEncoder, 0) -MAKE_SETTER1(compressionEncoder) - -MAKE_GETTER1(compressionRCMode, 0) -MAKE_SETTER1(compressionRCMode) - -MAKE_GETTER1(compressionBitrate, 7) -MAKE_SETTER1(compressionBitrate) - -MAKE_GETTER2(outputDir, QString()) -MAKE_SETTER2(outputDir) - -MAKE_GETTER3(writeMetaTags, true) -MAKE_SETTER3(writeMetaTags) - -MAKE_GETTER3(createPlaylist, true) -MAKE_SETTER3(createPlaylist) +MAKE_OPTION1(licenseAccepted, 0) +MAKE_OPTION1(interfaceStyle, 0) +MAKE_OPTION1(compressionEncoder, 0) +MAKE_OPTION1(compressionRCMode, 0) +MAKE_OPTION1(compressionBitrate, 7) +MAKE_OPTION2(outputDir, QString()) +MAKE_OPTION3(outputToSourceDir, false) +MAKE_OPTION3(writeMetaTags, true) +MAKE_OPTION3(createPlaylist, true) diff --git a/src/Model_Settings.h b/src/Model_Settings.h index c5ed184c..89fadf83 100644 --- a/src/Model_Settings.h +++ b/src/Model_Settings.h @@ -24,12 +24,17 @@ class QSettings; class QString; -#define MAKE_GETTER_DEC1(OPT) int OPT(void) -#define MAKE_SETTER_DEC1(OPT) void OPT(int value) -#define MAKE_GETTER_DEC2(OPT) QString OPT(void) -#define MAKE_SETTER_DEC2(OPT) void OPT(const QString &value) -#define MAKE_GETTER_DEC3(OPT) bool OPT(void) -#define MAKE_SETTER_DEC3(OPT) void OPT(bool value) +#define MAKE_OPTION_DEC1(OPT) \ +int OPT(void); \ +void OPT(int value); + +#define MAKE_OPTION_DEC2(OPT) \ +QString OPT(void); \ +void OPT(const QString &value); + +#define MAKE_OPTION_DEC3(OPT) \ +bool OPT(void); \ +void OPT(bool value); class SettingsModel { @@ -56,35 +61,24 @@ public: //Consts static const int mp3Bitrates[15]; - //Getters - MAKE_GETTER_DEC1(licenseAccepted); - MAKE_GETTER_DEC1(interfaceStyle); - MAKE_GETTER_DEC1(compressionEncoder); - MAKE_GETTER_DEC1(compressionRCMode); - MAKE_GETTER_DEC1(compressionBitrate); - MAKE_GETTER_DEC2(outputDir); - MAKE_GETTER_DEC3(writeMetaTags); - MAKE_GETTER_DEC3(createPlaylist); - - //Setters - MAKE_SETTER_DEC1(licenseAccepted); - MAKE_SETTER_DEC1(interfaceStyle); - MAKE_SETTER_DEC1(compressionBitrate); - MAKE_SETTER_DEC1(compressionRCMode); - MAKE_SETTER_DEC1(compressionEncoder); - MAKE_SETTER_DEC2(outputDir); - MAKE_SETTER_DEC3(writeMetaTags); - MAKE_SETTER_DEC3(createPlaylist); + //Getters & setters + MAKE_OPTION_DEC1(licenseAccepted); + MAKE_OPTION_DEC1(interfaceStyle); + MAKE_OPTION_DEC1(compressionEncoder); + MAKE_OPTION_DEC1(compressionRCMode); + MAKE_OPTION_DEC1(compressionBitrate); + MAKE_OPTION_DEC2(outputDir); + MAKE_OPTION_DEC3(outputToSourceDir); + MAKE_OPTION_DEC3(writeMetaTags); + MAKE_OPTION_DEC3(createPlaylist); + //Misc void validate(void); private: QSettings *m_settings; }; -#undef MAKE_GETTER_DEC1 -#undef MAKE_SETTER_DEC1 -#undef MAKE_GETTER_DEC2 -#undef MAKE_SETTER_DEC2 -#undef MAKE_GETTER_DEC3 -#undef MAKE_SETTER_DEC3 +#undef MAKE_OPTION_DEC1 +#undef MAKE_OPTION_DEC2 +#undef MAKE_OPTION_DEC3 diff --git a/src/Thread_Process.cpp b/src/Thread_Process.cpp index 38101aa9..59d57c7c 100644 --- a/src/Thread_Process.cpp +++ b/src/Thread_Process.cpp @@ -71,13 +71,13 @@ void ProcessThread::run() qDebug("Process thread %s has started.", m_jobId.toString().toLatin1().constData()); emit processStateInitialized(m_jobId, QFileInfo(m_audioFile.filePath()).fileName(), "Starting...", ProgressModel::JobRunning); - if(!QFileInfo(m_audioFile.filePath()).isFile()) + QString outFileName = generateOutFileName(); + if(outFileName.isEmpty()) { emit processStateChanged(m_jobId, "Not found!", ProgressModel::JobFailed); return; } - QString outFileName = generateOutFileName(); bool bSuccess = m_encoder->encode(m_audioFile, outFileName, &m_aborted); if(bSuccess) @@ -111,14 +111,28 @@ QString ProcessThread::generateOutFileName(void) int n = 1; - QString baseName = QFileInfo(m_audioFile.filePath()).completeBaseName(); - QString targetDir = m_outputDirectory.isEmpty() ? QFileInfo(m_audioFile.filePath()).canonicalPath() : m_outputDirectory; - QDir(targetDir).mkpath("."); - QString outFileName = QString("%1/%2.%3").arg(targetDir, baseName, "mp3"); + QFileInfo sourceFile(m_audioFile.filePath()); + if(!sourceFile.exists() || !sourceFile.isFile()) + { + return QString(); + } + QString baseName = sourceFile.completeBaseName(); + QDir targetDir(m_outputDirectory.isEmpty() ? sourceFile.canonicalPath() : m_outputDirectory); + + if(!targetDir.exists()) + { + targetDir.mkpath("."); + if(!targetDir.exists()) + { + return QString(); + } + } + + QString outFileName = QString("%1/%2.%3").arg(targetDir.canonicalPath(), baseName, "mp3"); while(QFileInfo(outFileName).exists()) { - outFileName = QString("%1/%2 (%3).%4").arg(targetDir, baseName, QString::number(++n), m_encoder->extension()); + outFileName = QString("%1/%2 (%3).%4").arg(targetDir.canonicalPath(), baseName, QString::number(++n), m_encoder->extension()); } QFile placeholder(outFileName);