2023-07-21 21:32:24 +00:00
|
|
|
#include "taskmanager.h"
|
|
|
|
|
|
|
|
#include "flactomp3.h"
|
|
|
|
|
2023-10-08 23:29:40 +00:00
|
|
|
TaskManager::TaskManager(const std::shared_ptr<Settings>& settings, const std::shared_ptr<Printer>& logger):
|
2023-10-07 22:36:20 +00:00
|
|
|
settings(settings),
|
2023-10-08 23:29:40 +00:00
|
|
|
logger(logger),
|
2023-07-21 21:32:24 +00:00
|
|
|
busyThreads(0),
|
|
|
|
maxTasks(0),
|
|
|
|
completeTasks(0),
|
|
|
|
terminate(false),
|
2023-10-08 23:29:40 +00:00
|
|
|
running(false),
|
2023-07-21 21:32:24 +00:00
|
|
|
queueMutex(),
|
|
|
|
loopConditional(),
|
|
|
|
waitConditional(),
|
|
|
|
threads(),
|
2023-10-08 23:29:40 +00:00
|
|
|
jobs()
|
2023-07-21 21:32:24 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
TaskManager::~TaskManager() {
|
|
|
|
}
|
|
|
|
|
2023-10-13 01:00:16 +00:00
|
|
|
void TaskManager::queueConvert(const std::filesystem::path& source, const std::filesystem::path& destination) {
|
2023-10-08 23:29:40 +00:00
|
|
|
std::unique_lock<std::mutex> lock(queueMutex);
|
2023-10-13 01:00:16 +00:00
|
|
|
jobs.emplace(Job::convert, source, destination);
|
2023-10-08 23:29:40 +00:00
|
|
|
|
2023-07-21 21:32:24 +00:00
|
|
|
++maxTasks;
|
2023-10-08 23:29:40 +00:00
|
|
|
logger->setStatusMessage(std::to_string(completeTasks) + "/" + std::to_string(maxTasks));
|
|
|
|
|
|
|
|
lock.unlock();
|
2023-07-21 21:32:24 +00:00
|
|
|
loopConditional.notify_one();
|
|
|
|
}
|
|
|
|
|
2023-10-13 01:00:16 +00:00
|
|
|
void TaskManager::queueCopy(const std::filesystem::path& source, const std::filesystem::path& destination) {
|
|
|
|
if (!settings->matchNonMusic(source.filename()))
|
|
|
|
return;
|
|
|
|
|
|
|
|
std::unique_lock<std::mutex> lock(queueMutex);
|
|
|
|
jobs.emplace(Job::copy, source, destination);
|
|
|
|
++maxTasks;
|
|
|
|
logger->setStatusMessage(std::to_string(completeTasks) + "/" + std::to_string(maxTasks));
|
|
|
|
|
|
|
|
lock.unlock();
|
|
|
|
loopConditional.notify_one();
|
|
|
|
}
|
|
|
|
|
2023-07-21 21:32:24 +00:00
|
|
|
bool TaskManager::busy() const {
|
2023-10-08 23:29:40 +00:00
|
|
|
std::lock_guard lock(queueMutex);
|
|
|
|
return !jobs.empty();
|
2023-07-21 21:32:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void TaskManager::start() {
|
2023-10-08 23:29:40 +00:00
|
|
|
std::lock_guard lock(queueMutex);
|
|
|
|
if (running)
|
|
|
|
return;
|
|
|
|
|
2023-10-09 21:47:00 +00:00
|
|
|
unsigned int amount = settings->getThreads();
|
|
|
|
if (amount == 0)
|
|
|
|
amount = std::thread::hardware_concurrency();
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < amount; ++i)
|
2023-07-21 21:32:24 +00:00
|
|
|
threads.emplace_back(std::thread(&TaskManager::loop, this));
|
2023-10-08 23:29:40 +00:00
|
|
|
|
|
|
|
running = true;
|
2023-07-21 21:32:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void TaskManager::loop() {
|
|
|
|
while (true) {
|
2023-10-08 23:29:40 +00:00
|
|
|
std::unique_lock<std::mutex> lock(queueMutex);
|
|
|
|
while (!terminate && jobs.empty())
|
|
|
|
loopConditional.wait(lock);
|
|
|
|
|
|
|
|
if (terminate)
|
|
|
|
return;
|
|
|
|
|
2023-10-13 01:00:16 +00:00
|
|
|
Job job = jobs.front();
|
2023-10-08 23:29:40 +00:00
|
|
|
++busyThreads;
|
|
|
|
jobs.pop();
|
|
|
|
lock.unlock();
|
2023-07-21 21:32:24 +00:00
|
|
|
|
2023-10-13 01:00:16 +00:00
|
|
|
JobResult result = execute(job);
|
2023-10-07 22:36:20 +00:00
|
|
|
|
2023-10-08 23:29:40 +00:00
|
|
|
lock.lock();
|
2023-07-21 21:32:24 +00:00
|
|
|
++completeTasks;
|
2023-10-13 01:00:16 +00:00
|
|
|
printResilt(job, result);
|
2023-07-21 21:32:24 +00:00
|
|
|
--busyThreads;
|
2023-10-08 23:29:40 +00:00
|
|
|
lock.unlock();
|
2023-07-21 21:32:24 +00:00
|
|
|
waitConditional.notify_all();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void TaskManager::stop() {
|
2023-10-08 23:29:40 +00:00
|
|
|
std::unique_lock lock(queueMutex);
|
|
|
|
if (!running)
|
|
|
|
return;
|
|
|
|
|
|
|
|
terminate = true;
|
2023-07-21 21:32:24 +00:00
|
|
|
|
2023-10-08 23:29:40 +00:00
|
|
|
lock.unlock();
|
2023-07-21 21:32:24 +00:00
|
|
|
loopConditional.notify_all();
|
|
|
|
for (std::thread& thread : threads)
|
|
|
|
thread.join();
|
|
|
|
|
2023-10-08 23:29:40 +00:00
|
|
|
lock.lock();
|
2023-07-21 21:32:24 +00:00
|
|
|
threads.clear();
|
2023-10-08 23:29:40 +00:00
|
|
|
running = false;
|
|
|
|
logger->clearStatusMessage();
|
2023-07-21 21:32:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void TaskManager::wait() {
|
2023-10-08 23:29:40 +00:00
|
|
|
std::unique_lock lock(queueMutex);
|
|
|
|
while (busyThreads != 0 || !jobs.empty())
|
|
|
|
waitConditional.wait(lock);
|
2023-07-21 21:32:24 +00:00
|
|
|
}
|
|
|
|
|
2023-10-08 23:29:40 +00:00
|
|
|
unsigned int TaskManager::getCompleteTasks() const {
|
|
|
|
std::lock_guard lock(queueMutex);
|
|
|
|
return completeTasks;
|
2023-07-21 21:32:24 +00:00
|
|
|
}
|
2023-07-23 12:04:26 +00:00
|
|
|
|
2023-10-13 19:10:08 +00:00
|
|
|
TaskManager::JobResult TaskManager::execute(Job& job) {
|
2023-10-13 01:00:16 +00:00
|
|
|
switch (job.type) {
|
|
|
|
case Job::copy:
|
2023-10-13 19:10:08 +00:00
|
|
|
return copyJob(job, settings);
|
2023-10-13 01:00:16 +00:00
|
|
|
case Job::convert:
|
|
|
|
switch (settings->getType()) {
|
|
|
|
case Settings::mp3:
|
2023-10-13 19:10:08 +00:00
|
|
|
job.destination.replace_extension("mp3");
|
|
|
|
return mp3Job(job, settings);
|
2023-10-13 01:00:16 +00:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return {false, {
|
|
|
|
{Logger::Severity::error, "Unknown job type: " + std::to_string(job.type)}
|
|
|
|
}};
|
|
|
|
}
|
|
|
|
|
|
|
|
void TaskManager::printResilt(const TaskManager::Job& job, const TaskManager::JobResult& result) {
|
|
|
|
std::string msg;
|
|
|
|
switch (job.type) {
|
|
|
|
case Job::copy:
|
|
|
|
if (result.first)
|
|
|
|
msg = "File copy complete, but there are messages about it:";
|
|
|
|
else
|
|
|
|
msg = "File copy failed!";
|
|
|
|
break;
|
|
|
|
case Job::convert:
|
|
|
|
if (result.first)
|
|
|
|
msg = "Encoding complete but there are messages about it:";
|
|
|
|
else
|
|
|
|
msg = "Encoding failed!";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
logger->printNested(
|
|
|
|
msg,
|
|
|
|
{"Source: \t" + job.source.string(), "Destination: \t" + job.destination.string()},
|
|
|
|
result.second,
|
|
|
|
std::to_string(completeTasks) + "/" + std::to_string(maxTasks)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-10-13 19:10:08 +00:00
|
|
|
TaskManager::JobResult TaskManager::mp3Job(const TaskManager::Job& job, const std::shared_ptr<Settings>& settings) {
|
|
|
|
FLACtoMP3 convertor(settings->getLogLevel());
|
2023-10-13 01:00:16 +00:00
|
|
|
convertor.setInputFile(job.source);
|
2023-10-13 19:10:08 +00:00
|
|
|
convertor.setOutputFile(job.destination);
|
|
|
|
convertor.setParameters(settings->getEncodingQuality(), settings->getOutputQuality(), settings->getVBR());
|
2023-10-08 23:29:40 +00:00
|
|
|
bool result = convertor.run();
|
2023-10-13 19:10:08 +00:00
|
|
|
|
2023-10-08 23:29:40 +00:00
|
|
|
return {result, convertor.getHistory()};
|
2023-07-23 12:04:26 +00:00
|
|
|
}
|
2023-10-13 01:00:16 +00:00
|
|
|
|
2023-10-13 19:10:08 +00:00
|
|
|
TaskManager::JobResult TaskManager::copyJob(const TaskManager::Job& job, const std::shared_ptr<Settings>& settings) {
|
|
|
|
(void)(settings);
|
2023-10-13 01:00:16 +00:00
|
|
|
bool success = std::filesystem::copy_file(
|
|
|
|
job.source,
|
|
|
|
job.destination,
|
|
|
|
std::filesystem::copy_options::overwrite_existing
|
|
|
|
);
|
|
|
|
|
|
|
|
return {success, {}};
|
|
|
|
}
|
|
|
|
|
|
|
|
TaskManager::Job::Job(Type type, const std::filesystem::path& source, std::filesystem::path destination):
|
|
|
|
type(type),
|
|
|
|
source(source),
|
|
|
|
destination(destination) {}
|