Implement support for Job Objects + improve log view.

This commit is contained in:
LoRd_MuldeR 2010-11-24 21:00:59 +01:00
parent 136d4a5350
commit 571df62e39
14 changed files with 440 additions and 157 deletions

View File

@ -10,13 +10,13 @@
<x>0</x>
<y>0</y>
<width>640</width>
<height>512</height>
<height>384</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>640</width>
<height>512</height>
<height>384</height>
</size>
</property>
<property name="windowTitle">
@ -26,9 +26,191 @@
<iconset resource="../res/Icons.qrc">
<normaloff>:/icons/application_xp_terminal.png</normaloff>:/icons/application_xp_terminal.png</iconset>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<number>0</number>
</property>
<item>
<layout class="QVBoxLayout" name="baseLayout">
<property name="spacing">
<number>0</number>
</property>
<item>
<widget class="QFrame" name="headerFrame">
<property name="minimumSize">
<size>
<width>0</width>
<height>64</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>64</height>
</size>
</property>
<property name="palette">
<palette>
<active>
<colorrole role="Base">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
<colorrole role="Window">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
</active>
<inactive>
<colorrole role="Base">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
<colorrole role="Window">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
</inactive>
<disabled>
<colorrole role="Base">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
<colorrole role="Window">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
</disabled>
</palette>
</property>
<property name="autoFillBackground">
<bool>true</bool>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="margin">
<number>3</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="headerIcon">
<property name="minimumSize">
<size>
<width>56</width>
<height>56</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>56</width>
<height>56</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="../res/Images.qrc">:/images/HeaderIcon_LogFile.png</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="headerSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>15</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="headerText">
<property name="text">
<string>&lt;b&gt;Log File&lt;/b&gt;&lt;br&gt;The log file shows detailed information about the selected job.</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="horizontalBar">
<property name="minimumSize">
<size>
<width>0</width>
<height>2</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>2</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::HLine</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
<property name="margin">
<number>10</number>
</property>
<property name="spacing">
<number>6</number>
</property>
<item row="0" column="0" colspan="4">
<widget class="QPlainTextEdit" name="textEdit">
<property name="palette">
@ -178,9 +360,13 @@ RUN\DOS\RUN
</layout>
</item>
</layout>
</item>
</layout>
</widget>
<resources>
<include location="../res/Icons.qrc"/>
<include location="../res/Images.qrc"/>
<include location="../res/Images.qrc"/>
</resources>
<connections>
<connection>

View File

@ -3,6 +3,7 @@
<qresource>
<file>images/Busy.gif</file>
<file>images/HeaderIcon_MetaInfo.png</file>
<file>images/HeaderIcon_LogFile.png</file>
<file>images/Label.png</file>
<file>images/Loading.gif</file>
<file>images/Logo.png</file>

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@ -25,7 +25,7 @@
#define VER_LAMEXP_MAJOR 4
#define VER_LAMEXP_MINOR_HI 0
#define VER_LAMEXP_MINOR_LO 0
#define VER_LAMEXP_BUILD 70
#define VER_LAMEXP_BUILD 74
#define VER_LAMEXP_SUFFIX TechPreview
/*

View File

@ -23,6 +23,7 @@
#include <QClipboard>
#include <QFileDialog>
#include <Windows.h>
LogViewDialog::LogViewDialog(QWidget *parent)
:
@ -64,6 +65,7 @@ void LogViewDialog::copyButtonClicked(void)
mime->setData("text/plain", textEdit->toPlainText().toUtf8().constData());
QApplication::clipboard()->setMimeData(mime);
m_clipboardUsed = true;
MessageBeep(MB_ICONINFORMATION);
}
void LogViewDialog::saveButtonClicked(void)

View File

@ -132,6 +132,7 @@ MainWindow::MainWindow(FileListModel *fileListModel, AudioFileModel *metaInfo, S
m_fileSystemModel = new QFileSystemModel();
m_fileSystemModel->setFilter(QDir::Dirs | QDir::NoDotAndDotDot);
m_fileSystemModel->setRootPath(m_fileSystemModel->rootPath());
m_fileSystemModel->installEventFilter(this);
outputFolderView->setModel(m_fileSystemModel);
outputFolderView->header()->setStretchLastSection(true);
outputFolderView->header()->hideSection(1);
@ -393,6 +394,17 @@ void MainWindow::resizeEvent(QResizeEvent *event)
m_dropNoteLabel->setGeometry(0, 0, sourceFileView->width(), sourceFileView->height());
}
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
if(obj == m_fileSystemModel)
{
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
QTimer::singleShot(0, this, SLOT(restoreCursor()));
}
return false;
}
////////////////////////////////////////////////////////////
// Slots
////////////////////////////////////////////////////////////
@ -1111,3 +1123,11 @@ void MainWindow::saveToSourceFolderChanged(void)
{
m_settings->outputToSourceDir(saveToSourceFolderCheckBox->isChecked());
}
/*
* Restore the override cursor
*/
void MainWindow::restoreCursor(void)
{
QApplication::restoreOverrideCursor();
}

View File

@ -80,6 +80,7 @@ private slots:
void metaTagsEnabledChanged(void);
void playlistEnabledChanged(void);
void saveToSourceFolderChanged(void);
void restoreCursor(void);
protected:
void showEvent(QShowEvent *event);
@ -87,6 +88,7 @@ protected:
void dropEvent(QDropEvent *event);
void closeEvent(QCloseEvent *event);
void resizeEvent(QResizeEvent *event);
bool eventFilter(QObject *obj, QEvent *event);
private:
void addFiles(const QStringList &files);

View File

@ -41,6 +41,7 @@
#include <QUuid>
#include <QFileInfo>
#include <QDir>
#include <QMenu>
#include <Windows.h>
@ -90,6 +91,13 @@ ProcessingDialog::ProcessingDialog(FileListModel *fileListModel, AudioFileModel
connect(m_progressModel, SIGNAL(modelReset()), this, SLOT(progressModelChanged()));
connect(view_log, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(logViewDoubleClicked(QModelIndex)));
//Create context menu
m_contextMenu = new QMenu();
QAction *contextMenuAction = m_contextMenu->addAction(QIcon(":/icons/zoom.png"), "Show details for selected job");
view_log->setContextMenuPolicy(Qt::CustomContextMenu);
connect(view_log, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextMenuTriggered(QPoint)));
connect(contextMenuAction, SIGNAL(triggered(bool)), this, SLOT(contextMenuActionTriggered()));
//Enque jobs
if(fileListModel)
{
@ -117,6 +125,7 @@ ProcessingDialog::~ProcessingDialog(void)
if(m_progressIndicator) m_progressIndicator->stop();
LAMEXP_DELETE(m_progressIndicator);
LAMEXP_DELETE(m_progressModel);
LAMEXP_DELETE(m_contextMenu);
while(!m_threadList.isEmpty())
{
@ -194,8 +203,12 @@ void ProcessingDialog::initEncoding(void)
button_AbortProcess->setEnabled(true);
progressBar->setRange(0, m_pendingJobs.count());
startNextJob(); //TODO: Start as many jobs in parallel as processors available
lamexp_cpu_t cpuFeatures = lamexp_detect_cpu_features();
for(int i = 0; i < min(max(cpuFeatures.count, 1), 4); i++)
{
startNextJob();
}
}
void ProcessingDialog::abortEncoding(void)
@ -292,9 +305,25 @@ void ProcessingDialog::logViewDoubleClicked(const QModelIndex &index)
{
const QStringList &logFile = m_progressModel->getLogFile(index);
LogViewDialog *logView = new LogViewDialog(this);
logView->setWindowTitle(QString("LameXP - %1").arg(m_progressModel->data(index, Qt::DisplayRole).toString()));
logView->exec(logFile);
LAMEXP_DELETE(logView);
}
else
{
MessageBeep(MB_ICONWARNING);
}
}
void ProcessingDialog::contextMenuTriggered(const QPoint &pos)
{
m_contextMenu->popup(view_log->mapToGlobal(pos));
}
void ProcessingDialog::contextMenuActionTriggered(void)
{
QModelIndex index = view_log->indexAt(view_log->mapFromGlobal(m_contextMenu->pos()));
logViewDoubleClicked(index.isValid() ? index : view_log->currentIndex());
}
////////////////////////////////////////////////////////////

View File

@ -26,6 +26,7 @@
#include <QUuid>
class QMovie;
class QMenu;
class ProgressModel;
class ProcessThread;
class FileListModel;
@ -47,6 +48,8 @@ private slots:
void processFinished(const QUuid &jobId, const QString &outFileName, bool success);
void progressModelChanged(void);
void logViewDoubleClicked(const QModelIndex &index);
void contextMenuTriggered(const QPoint &pos);
void contextMenuActionTriggered(void);
protected:
void showEvent(QShowEvent *event);
@ -66,6 +69,7 @@ private:
QMovie *m_progressIndicator;
ProgressModel *m_progressModel;
QStringList m_playList;
QMenu *m_contextMenu;
unsigned int m_runningThreads;
unsigned int m_currentFile;
unsigned int m_succeededFiles;

View File

@ -22,12 +22,36 @@
#include "Encoder_Abstract.h"
#include <QStringList>
#include <QProcess>
#include <QMutex>
#include <QMutexLocker>
#include <Windows.h>
#define max(a,b) (((a) > (b)) ? (a) : (b))
#define min(a,b) (((a) < (b)) ? (a) : (b))
QMutex *AbstractEncoder::m_mutex_startProcess = NULL;
HANDLE AbstractEncoder::m_handle_jobObject = NULL;
AbstractEncoder::AbstractEncoder(void)
{
if(!m_mutex_startProcess)
{
m_mutex_startProcess = new QMutex();
}
if(!m_handle_jobObject)
{
m_handle_jobObject = CreateJobObject(NULL, NULL);
if(m_handle_jobObject)
{
JOBOBJECT_EXTENDED_LIMIT_INFORMATION jobExtendedLimitInfo;
memset(&jobExtendedLimitInfo, 0, sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
jobExtendedLimitInfo.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE | JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION;
SetInformationJobObject(m_handle_jobObject, JobObjectExtendedLimitInformation, &jobExtendedLimitInfo, sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
}
}
m_configBitrate = 0;
m_configRCMode = 0;
}
@ -36,10 +60,40 @@ AbstractEncoder::~AbstractEncoder(void)
{
}
//Setters
/*
* Setters
*/
void AbstractEncoder::setBitrate(int bitrate) { m_configBitrate = max(0, bitrate); }
void AbstractEncoder::setRCMode(int mode) { m_configRCMode = max(0, mode); }
/*
* Auxiliary functions
*/
bool AbstractEncoder::startProcess(QProcess &process, const QString &program, const QStringList &args)
{
QMutexLocker lock(m_mutex_startProcess);
emit messageLogged(commandline2string(program, args) + "\n");
process.setProcessChannelMode(QProcess::MergedChannels);
process.setReadChannel(QProcess::StandardOutput);
process.start(program, args);
if(process.waitForStarted())
{
AssignProcessToJobObject(m_handle_jobObject, process.pid()->hProcess);
SetPriorityClass(process.pid()->hProcess, BELOW_NORMAL_PRIORITY_CLASS);
lock.unlock();
emit statusUpdated(0);
return true;
}
return false;
}
QString AbstractEncoder::commandline2string(const QString &program, const QStringList &arguments)
{
QString commandline = (program.contains(' ') ? QString("\"%1\"").arg(program) : program);

View File

@ -25,6 +25,10 @@
#include <QObject>
class QProcess;
class QStringList;
class QMutex;
class AbstractEncoder : public QObject
{
Q_OBJECT
@ -39,10 +43,18 @@ public:
void setBitrate(int bitrate);
void setRCMode(int mode);
bool startProcess(QProcess &process, const QString &program, const QStringList &args);
static QString commandline2string(const QString &program, const QStringList &arguments);
signals:
void statusUpdated(int progress);
void messageLogged(const QString &line);
protected:
int m_configBitrate;
int m_configRCMode;
private:
static QMutex *m_mutex_startProcess;
static void *m_handle_jobObject;
};

View File

@ -45,14 +45,10 @@ MP3Encoder::~MP3Encoder(void)
bool MP3Encoder::encode(const AudioFileModel &sourceFile, const QString &outputFile, volatile bool *abortFlag)
{
const QString baseName = QFileInfo(outputFile).fileName();
emit statusUpdated(0);
QProcess process;
process.setProcessChannelMode(QProcess::MergedChannels);
process.setReadChannel(QProcess::StandardOutput);
const QString baseName = QFileInfo(outputFile).fileName();
QStringList args;
args << "--nohist";
args << "-h";
@ -86,11 +82,7 @@ bool MP3Encoder::encode(const AudioFileModel &sourceFile, const QString &outputF
args << QDir::toNativeSeparators(sourceFile.filePath());
args << QDir::toNativeSeparators(outputFile);
emit messageLogged(commandline2string(m_binary, args));
emit messageLogged(QString());
process.start(m_binary, args);
if(!process.waitForStarted())
if(!startProcess(process, m_binary, args))
{
return false;
}
@ -106,6 +98,7 @@ bool MP3Encoder::encode(const AudioFileModel &sourceFile, const QString &outputF
{
process.kill();
bAborted = true;
emit messageLogged("ABORTED BY USER !!!");
break;
}
process.waitForReadyRead();
@ -128,7 +121,7 @@ bool MP3Encoder::encode(const AudioFileModel &sourceFile, const QString &outputF
}
else if(!text.isEmpty())
{
emit messageLogged(text); //qDebug("%s", text.toUtf8().constData());
emit messageLogged(text);
}
}
}
@ -140,6 +133,8 @@ bool MP3Encoder::encode(const AudioFileModel &sourceFile, const QString &outputF
process.waitForFinished(-1);
}
emit messageLogged(QString().sprintf("\n--> Exited with code: 0x%08x", process.exitCode()));
if(bTimeout || bAborted || process.exitStatus() != QProcess::NormalExit)
{
return false;

View File

@ -36,10 +36,6 @@ public:
virtual bool encode(const AudioFileModel &sourceFile, const QString &outputFile, volatile bool *abortFlag);
virtual QString extension(void);
signals:
void statusUpdated(int progress);
void messageLogged(const QString &line);
private:
const QString m_binary;
};

View File

@ -51,24 +51,6 @@ int lamexp_main(int argc, char* argv[])
//Init console
lamexp_init_console(argc, argv);
//LPWSTR *szArglist;
//int nArgs;
//szArglist = CommandLineToArgvW(GetCommandLineW(), &nArgs);
//
//if(nArgs >= 2)
//{
// static HANDLE hConsole = NULL;
// hConsole = CreateFile(L"CONOUT$", GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL);
// if(!SetConsoleCP(CP_UTF8))
// {
// wprintf(L"Failed to set CP !!!\n");
// }
// char buffer[4096];
// WideCharToMultiByte(CP_UTF8, 0, szArglist[1], -1, buffer, 4096, NULL, NULL);
// wprintf(L"%S\n", buffer);
// WriteConsoleA(hConsole, buffer, strlen(buffer), NULL, NULL);
//}
//Print version info
qDebug("LameXP - Audio Encoder Front-End");
qDebug("Version %d.%02d %s, Build %d [%s], compiled with %s", lamexp_version_major(), lamexp_version_minor(), lamexp_version_release(), lamexp_version_build(), lamexp_version_date().toString(Qt::ISODate).toLatin1().constData(), lamexp_version_compiler());
@ -87,7 +69,7 @@ int lamexp_main(int argc, char* argv[])
qDebug("CPU brand string : %s", cpuFeatures.brand);
qDebug(" CPU signature : Family: %d, Model: %d, Stepping: %d", cpuFeatures.family, cpuFeatures.model, cpuFeatures.stepping);
qDebug("CPU capabilities : MMX: %s, SSE: %s, SSE2: %s, SSE3: %s, SSSE3: %s, x64: %s", LAMEXP_BOOL(cpuFeatures.mmx), LAMEXP_BOOL(cpuFeatures.sse), LAMEXP_BOOL(cpuFeatures.sse2), LAMEXP_BOOL(cpuFeatures.sse3), LAMEXP_BOOL(cpuFeatures.ssse3), LAMEXP_BOOL(cpuFeatures.x64));
qDebug("CPU no. of cores : %d\n", cpuFeatures.count);
qDebug(" Number of CPU's : %d\n", cpuFeatures.count);
//Initialize Qt
lamexp_init_qt(argc, argv);