Refactored Cue Sheet splitter thread: Now we simply pass a pointer to the Cue Sheet model into the Cue Sheet splitter thread instead of having to copying all the information in the Cue Sheet import dialog. Also the Cue Sheet import process can now be aborted by the user.
This commit is contained in:
parent
243993434e
commit
489829fb37
@ -341,6 +341,10 @@
|
||||
<source>Splitting file(s), please wait...</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Process was aborted by the user after %1 track(s)!</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>An unexpected error has occured while splitting the Cue Sheet!</source>
|
||||
<translation type="unfinished"></translation>
|
||||
|
@ -353,6 +353,10 @@
|
||||
<source>Abort</source>
|
||||
<translation>Abbrechen</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Process was aborted by the user after %1 track(s)!</source>
|
||||
<translation>Der Vorgang wurde vom Benutzter nach %1 Track(s) abgebrochen!</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>CueSheetImport</name>
|
||||
|
@ -353,6 +353,10 @@
|
||||
<source>Abort</source>
|
||||
<translation type="unfinished">Cancelar</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Process was aborted by the user after %1 track(s)!</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>CueSheetImport</name>
|
||||
|
@ -357,6 +357,10 @@
|
||||
<source>Abort</source>
|
||||
<translation type="unfinished">Abandonner</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Process was aborted by the user after %1 track(s)!</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>CueSheetImport</name>
|
||||
|
@ -353,6 +353,10 @@
|
||||
<source>Abort</source>
|
||||
<translation type="unfinished">Ferma</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Process was aborted by the user after %1 track(s)!</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>CueSheetImport</name>
|
||||
|
@ -353,6 +353,10 @@
|
||||
<source>Abort</source>
|
||||
<translation type="unfinished">취소</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Process was aborted by the user after %1 track(s)!</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>CueSheetImport</name>
|
||||
|
@ -353,6 +353,10 @@
|
||||
<source>Abort</source>
|
||||
<translation type="unfinished">Отмена</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Process was aborted by the user after %1 track(s)!</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>CueSheetImport</name>
|
||||
|
@ -353,6 +353,10 @@
|
||||
<source>Abort</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Process was aborted by the user after %1 track(s)!</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>CueSheetImport</name>
|
||||
|
Binary file not shown.
@ -28,9 +28,9 @@
|
||||
#define VER_LAMEXP_MAJOR 4
|
||||
#define VER_LAMEXP_MINOR_HI 0
|
||||
#define VER_LAMEXP_MINOR_LO 2
|
||||
#define VER_LAMEXP_TYPE Alpha
|
||||
#define VER_LAMEXP_PATCH 15
|
||||
#define VER_LAMEXP_BUILD 526
|
||||
#define VER_LAMEXP_TYPE Beta
|
||||
#define VER_LAMEXP_PATCH 1
|
||||
#define VER_LAMEXP_BUILD 528
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Tools versions
|
||||
|
@ -111,6 +111,11 @@ int CueImportDialog::exec(void)
|
||||
}
|
||||
|
||||
m_outputDir = QString("%1/%2").arg(cueFileInfo.canonicalPath(), cueFileInfo.completeBaseName());
|
||||
for(int n = 2; QDir(m_outputDir).exists(); n++)
|
||||
{
|
||||
m_outputDir = QString("%1/%2 (%3)").arg(cueFileInfo.canonicalPath(), cueFileInfo.completeBaseName(), QString::number(n));
|
||||
}
|
||||
|
||||
setWindowTitle(QString("%1: %2").arg(windowTitle().split(":", QString::SkipEmptyParts).first().trimmed(), cueFileInfo.fileName()));
|
||||
|
||||
int iResult = m_model->loadCueSheet(m_cueFileName, QApplication::instance());
|
||||
@ -259,7 +264,7 @@ bool CueImportDialog::analyzeFiles(QStringList &files)
|
||||
progress->show(tr("Analyzing file(s), please wait..."), analyzer);
|
||||
progress->close();
|
||||
|
||||
if(analyzer->filesAccepted() < files.count())
|
||||
if(analyzer->filesAccepted() < static_cast<unsigned int>(files.count()))
|
||||
{
|
||||
if(QMessageBox::warning(this, tr("Analysis Failed"), tr("Warning: The format of some of the input files could not be determined!"), tr("Continue Anyway"), tr("Abort")) == 1)
|
||||
{
|
||||
@ -275,55 +280,29 @@ bool CueImportDialog::analyzeFiles(QStringList &files)
|
||||
|
||||
void CueImportDialog::splitFiles(void)
|
||||
{
|
||||
int nTracksSkipped = 0;
|
||||
QString baseName = QFileInfo(m_cueFileName).completeBaseName().replace(".", " ").left(42).trimmed();
|
||||
|
||||
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());
|
||||
CueSplitter *splitter = new CueSplitter(m_outputDir, baseName, m_model, m_fileInfo);
|
||||
|
||||
connect(splitter, SIGNAL(fileSelected(QString)), progress, SLOT(setText(QString)), Qt::QueuedConnection);
|
||||
connect(progress, SIGNAL(userAbort()), splitter, SLOT(abortProcess()), Qt::DirectConnection);
|
||||
connect(splitter, SIGNAL(fileSplit(AudioFileModel)), m_fileList, SLOT(addFile(AudioFileModel)), Qt::QueuedConnection);
|
||||
|
||||
int nFiles = m_model->getFileCount();
|
||||
for(int i = 0; i < nFiles; i++)
|
||||
{
|
||||
QString currentFileName = m_model->getFileName(i);
|
||||
int nTracks = m_model->getTrackCount(i);
|
||||
|
||||
for(int j = 0; j < nTracks; j++)
|
||||
{
|
||||
int trackNo = m_model->getTrackNo(i, j);
|
||||
double startIndex = std::numeric_limits<double>::quiet_NaN();
|
||||
double duration = std::numeric_limits<double>::quiet_NaN();
|
||||
m_model->getTrackIndex(i, j, &startIndex, &duration);
|
||||
|
||||
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
|
||||
{
|
||||
splitter->addTrack(trackNo, currentFileName, startIndex, duration, metaInfo);
|
||||
}
|
||||
catch(char *err)
|
||||
{
|
||||
qWarning("Failed to add track #%02d: %s", trackNo, err);
|
||||
nTracksSkipped++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
progress->show(tr("Splitting file(s), please wait..."), splitter);
|
||||
progress->close();
|
||||
|
||||
if(!splitter->getSuccess())
|
||||
if(splitter->getAborted())
|
||||
{
|
||||
QMessageBox::warning(this, tr("Cue Sheet Error"), tr("Process was aborted by the user after %1 track(s)!").arg(QString::number(splitter->getTracksSuccess())));
|
||||
}
|
||||
else if(!splitter->getSuccess())
|
||||
{
|
||||
QMessageBox::warning(this, tr("Cue Sheet Error"), tr("An unexpected error has occured while splitting the Cue Sheet!"));
|
||||
}
|
||||
else
|
||||
{
|
||||
QString text = QString("<nobr>%1</nobr>").arg(tr("Imported %1 track(s) from the Cue Sheet and skipped %2 track(s).").arg(QString::number(splitter->getTracksSuccess()), QString::number(splitter->getTracksSkipped() + nTracksSkipped)));
|
||||
QString text = QString("<nobr>%1</nobr>").arg(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);
|
||||
}
|
||||
|
||||
|
@ -139,6 +139,11 @@ void WorkingBanner::show(const QString &text, QEventLoop *loop)
|
||||
|
||||
void WorkingBanner::keyPressEvent(QKeyEvent *event)
|
||||
{
|
||||
if(event->key() == Qt::Key_Escape)
|
||||
{
|
||||
emit userAbort();
|
||||
}
|
||||
|
||||
event->ignore();
|
||||
}
|
||||
|
||||
|
@ -47,6 +47,9 @@ private:
|
||||
public slots:
|
||||
void setText(const QString &text);
|
||||
|
||||
signals:
|
||||
void userAbort(void);
|
||||
|
||||
protected:
|
||||
void keyPressEvent(QKeyEvent *event);
|
||||
void keyReleaseEvent(QKeyEvent *event);
|
||||
|
@ -95,6 +95,8 @@ private:
|
||||
// Constructor & Destructor
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
QMutex CueSheetModel::m_mutex(QMutex::Recursive);
|
||||
|
||||
CueSheetModel::CueSheetModel()
|
||||
:
|
||||
m_fileIcon(":/icons/music.png"),
|
||||
@ -127,6 +129,8 @@ CueSheetModel::~CueSheetModel(void)
|
||||
|
||||
QModelIndex CueSheetModel::index(int row, int column, const QModelIndex &parent) const
|
||||
{
|
||||
QMutexLocker lock(&m_mutex);
|
||||
|
||||
if(!parent.isValid())
|
||||
{
|
||||
return (row < m_files.count()) ? createIndex(row, column, m_files.at(row)) : QModelIndex();
|
||||
@ -143,11 +147,14 @@ QModelIndex CueSheetModel::index(int row, int column, const QModelIndex &parent)
|
||||
|
||||
int CueSheetModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
QMutexLocker lock(&m_mutex);
|
||||
return 4;
|
||||
}
|
||||
|
||||
int CueSheetModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
QMutexLocker lock(&m_mutex);
|
||||
|
||||
if(!parent.isValid())
|
||||
{
|
||||
return m_files.count();
|
||||
@ -164,6 +171,8 @@ int CueSheetModel::rowCount(const QModelIndex &parent) const
|
||||
|
||||
QModelIndex CueSheetModel::parent(const QModelIndex &child) const
|
||||
{
|
||||
QMutexLocker lock(&m_mutex);
|
||||
|
||||
if(child.isValid())
|
||||
{
|
||||
CueSheetItem *childItem = static_cast<CueSheetItem*>(child.internalPointer());
|
||||
@ -178,6 +187,8 @@ QModelIndex CueSheetModel::parent(const QModelIndex &child) const
|
||||
|
||||
QVariant CueSheetModel::headerData (int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
QMutexLocker lock(&m_mutex);
|
||||
|
||||
if(role == Qt::DisplayRole)
|
||||
{
|
||||
switch(section)
|
||||
@ -207,6 +218,8 @@ QVariant CueSheetModel::headerData (int section, Qt::Orientation orientation, in
|
||||
|
||||
QVariant CueSheetModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
QMutexLocker lock(&m_mutex);
|
||||
|
||||
if(role == Qt::DisplayRole)
|
||||
{
|
||||
CueSheetItem *item = reinterpret_cast<CueSheetItem*>(index.internalPointer());
|
||||
@ -331,6 +344,8 @@ QVariant CueSheetModel::data(const QModelIndex &index, int role) const
|
||||
|
||||
void CueSheetModel::clearData(void)
|
||||
{
|
||||
QMutexLocker lock(&m_mutex);
|
||||
|
||||
beginResetModel();
|
||||
while(!m_files.isEmpty()) delete m_files.takeLast();
|
||||
endResetModel();
|
||||
@ -342,11 +357,14 @@ void CueSheetModel::clearData(void)
|
||||
|
||||
int CueSheetModel::getFileCount(void)
|
||||
{
|
||||
QMutexLocker lock(&m_mutex);
|
||||
return m_files.count();
|
||||
}
|
||||
|
||||
QString CueSheetModel::getFileName(int fileIndex)
|
||||
{
|
||||
QMutexLocker lock(&m_mutex);
|
||||
|
||||
if(fileIndex < 0 || fileIndex >= m_files.count())
|
||||
{
|
||||
return QString();
|
||||
@ -357,6 +375,8 @@ QString CueSheetModel::getFileName(int fileIndex)
|
||||
|
||||
int CueSheetModel::getTrackCount(int fileIndex)
|
||||
{
|
||||
QMutexLocker lock(&m_mutex);
|
||||
|
||||
if(fileIndex < 0 || fileIndex >= m_files.count())
|
||||
{
|
||||
return -1;
|
||||
@ -367,6 +387,8 @@ int CueSheetModel::getTrackCount(int fileIndex)
|
||||
|
||||
int CueSheetModel::getTrackNo(int fileIndex, int trackIndex)
|
||||
{
|
||||
QMutexLocker lock(&m_mutex);
|
||||
|
||||
if(fileIndex >= 0 && fileIndex < m_files.count())
|
||||
{
|
||||
CueSheetFile *currentFile = m_files.at(fileIndex);
|
||||
@ -381,6 +403,8 @@ int CueSheetModel::getTrackNo(int fileIndex, int trackIndex)
|
||||
|
||||
void CueSheetModel::getTrackIndex(int fileIndex, int trackIndex, double *startIndex, double *duration)
|
||||
{
|
||||
QMutexLocker lock(&m_mutex);
|
||||
|
||||
*startIndex = std::numeric_limits<double>::quiet_NaN();
|
||||
*duration = std::numeric_limits<double>::quiet_NaN();
|
||||
|
||||
@ -398,6 +422,8 @@ void CueSheetModel::getTrackIndex(int fileIndex, int trackIndex, double *startIn
|
||||
|
||||
QString CueSheetModel::getTrackPerformer(int fileIndex, int trackIndex)
|
||||
{
|
||||
QMutexLocker lock(&m_mutex);
|
||||
|
||||
if(fileIndex >= 0 && fileIndex < m_files.count())
|
||||
{
|
||||
CueSheetFile *currentFile = m_files.at(fileIndex);
|
||||
@ -407,11 +433,14 @@ QString CueSheetModel::getTrackPerformer(int fileIndex, int trackIndex)
|
||||
return currentTrack->performer();
|
||||
}
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString CueSheetModel::getTrackTitle(int fileIndex, int trackIndex)
|
||||
{
|
||||
QMutexLocker lock(&m_mutex);
|
||||
|
||||
if(fileIndex >= 0 && fileIndex < m_files.count())
|
||||
{
|
||||
CueSheetFile *currentFile = m_files.at(fileIndex);
|
||||
@ -421,15 +450,30 @@ QString CueSheetModel::getTrackTitle(int fileIndex, int trackIndex)
|
||||
return currentTrack->title();
|
||||
}
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString CueSheetModel::getAlbumPerformer(void)
|
||||
{
|
||||
QMutexLocker lock(&m_mutex);
|
||||
return m_albumPerformer;
|
||||
}
|
||||
|
||||
QString CueSheetModel::getAlbumTitle(void)
|
||||
{
|
||||
QMutexLocker lock(&m_mutex);
|
||||
return m_albumTitle;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Cue Sheet Parser
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
int CueSheetModel::loadCueSheet(const QString &cueFileName, QCoreApplication *application)
|
||||
{
|
||||
QMutexLocker lock(&m_mutex);
|
||||
|
||||
QFile cueFile(cueFileName);
|
||||
if(!cueFile.open(QIODevice::ReadOnly))
|
||||
{
|
||||
|
@ -65,8 +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; }
|
||||
QString getAlbumPerformer(void);
|
||||
QString getAlbumTitle(void);
|
||||
|
||||
//Cue Sheet functions
|
||||
int loadCueSheet(const QString &cueFile, QCoreApplication *application = NULL);
|
||||
@ -76,6 +76,8 @@ private:
|
||||
double parseTimeIndex(const QString &index);
|
||||
QString indexToString(const double index) const;
|
||||
|
||||
static QMutex m_mutex;
|
||||
|
||||
QList<CueSheetFile*> m_files;
|
||||
QString m_albumTitle;
|
||||
QString m_albumPerformer;
|
||||
|
@ -24,7 +24,7 @@
|
||||
#include "Global.h"
|
||||
#include "LockedFile.h"
|
||||
#include "Model_AudioFile.h"
|
||||
#include "PlaylistImporter.h"
|
||||
#include "Model_CueSheet.h"
|
||||
#include "Registry_Decoder.h"
|
||||
#include "Decoder_Abstract.h"
|
||||
|
||||
@ -41,8 +41,9 @@
|
||||
// Constructor
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
CueSplitter::CueSplitter(const QString &outputDir, const QString &baseName, const QList<AudioFileModel> &inputFiles)
|
||||
CueSplitter::CueSplitter(const QString &outputDir, const QString &baseName, CueSheetModel *model, const QList<AudioFileModel> &inputFilesInfo)
|
||||
:
|
||||
m_model(model),
|
||||
m_outputDir(outputDir),
|
||||
m_baseName(baseName),
|
||||
m_soxBin(lamexp_lookup_tool("sox.exe"))
|
||||
@ -52,18 +53,16 @@ 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();
|
||||
m_decompressedFiles.clear();
|
||||
m_tempFiles.clear();
|
||||
|
||||
qDebug("\n[CueSplitter::CueSplitter]");
|
||||
|
||||
int nInputFiles = inputFiles.count();
|
||||
int nInputFiles = inputFilesInfo.count();
|
||||
for(int i = 0; i < nInputFiles; i++)
|
||||
{
|
||||
m_inputFiles.insert(inputFiles[i].filePath(), inputFiles[i]);
|
||||
qDebug("%02d <%s>", i, inputFiles[i].filePath().toUtf8().constData());
|
||||
m_inputFilesInfo.insert(inputFilesInfo[i].filePath(), inputFilesInfo[i]);
|
||||
qDebug("%02d <%s>", i, inputFilesInfo[i].filePath().toUtf8().constData());
|
||||
}
|
||||
|
||||
qDebug("All input files added.");
|
||||
@ -85,6 +84,7 @@ CueSplitter::~CueSplitter(void)
|
||||
void CueSplitter::run()
|
||||
{
|
||||
m_bSuccess = false;
|
||||
m_bAborted = false;
|
||||
m_abortFlag = false;
|
||||
m_nTracksSuccess = 0;
|
||||
m_nTracksSkipped = 0;
|
||||
@ -97,13 +97,13 @@ void CueSplitter::run()
|
||||
return;
|
||||
}
|
||||
|
||||
QStringList inputFileList = m_inputFiles.keys();
|
||||
QStringList inputFileList = m_inputFilesInfo.keys();
|
||||
int nInputFiles = inputFileList.count();
|
||||
|
||||
//Decompress all input files
|
||||
for(int i = 0; i < nInputFiles; i++)
|
||||
{
|
||||
AudioFileModel &inputFileInfo = m_inputFiles[inputFileList.at(i)];
|
||||
AudioFileModel &inputFileInfo = m_inputFilesInfo[inputFileList.at(i)];
|
||||
if(inputFileInfo.formatContainerType().compare("Wave", Qt::CaseInsensitive) || inputFileInfo.formatAudioType().compare("PCM", Qt::CaseInsensitive))
|
||||
{
|
||||
AbstractDecoder *decoder = DecoderRegistry::lookup(inputFileInfo.formatContainerType(), inputFileInfo.formatContainerProfile(), inputFileInfo.formatAudioType(), inputFileInfo.formatAudioProfile(), inputFileInfo.formatAudioVersion());
|
||||
@ -135,50 +135,78 @@ void CueSplitter::run()
|
||||
{
|
||||
m_decompressedFiles.insert(inputFileList.at(i), inputFileList.at(i));
|
||||
}
|
||||
if(m_abortFlag)
|
||||
{
|
||||
m_bAborted = true;
|
||||
qWarning("The user has requested to abort the process!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int nTracks = min(min(min(m_trackFile.count(), m_trackNo.count()), min(m_trackOffset.count(), m_trackLength.count())), m_trackMetaInfo.count());
|
||||
int nFiles = m_model->getFileCount();
|
||||
QString albumPerformer = m_model->getAlbumPerformer();
|
||||
QString albumTitle = m_model->getAlbumTitle();
|
||||
|
||||
//Now split all tracks
|
||||
for(int i = 0; i < nTracks; i++)
|
||||
for(int i = 0; i < nFiles; i++)
|
||||
{
|
||||
QString outputFile = QString("%1/%2 - Track %3.wav").arg(m_outputDir, m_baseName, QString().sprintf("%02d", m_trackNo.at(i)));
|
||||
for(int n = 2; QFileInfo(outputFile).exists(); n++)
|
||||
{
|
||||
outputFile = QString("%1/%2 - Track %3 (%4).wav").arg(m_outputDir, m_baseName, QString().sprintf("%02d", m_trackNo.at(i)), QString::number(n));
|
||||
}
|
||||
int nTracks = m_model->getTrackCount(i);
|
||||
QString trackFile = m_model->getFileName(i);
|
||||
int maxProgress = 0;
|
||||
|
||||
emit fileSelected(QFileInfo(outputFile).fileName());
|
||||
splitFile(outputFile, m_trackNo.at(i), m_trackFile.at(i), m_trackOffset.at(i), m_trackLength.at(i), m_trackMetaInfo.at(i));
|
||||
for(int j = 0; j < nTracks; j++)
|
||||
{
|
||||
int trackNo = m_model->getTrackNo(i, j);
|
||||
double trackOffset = std::numeric_limits<double>::quiet_NaN();
|
||||
double trackLength = std::numeric_limits<double>::quiet_NaN();
|
||||
m_model->getTrackIndex(i, j, &trackOffset, &trackLength);
|
||||
|
||||
if((trackNo < 0) || _isnan(trackOffset) || _isnan(trackLength))
|
||||
{
|
||||
qWarning("Failed to fetch information for track #%d of file #%d!", j, i);
|
||||
continue;
|
||||
}
|
||||
|
||||
AudioFileModel trackMetaInfo(QString().sprintf("cue://File%02d/Track%02d", i, j));
|
||||
trackMetaInfo.setFileName(m_model->getTrackTitle(i, j));
|
||||
trackMetaInfo.setFileArtist(m_model->getTrackPerformer(i, j));
|
||||
trackMetaInfo.setFilePosition(trackNo);
|
||||
|
||||
if(!albumTitle.isEmpty())
|
||||
{
|
||||
trackMetaInfo.setFileAlbum(albumTitle);
|
||||
}
|
||||
if(!albumPerformer.isEmpty() && trackMetaInfo.fileArtist().isEmpty())
|
||||
{
|
||||
trackMetaInfo.setFileArtist(albumPerformer);
|
||||
}
|
||||
if(_finite(trackLength))
|
||||
{
|
||||
trackMetaInfo.setFileDuration(static_cast<unsigned int>(abs(trackLength)));
|
||||
}
|
||||
|
||||
QString outputFile = QString("%1/%2 - Track %3.wav").arg(m_outputDir, m_baseName, QString().sprintf("%02d", trackNo));
|
||||
for(int n = 2; QFileInfo(outputFile).exists(); n++)
|
||||
{
|
||||
outputFile = QString("%1/%2 - Track %3 (%4).wav").arg(m_outputDir, m_baseName, QString().sprintf("%02d", trackNo), QString::number(n));
|
||||
}
|
||||
|
||||
emit fileSelected(QFileInfo(outputFile).fileName());
|
||||
splitFile(outputFile, trackNo, trackFile, trackOffset, trackLength, trackMetaInfo, maxProgress);
|
||||
|
||||
if(m_abortFlag)
|
||||
{
|
||||
m_bAborted = true;
|
||||
qWarning("The user has requested to abort the process!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
qDebug("All files were split.\n");
|
||||
m_bSuccess = true;
|
||||
}
|
||||
|
||||
void CueSplitter::addTrack(const int trackNo, const QString &file, const double offset, const double length, const AudioFileModel &metaInfo)
|
||||
{
|
||||
|
||||
if(m_inputFiles.contains(file))
|
||||
{
|
||||
m_trackFile << file;
|
||||
m_trackNo << trackNo;
|
||||
m_trackOffset << offset;
|
||||
m_trackLength << length;
|
||||
m_trackMetaInfo << metaInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw "The input file is unknown/missing!";
|
||||
}
|
||||
}
|
||||
|
||||
void CueSplitter::setAlbumInfo(const QString &performer, const QString &title)
|
||||
{
|
||||
if(!performer.isEmpty()) m_albumPerformer = performer;
|
||||
if(!title.isEmpty()) m_albumTitle = title;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Slots
|
||||
////////////////////////////////////////////////////////////
|
||||
@ -192,7 +220,7 @@ void CueSplitter::handleUpdate(int progress)
|
||||
// Privtae Functions
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
void CueSplitter::splitFile(const QString &output, const int trackNo, const QString &file, const double offset, const double length, const AudioFileModel &metaInfo)
|
||||
void CueSplitter::splitFile(const QString &output, const int trackNo, const QString &file, const double offset, const double length, const AudioFileModel &metaInfo, int &maxProgress)
|
||||
{
|
||||
qDebug("[Track %02d]", trackNo);
|
||||
qDebug("File: <%s>", file.toUtf8().constData());
|
||||
@ -212,23 +240,12 @@ void CueSplitter::splitFile(const QString &output, const int trackNo, const QStr
|
||||
QString decompressedInput = m_decompressedFiles[file];
|
||||
qDebug("Input: <%s>", decompressedInput.toUtf8().constData());
|
||||
|
||||
emit fileSelected(QString("%1 [%2%]").arg(baseName, QString::number(maxProgress)));
|
||||
|
||||
AudioFileModel outFileInfo(metaInfo);
|
||||
outFileInfo.setFilePath(output);
|
||||
outFileInfo.setFormatContainerType("Wave");
|
||||
outFileInfo.setFormatAudioType("PCM");
|
||||
|
||||
if(length != std::numeric_limits<double>::infinity())
|
||||
{
|
||||
outFileInfo.setFileDuration(static_cast<unsigned int>(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";
|
||||
@ -237,12 +254,12 @@ void CueSplitter::splitFile(const QString &output, const int trackNo, const QStr
|
||||
args << QDir::toNativeSeparators(output);
|
||||
|
||||
//Add trim parameters, if needed
|
||||
if(offset != 0.0 || length != std::numeric_limits<double>::infinity())
|
||||
if(_finite(offset) || _finite(length))
|
||||
{
|
||||
args << "trim";
|
||||
args << indexToString(offset);
|
||||
|
||||
if((length != std::numeric_limits<double>::quiet_NaN()) && (length != std::numeric_limits<double>::infinity()))
|
||||
if(_finite(length))
|
||||
{
|
||||
args << indexToString(length);
|
||||
}
|
||||
@ -275,6 +292,7 @@ void CueSplitter::splitFile(const QString &output, const int trackNo, const QStr
|
||||
if(m_abortFlag)
|
||||
{
|
||||
process.kill();
|
||||
qWarning("Process was aborted on user request!");
|
||||
break;
|
||||
}
|
||||
process.waitForReadyRead();
|
||||
@ -294,7 +312,8 @@ void CueSplitter::splitFile(const QString &output, const int trackNo, const QStr
|
||||
int progress = rxProgress.cap(1).toInt(&ok);
|
||||
if(ok)
|
||||
{
|
||||
emit fileSelected(QString("%1 [%2%]").arg(baseName, QString::number(progress)));
|
||||
maxProgress = max(maxProgress, progress);
|
||||
emit fileSelected(QString("%1 [%2%]").arg(baseName, QString::number(maxProgress)));
|
||||
}
|
||||
}
|
||||
else if(rxChannels.lastIndexIn(text) >= 0)
|
||||
@ -361,7 +380,7 @@ void CueSplitter::splitFile(const QString &output, const int trackNo, const QStr
|
||||
|
||||
QString CueSplitter::indexToString(const double index) const
|
||||
{
|
||||
if(index == std::numeric_limits<double>::quiet_NaN() || index == std::numeric_limits<double>::infinity() || index < 0.0)
|
||||
if(!_finite(index) || (index < 0.0))
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include <QMap>
|
||||
|
||||
class AudioFileModel;
|
||||
class CueSheetModel;
|
||||
class QFile;
|
||||
class QDir;
|
||||
class QFileInfo;
|
||||
@ -39,14 +40,14 @@ class CueSplitter: public QThread
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CueSplitter(const QString &outputDir, const QString &baseName, const QList<AudioFileModel> &inputFiles);
|
||||
CueSplitter(const QString &outputDir, const QString &baseName, CueSheetModel *model, const QList<AudioFileModel> &inputFilesInfo);
|
||||
~CueSplitter(void);
|
||||
|
||||
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);
|
||||
bool getSuccess(void) { return !isRunning() && m_bSuccess; }
|
||||
bool getAborted(void) { return m_bAborted; }
|
||||
|
||||
signals:
|
||||
void fileSelected(const QString &fileName);
|
||||
@ -55,8 +56,11 @@ signals:
|
||||
private slots:
|
||||
void handleUpdate(int progress);
|
||||
|
||||
public slots:
|
||||
void abortProcess(void) { m_abortFlag = true; }
|
||||
|
||||
private:
|
||||
void splitFile(const QString &output, const int trackNo, const QString &file, const double offset, const double length, const AudioFileModel &metaInfo);
|
||||
void splitFile(const QString &output, const int trackNo, const QString &file, const double offset, const double length, const AudioFileModel &metaInfo, int &maxProgress);
|
||||
QString indexToString(const double index) const;
|
||||
|
||||
const QString m_soxBin;
|
||||
@ -64,18 +68,15 @@ private:
|
||||
const QString m_baseName;
|
||||
unsigned int m_nTracksSuccess;
|
||||
unsigned int m_nTracksSkipped;
|
||||
|
||||
bool m_bAborted;
|
||||
bool m_bSuccess;
|
||||
|
||||
volatile bool m_abortFlag;
|
||||
|
||||
QString m_albumTitle;
|
||||
QString m_albumPerformer;
|
||||
QString m_activeFile;
|
||||
QMap<QString,AudioFileModel> m_inputFiles;
|
||||
CueSheetModel *m_model;
|
||||
QMap<QString,AudioFileModel> m_inputFilesInfo;
|
||||
QMap<QString,QString> m_decompressedFiles;
|
||||
QStringList m_tempFiles;
|
||||
QList<QString> m_trackFile;
|
||||
QList<int> m_trackNo;
|
||||
QList<double> m_trackOffset;
|
||||
QList<double> m_trackLength;
|
||||
QList<AudioFileModel> m_trackMetaInfo;
|
||||
QString m_activeFile;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user