///////////////////////////////////////////////////////////////////////////////
// LameXP - Audio Encoder Front-End
-// Copyright (C) 2004-2013 LoRd_MuldeR <MuldeR2@GMX.de>
+// Copyright (C) 2004-2015 LoRd_MuldeR <MuldeR2@GMX.de>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
-// (at your option) any later version.
+// (at your option) any later version, but always including the *additional*
+// restrictions defined in the "License.txt" file.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
#include "Thread_FileAnalyzer.h"
+//Internal
#include "Global.h"
#include "LockedFile.h"
#include "Model_AudioFile.h"
#include "Thread_FileAnalyzer_Task.h"
#include "PlaylistImporter.h"
+//MUtils
+#include <MUtils/Global.h>
+#include <MUtils/Exception.h>
+
+//Qt
#include <QDir>
#include <QFileInfo>
#include <QProcess>
#include <QTime>
#include <QElapsedTimer>
#include <QTimer>
+#include <QQueue>
+
+//Insert into QStringList *without* duplicates
+static inline void SAFE_APPEND_STRING(QStringList &list, const QString &str)
+{
+ if(!list.contains(str, Qt::CaseInsensitive))
+ {
+ list << str;
+ }
+}
////////////////////////////////////////////////////////////
// Constructor
m_filesDummyCDDA = 0;
m_filesCueSheet = 0;
+ moveToThread(this); /*makes sure queued slots are executed in the proper thread context*/
+
m_timer = new QElapsedTimer;
}
FileAnalyzer::~FileAnalyzer(void)
{
- if(m_templateFile)
- {
- QString templatePath = m_templateFile->filePath();
- LAMEXP_DELETE(m_templateFile);
- if(QFile::exists(templatePath)) QFile::remove(templatePath);
- }
-
- if(!m_pool->waitForDone(2500))
+ if(m_pool)
{
- qWarning("There are still running tasks in the thread pool!");
+ if(!m_pool->waitForDone(2500))
+ {
+ qWarning("There are still running tasks in the thread pool!");
+ }
}
- LAMEXP_DELETE(m_pool);
- LAMEXP_DELETE(m_timer);
+ MUTILS_DELETE(m_templateFile);
+ MUTILS_DELETE(m_pool);
+ MUTILS_DELETE(m_timer);
}
////////////////////////////////////////////////////////////
m_timer->invalidate();
- //Update progress
- emit progressMaxChanged(m_inputFiles.count());
- emit progressValChanged(0);
-
//Create MediaInfo template file
if(!m_templateFile)
{
}
}
- //Handle playlist files
- lamexp_natural_string_sort(m_inputFiles, true);
+ //Sort files
+ MUtils::natural_string_sort(m_inputFiles, true);
+
+ //Handle playlist files first!
handlePlaylistFiles();
- lamexp_natural_string_sort(m_inputFiles, true);
const unsigned int nFiles = m_inputFiles.count();
+ if(nFiles < 1)
+ {
+ qWarning("File list is empty, nothing to do!");
+ return;
+ }
//Update progress
emit progressMaxChanged(nFiles);
+ emit progressValChanged(0);
//Create thread pool
if(!m_pool) m_pool = new QThreadPool();
- m_pool->setMaxThreadCount(qBound(2, ((QThread::idealThreadCount() * 3) / 2), 12));
+ const int idealThreadCount = QThread::idealThreadCount();
+ if(idealThreadCount > 0)
+ {
+ m_pool->setMaxThreadCount(qBound(2, ((idealThreadCount * 3) / 2), 12));
+ }
//Start first N threads
QTimer::singleShot(0, this, SLOT(initializeTasks()));
const unsigned int taskId = m_tasksCounterNext++;
const QString currentFile = QDir::fromNativeSeparators(m_inputFiles.takeFirst());
- if((!m_timer->isValid()) || (m_timer->elapsed() >= 250))
+ if((!m_timer->isValid()) || (m_timer->elapsed() >= 333))
{
emit fileSelected(QFileInfo(currentFile).fileName());
m_timer->restart();
void FileAnalyzer::handlePlaylistFiles(void)
{
- QStringList importedFiles;
+ QQueue<QVariant> queue;
+ QStringList importedFromPlaylist;
+
+ //Import playlist files into "hierarchical" list
while(!m_inputFiles.isEmpty())
{
const QString currentFile = m_inputFiles.takeFirst();
- if(!PlaylistImporter::importPlaylist(importedFiles, currentFile))
+ QStringList importedFiles;
+ if(PlaylistImporter::importPlaylist(importedFiles, currentFile))
+ {
+ queue.enqueue(importedFiles);
+ importedFromPlaylist << importedFiles;
+ }
+ else
{
- importedFiles << currentFile;
+ queue.enqueue(currentFile);
}
}
- while(!importedFiles.isEmpty())
+ //Reduce temporary list
+ importedFromPlaylist.removeDuplicates();
+
+ //Now build the complete "flat" file list (files imported from playlist take precedence!)
+ while(!queue.isEmpty())
{
- const QString currentFile = importedFiles.takeFirst();
- if(!m_inputFiles.contains(currentFile, Qt::CaseInsensitive))
+ const QVariant current = queue.dequeue();
+ if(current.type() == QVariant::String)
+ {
+ const QString temp = current.toString();
+ if(!importedFromPlaylist.contains(temp, Qt::CaseInsensitive))
+ {
+ SAFE_APPEND_STRING(m_inputFiles, temp);
+ }
+ }
+ else if(current.type() == QVariant::StringList)
{
- m_inputFiles << currentFile;
+ const QStringList temp = current.toStringList();
+ for(QStringList::ConstIterator iter = temp.constBegin(); iter != temp.constEnd(); iter++)
+ {
+ SAFE_APPEND_STRING(m_inputFiles, (*iter));
+ }
+ }
+ else
+ {
+ qWarning("Encountered an unexpected variant type!");
}
}
}
return true;
}
- QString templatePath = QString("%1/%2.txt").arg(lamexp_temp_folder2(), lamexp_rand_str());
+ QString templatePath = QString("%1/%2.txt").arg(MUtils::temp_folder(), MUtils::rand_str());
QFile templateFile(templatePath);
if(!templateFile.open(QIODevice::WriteOnly))
try
{
- m_templateFile = new LockedFile(templatePath);
+ m_templateFile = new LockedFile(templatePath, true);
+ }
+ catch(const std::exception &error)
+ {
+ qWarning("Failed to lock template file:\n%s\n", error.what());
+ return false;
}
catch(...)
{
m_filesRejected++;
break;
default:
- throw "Unknown file type identifier!";
+ MUTILS_THROW("Unknown file type identifier!");
}
//Emit all pending files