OSDN Git Service

Removed a lot of old cruft and use MUtils functions where possible.
[x264-launcher/x264-launcher.git] / src / model_jobList.cpp
index 9f3e9e2..87367a1 100644 (file)
@@ -1,6 +1,6 @@
 ///////////////////////////////////////////////////////////////////////////////
 // Simple x264 Launcher
-// Copyright (C) 2004-2012 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
 // http://www.gnu.org/licenses/gpl-2.0.txt
 ///////////////////////////////////////////////////////////////////////////////
 
-#include "model_jobList.h"
+//Internal
 #include "global.h"
+#include "model_jobList.h"
 #include "thread_encode.h"
+#include "model_options.h"
+#include "model_preferences.h"
+#include "resource.h"
 
+//MUtils
+#include <MUtils/Sound.h>
+
+//Qt
 #include <QIcon>
 #include <QFileInfo>
+#include <QSettings>
+
+static const char *KEY_ENTRY_COUNT = "entry_count";
+static const char *KEY_SOURCE_FILE = "source_file";
+static const char *KEY_OUTPUT_FILE = "output_file";
+static const char *KEY_ENC_OPTIONS = "enc_options";
 
-JobListModel::JobListModel(void)
+static const char *JOB_TEMPLATE = "job_%08x";
+
+#define VALID_INDEX(INDEX) ((INDEX).isValid() && ((INDEX).row() >= 0) && ((INDEX).row() < m_jobs.count()))
+
+JobListModel::JobListModel(PreferencesModel *preferences)
 {
+       m_preferences = preferences;
 }
 
 JobListModel::~JobListModel(void)
@@ -37,8 +56,8 @@ JobListModel::~JobListModel(void)
                QUuid id = m_jobs.takeFirst();
                EncodeThread *thread = m_threads.value(id, NULL);
                LogFileModel *logFile = m_logFile.value(id, NULL);
-               X264_DELETE(thread);
-               X264_DELETE(logFile);
+               MUTILS_DELETE(thread);
+               MUTILS_DELETE(logFile);
        }
 }
 
@@ -107,43 +126,43 @@ QVariant JobListModel::data(const QModelIndex &index, int role) const
                        case 1:
                                switch(m_status.value(m_jobs.at(index.row())))
                                {
-                               case EncodeThread::JobStatus_Enqueued:
+                               case JobStatus_Enqueued:
                                        return QVariant::fromValue<QString>(tr("Enqueued."));
                                        break;
-                               case EncodeThread::JobStatus_Starting:
+                               case JobStatus_Starting:
                                        return QVariant::fromValue<QString>(tr("Starting..."));
                                        break;
-                               case EncodeThread::JobStatus_Indexing:
+                               case JobStatus_Indexing:
                                        return QVariant::fromValue<QString>(tr("Indexing..."));
                                        break;
-                               case EncodeThread::JobStatus_Running:
+                               case JobStatus_Running:
                                        return QVariant::fromValue<QString>(tr("Running..."));
                                        break;
-                               case EncodeThread::JobStatus_Running_Pass1:
+                               case JobStatus_Running_Pass1:
                                        return QVariant::fromValue<QString>(tr("Running... (Pass 1)"));
                                        break;
-                               case EncodeThread::JobStatus_Running_Pass2:
+                               case JobStatus_Running_Pass2:
                                        return QVariant::fromValue<QString>(tr("Running... (Pass 2)"));
                                        break;
-                               case EncodeThread::JobStatus_Completed:
+                               case JobStatus_Completed:
                                        return QVariant::fromValue<QString>(tr("Completed."));
                                        break;
-                               case EncodeThread::JobStatus_Failed:
+                               case JobStatus_Failed:
                                        return QVariant::fromValue<QString>(tr("Failed!"));
                                        break;
-                               case EncodeThread::JobStatus_Pausing:
+                               case JobStatus_Pausing:
                                        return QVariant::fromValue<QString>(tr("Pausing..."));
                                        break;
-                               case EncodeThread::JobStatus_Paused:
+                               case JobStatus_Paused:
                                        return QVariant::fromValue<QString>(tr("Paused."));
                                        break;
-                               case EncodeThread::JobStatus_Resuming:
+                               case JobStatus_Resuming:
                                        return QVariant::fromValue<QString>(tr("Resuming..."));
                                        break;
-                               case EncodeThread::JobStatus_Aborting:
+                               case JobStatus_Aborting:
                                        return QVariant::fromValue<QString>(tr("Aborting..."));
                                        break;
-                               case EncodeThread::JobStatus_Aborted:
+                               case JobStatus_Aborted:
                                        return QVariant::fromValue<QString>(tr("Aborted!"));
                                        break;
                                default:
@@ -169,39 +188,39 @@ QVariant JobListModel::data(const QModelIndex &index, int role) const
                {
                        switch(m_status.value(m_jobs.at(index.row())))
                        {
-                       case EncodeThread::JobStatus_Enqueued:
+                       case JobStatus_Enqueued:
                                return QIcon(":/buttons/hourglass.png");
                                break;
-                       case EncodeThread::JobStatus_Starting:
+                       case JobStatus_Starting:
                                return QIcon(":/buttons/lightning.png");
                                break;
-                       case EncodeThread::JobStatus_Indexing:
+                       case JobStatus_Indexing:
                                return QIcon(":/buttons/find.png");
                                break;
-                       case EncodeThread::JobStatus_Running:
-                       case EncodeThread::JobStatus_Running_Pass1:
-                       case EncodeThread::JobStatus_Running_Pass2:
+                       case JobStatus_Running:
+                       case JobStatus_Running_Pass1:
+                       case JobStatus_Running_Pass2:
                                return QIcon(":/buttons/play.png");
                                break;
-                       case EncodeThread::JobStatus_Completed:
+                       case JobStatus_Completed:
                                return QIcon(":/buttons/accept.png");
                                break;
-                       case EncodeThread::JobStatus_Failed:
+                       case JobStatus_Failed:
                                return QIcon(":/buttons/exclamation.png");
                                break;
-                       case EncodeThread::JobStatus_Pausing:
+                       case JobStatus_Pausing:
                                return QIcon(":/buttons/clock_pause.png");
                                break;
-                       case EncodeThread::JobStatus_Paused:
+                       case JobStatus_Paused:
                                return QIcon(":/buttons/suspended.png");
                                break;
-                       case EncodeThread::JobStatus_Resuming:
+                       case JobStatus_Resuming:
                                return QIcon(":/buttons/clock_play.png");
                                break;
-                       case EncodeThread::JobStatus_Aborting:
+                       case JobStatus_Aborting:
                                return QIcon(":/buttons/clock_stop.png");
                                break;
-                       case EncodeThread::JobStatus_Aborted:
+                       case JobStatus_Aborted:
                                return QIcon(":/buttons/error.png");
                                break;
                        default:
@@ -221,15 +240,42 @@ QVariant JobListModel::data(const QModelIndex &index, int role) const
 QModelIndex JobListModel::insertJob(EncodeThread *thread)
 {
        QUuid id = thread->getId();
-       LogFileModel *logFile = NULL;
 
        if(m_jobs.contains(id))
        {
                return QModelIndex();
        }
-               
+       
+       QString config = "N/A";
+
+       switch(thread->options()->rcMode())
+       {
+       case OptionsModel::EncType_X264:
+               config = QString("x264");
+               break;
+       case OptionsModel::EncType_X265:
+               config = QString("x265");
+               break;
+       }
+       
+       switch(thread->options()->rcMode())
+       {
+       case OptionsModel::RCMode_CRF:
+               config = QString("%1 CRF@%2")  .arg(config, QString::number(thread->options()->quantizer()));
+               break;
+       case OptionsModel::RCMode_CQ:
+               config = QString("%1 CQ@%2")   .arg(config, QString::number(qRound(thread->options()->quantizer())));
+               break;
+       case OptionsModel::RCMode_2Pass:
+               config = QString("%1 2Pass@%2").arg(config, QString::number(thread->options()->bitrate()));
+               break;
+       case OptionsModel::RCMode_ABR:
+               config = QString("%1 ABR@%2")  .arg(config, QString::number(thread->options()->bitrate()));
+               break;
+       }
+
        int n = 2;
-       QString jobName = QFileInfo(thread->sourceFileName()).completeBaseName();
+       QString jobName = QString("%1 (%2)").arg(QFileInfo(thread->sourceFileName()).completeBaseName().simplified(), config);
 
        forever
        {
@@ -244,23 +290,25 @@ QModelIndex JobListModel::insertJob(EncodeThread *thread)
                }
                if(!unique)
                {
-                       jobName = QString("%1 (%2)").arg(QFileInfo(thread->sourceFileName()).completeBaseName(), QString::number(n++));
+                       jobName = QString("%1 %2 (%3)").arg(QFileInfo(thread->sourceFileName()).completeBaseName().simplified(), QString::number(n++), config);
                        continue;
                }
                break;
        }
-
+       
+       LogFileModel *logFile = new LogFileModel(thread->sourceFileName(), thread->outputFileName(), config);
+       
        beginInsertRows(QModelIndex(), m_jobs.count(), m_jobs.count());
        m_jobs.append(id);
        m_name.insert(id, jobName);
-       m_status.insert(id, EncodeThread::JobStatus_Enqueued);
+       m_status.insert(id, JobStatus_Enqueued);
        m_progress.insert(id, 0);
        m_threads.insert(id, thread);
-       m_logFile.insert(id, (logFile = new LogFileModel));
+       m_logFile.insert(id, logFile);
        m_details.insert(id, tr("Not started yet."));
        endInsertRows();
 
-       connect(thread, SIGNAL(statusChanged(QUuid, EncodeThread::JobStatus)), this, SLOT(updateStatus(QUuid, EncodeThread::JobStatus)), Qt::QueuedConnection);
+       connect(thread, SIGNAL(statusChanged(QUuid, JobStatus)), this, SLOT(updateStatus(QUuid, JobStatus)), Qt::QueuedConnection);
        connect(thread, SIGNAL(progressChanged(QUuid, unsigned int)), this, SLOT(updateProgress(QUuid, unsigned int)), Qt::QueuedConnection);
        connect(thread, SIGNAL(messageLogged(QUuid, QString)), logFile, SLOT(addLogMessage(QUuid, QString)), Qt::QueuedConnection);
        connect(thread, SIGNAL(detailsChanged(QUuid, QString)), this, SLOT(updateDetails(QUuid, QString)), Qt::QueuedConnection);
@@ -270,12 +318,12 @@ QModelIndex JobListModel::insertJob(EncodeThread *thread)
 
 bool JobListModel::startJob(const QModelIndex &index)
 {
-       if(index.isValid() && index.row() >= 0 && index.row() < m_jobs.count())
+       if(VALID_INDEX(index))
        {
                QUuid id = m_jobs.at(index.row());
-               if(m_status.value(id) == EncodeThread::JobStatus_Enqueued)
+               if(m_status.value(id) == JobStatus_Enqueued)
                {
-                       updateStatus(id, EncodeThread::JobStatus_Starting);
+                       updateStatus(id, JobStatus_Starting);
                        updateDetails(id, tr("Starting up, please wait..."));
                        m_threads.value(id)->start();
                        return true;
@@ -287,14 +335,14 @@ bool JobListModel::startJob(const QModelIndex &index)
 
 bool JobListModel::pauseJob(const QModelIndex &index)
 {
-       if(index.isValid() && index.row() >= 0 && index.row() < m_jobs.count())
+       if(VALID_INDEX(index))
        {
                QUuid id = m_jobs.at(index.row());
-               EncodeThread::JobStatus status = m_status.value(id);
-               if((status == EncodeThread::JobStatus_Indexing) || (status == EncodeThread::JobStatus_Running) ||
-                       (status == EncodeThread::JobStatus_Running_Pass1) || (status == EncodeThread::JobStatus_Running_Pass2))
+               JobStatus status = m_status.value(id);
+               if((status == JobStatus_Indexing) || (status == JobStatus_Running) ||
+                       (status == JobStatus_Running_Pass1) || (status == JobStatus_Running_Pass2))
                {
-                       updateStatus(id, EncodeThread::JobStatus_Pausing);
+                       updateStatus(id, JobStatus_Pausing);
                        m_threads.value(id)->pauseJob();
                        return true;
                }
@@ -305,13 +353,13 @@ bool JobListModel::pauseJob(const QModelIndex &index)
 
 bool JobListModel::resumeJob(const QModelIndex &index)
 {
-       if(index.isValid() && index.row() >= 0 && index.row() < m_jobs.count())
+       if(VALID_INDEX(index))
        {
                QUuid id = m_jobs.at(index.row());
-               EncodeThread::JobStatus status = m_status.value(id);
-               if(status == EncodeThread::JobStatus_Paused)
+               JobStatus status = m_status.value(id);
+               if(status == JobStatus_Paused)
                {
-                       updateStatus(id, EncodeThread::JobStatus_Resuming);
+                       updateStatus(id, JobStatus_Resuming);
                        m_threads.value(id)->resumeJob();
                        return true;
                }
@@ -322,13 +370,13 @@ bool JobListModel::resumeJob(const QModelIndex &index)
 
 bool JobListModel::abortJob(const QModelIndex &index)
 {
-       if(index.isValid() && index.row() >= 0 && index.row() < m_jobs.count())
+       if(VALID_INDEX(index))
        {
                QUuid id = m_jobs.at(index.row());
-               if(m_status.value(id) == EncodeThread::JobStatus_Indexing || m_status.value(id) == EncodeThread::JobStatus_Running ||
-                       m_status.value(id) == EncodeThread::JobStatus_Running_Pass1 || EncodeThread::JobStatus_Running_Pass2)
+               if(m_status.value(id) == JobStatus_Indexing || m_status.value(id) == JobStatus_Running ||
+                       m_status.value(id) == JobStatus_Running_Pass1 || JobStatus_Running_Pass2)
                {
-                       updateStatus(id, EncodeThread::JobStatus_Aborting);
+                       updateStatus(id, JobStatus_Aborting);
                        m_threads.value(id)->abortJob();
                        return true;
                }
@@ -337,6 +385,63 @@ bool JobListModel::abortJob(const QModelIndex &index)
        return false;
 }
 
+bool JobListModel::deleteJob(const QModelIndex &index)
+{
+       if(VALID_INDEX(index))
+       {
+               QUuid id = m_jobs.at(index.row());
+               if(m_status.value(id) == JobStatus_Completed || m_status.value(id) == JobStatus_Failed ||
+                       m_status.value(id) == JobStatus_Aborted || m_status.value(id) == JobStatus_Enqueued)
+               {
+                       int idx = index.row();
+                       QUuid id = m_jobs.at(idx);
+                       EncodeThread *thread = m_threads.value(id, NULL);
+                       LogFileModel *logFile = m_logFile.value(id, NULL);
+                       if((thread == NULL) || (!thread->isRunning()))
+                       {
+                               
+                               beginRemoveRows(QModelIndex(), idx, idx);
+                               m_jobs.removeAt(index.row());
+                               m_name.remove(id);
+                               m_threads.remove(id);
+                               m_status.remove(id);
+                               m_progress.remove(id);
+                               m_logFile.remove(id);
+                               m_details.remove(id);
+                               endRemoveRows();
+                               MUTILS_DELETE(thread);
+                               MUTILS_DELETE(logFile);
+                               return true;
+                       }
+               }
+       }
+
+       return false;
+}
+
+bool JobListModel::moveJob(const QModelIndex &index, const int &direction)
+{
+       if(VALID_INDEX(index))
+       {
+               if((direction == MOVE_UP) && (index.row() > 0))
+               {
+                       beginMoveRows(QModelIndex(), index.row(), index.row(), QModelIndex(), index.row() - 1);
+                       m_jobs.swap(index.row(), index.row() - 1);
+                       endMoveRows();
+                       return true;
+               }
+               if((direction == MOVE_DOWN) && (index.row() < m_jobs.size() - 1))
+               {
+                       beginMoveRows(QModelIndex(), index.row(), index.row(), QModelIndex(), index.row() + 2);
+                       m_jobs.swap(index.row(), index.row() + 1);
+                       endMoveRows();
+                       return true;
+               }
+       }
+
+       return false;
+}
+
 LogFileModel *JobListModel::getLogFile(const QModelIndex &index)
 {
        if(index.isValid() && index.row() >= 0 && index.row() < m_jobs.count())
@@ -347,14 +452,40 @@ LogFileModel *JobListModel::getLogFile(const QModelIndex &index)
        return NULL;
 }
 
-EncodeThread::JobStatus JobListModel::getJobStatus(const QModelIndex &index)
+const QString &JobListModel::getJobSourceFile(const QModelIndex &index)
+{
+       static QString nullStr;
+       
+       if(index.isValid() && index.row() >= 0 && index.row() < m_jobs.count())
+       {
+               EncodeThread *thread = m_threads.value(m_jobs.at(index.row()));
+               return (thread != NULL) ? thread->sourceFileName() : nullStr;
+       }
+
+       return nullStr;
+}
+
+const QString &JobListModel::getJobOutputFile(const QModelIndex &index)
+{
+       static QString nullStr;
+       
+       if(index.isValid() && index.row() >= 0 && index.row() < m_jobs.count())
+       {
+               EncodeThread *thread = m_threads.value(m_jobs.at(index.row()));
+               return (thread != NULL) ? thread->outputFileName() : nullStr;
+       }
+
+       return nullStr;
+}
+
+JobStatus JobListModel::getJobStatus(const QModelIndex &index)
 {
        if(index.isValid() && index.row() >= 0 && index.row() < m_jobs.count())
        {
                return m_status.value(m_jobs.at(index.row()));
        }
 
-       return static_cast<EncodeThread::JobStatus>(-1);
+       return static_cast<JobStatus>(-1);
 }
 
 unsigned int JobListModel::getJobProgress(const QModelIndex &index)
@@ -367,6 +498,19 @@ unsigned int JobListModel::getJobProgress(const QModelIndex &index)
        return 0;
 }
 
+const OptionsModel *JobListModel::getJobOptions(const QModelIndex &index)
+{
+       static QString nullStr;
+       
+       if(index.isValid() && index.row() >= 0 && index.row() < m_jobs.count())
+       {
+               EncodeThread *thread = m_threads.value(m_jobs.at(index.row()));
+               return (thread != NULL) ? thread->options() : NULL;
+       }
+
+       return NULL;
+}
+
 QModelIndex JobListModel::getJobIndexById(const QUuid &id)
 {
        if(m_jobs.contains(id))
@@ -381,7 +525,7 @@ QModelIndex JobListModel::getJobIndexById(const QUuid &id)
 // Slots
 ///////////////////////////////////////////////////////////////////////////////
 
-void JobListModel::updateStatus(const QUuid &jobId, EncodeThread::JobStatus newStatus)
+void JobListModel::updateStatus(const QUuid &jobId, JobStatus newStatus)
 {
        int index = -1;
        
@@ -389,6 +533,22 @@ void JobListModel::updateStatus(const QUuid &jobId, EncodeThread::JobStatus newS
        {
                m_status.insert(jobId, newStatus);
                emit dataChanged(createIndex(index, 0), createIndex(index, 1));
+
+               if(m_preferences->getEnableSounds())
+               {
+                       switch(newStatus)
+                       {
+                       case JobStatus_Completed:
+                               MUtils::Sound::play_sound("tada", true);
+                               break;
+                       case JobStatus_Aborted:
+                               MUtils::Sound::play_sound("shattering", true);
+                               break;
+                       case JobStatus_Failed:
+                               MUtils::Sound::play_sound("failure", true);
+                               break;
+                       }
+               }
        }
 }
 
@@ -413,3 +573,99 @@ void JobListModel::updateDetails(const QUuid &jobId, const QString &details)
                emit dataChanged(createIndex(index, 3), createIndex(index, 3));
        }
 }
+
+size_t JobListModel::saveQueuedJobs(void)
+{
+       const QString appDir = x264_data_path();
+       QSettings settings(QString("%1/queue.ini").arg(appDir), QSettings::IniFormat);
+       
+       settings.clear();
+       settings.setValue(KEY_ENTRY_COUNT, 0);
+       size_t jobCounter = 0;
+
+       for(QList<QUuid>::ConstIterator iter = m_jobs.constBegin(); iter != m_jobs.constEnd(); iter++)
+       {
+               if(m_status.value(*iter) == JobStatus_Enqueued)
+               {
+                       if(const EncodeThread *thread = m_threads.value(*iter))
+                       {
+                               settings.beginGroup(QString().sprintf(JOB_TEMPLATE, jobCounter++));
+                               settings.setValue(KEY_SOURCE_FILE, thread->sourceFileName());
+                               settings.setValue(KEY_OUTPUT_FILE, thread->outputFileName());
+
+                               settings.beginGroup(KEY_ENC_OPTIONS);
+                               OptionsModel::saveOptions(thread->options(), settings);
+
+                               settings.endGroup();
+                               settings.endGroup();
+
+                               settings.setValue(KEY_ENTRY_COUNT, jobCounter);
+                       }
+               }
+       }
+
+       settings.sync();
+       return jobCounter;
+}
+
+size_t JobListModel::loadQueuedJobs(const SysinfoModel *sysinfo)
+{
+       const QString appDir = x264_data_path();
+       QSettings settings(QString("%1/queue.ini").arg(appDir), QSettings::IniFormat);
+
+       bool ok = false;
+       const size_t jobCounter = settings.value(KEY_ENTRY_COUNT, 0).toUInt(&ok);
+
+       if((!ok) || (jobCounter < 1))
+       {
+               return 0;
+       }
+
+       const QStringList groups = settings.childGroups();
+       for(size_t i = 0; i < jobCounter; i++)
+       {
+               if(!groups.contains(QString().sprintf(JOB_TEMPLATE, i)))
+               {
+                       return 0;
+               }
+       }
+
+       size_t jobsCreated = 0;
+       for(size_t i = 0; i < jobCounter; i++)
+       {
+               settings.beginGroup(QString().sprintf(JOB_TEMPLATE, i));
+               const QString sourceFileName = settings.value(KEY_SOURCE_FILE, QString()).toString().trimmed();
+               const QString outputFileName = settings.value(KEY_OUTPUT_FILE, QString()).toString().trimmed();
+
+               if(sourceFileName.isEmpty() || outputFileName.isEmpty())
+               {
+                       settings.endGroup();
+                       continue;
+               }
+
+               settings.beginGroup(KEY_ENC_OPTIONS);
+               OptionsModel options(sysinfo);
+               const bool okay = OptionsModel::loadOptions(&options, settings);
+
+               settings.endGroup();
+               settings.endGroup();
+
+               if(okay)
+               {
+                       EncodeThread *thread = new EncodeThread(sourceFileName, outputFileName, &options, sysinfo, m_preferences);
+                       insertJob(thread);
+                       jobsCreated++;
+               }
+       }
+
+       return jobsCreated;
+}
+
+void JobListModel::clearQueuedJobs(void)
+{
+       const QString appDir = x264_data_path();
+       QSettings settings(QString("%1/queue.ini").arg(appDir), QSettings::IniFormat);
+       settings.clear();
+       settings.setValue(KEY_ENTRY_COUNT, 0);
+       settings.sync();
+}