<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">
<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="QGridLayout" name="gridLayout">
- <item row="0" column="0" colspan="4">
- <widget class="QPlainTextEdit" name="textEdit">
+ <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="Text">
+ <colorrole role="Base">
<brush brushstyle="SolidPattern">
<color alpha="255">
- <red>170</red>
+ <red>255</red>
<green>255</green>
- <blue>0</blue>
+ <blue>255</blue>
</color>
</brush>
</colorrole>
- <colorrole role="Base">
+ <colorrole role="Window">
<brush brushstyle="SolidPattern">
<color alpha="255">
- <red>0</red>
- <green>31</green>
- <blue>0</blue>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
</color>
</brush>
</colorrole>
</active>
<inactive>
- <colorrole role="Text">
+ <colorrole role="Base">
<brush brushstyle="SolidPattern">
<color alpha="255">
- <red>170</red>
+ <red>255</red>
<green>255</green>
- <blue>0</blue>
+ <blue>255</blue>
</color>
</brush>
</colorrole>
- <colorrole role="Base">
+ <colorrole role="Window">
<brush brushstyle="SolidPattern">
<color alpha="255">
- <red>0</red>
- <green>31</green>
- <blue>0</blue>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
</color>
</brush>
</colorrole>
</inactive>
<disabled>
- <colorrole role="Text">
+ <colorrole role="Base">
<brush brushstyle="SolidPattern">
<color alpha="255">
- <red>120</red>
- <green>120</green>
- <blue>120</blue>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
</color>
</brush>
</colorrole>
- <colorrole role="Base">
+ <colorrole role="Window">
<brush brushstyle="SolidPattern">
<color alpha="255">
- <red>240</red>
- <green>240</green>
- <blue>240</blue>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
</color>
</brush>
</colorrole>
</disabled>
</palette>
</property>
- <property name="font">
- <font>
- <family>Lucida Console</family>
- </font>
+ <property name="autoFillBackground">
+ <bool>true</bool>
</property>
- <property name="plainText">
- <string>C:\DOS
-C:\DOS\RUN
-RUN\DOS\RUN
-</string>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::NoTextInteraction</set>
+ <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><b>Log File</b><br>The log file shows detailed information about the selected job.</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
</widget>
</item>
- <item row="1" column="3">
- <widget class="QPushButton" name="buttonDiscard">
+ <item>
+ <widget class="QFrame" name="horizontalBar">
<property name="minimumSize">
<size>
- <width>90</width>
- <height>0</height>
+ <width>0</width>
+ <height>2</height>
</size>
</property>
- <property name="text">
- <string>Discard</string>
- </property>
- <property name="icon">
- <iconset resource="../res/Icons.qrc">
- <normaloff>:/icons/cross.png</normaloff>:/icons/cross.png</iconset>
- </property>
- </widget>
- </item>
- <item row="1" column="2">
- <widget class="QPushButton" name="buttonSave">
- <property name="minimumSize">
+ <property name="maximumSize">
<size>
- <width>130</width>
- <height>0</height>
+ <width>16777215</width>
+ <height>2</height>
</size>
</property>
- <property name="text">
- <string>Save to File...</string>
+ <property name="frameShape">
+ <enum>QFrame::HLine</enum>
</property>
- <property name="icon">
- <iconset resource="../res/Icons.qrc">
- <normaloff>:/icons/disk.png</normaloff>:/icons/disk.png</iconset>
+ <property name="frameShadow">
+ <enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
- <item row="1" column="0">
- <spacer name="horizontalSpacer">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
+ <item>
+ <layout class="QGridLayout" name="gridLayout">
+ <property name="margin">
+ <number>10</number>
</property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
+ <property name="spacing">
+ <number>6</number>
</property>
- </spacer>
- </item>
- <item row="1" column="1">
- <widget class="QPushButton" name="buttonCopy">
- <property name="minimumSize">
- <size>
- <width>130</width>
- <height>0</height>
- </size>
- </property>
- <property name="text">
- <string>Copy to Clipboard</string>
- </property>
- <property name="icon">
- <iconset resource="../res/Icons.qrc">
- <normaloff>:/icons/paste_plain.png</normaloff>:/icons/paste_plain.png</iconset>
- </property>
- </widget>
+ <item row="0" column="0" colspan="4">
+ <widget class="QPlainTextEdit" name="textEdit">
+ <property name="palette">
+ <palette>
+ <active>
+ <colorrole role="Text">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>170</red>
+ <green>255</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Base">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>31</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </active>
+ <inactive>
+ <colorrole role="Text">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>170</red>
+ <green>255</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Base">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>0</red>
+ <green>31</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </inactive>
+ <disabled>
+ <colorrole role="Text">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>120</red>
+ <green>120</green>
+ <blue>120</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Base">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>240</red>
+ <green>240</green>
+ <blue>240</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </disabled>
+ </palette>
+ </property>
+ <property name="font">
+ <font>
+ <family>Lucida Console</family>
+ </font>
+ </property>
+ <property name="plainText">
+ <string>C:\DOS
+C:\DOS\RUN
+RUN\DOS\RUN
+</string>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::NoTextInteraction</set>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="3">
+ <widget class="QPushButton" name="buttonDiscard">
+ <property name="minimumSize">
+ <size>
+ <width>90</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Discard</string>
+ </property>
+ <property name="icon">
+ <iconset resource="../res/Icons.qrc">
+ <normaloff>:/icons/cross.png</normaloff>:/icons/cross.png</iconset>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QPushButton" name="buttonSave">
+ <property name="minimumSize">
+ <size>
+ <width>130</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Save to File...</string>
+ </property>
+ <property name="icon">
+ <iconset resource="../res/Icons.qrc">
+ <normaloff>:/icons/disk.png</normaloff>:/icons/disk.png</iconset>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="1" column="1">
+ <widget class="QPushButton" name="buttonCopy">
+ <property name="minimumSize">
+ <size>
+ <width>130</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Copy to Clipboard</string>
+ </property>
+ <property name="icon">
+ <iconset resource="../res/Icons.qrc">
+ <normaloff>:/icons/paste_plain.png</normaloff>:/icons/paste_plain.png</iconset>
+ </property>
+ </widget>
+ </item>
+ </layout>
</item>
</layout>
</item>
</widget>
<resources>
<include location="../res/Icons.qrc"/>
+ <include location="../res/Images.qrc"/>
+ <include location="../res/Images.qrc"/>
</resources>
<connections>
<connection>
<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>
#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
/*
#include <QClipboard>
#include <QFileDialog>
+#include <Windows.h>
LogViewDialog::LogViewDialog(QWidget *parent)
:
mime->setData("text/plain", textEdit->toPlainText().toUtf8().constData());
QApplication::clipboard()->setMimeData(mime);
m_clipboardUsed = true;
+ MessageBeep(MB_ICONINFORMATION);
}
void LogViewDialog::saveButtonClicked(void)
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);
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
////////////////////////////////////////////////////////////
{
m_settings->outputToSourceDir(saveToSourceFolderCheckBox->isChecked());
}
+
+/*
+ * Restore the override cursor
+ */
+void MainWindow::restoreCursor(void)
+{
+ QApplication::restoreOverrideCursor();
+}
void metaTagsEnabledChanged(void);
void playlistEnabledChanged(void);
void saveToSourceFolderChanged(void);
+ void restoreCursor(void);
protected:
void showEvent(QShowEvent *event);
void dropEvent(QDropEvent *event);
void closeEvent(QCloseEvent *event);
void resizeEvent(QResizeEvent *event);
+ bool eventFilter(QObject *obj, QEvent *event);
private:
void addFiles(const QStringList &files);
#include <QUuid>
#include <QFileInfo>
#include <QDir>
+#include <QMenu>
#include <Windows.h>
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)
{
if(m_progressIndicator) m_progressIndicator->stop();
LAMEXP_DELETE(m_progressIndicator);
LAMEXP_DELETE(m_progressModel);
+ LAMEXP_DELETE(m_contextMenu);
while(!m_threadList.isEmpty())
{
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)
{
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());
}
////////////////////////////////////////////////////////////
#include <QUuid>
class QMovie;
+class QMenu;
class ProgressModel;
class ProcessThread;
class FileListModel;
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);
QMovie *m_progressIndicator;
ProgressModel *m_progressModel;
QStringList m_playList;
+ QMenu *m_contextMenu;
unsigned int m_runningThreads;
unsigned int m_currentFile;
unsigned int m_succeededFiles;
#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;
}
{
}
-//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);
#include <QObject>
+class QProcess;
+class QStringList;
+class QMutex;
+
class AbstractEncoder : public QObject
{
Q_OBJECT
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;
};
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";
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;
}
{
process.kill();
bAborted = true;
+ emit messageLogged("ABORTED BY USER !!!");
break;
}
process.waitForReadyRead();
}
else if(!text.isEmpty())
{
- emit messageLogged(text); //qDebug("%s", text.toUtf8().constData());
+ emit messageLogged(text);
}
}
}
process.kill();
process.waitForFinished(-1);
}
+
+ emit messageLogged(QString().sprintf("\n--> Exited with code: 0x%08x", process.exitCode()));
if(bTimeout || bAborted || process.exitStatus() != QProcess::NormalExit)
{
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;
};
//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("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);