diff --git a/gui/CueSheetImport.ui b/gui/CueSheetImport.ui index 7ed6d920..9e9f4c3f 100644 --- a/gui/CueSheetImport.ui +++ b/gui/CueSheetImport.ui @@ -171,17 +171,281 @@ 9 - - - true + + + 2 - - QAbstractItemView::SingleSelection - - - QAbstractItemView::SelectRows - - + + + + true + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + + + + + + + + 16 + 16 + + + + + 16 + 16 + + + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + + + 0 + 0 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + + true + + + QFrame::StyledPanel + + + QFrame::Plain + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 4 + 20 + + + + + + + + Existing Source File + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 12 + 20 + + + + + + + + + 16 + 16 + + + + + 16 + 16 + + + + + + + + + 255 + 255 + 255 + + + + + + + 170 + 0 + 0 + + + + + + + + + 255 + 255 + 255 + + + + + + + 170 + 0 + 0 + + + + + + + + + 170 + 0 + 0 + + + + + + + 170 + 0 + 0 + + + + + + + + true + + + QFrame::StyledPanel + + + QFrame::Plain + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 4 + 20 + + + + + + + + Missing Source File (Tracks will be skipped!) + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + @@ -316,7 +580,6 @@ abortButton editOutputDir browseButton - treeView @@ -351,6 +614,8 @@ + + diff --git a/res/icons/wma.png b/res/icons/wma.png index 6913582a..80b5ce6e 100644 Binary files a/res/icons/wma.png and b/res/icons/wma.png differ diff --git a/src/Config.h b/src/Config.h index 07f69e0f..10c2c019 100644 --- a/src/Config.h +++ b/src/Config.h @@ -30,7 +30,7 @@ #define VER_LAMEXP_MINOR_LO 2 #define VER_LAMEXP_TYPE Alpha #define VER_LAMEXP_PATCH 14 -#define VER_LAMEXP_BUILD 513 +#define VER_LAMEXP_BUILD 515 /////////////////////////////////////////////////////////////////////////////// // Tools versions diff --git a/src/Dialog_CueImport.cpp b/src/Dialog_CueImport.cpp index 9df31e2c..3a2c0fc1 100644 --- a/src/Dialog_CueImport.cpp +++ b/src/Dialog_CueImport.cpp @@ -23,7 +23,9 @@ #include "Global.h" #include "Model_CueSheet.h" +#include "Model_AudioFile.h" #include "Dialog_WorkingBanner.h" +#include "Thread_FileAnalyzer.h" #include #include @@ -96,6 +98,8 @@ int CueImportDialog::exec(const QString &cueFile) QFileInfo cueFileInfo(cueFile); m_outputDir = QFileInfo(cueFile).canonicalPath(); + setWindowTitle(QString("%1: %2").arg(windowTitle().split(":", QString::SkipEmptyParts).first().trimmed(), cueFileInfo.fileName())); + if(!cueFileInfo.exists() || !cueFileInfo.isFile() || m_outputDir.isEmpty()) { QString text = QString("%1
%2

%3").arg(tr("Failed to load the Cue Sheet file:"), QDir::toNativeSeparators(cueFile), tr("The specified file could not be found!")).replace("-", "−"); @@ -156,5 +160,67 @@ void CueImportDialog::browseButtonClicked(void) void CueImportDialog::importButtonClicked(void) { - QMessageBox::information(this, "Not implemenred", "Sorry, not yet. Please try again in a later version!"); + static const __int64 oneGigabyte = 1073741824i64; + static const __int64 minimumFreeDiskspaceMultiplier = 2i64; + static const char *writeTestBuffer = "LAMEXP_WRITE_TEST"; + + QFile writeTest(QString("%1/~%2.txt").arg(m_outputDir, lamexp_rand_str())); + if(!(writeTest.open(QIODevice::ReadWrite) && (writeTest.write(writeTestBuffer) == strlen(writeTestBuffer)))) + { + QMessageBox::warning(this, tr("LameXP"), QString("%2").arg(tr("Error: The selected output directory is not writable!"))); + return; + } + else + { + writeTest.close(); + writeTest.remove(); + } + + qint64 currentFreeDiskspace = lamexp_free_diskspace(m_outputDir); + if(currentFreeDiskspace < (oneGigabyte * minimumFreeDiskspaceMultiplier)) + { + QMessageBox::warning(this, tr("Low Diskspace Warning"), QString("%1
%2").arg(tr("There are less than %1 GB of free diskspace available in the selected output directory.").arg(QString::number(minimumFreeDiskspaceMultiplier)), tr("It is highly recommend to free up more diskspace before proceeding with the import!"))); + return; + } + + importCueSheet(); +} + +void CueImportDialog::analyzedFile(const AudioFileModel &file) +{ + qWarning("Received results for: %s", file.filePath().toLatin1().constData()); + m_fileInfo.insert(file.filePath(), file); +} + +//////////////////////////////////////////////////////////// +// Private FUnctions +//////////////////////////////////////////////////////////// + +void CueImportDialog::importCueSheet(void) +{ + QStringList files; + int nFiles = m_model->getFileCount(); + + //Fetch all files that are referenced in the Cue Sheet + for(int i = 0; i < nFiles; i++) + { + files << m_model->getFileName(i); + } + + //Analyze all source files + analyzeFiles(files); +} + +void CueImportDialog::analyzeFiles(QStringList &files) +{ + m_fileInfo.clear(); + + WorkingBanner *progress = new WorkingBanner(dynamic_cast(parent())); + FileAnalyzer *analyzer = new FileAnalyzer(files); + connect(analyzer, SIGNAL(fileSelected(QString)), progress, SLOT(setText(QString)), Qt::QueuedConnection); + connect(analyzer, SIGNAL(fileAnalyzed(AudioFileModel)), this, SLOT(analyzedFile(AudioFileModel)), Qt::QueuedConnection); + + progress->show(tr("Adding file(s), please wait..."), analyzer); + progress->close(); + LAMEXP_DELETE(progress); } diff --git a/src/Dialog_CueImport.h b/src/Dialog_CueImport.h index 2b35f035..5fc542de 100644 --- a/src/Dialog_CueImport.h +++ b/src/Dialog_CueImport.h @@ -45,8 +45,13 @@ private slots: void browseButtonClicked(void); void importButtonClicked(void); void modelChanged(void); + void analyzedFile(const AudioFileModel &file); private: + void importCueSheet(void); + void analyzeFiles(QStringList &files); + CueSheetModel *m_model; + QMap m_fileInfo; QString m_outputDir; }; diff --git a/src/Dialog_MainWindow.cpp b/src/Dialog_MainWindow.cpp index 23be3c69..1aa069bc 100644 --- a/src/Dialog_MainWindow.cpp +++ b/src/Dialog_MainWindow.cpp @@ -1025,6 +1025,7 @@ void MainWindow::encodeButtonClicked(void) { static const __int64 oneGigabyte = 1073741824i64; static const __int64 minimumFreeDiskspaceMultiplier = 2i64; + static const char *writeTestBuffer = "LAMEXP_WRITE_TEST"; ABORT_IF_BUSY; @@ -1081,8 +1082,8 @@ void MainWindow::encodeButtonClicked(void) if(!m_settings->outputToSourceDir()) { - QFile writeTest(QString("%1/~%2.txt").arg(m_settings->outputDir(), QUuid::createUuid().toString())); - if(!writeTest.open(QIODevice::ReadWrite)) + QFile writeTest(QString("%1/~%2.txt").arg(m_settings->outputDir(), lamexp_rand_str())); + if(!(writeTest.open(QIODevice::ReadWrite) && (writeTest.write(writeTestBuffer) == strlen(writeTestBuffer)))) { QMessageBox::warning(this, tr("LameXP"), QString("%1
%2

%3").arg(tr("Cannot write to the selected output directory."), m_settings->outputDir(), tr("Please choose a different directory!"))); tabWidget->setCurrentIndex(1); diff --git a/src/Model_CueSheet.cpp b/src/Model_CueSheet.cpp index 0a0c2a8d..91e89121 100644 --- a/src/Model_CueSheet.cpp +++ b/src/Model_CueSheet.cpp @@ -260,6 +260,19 @@ QVariant CueSheetModel::data(const QModelIndex &index, int role) const } } } + else if(role == Qt::ToolTipRole) + { + CueSheetItem *item = reinterpret_cast(index.internalPointer()); + + if(CueSheetFile *filePtr = dynamic_cast(item)) + { + return QDir::toNativeSeparators(filePtr->fileName()); + } + else if(CueSheetTrack *trackPtr = dynamic_cast(item)) + { + return QDir::toNativeSeparators(trackPtr->parent()->fileName()); + } + } else if(role == Qt::FontRole) { QFont font("Monospace"); @@ -278,7 +291,7 @@ QVariant CueSheetModel::data(const QModelIndex &index, int role) const CueSheetItem *item = reinterpret_cast(index.internalPointer()); if(CueSheetFile *filePtr = dynamic_cast(item)) { - return QFileInfo(filePtr->fileName()).exists() ? QColor("mediumblue") : QColor("darkred"); + return (QFileInfo(filePtr->fileName()).size() > 4) ? QColor("mediumblue") : QColor("darkred"); } } else if((index.column() == 3)) @@ -304,6 +317,52 @@ void CueSheetModel::clearData(void) endResetModel(); } +//////////////////////////////////////////////////////////// +// External API +//////////////////////////////////////////////////////////// + +int CueSheetModel::getFileCount(void) +{ + return m_files.count(); +} + +QString CueSheetModel::getFileName(int fileIndex) +{ + if(fileIndex < 0 || fileIndex >= m_files.count()) + { + return QString(); + } + + return m_files.at(fileIndex)->fileName(); +} + +int CueSheetModel::getTrackCount(int fileIndex) +{ + if(fileIndex < 0 || fileIndex >= m_files.count()) + { + return -1; + } + + return m_files.at(fileIndex)->trackCount(); +} + +void CueSheetModel::getTrackIndex(int fileIndex, int trackIndex, double *startIndex, double *duration) +{ + *startIndex = std::numeric_limits::quiet_NaN(); + *duration = std::numeric_limits::quiet_NaN(); + + if(fileIndex >= 0 && fileIndex < m_files.count()) + { + CueSheetFile *currentFile = m_files.at(fileIndex); + if(trackIndex >= 0 && trackIndex < currentFile->trackCount()) + { + CueSheetTrack *currentTrack = currentFile->track(trackIndex); + *startIndex = currentTrack->startIndex(); + *duration = currentTrack->duration(); + } + } +} + //////////////////////////////////////////////////////////// // Cue Sheet Parser //////////////////////////////////////////////////////////// @@ -359,12 +418,12 @@ int CueSheetModel::parseCueFile(QFile &cueFile, const QDir &baseDir, QCoreApplic QString albumPerformer; //Loop over the Cue Sheet until all lines were processed - while(true) + for(int lines = 0; lines < INT_MAX; lines++) { if(application) { application->processEvents(); - Sleep(10); + if(lines < 128) Sleep(10); } QByteArray lineData = cueFile.readLine(); @@ -379,7 +438,7 @@ int CueSheetModel::parseCueFile(QFile &cueFile, const QDir &baseDir, QCoreApplic /* --- FILE --- */ if(rxFile.indexIn(line) >= 0) { - qDebug("File: <%s> <%s>", rxFile.cap(1).toUtf8().constData(), rxFile.cap(2).toUtf8().constData()); + qDebug("%03d File: <%s> <%s>", lines, rxFile.cap(1).toUtf8().constData(), rxFile.cap(2).toUtf8().constData()); if(currentFile) { if(currentTrack) @@ -413,12 +472,12 @@ int CueSheetModel::parseCueFile(QFile &cueFile, const QDir &baseDir, QCoreApplic if(!rxFile.cap(2).compare("WAVE", Qt::CaseInsensitive) || !rxFile.cap(2).compare("MP3", Qt::CaseInsensitive) || !rxFile.cap(2).compare("AIFF", Qt::CaseInsensitive)) { currentFile = new CueSheetFile(baseDir.absoluteFilePath(rxFile.cap(1))); - qDebug("File path: <%s>", currentFile->fileName().toUtf8().constData()); + qDebug("%03d File path: <%s>", lines, currentFile->fileName().toUtf8().constData()); } else { bUnsupportedTrack = true; - qWarning("Skipping unsupported file of type '%s'.", rxFile.cap(2).toUtf8().constData()); + qWarning("%03d Skipping unsupported file of type '%s'.", lines, rxFile.cap(2).toUtf8().constData()); currentFile = NULL; } bPreamble = false; @@ -431,7 +490,7 @@ int CueSheetModel::parseCueFile(QFile &cueFile, const QDir &baseDir, QCoreApplic { if(currentFile) { - qDebug(" Track: <%s> <%s>", rxTrack.cap(1).toUtf8().constData(), rxTrack.cap(2).toUtf8().constData()); + qDebug("%03d Track: <%s> <%s>", lines, rxTrack.cap(1).toUtf8().constData(), rxTrack.cap(2).toUtf8().constData()); if(currentTrack) { if(currentTrack->isValid()) @@ -453,7 +512,7 @@ int CueSheetModel::parseCueFile(QFile &cueFile, const QDir &baseDir, QCoreApplic else { bUnsupportedTrack = true; - qWarning(" Skipping unsupported track of type '%s'.", rxTrack.cap(2).toUtf8().constData()); + qWarning("%03d Skipping unsupported track of type '%s'.", lines, rxTrack.cap(2).toUtf8().constData()); currentTrack = NULL; } } @@ -470,7 +529,7 @@ int CueSheetModel::parseCueFile(QFile &cueFile, const QDir &baseDir, QCoreApplic { if(currentFile && currentTrack) { - qDebug(" Index: <%s> <%s>", rxIndex.cap(1).toUtf8().constData(), rxIndex.cap(2).toUtf8().constData()); + qDebug("%03d Index: <%s> <%s>", lines, rxIndex.cap(1).toUtf8().constData(), rxIndex.cap(2).toUtf8().constData()); if(rxIndex.cap(1).toInt() == 1) { currentTrack->setStartIndex(parseTimeIndex(rxIndex.cap(2))); @@ -488,7 +547,7 @@ int CueSheetModel::parseCueFile(QFile &cueFile, const QDir &baseDir, QCoreApplic } else if(currentFile && currentTrack) { - qDebug(" Title: <%s>", rxTitle.cap(1).toUtf8().constData()); + qDebug("%03d Title: <%s>", lines, rxTitle.cap(1).toUtf8().constData()); currentTrack->setTitle(rxTitle.cap(1)); } continue; @@ -503,7 +562,7 @@ int CueSheetModel::parseCueFile(QFile &cueFile, const QDir &baseDir, QCoreApplic } else if(currentFile && currentTrack) { - qDebug(" Title: <%s>", rxPerformer.cap(1).toUtf8().constData()); + qDebug("%03d Title: <%s>", lines, rxPerformer.cap(1).toUtf8().constData()); currentTrack->setPerformer(rxPerformer.cap(1)); } continue; diff --git a/src/Model_CueSheet.h b/src/Model_CueSheet.h index acb66df2..fa509f33 100644 --- a/src/Model_CueSheet.h +++ b/src/Model_CueSheet.h @@ -57,6 +57,12 @@ public: QModelIndex parent(const QModelIndex &child) const; void clearData(void); + //External API + int CueSheetModel::getFileCount(void); + QString getFileName(int fileIndex); + int getTrackCount(int fileIndex); + void getTrackIndex(int fileIndex, int trackIndex, double *startIndex, double *duration); + //Cue Sheet functions int loadCueSheet(const QString &cueFile, QCoreApplication *application = NULL);