From: lordmulder Date: Wed, 24 Nov 2010 20:00:59 +0000 (+0100) Subject: Implement support for Job Objects + improve log view. X-Git-Tag: Release_400~187 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=571df62e39b16e4e2fce46c406ebaa2dfe932dab;p=lamexp%2FLameXP.git Implement support for Job Objects + improve log view. --- diff --git a/gui/LogViewDialog.ui b/gui/LogViewDialog.ui index ea0e5139..4a9eb201 100644 --- a/gui/LogViewDialog.ui +++ b/gui/LogViewDialog.ui @@ -10,13 +10,13 @@ 0 0 640 - 512 + 384 640 - 512 + 384 @@ -26,154 +26,338 @@ :/icons/application_xp_terminal.png:/icons/application_xp_terminal.png - - - - - + + + 0 + + + 0 + + + + + 0 + + + + + + 0 + 64 + + + + + 16777215 + 64 + + - + - 170 + 255 255 - 0 + 255 - + - 0 - 31 - 0 + 255 + 255 + 255 - + - 170 + 255 255 - 0 + 255 - + - 0 - 31 - 0 + 255 + 255 + 255 - + - 120 - 120 - 120 + 255 + 255 + 255 - + - 240 - 240 - 240 + 255 + 255 + 255 - - - Lucida Console - + + true - - C:\DOS -C:\DOS\RUN -RUN\DOS\RUN - - - - Qt::NoTextInteraction + + QFrame::NoFrame + + + 3 + + + + + + + + 56 + 56 + + + + + 56 + 56 + + + + + + + :/images/HeaderIcon_LogFile.png + + + true + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 15 + 20 + + + + + + + + <b>Log File</b><br>The log file shows detailed information about the selected job. + + + + + + - - + + - 90 - 0 + 0 + 2 - - Discard - - - - :/icons/cross.png:/icons/cross.png - - - - - - + - 130 - 0 + 16777215 + 2 - - Save to File... + + QFrame::HLine - - - :/icons/disk.png:/icons/disk.png + + QFrame::Sunken - - - - Qt::Horizontal + + + + 10 - - - 40 - 20 - + + 6 - - - - - - - 130 - 0 - - - - Copy to Clipboard - - - - :/icons/paste_plain.png:/icons/paste_plain.png - - + + + + + + + + + 170 + 255 + 0 + + + + + + + 0 + 31 + 0 + + + + + + + + + 170 + 255 + 0 + + + + + + + 0 + 31 + 0 + + + + + + + + + 120 + 120 + 120 + + + + + + + 240 + 240 + 240 + + + + + + + + + Lucida Console + + + + C:\DOS +C:\DOS\RUN +RUN\DOS\RUN + + + + Qt::NoTextInteraction + + + + + + + + 90 + 0 + + + + Discard + + + + :/icons/cross.png:/icons/cross.png + + + + + + + + 130 + 0 + + + + Save to File... + + + + :/icons/disk.png:/icons/disk.png + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 130 + 0 + + + + Copy to Clipboard + + + + :/icons/paste_plain.png:/icons/paste_plain.png + + + + @@ -181,6 +365,8 @@ RUN\DOS\RUN + + diff --git a/res/Images.qrc b/res/Images.qrc index 9fe1e8cc..6249dadd 100644 --- a/res/Images.qrc +++ b/res/Images.qrc @@ -3,6 +3,7 @@ images/Busy.gif images/HeaderIcon_MetaInfo.png + images/HeaderIcon_LogFile.png images/Label.png images/Loading.gif images/Logo.png diff --git a/res/images/HeaderIcon_LogFile.png b/res/images/HeaderIcon_LogFile.png new file mode 100644 index 00000000..67e09859 Binary files /dev/null and b/res/images/HeaderIcon_LogFile.png differ diff --git a/src/Config.h b/src/Config.h index d3bb937e..813275ad 100644 --- a/src/Config.h +++ b/src/Config.h @@ -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 /* diff --git a/src/Dialog_LogView.cpp b/src/Dialog_LogView.cpp index 1deab260..d5c73d31 100644 --- a/src/Dialog_LogView.cpp +++ b/src/Dialog_LogView.cpp @@ -23,6 +23,7 @@ #include #include +#include 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) diff --git a/src/Dialog_MainWindow.cpp b/src/Dialog_MainWindow.cpp index 6d8f8fa9..8547aa8e 100644 --- a/src/Dialog_MainWindow.cpp +++ b/src/Dialog_MainWindow.cpp @@ -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(); +} diff --git a/src/Dialog_MainWindow.h b/src/Dialog_MainWindow.h index a01c06a2..87153907 100644 --- a/src/Dialog_MainWindow.h +++ b/src/Dialog_MainWindow.h @@ -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); diff --git a/src/Dialog_Processing.cpp b/src/Dialog_Processing.cpp index de7952fe..4a6058a1 100644 --- a/src/Dialog_Processing.cpp +++ b/src/Dialog_Processing.cpp @@ -41,6 +41,7 @@ #include #include #include +#include #include @@ -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 - startNextJob(); + 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()); } //////////////////////////////////////////////////////////// diff --git a/src/Dialog_Processing.h b/src/Dialog_Processing.h index 5fe602bd..69626cff 100644 --- a/src/Dialog_Processing.h +++ b/src/Dialog_Processing.h @@ -26,6 +26,7 @@ #include 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; diff --git a/src/Encoder_Abstract.cpp b/src/Encoder_Abstract.cpp index fdd44c6e..de965e24 100644 --- a/src/Encoder_Abstract.cpp +++ b/src/Encoder_Abstract.cpp @@ -22,12 +22,36 @@ #include "Encoder_Abstract.h" #include +#include +#include +#include +#include #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); diff --git a/src/Encoder_Abstract.h b/src/Encoder_Abstract.h index dc8b2f2d..ff0507a8 100644 --- a/src/Encoder_Abstract.h +++ b/src/Encoder_Abstract.h @@ -25,6 +25,10 @@ #include +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; }; diff --git a/src/Encoder_MP3.cpp b/src/Encoder_MP3.cpp index 31181afb..f56131c4 100644 --- a/src/Encoder_MP3.cpp +++ b/src/Encoder_MP3.cpp @@ -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); } } } @@ -139,6 +132,8 @@ bool MP3Encoder::encode(const AudioFileModel &sourceFile, const QString &outputF process.kill(); process.waitForFinished(-1); } + + emit messageLogged(QString().sprintf("\n--> Exited with code: 0x%08x", process.exitCode())); if(bTimeout || bAborted || process.exitStatus() != QProcess::NormalExit) { diff --git a/src/Encoder_MP3.h b/src/Encoder_MP3.h index 677a4cf5..7c99cce6 100644 --- a/src/Encoder_MP3.h +++ b/src/Encoder_MP3.h @@ -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; }; diff --git a/src/Main.cpp b/src/Main.cpp index c381d8f0..7c933f0a 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -50,24 +50,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"); @@ -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);