diff --git a/etc/Translation/Blank.ts b/etc/Translation/Blank.ts index fae5335f..a7699e6c 100644 --- a/etc/Translation/Blank.ts +++ b/etc/Translation/Blank.ts @@ -254,11 +254,11 @@ - An unknown error has occured! + Failed to load the Cue Sheet file: - Failed to load the Cue Sheet file: + The specified file could not be found! @@ -266,7 +266,7 @@ - The specified file could not be found! + An unknown error has occured! @@ -297,6 +297,10 @@ LameXP + + Error: The selected output directory could not be created! + + Error: The selected output directory is not writable! @@ -321,6 +325,18 @@ Splitting file(s), please wait... + + An unexpected error has occured while splitting the Cue Sheet! + + + + Imported %1 track(s) from the Cue Sheet and skipped %2 track(s). + + + + Cue Sheet Completed + + CueSheetImport @@ -328,6 +344,14 @@ Import Cue Sheet + + Existing Source File + + + + Missing Source File (Tracks will be skipped!) + + Output Directory @@ -340,14 +364,6 @@ Discard - - Existing Source File - - - - Missing Source File (Tracks will be skipped!) - - CueSheetModel @@ -363,6 +379,10 @@ Index + + Duration + + File %1 @@ -379,10 +399,6 @@ Unknown Title - - Duration - - DecoderRegistry @@ -1037,6 +1053,10 @@ Check for Beta Updates + + Import Cue Sheet + + Adding file(s), please wait... @@ -1485,6 +1505,14 @@ The WMA Decoder notifications have been re-enabled. + + Open Cue Sheet + + + + Cue Sheet File + + Beta Updates @@ -1521,18 +1549,6 @@ The LameXP shell integration has been re-enabled. - - Import Cue Sheet - - - - Open Cue Sheet - - - - Cue Sheet File - - MetaInfo diff --git a/etc/Translation/LameXP_DE.ts b/etc/Translation/LameXP_DE.ts index 78c71abd..4b9854b2 100644 --- a/etc/Translation/LameXP_DE.ts +++ b/etc/Translation/LameXP_DE.ts @@ -243,145 +243,161 @@ CueImportDialog Import Cue Sheet - + Cuehseet Assistent The following Cue Sheet will be split and imported into LameXP. - + Das folgende Cuesheet wird aufgeteilt und in LameXP importiert. Loading Cue Sheet file, please be patient... - + Cuesheet Datei wird geladen, bitte warten... An unknown error has occured! - + Ein unbekannter Fehler ist aufgetreten! Failed to load the Cue Sheet file: - + Fehler beim Laden der Cuesheet Datei: Cue Sheet Error - + Cuesheet Fehler The specified file could not be found! - + Die angegebene Datei konnte nicht gefunden werden! The file could not be opened for reading. Make sure you have the required rights! - + Datei kann nicht geöffnet werden. Stellen Sie sicher, dass Sie über die notwendigen Rechte verfügen! The provided file does not look like a valid Cue Sheet disc image file! - + Die angegebene Datei scheint keine gültige Cuesheet Datei zu sein! Could not find any supported audio track in the Cue Sheet image! - + Es konnte kein unterstützter Audio-Track im Cuesheet gefunden werden! Note that LameXP can not handle "binary" Cue Sheet images. - + Beachten Sie, dass LameXP keine "binären" Cuesheets unterstützt. The selected Cue Sheet file contains inconsistent information. Take care! - + Das Cuesheet enthält inkonsistente Informationen. Bitte geben Sie Acht! Choose Output Directory - + Ausgabe-Verzeichnis auswählen LameXP - LameXP + LameXP Error: The selected output directory is not writable! - + Fehler: Im Ausgabe-Verzeichnis kann nicht geschrieben werden! Low Diskspace Warning - Warnung: Wenig freier Festplattenspeicher + Warnung: Wenig freier Festplattenspeicher There are less than %1 GB of free diskspace available in the selected output directory. - + Es sind weniger als %1 GB freier Speicherplatz im Ausgabe-Verzeichnis verfügbar. It is highly recommend to free up more diskspace before proceeding with the import! - + Es wird dringend empfohlen, vor dem Fortfahren mehr Speicherplatz freizugeben! Analyzing file(s), please wait... - + Analysiere Dateien, bitte warten... Splitting file(s), please wait... - + Dateien werden aufgeteilt, bitte warten... + + + Error: The selected output directory could not be created! + Fehler: Das Ausgabe-Verzeichnis konnte nicht erstellt werden! + + + An unexpected error has occured while splitting the Cue Sheet! + Beim Aufteilen des Cuesheets is ein unerwarteter Fehler aufgetreten! + + + Imported %1 track(s) from the Cue Sheet and skipped %2 track(s). + %1 Datei(ein) wurden aus dem Cuesheet importiert und %2 Datei(en) übersprungen. + + + Cue Sheet Completed + Cuesheet Abgeschlossen CueSheetImport Import Cue Sheet - + Cuesheet Importieren Output Directory - + Ausgabe-Verzeichnis Browse... - Durchsuchen... + Durchsuchen... Discard - Schließen + Schließen Existing Source File - + Existierende Quelldatei Missing Source File (Tracks will be skipped!) - + Fehlende Quelldatei (Tracks werden übersprungen!) CueSheetModel No. - + Nr. File / Track - + Datei / Track Index - + Index File %1 - + Datei %1 Track %1 - + Titel %1 Unknown Artist - + Unbekannter Künstler Unknown Title - + Unbekannter Titel Duration - Dauer + Dauer @@ -1524,15 +1540,15 @@ Import Cue Sheet - + Cuesheet importieren Open Cue Sheet - + Cuesheet öffnen Cue Sheet File - + Cuesheet Datei diff --git a/etc/Translation/LameXP_ES.ts b/etc/Translation/LameXP_ES.ts index 5f2eb955..5dc0e994 100644 --- a/etc/Translation/LameXP_ES.ts +++ b/etc/Translation/LameXP_ES.ts @@ -321,6 +321,22 @@ Splitting file(s), please wait... + + Error: The selected output directory could not be created! + + + + An unexpected error has occured while splitting the Cue Sheet! + + + + Imported %1 track(s) from the Cue Sheet and skipped %2 track(s). + + + + Cue Sheet Completed + + CueSheetImport diff --git a/etc/Translation/LameXP_FR.ts b/etc/Translation/LameXP_FR.ts index 63b5ebd3..0f358b9a 100644 --- a/etc/Translation/LameXP_FR.ts +++ b/etc/Translation/LameXP_FR.ts @@ -325,6 +325,22 @@ Splitting file(s), please wait... + + Error: The selected output directory could not be created! + + + + An unexpected error has occured while splitting the Cue Sheet! + + + + Imported %1 track(s) from the Cue Sheet and skipped %2 track(s). + + + + Cue Sheet Completed + + CueSheetImport diff --git a/etc/Translation/LameXP_IT.ts b/etc/Translation/LameXP_IT.ts index 43f4b88f..f18d3ea9 100644 --- a/etc/Translation/LameXP_IT.ts +++ b/etc/Translation/LameXP_IT.ts @@ -321,6 +321,22 @@ Splitting file(s), please wait... + + Error: The selected output directory could not be created! + + + + An unexpected error has occured while splitting the Cue Sheet! + + + + Imported %1 track(s) from the Cue Sheet and skipped %2 track(s). + + + + Cue Sheet Completed + + CueSheetImport diff --git a/etc/Translation/LameXP_KR.ts b/etc/Translation/LameXP_KR.ts index f3ae76cd..23a3386e 100644 --- a/etc/Translation/LameXP_KR.ts +++ b/etc/Translation/LameXP_KR.ts @@ -321,6 +321,22 @@ Splitting file(s), please wait... + + Error: The selected output directory could not be created! + + + + An unexpected error has occured while splitting the Cue Sheet! + + + + Imported %1 track(s) from the Cue Sheet and skipped %2 track(s). + + + + Cue Sheet Completed + + CueSheetImport diff --git a/etc/Translation/LameXP_RU.ts b/etc/Translation/LameXP_RU.ts index 7181c092..237f27cd 100644 --- a/etc/Translation/LameXP_RU.ts +++ b/etc/Translation/LameXP_RU.ts @@ -321,6 +321,22 @@ Splitting file(s), please wait... + + Error: The selected output directory could not be created! + + + + An unexpected error has occured while splitting the Cue Sheet! + + + + Imported %1 track(s) from the Cue Sheet and skipped %2 track(s). + + + + Cue Sheet Completed + + CueSheetImport diff --git a/etc/Translation/LameXP_UK.ts b/etc/Translation/LameXP_UK.ts index e577d303..5d08ef25 100644 --- a/etc/Translation/LameXP_UK.ts +++ b/etc/Translation/LameXP_UK.ts @@ -321,6 +321,22 @@ Splitting file(s), please wait... + + Error: The selected output directory could not be created! + + + + An unexpected error has occured while splitting the Cue Sheet! + + + + Imported %1 track(s) from the Cue Sheet and skipped %2 track(s). + + + + Cue Sheet Completed + + CueSheetImport diff --git a/etc/Translation/update.lst b/etc/Translation/update.lst index dcaf58f2..75523405 100644 --- a/etc/Translation/update.lst +++ b/etc/Translation/update.lst @@ -1,3 +1,4 @@ +..\..\gui\CueSheetImport.ui ..\..\gui\DropBox.ui ..\..\gui\LogViewDialog.ui ..\..\gui\MainWindow.ui @@ -23,6 +24,7 @@ ..\..\src\Decoder_WavPack.cpp ..\..\src\Decoder_WMA.cpp ..\..\src\Dialog_About.cpp +..\..\src\Dialog_CueImport.cpp ..\..\src\Dialog_DropBox.cpp ..\..\src\Dialog_LogView.cpp ..\..\src\Dialog_MainWindow.cpp @@ -49,6 +51,7 @@ ..\..\src\Main.cpp ..\..\src\Model_Artwork.cpp ..\..\src\Model_AudioFile.cpp +..\..\src\Model_CueSheet.cpp ..\..\src\Model_FileList.cpp ..\..\src\Model_FileSystem.cpp ..\..\src\Model_MetaInfo.cpp @@ -57,6 +60,7 @@ ..\..\src\PlaylistImporter.cpp ..\..\src\Registry_Decoder.cpp ..\..\src\ShellIntegration.cpp +..\..\src\Thread_CueSplitter.cpp ..\..\src\Thread_DiskObserver.cpp ..\..\src\Thread_FileAnalyzer.cpp ..\..\src\Thread_Initialization.cpp @@ -83,6 +87,7 @@ ..\..\src\Decoder_WavPack.h ..\..\src\Decoder_WMA.h ..\..\src\Dialog_About.h +..\..\src\Dialog_CueImport.h ..\..\src\Dialog_DropBox.h ..\..\src\Dialog_LogView.h ..\..\src\Dialog_MainWindow.h @@ -108,6 +113,7 @@ ..\..\src\LockedFile.h ..\..\src\Model_Artwork.h ..\..\src\Model_AudioFile.h +..\..\src\Model_CueSheet.h ..\..\src\Model_FileList.h ..\..\src\Model_FileSystem.h ..\..\src\Model_MetaInfo.h @@ -118,6 +124,7 @@ ..\..\src\Resource.h ..\..\src\ShellIntegration.h ..\..\src\Targetver.h +..\..\src\Thread_CueSplitter.h ..\..\src\Thread_DiskObserver.h ..\..\src\Thread_FileAnalyzer.h ..\..\src\Thread_Initialization.h diff --git a/res/localization/LameXP_DE.qm b/res/localization/LameXP_DE.qm index 6efffd57..a9fd4631 100644 Binary files a/res/localization/LameXP_DE.qm and b/res/localization/LameXP_DE.qm differ diff --git a/src/Config.h b/src/Config.h index 9b97d6fd..895c76fb 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 15 -#define VER_LAMEXP_BUILD 520 +#define VER_LAMEXP_BUILD 523 /////////////////////////////////////////////////////////////////////////////// // Tools versions diff --git a/src/Dialog_CueImport.cpp b/src/Dialog_CueImport.cpp index 64bb5296..d58f80f7 100644 --- a/src/Dialog_CueImport.cpp +++ b/src/Dialog_CueImport.cpp @@ -101,12 +101,7 @@ int CueImportDialog::exec(void) progress->show(tr("Loading Cue Sheet file, please be patient...")); QFileInfo cueFileInfo(m_cueFileName); - QDir outputDir(cueFileInfo.canonicalPath()); - m_outputDir = outputDir.canonicalPath(); - - setWindowTitle(QString("%1: %2").arg(windowTitle().split(":", QString::SkipEmptyParts).first().trimmed(), cueFileInfo.fileName())); - - if(!cueFileInfo.exists() || !cueFileInfo.isFile() || m_outputDir.isEmpty()) + if(!cueFileInfo.exists() || !cueFileInfo.isFile()) { QString text = QString("%1
%2

%3").arg(tr("Failed to load the Cue Sheet file:"), QDir::toNativeSeparators(m_cueFileName), tr("The specified file could not be found!")).replace("-", "−"); QMessageBox::warning(progress, tr("Cue Sheet Error"), text); @@ -115,11 +110,8 @@ int CueImportDialog::exec(void) return CueSheetModel::ErrorIOFailure; } - outputDir.mkdir(cueFileInfo.completeBaseName()); - if(outputDir.cd(cueFileInfo.completeBaseName())) - { - m_outputDir = outputDir.canonicalPath(); - } + m_outputDir = QString("%1/%2").arg(cueFileInfo.canonicalPath(), cueFileInfo.completeBaseName()); + setWindowTitle(QString("%1: %2").arg(windowTitle().split(":", QString::SkipEmptyParts).first().trimmed(), cueFileInfo.fileName())); int iResult = m_model->loadCueSheet(m_cueFileName, QApplication::instance()); if(iResult != CueSheetModel::ErrorSuccess) @@ -176,6 +168,14 @@ void CueImportDialog::importButtonClicked(void) static const __int64 minimumFreeDiskspaceMultiplier = 2i64; static const char *writeTestBuffer = "LAMEXP_WRITE_TEST"; + QDir outputDir(m_outputDir); + outputDir.mkpath("."); + if(!(outputDir.exists() && outputDir.isReadable())) + { + QMessageBox::warning(this, tr("LameXP"), QString("%2").arg(tr("Error: The selected output directory could not be created!"))); + return; + } + QFile writeTest(QString("%1/~%2.txt").arg(m_outputDir, lamexp_rand_str())); if(!(writeTest.open(QIODevice::ReadWrite) && (writeTest.write(writeTestBuffer) == strlen(writeTestBuffer)))) { @@ -247,7 +247,7 @@ void CueImportDialog::analyzeFiles(QStringList &files) { m_fileInfo.clear(); - WorkingBanner *progress = new WorkingBanner(dynamic_cast(parent())); + WorkingBanner *progress = new WorkingBanner(this); FileAnalyzer *analyzer = new FileAnalyzer(files); connect(analyzer, SIGNAL(fileSelected(QString)), progress, SLOT(setText(QString)), Qt::QueuedConnection); @@ -260,12 +260,15 @@ void CueImportDialog::analyzeFiles(QStringList &files) void CueImportDialog::splitFiles(void) { + int nTracksSkipped = 0; + WorkingBanner *progress = new WorkingBanner(this); CueSplitter *splitter = new CueSplitter(m_outputDir, QFileInfo(m_cueFileName).completeBaseName().replace(".", " ").left(42).trimmed(), m_fileInfo); - + splitter->setAlbumInfo(m_model->getAlbumPerformer(), m_model->getAlbumTitle()); + connect(splitter, SIGNAL(fileSelected(QString)), progress, SLOT(setText(QString)), Qt::QueuedConnection); connect(splitter, SIGNAL(fileSplit(AudioFileModel)), m_fileList, SLOT(addFile(AudioFileModel)), Qt::QueuedConnection); - + int nFiles = m_model->getFileCount(); for(int i = 0; i < nFiles; i++) { @@ -282,6 +285,7 @@ void CueImportDialog::splitFiles(void) AudioFileModel metaInfo(QString().sprintf("cue://File%02d/Track%02d", i, j)); metaInfo.setFileName(m_model->getTrackTitle(i, j)); metaInfo.setFileArtist(m_model->getTrackPerformer(i, j)); + metaInfo.setFilePosition(trackNo); try { @@ -290,6 +294,7 @@ void CueImportDialog::splitFiles(void) catch(char *err) { qWarning("Failed to add track #%02d: %s", trackNo, err); + nTracksSkipped++; } } } @@ -297,6 +302,16 @@ void CueImportDialog::splitFiles(void) progress->show(tr("Splitting file(s), please wait..."), splitter); progress->close(); + if(!splitter->getSuccess()) + { + QMessageBox::warning(this, tr("Cue Sheet Error"), tr("An unexpected error has occured while splitting the Cue Sheet!")); + } + else + { + QString text = tr("Imported %1 track(s) from the Cue Sheet and skipped %2 track(s).").arg(QString::number(splitter->getTracksSuccess()), QString::number(splitter->getTracksSkipped() + nTracksSkipped)); + QMessageBox::information(this, tr("Cue Sheet Completed"), text); + } + LAMEXP_DELETE(splitter); LAMEXP_DELETE(progress); } diff --git a/src/Model_CueSheet.cpp b/src/Model_CueSheet.cpp index 4a9a9f79..b05c23fc 100644 --- a/src/Model_CueSheet.cpp +++ b/src/Model_CueSheet.cpp @@ -96,6 +96,9 @@ private: //////////////////////////////////////////////////////////// CueSheetModel::CueSheetModel() +: + m_fileIcon(":/icons/music.png"), + m_trackIcon(":/icons/control_play_blue.png") { int trackNo = 0; @@ -273,6 +276,22 @@ QVariant CueSheetModel::data(const QModelIndex &index, int role) const return QDir::toNativeSeparators(trackPtr->parent()->fileName()); } } + else if(role == Qt::DecorationRole) + { + if(index.column() == 0) + { + CueSheetItem *item = reinterpret_cast(index.internalPointer()); + + if(dynamic_cast(item)) + { + return m_fileIcon; + } + else if(dynamic_cast(item)) + { + return m_trackIcon; + } + } + } else if(role == Qt::FontRole) { QFont font("Monospace"); @@ -456,8 +475,8 @@ int CueSheetModel::parseCueFile(QFile &cueFile, const QDir &baseDir, QCoreApplic CueSheetFile *currentFile = NULL; CueSheetTrack *currentTrack = NULL; - QString albumTitle; - QString albumPerformer; + m_albumTitle.clear(); + m_albumPerformer.clear(); //Loop over the Cue Sheet until all lines were processed for(int lines = 0; lines < INT_MAX; lines++) @@ -487,8 +506,6 @@ int CueSheetModel::parseCueFile(QFile &cueFile, const QDir &baseDir, QCoreApplic { if(currentTrack->isValid()) { - currentTrack->setTitle(albumTitle, true); - currentTrack->setPerformer(albumPerformer, true); currentFile->addTrack(currentTrack); currentTrack = NULL; } @@ -537,8 +554,6 @@ int CueSheetModel::parseCueFile(QFile &cueFile, const QDir &baseDir, QCoreApplic { if(currentTrack->isValid()) { - currentTrack->setTitle(albumTitle, true); - currentTrack->setPerformer(albumPerformer, true); currentFile->addTrack(currentTrack); currentTrack = NULL; } @@ -585,7 +600,7 @@ int CueSheetModel::parseCueFile(QFile &cueFile, const QDir &baseDir, QCoreApplic { if(bPreamble) { - albumTitle = rxTitle.cap(1); + m_albumTitle = rxTitle.cap(1).simplified(); } else if(currentFile && currentTrack) { @@ -600,7 +615,7 @@ int CueSheetModel::parseCueFile(QFile &cueFile, const QDir &baseDir, QCoreApplic { if(bPreamble) { - albumPerformer = rxPerformer.cap(1); + m_albumPerformer = rxPerformer.cap(1).simplified(); } else if(currentFile && currentTrack) { @@ -618,8 +633,6 @@ int CueSheetModel::parseCueFile(QFile &cueFile, const QDir &baseDir, QCoreApplic { if(currentTrack->isValid()) { - currentTrack->setTitle(albumTitle, true); - currentTrack->setPerformer(albumPerformer, true); currentFile->addTrack(currentTrack); currentTrack = NULL; } @@ -749,7 +762,7 @@ QString CueSheetModel::indexToString(const double index) const } else { - int temp = static_cast(index * 100.0); + int temp = static_cast(floor(0.5 + (index * 100.0))); int msec = temp % 100; int secs = temp / 100; diff --git a/src/Model_CueSheet.h b/src/Model_CueSheet.h index d0ff6403..cf817e53 100644 --- a/src/Model_CueSheet.h +++ b/src/Model_CueSheet.h @@ -65,6 +65,8 @@ public: void getTrackIndex(int fileIndex, int trackIndex, double *startIndex, double *duration); QString getTrackPerformer(int fileIndex, int trackIndex); QString getTrackTitle(int fileIndex, int trackIndex); + QString getAlbumPerformer(void) { return m_albumPerformer; } + QString getAlbumTitle(void) { return m_albumTitle; } //Cue Sheet functions int loadCueSheet(const QString &cueFile, QCoreApplication *application = NULL); @@ -73,5 +75,11 @@ private: int parseCueFile(QFile &cueFile, const QDir &baseDir, QCoreApplication *application); double parseTimeIndex(const QString &index); QString indexToString(const double index) const; + QList m_files; + QString m_albumTitle; + QString m_albumPerformer; + + const QIcon m_fileIcon; + const QIcon m_trackIcon; }; diff --git a/src/Thread_CueSplitter.cpp b/src/Thread_CueSplitter.cpp index 1f01f4ae..692cb803 100644 --- a/src/Thread_CueSplitter.cpp +++ b/src/Thread_CueSplitter.cpp @@ -50,6 +50,9 @@ CueSplitter::CueSplitter(const QString &outputDir, const QString &baseName, cons qFatal("Invalid path to SoX binary. Tool not initialized properly."); } + m_albumPerformer.clear(); + m_albumTitle.clear(); + qDebug("\n[CueSplitter::CueSplitter]"); int nInputFiles = inputFiles.count(); @@ -70,6 +73,8 @@ CueSplitter::CueSplitter(const QString &outputDir, const QString &baseName, cons void CueSplitter::run() { m_bSuccess = false; + m_nTracksSuccess = 0; + m_nTracksSkipped = 0; m_abortFlag = false; int nTracks = min(min(min(m_trackFile.count(), m_trackNo.count()), min(m_trackOffset.count(), m_trackLength.count())), m_trackMetaInfo.count()); @@ -113,6 +118,12 @@ void CueSplitter::addTrack(const int trackNo, const QString &file, const double } } +void CueSplitter::setAlbumInfo(const QString &performer, const QString &title) +{ + if(!performer.isEmpty()) m_albumPerformer = performer; + if(!title.isEmpty()) m_albumTitle = title; +} + //////////////////////////////////////////////////////////// // Privtae Functions //////////////////////////////////////////////////////////// @@ -125,13 +136,13 @@ void CueSplitter::splitFile(const QString &output, const int trackNo, const QStr qDebug("Length: %f", length); qDebug("Artist: <%s>", metaInfo.fileArtist().toUtf8().constData()); qDebug("Title: <%s>", metaInfo.fileName().toUtf8().constData()); - - QRegExp regExp("In:(\\d+)(\\.\\d+)*%"); + QString baseName = QFileInfo(output).fileName(); if(!m_inputFiles.contains(file)) { qWarning("Unknown input file, skipping!"); + m_nTracksSkipped++; return; } @@ -139,22 +150,51 @@ void CueSplitter::splitFile(const QString &output, const int trackNo, const QStr if(inputFileInfo.formatContainerType().compare("Wave", Qt::CaseInsensitive) || inputFileInfo.formatAudioType().compare("PCM", Qt::CaseInsensitive)) { qWarning("Sorry, only Wave/PCM files are supported at this time!"); + m_nTracksSkipped++; return; } + AudioFileModel outFileInfo(metaInfo); + outFileInfo.setFilePath(output); + outFileInfo.setFormatContainerType(inputFileInfo.formatContainerType()); + outFileInfo.setFormatAudioType(inputFileInfo.formatAudioType()); + + if(length != std::numeric_limits::infinity()) + { + outFileInfo.setFileDuration(static_cast(abs(length))); + } + if(!m_albumTitle.isEmpty()) + { + outFileInfo.setFileAlbum(m_albumTitle); + } + if(!m_albumPerformer.isEmpty() && outFileInfo.fileArtist().isEmpty()) + { + outFileInfo.setFileArtist(m_albumPerformer); + } + QStringList args; args << "-S" << "-V3"; args << "--guard" << "--temp" << "."; args << QDir::toNativeSeparators(file); args << QDir::toNativeSeparators(output); - args << "trim"; - args << indexToString(offset); - if((length != std::numeric_limits::quiet_NaN()) && (length != std::numeric_limits::infinity())) + if(offset != 0.0 || length != std::numeric_limits::infinity()) { - args << indexToString(length); + args << "trim"; + args << indexToString(offset); + + if((length != std::numeric_limits::quiet_NaN()) && (length != std::numeric_limits::infinity())) + { + args << indexToString(length); + } } + QRegExp rxProgress("In:(\\d+)(\\.\\d+)*%", Qt::CaseInsensitive); + QRegExp rxChannels("Channels\\s*:\\s*(\\d+)", Qt::CaseInsensitive); + QRegExp rxSamplerate("Sample Rate\\s*:\\s*(\\d+)", Qt::CaseInsensitive); + QRegExp rxPrecision("Precision\\s*:\\s*(\\d+)-bit", Qt::CaseInsensitive); + QRegExp rxDuration("Duration\\s*:\\s*(\\d\\d):(\\d\\d):(\\d\\d).(\\d\\d)", Qt::CaseInsensitive); + QProcess process; process.setProcessChannelMode(QProcess::MergedChannels); process.setReadChannel(QProcess::StandardOutput); @@ -167,6 +207,7 @@ void CueSplitter::splitFile(const QString &output, const int trackNo, const QStr qWarning("Error message: \"%s\"\n", process.errorString().toLatin1().constData()); process.kill(); process.waitForFinished(-1); + m_nTracksSkipped++; return; } @@ -188,18 +229,58 @@ void CueSplitter::splitFile(const QString &output, const int trackNo, const QStr { QByteArray line = process.readLine(); QString text = QString::fromUtf8(line.constData()).simplified(); - if(regExp.lastIndexIn(text) >= 0) + if(rxProgress.lastIndexIn(text) >= 0) { bool ok = false; - int progress = regExp.cap(1).toInt(&ok); + int progress = rxProgress.cap(1).toInt(&ok); if(ok) { emit fileSelected(QString("%1 [%2%]").arg(baseName, QString::number(progress))); } } + else if(rxChannels.lastIndexIn(text) >= 0) + { + bool ok = false; + unsigned int channels = rxChannels.cap(1).toUInt(&ok); + if(ok) outFileInfo.setFormatAudioChannels(channels); + } + else if(rxSamplerate.lastIndexIn(text) >= 0) + { + bool ok = false; + unsigned int samplerate = rxSamplerate.cap(1).toUInt(&ok); + if(ok) outFileInfo.setFormatAudioSamplerate(samplerate); + } + else if(rxPrecision.lastIndexIn(text) >= 0) + { + bool ok = false; + unsigned int precision = rxPrecision.cap(1).toUInt(&ok); + if(ok) outFileInfo.setFormatAudioBitdepth(precision); + } + else if(rxDuration.lastIndexIn(text) >= 0) + { + bool ok1 = false, ok2 = false, ok3 = false; + unsigned int hh = rxDuration.cap(1).toUInt(&ok1); + unsigned int mm = rxDuration.cap(2).toUInt(&ok2); + unsigned int ss = rxDuration.cap(3).toUInt(&ok3); + if(ok1 && ok2 && ok3) + { + unsigned intputLen = (hh * 3600) + (mm * 60) + ss; + if(length == std::numeric_limits::infinity()) + { + qDebug("Duration updated from SoX info!"); + outFileInfo.setFileDuration(max(0, intputLen - static_cast(floor(offset + 0.5)))); + } + else + { + unsigned int trackEnd = static_cast(floor(offset + 0.5)) + static_cast(floor(length + 0.5)); + if(trackEnd > intputLen) qWarning("Track is out of bounds: End of track exceeds input file duration!"); + } + } + } } } + process.waitForFinished(); if(process.state() != QProcess::NotRunning) { process.kill(); @@ -208,16 +289,13 @@ void CueSplitter::splitFile(const QString &output, const int trackNo, const QStr if(process.exitStatus() != QProcess::NormalExit || QFileInfo(output).size() == 0) { - qWarning("Splitting has failed!"); + qWarning("Splitting has failed !!!"); + m_nTracksSkipped++; return; } - AudioFileModel outFileInfo(metaInfo); - outFileInfo.setFilePath(output); - outFileInfo.setFormatContainerType(inputFileInfo.formatContainerType()); - outFileInfo.setFormatAudioType(inputFileInfo.formatAudioType()); - outFileInfo.setFileDuration(static_cast(abs(length))); emit fileSplit(outFileInfo); + m_nTracksSuccess++; } QString CueSplitter::indexToString(const double index) const @@ -227,7 +305,7 @@ QString CueSplitter::indexToString(const double index) const return QString(); } - int temp = static_cast(index * 1000.0); + int temp = static_cast(floor(0.5 + (index * 1000.0))); int msec = temp % 1000; int secs = temp / 1000; diff --git a/src/Thread_CueSplitter.h b/src/Thread_CueSplitter.h index b31efad1..0baa6a22 100644 --- a/src/Thread_CueSplitter.h +++ b/src/Thread_CueSplitter.h @@ -42,7 +42,10 @@ public: CueSplitter(const QString &outputDir, const QString &baseName, const QList &inputFiles); void run(); bool getSuccess(void) { return !isRunning() && m_bSuccess; } + unsigned int getTracksSuccess(void) { return m_nTracksSuccess; } + unsigned int getTracksSkipped(void) { return m_nTracksSkipped; } void addTrack(const int trackNo, const QString &file, const double offset, const double length, const AudioFileModel &metaInfo); + void setAlbumInfo(const QString &performer, const QString &title); signals: void fileSelected(const QString &fileName); @@ -55,9 +58,13 @@ private: const QString m_soxBin; const QString m_outputDir; const QString m_baseName; + unsigned int m_nTracksSuccess; + unsigned int m_nTracksSkipped; bool m_bSuccess; volatile bool m_abortFlag; + QString m_albumTitle; + QString m_albumPerformer; QMap m_inputFiles; QList m_trackFile; QList m_trackNo;