diff --git a/MediaInfoXP.vcxproj b/MediaInfoXP.vcxproj
index c44e756..17dc20e 100644
--- a/MediaInfoXP.vcxproj
+++ b/MediaInfoXP.vcxproj
@@ -130,6 +130,7 @@
+
@@ -145,7 +146,14 @@
-
+
+ "$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)\tmp\Common\moc\MOC_%(Filename).cpp" "%(FullPath)"
+ "$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)\tmp\Common\moc\MOC_%(Filename).cpp" "%(FullPath)"
+ MOC "$(SolutionDir)\tmp\Common\moc\MOC_%(Filename).cpp"
+ MOC "$(SolutionDir)\tmp\Common\moc\MOC_%(Filename).cpp"
+ $(SolutionDir)\tmp\Common\moc\MOC_%(Filename).cpp;%(Outputs)
+ $(SolutionDir)\tmp\Common\moc\MOC_%(Filename).cpp;%(Outputs)
+
diff --git a/MediaInfoXP.vcxproj.filters b/MediaInfoXP.vcxproj.filters
index 918e0c6..5b7ddbe 100644
--- a/MediaInfoXP.vcxproj.filters
+++ b/MediaInfoXP.vcxproj.filters
@@ -31,6 +31,9 @@
Header Files
+
+ Header Files
+
@@ -54,6 +57,9 @@
Source Files
+
+ Source Files\Generated
+
@@ -65,9 +71,6 @@
Header Files
-
- Header Files
-
diff --git a/src/IPC.cpp b/src/IPC.cpp
index 463bde2..a52ac7c 100644
--- a/src/IPC.cpp
+++ b/src/IPC.cpp
@@ -25,7 +25,6 @@
#include
#include
-#include
static const size_t MAX_STR_LEN = 1024;
static const size_t MAX_ENTRIES = 16;
@@ -39,57 +38,101 @@ typedef struct
wchar_t data[MAX_ENTRIES][MAX_STR_LEN];
size_t posRd;
size_t posWr;
+ size_t counter;
}
mixp_ipc_t;
+///////////////////////////////////////////////////////////////////////////////
+// Send Thread
+///////////////////////////////////////////////////////////////////////////////
+
+IPCSendThread::IPCSendThread(IPC *ipc, const QString &str)
+:
+ m_ipc(ipc), m_str(str)
+{
+ m_result = false;
+}
+
+void IPCSendThread::run(void)
+{
+ try
+ {
+ m_result = m_ipc->pushStr(m_str);
+ }
+ catch(...)
+ {
+ m_result = false;
+ }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Receive Thread
+///////////////////////////////////////////////////////////////////////////////
+
+IPCReceiveThread::IPCReceiveThread(IPC *ipc)
+:
+ m_ipc(ipc)
+{
+ m_stopped = false;
+}
+
+void IPCReceiveThread::run(void)
+{
+ try
+ {
+ receiveLoop();
+ }
+ catch(...)
+ {
+ qWarning("Exception in IPC receive thread!");
+ }
+}
+
+void IPCReceiveThread::receiveLoop(void)
+{
+ while(!m_stopped)
+ {
+ QString temp;
+ if(m_ipc->popStr(temp))
+ {
+ if(!temp.isEmpty())
+ {
+ emit receivedStr(temp);
+ }
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// IPC Class
+///////////////////////////////////////////////////////////////////////////////
+
IPC::IPC(void)
{
m_initialized = -1;
m_sharedMemory = NULL;
m_semaphoreWr = NULL;
m_semaphoreRd = NULL;
+ m_recvThread = NULL;
}
IPC::~IPC(void)
{
+ if(m_recvThread && m_recvThread->isRunning())
+ {
+ qWarning("Receive thread still running -> terminating!");
+ m_recvThread->terminate();
+ m_recvThread->wait();
+ }
+
+ MIXP_DELETE_OBJ(m_recvThread);
MIXP_DELETE_OBJ(m_sharedMemory);
MIXP_DELETE_OBJ(m_semaphoreWr);
MIXP_DELETE_OBJ(m_semaphoreRd);
}
-///////////////////////////////////////////////////////////////////////////////
-
-class SendThread : public QThread
-{
-public:
- SendThread(IPC *ipc, const QString &str) : m_ipc(ipc), m_str(str)
- {
- m_result = false;
- }
-
- virtual void run(void)
- {
- try
- {
- m_result = m_ipc->pushStr(m_str);
- }
- catch(...)
- {
- m_result = false;
- }
- }
-
- inline bool result(void) { return m_result; }
-
-protected:
- volatile bool m_result;
- IPC *const m_ipc;
- const QString m_str;
-};
-
-///////////////////////////////////////////////////////////////////////////////
-
-int IPC::init(void)
+int IPC::initialize(void)
{
if(m_initialized >= 0)
{
@@ -148,11 +191,22 @@ bool IPC::pushStr(const QString &str)
return false;
}
+ bool success = true;
+
try
{
mixp_ipc_t *memory = (mixp_ipc_t*) m_sharedMemory->data();
- wcsncpy_s(memory->data[memory->posWr], MAX_STR_LEN, (wchar_t*)str.utf16(), _TRUNCATE);
- memory->posWr = (memory->posWr + 1) % MAX_ENTRIES;
+ if(memory->counter < MAX_ENTRIES)
+ {
+ wcsncpy_s(memory->data[memory->posWr], MAX_STR_LEN, (wchar_t*)str.utf16(), _TRUNCATE);
+ memory->posWr = (memory->posWr + 1) % MAX_ENTRIES;
+ memory->counter++;
+ }
+ else
+ {
+ qWarning("IPC: Shared memory is full -> cannot push string!");
+ success = false;
+ }
}
catch(...)
{
@@ -160,9 +214,13 @@ bool IPC::pushStr(const QString &str)
}
m_sharedMemory->unlock();
- m_semaphoreRd->release();
- return true;
+ if(success)
+ {
+ m_semaphoreRd->release();
+ }
+
+ return success;
}
bool IPC::popStr(QString &str)
@@ -185,11 +243,23 @@ bool IPC::popStr(QString &str)
return false;
}
+ bool success = true;
+
try
{
mixp_ipc_t *memory = (mixp_ipc_t*) m_sharedMemory->data();
- str = QString::fromUtf16((const ushort*)memory->data[memory->posRd]);
- memory->posRd = (memory->posRd + 1) % MAX_ENTRIES;
+ if(memory->counter > 0)
+ {
+ memory->data[memory->posRd][MAX_STR_LEN-1] = L'\0';
+ str = QString::fromUtf16((const ushort*)memory->data[memory->posRd]);
+ memory->posRd = (memory->posRd + 1) % MAX_ENTRIES;
+ memory->counter--;
+ }
+ else
+ {
+ qWarning("IPC: Shared memory is empty -> cannot pop string!");
+ success = false;
+ }
}
catch(...)
{
@@ -197,14 +267,18 @@ bool IPC::popStr(QString &str)
}
m_sharedMemory->unlock();
- m_semaphoreWr->release();
- return true;
+ if(success)
+ {
+ m_semaphoreWr->release();
+ }
+
+ return success;
}
bool IPC::sendAsync(const QString &str, const int timeout)
{
- SendThread sendThread(this, str);
+ IPCSendThread sendThread(this, str);
sendThread.start();
if(!sendThread.wait(timeout))
@@ -217,3 +291,42 @@ bool IPC::sendAsync(const QString &str, const int timeout)
return sendThread.result();
}
+
+void IPC::startListening(void)
+{
+ if(!m_recvThread)
+ {
+ m_recvThread = new IPCReceiveThread(this);
+ connect(m_recvThread, SIGNAL(receivedStr(QString)), this, SIGNAL(receivedStr(QString)), Qt::QueuedConnection);
+ }
+
+ if(!m_recvThread->isRunning())
+ {
+ m_recvThread->start();
+ }
+ else
+ {
+ qWarning("Receive thread was already running!");
+ }
+
+}
+
+void IPC::stopListening(void)
+{
+ if(m_recvThread && m_recvThread->isRunning())
+ {
+ m_recvThread->stop();
+ m_semaphoreRd->release();
+
+ if(!m_recvThread->wait(5000))
+ {
+ qWarning("Receive thread seems deadlocked -> terminating!");
+ m_recvThread->terminate();
+ m_recvThread->wait();
+ }
+ }
+ else
+ {
+ qWarning("Receive thread was not running!");
+ }
+}
diff --git a/src/IPC.h b/src/IPC.h
index cc93952..5c6667d 100644
--- a/src/IPC.h
+++ b/src/IPC.h
@@ -21,30 +21,80 @@
#pragma once
-#include
+#include
class QSharedMemory;
class QSystemSemaphore;
+class IPCSendThread;
+class IPCReceiveThread;
class IPC : public QObject
{
+ Q_OBJECT
+ friend class IPCReceiveThread;
+ friend class IPCSendThread;
+
public:
IPC(void);
~IPC(void);
- int init(void);
-
- //async support
+ int initialize(void);
bool sendAsync(const QString &str, const int timeout = 5000);
-
- //blocking operations
- bool pushStr(const QString &str);
- bool popStr(QString &str);
+
+public slots:
+ void startListening(void);
+ void stopListening(void);
+
+signals:
+ void receivedStr(const QString &str);
protected:
+ bool popStr(QString &str);
+ bool pushStr(const QString &str);
+
int m_initialized;
QSharedMemory *m_sharedMemory;
QSystemSemaphore *m_semaphoreRd;
QSystemSemaphore *m_semaphoreWr;
+ IPCReceiveThread *m_recvThread;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+class IPCSendThread : public QThread
+{
+ Q_OBJECT
+ friend class IPC;
+
+protected:
+ IPCSendThread(IPC *ipc, const QString &str);
+ inline bool result(void) { return m_result; }
+
+ virtual void run(void);
+
+private:
+ volatile bool m_result;
+ IPC *const m_ipc;
+ const QString m_str;
+};
+
+class IPCReceiveThread : public QThread
+{
+ Q_OBJECT
+ friend class IPC;
+
+protected:
+ IPCReceiveThread(IPC *ipc);
+ inline void stop(void) { m_stopped = true; }
+
+ virtual void run(void);
+
+signals:
+ void receivedStr(const QString &str);
+
+private:
+ void receiveLoop(void);
+ volatile bool m_stopped;
+ IPC *const m_ipc;
};
diff --git a/src/Main.cpp b/src/Main.cpp
index 7cc9273..8cb8b79 100644
--- a/src/Main.cpp
+++ b/src/Main.cpp
@@ -102,24 +102,45 @@ int mixp_main(int argc, char* argv[])
qDebug("Copyright (c) 2004-%s LoRd_MuldeR . Some rights reserved.", &mixp_buildDate[7]);
qDebug("Built with Qt v%s, running with Qt v%s.\n", QT_VERSION_STR, qVersion());
- //Initialize IPC
+ //Create application
+ QApplication *application = new QApplication(argc, argv);
+
+ //Create IPC
IPC *ipc = new IPC();
- if(ipc->init() == 0)
+
+ //Is this the *first* instance?
+ if(ipc->initialize() == 0)
{
- ipc->sendAsync("Test Hello World 123!");
- return 0;
+ //We are *not* the first instance -> pass all file names to the running instance
+ const QStringList arguments = qApp->arguments();
+ bool bHaveFile = false;
+ for(QStringList::ConstIterator iter = arguments.constBegin(); iter != arguments.constEnd(); iter++)
+ {
+ if(QString::compare(*iter, "--open", Qt::CaseInsensitive) == 0)
+ {
+ if(++iter != arguments.constEnd())
+ {
+ if(ipc->sendAsync(*iter))
+ {
+ bHaveFile = true;
+ continue;
+ }
+ }
+ break;
+ }
+ }
+ //If no file was sent, we will at least try to bring the other instance to front
+ if(!bHaveFile)
+ {
+ ipc->sendAsync("?");
+ }
+ MIXP_DELETE_OBJ(ipc);
+ MIXP_DELETE_OBJ(application);
+ return 42;
}
- QString test;
- qDebug("Awaiting data from other instance...");
- if(ipc->popStr(test))
- {
- qDebug("Got the data: %s\n", test.toUtf8().constData());
- }
-
- QFile *lockFile = NULL;
-
//Get temp folder
+ QFile *lockFile = NULL;
const QString tempFolder = mixp_getTempFolder(&lockFile);
if(tempFolder.isEmpty())
{
@@ -130,18 +151,17 @@ int mixp_main(int argc, char* argv[])
qDebug("TEMP folder is:\n%s\n", QDir::toNativeSeparators(tempFolder).toUtf8().constData());
- //Create application
- QApplication *application = new QApplication(argc, argv);
- application->setWindowIcon(QIcon(":/QtTestApp.ico"));
-
//Create main window
- CMainWindow *mainWindow = new CMainWindow(tempFolder);
+ CMainWindow *mainWindow = new CMainWindow(tempFolder, ipc);
mainWindow->show();
//Run application
const int exit_code = application->exec();
qDebug("\nTime to say goodbye... (%d)\n", exit_code);
+ //Stop IPC
+ ipc->stopListening();
+
//Clean up
MIXP_DELETE_OBJ(mainWindow);
MIXP_DELETE_OBJ(application);
diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp
index fea8a89..9354472 100644
--- a/src/MainWindow.cpp
+++ b/src/MainWindow.cpp
@@ -39,18 +39,16 @@
//CRT
#include
-//Win32
-//#define WIN32_LEAN_AND_MEAN
-//#include
-
//Internal
#include "Config.h"
#include "Utils.h"
#include "ShellExtension.h"
+#include "IPC.h"
//Macros
#define SET_FONT_BOLD(WIDGET,BOLD) { QFont _font = WIDGET->font(); _font.setBold(BOLD); WIDGET->setFont(_font); }
#define SET_TEXT_COLOR(WIDGET,COLOR) { QPalette _palette = WIDGET->palette(); _palette.setColor(QPalette::WindowText, (COLOR)); _palette.setColor(QPalette::Text, (COLOR)); WIDGET->setPalette(_palette); }
+#define APPLICATION_IS_IDLE (m_status == APP_STATUS_IDLE)
//Text
const char *STATUS_BLNK = ">> You can drop any type of media files here <<";
@@ -71,16 +69,20 @@ static QList> HTML_ESCAPE(void)
return htmlEscape;
}
+//Const
+static const int FILE_RECEIVE_DELAY = 1750;
+
////////////////////////////////////////////////////////////
// Constructor
////////////////////////////////////////////////////////////
-CMainWindow::CMainWindow(const QString &tempFolder, QWidget *parent)
+CMainWindow::CMainWindow(const QString &tempFolder, IPC *const ipc, QWidget *parent)
:
QMainWindow(parent),
m_tempFolder(tempFolder),
- m_firstShow(true),
+ m_ipc(ipc),
m_htmlEscape(HTML_ESCAPE()),
+ m_status(APP_STATUS_STARTING),
ui(new Ui::MainWindow)
{
//Init UI
@@ -107,6 +109,7 @@ CMainWindow::CMainWindow(const QString &tempFolder, QWidget *parent)
connect(ui->actionLink_Discuss, SIGNAL(triggered()), this, SLOT(linkTriggered()));
connect(ui->actionAbout, SIGNAL(triggered()), this, SLOT(showAboutScreen()));
connect(ui->actionShellExtension, SIGNAL(toggled(bool)), this, SLOT(updateShellExtension(bool)));
+ connect(m_ipc, SIGNAL(receivedStr(QString)), this, SLOT(fileReceived(QString)));
ui->versionLabel->installEventFilter(this);
//Context menu
@@ -168,10 +171,7 @@ void CMainWindow::showEvent(QShowEvent *event)
resizeEvent(NULL);
QTimer::singleShot(0, this, SLOT(updateSize()));
- //Enable drag & drop support
- setAcceptDrops(true);
-
- if(m_firstShow)
+ if(m_status == APP_STATUS_STARTING)
{
const QStringList arguments = qApp->arguments();
for(QStringList::ConstIterator iter = arguments.constBegin(); iter != arguments.constEnd(); iter++)
@@ -192,19 +192,28 @@ void CMainWindow::showEvent(QShowEvent *event)
}
if(!m_pendingFiles.empty())
{
- QTimer::singleShot(0, this, SLOT(analyzeFiles()));
+ m_status = APP_STATUS_AWAITING;
+ QTimer::singleShot(FILE_RECEIVE_DELAY, this, SLOT(analyzeFiles()));
}
- QTimer::singleShot(1250, this, SLOT(initShellExtension()));
- m_firstShow = false;
+ QTimer::singleShot(125, m_ipc, SLOT(startListening()));
+ QTimer::singleShot(250, this, SLOT(initShellExtension()));
+
+ if(m_status == APP_STATUS_STARTING)
+ {
+ m_status = APP_STATUS_IDLE;
+ }
}
+
+ //Enable drag & drop support
+ setAcceptDrops(true);
}
void CMainWindow::closeEvent(QCloseEvent *event)
{
if(m_process)
{
- if(m_process->state() != QProcess::NotRunning)
+ if(!APPLICATION_IS_IDLE)
{
event->ignore();
}
@@ -238,9 +247,9 @@ void CMainWindow::dragEnterEvent(QDragEnterEvent *event)
void CMainWindow::dropEvent(QDropEvent *event)
{
- if(m_process && (m_process->state() != QProcess::NotRunning))
+ if(!APPLICATION_IS_IDLE)
{
- qWarning("Process is still running!\n");
+ qWarning("Cannot process files at this time!\n");
return;
}
@@ -259,6 +268,7 @@ void CMainWindow::dropEvent(QDropEvent *event)
if(!m_pendingFiles.isEmpty())
{
+ m_status = APP_STATUS_WORKING;
QTimer::singleShot(0, this, SLOT(analyzeFiles()));
}
}
@@ -318,6 +328,8 @@ void CMainWindow::analyzeFiles(void)
return;
}
+ m_status = APP_STATUS_WORKING;
+
//Clear data
ui->textBrowser->clear();
m_outputLines.clear();
@@ -335,10 +347,7 @@ void CMainWindow::analyzeFiles(void)
m_floatingLabel->show();
m_floatingLabel->setText(QString::fromLatin1(STATUS_WORK));
m_floatingLabel->setCursor(Qt::WaitCursor);
-
- //Trigger GUI update
- QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
-
+
//Give it a go!
QTimer::singleShot(0, this, SLOT(analyzeNextFile()));
}
@@ -351,6 +360,13 @@ void CMainWindow::analyzeNextFile(void)
return;
}
+ //Still running?
+ if(m_process->state() != QProcess::NotRunning)
+ {
+ qWarning("Process is still running!\n");
+ return;
+ }
+
//Lookup MediaInfo path
const QString mediaInfoPath = getMediaInfoPath();
if(mediaInfoPath.isEmpty())
@@ -362,6 +378,7 @@ void CMainWindow::analyzeNextFile(void)
ui->analyzeButton->setEnabled(true);
ui->exitButton->setEnabled(true);
ui->menuPreferences->setEnabled(true);
+ m_status = APP_STATUS_IDLE;
return;
}
@@ -387,6 +404,7 @@ void CMainWindow::analyzeNextFile(void)
ui->analyzeButton->setEnabled(true);
ui->exitButton->setEnabled(true);
ui->menuPreferences->setEnabled(true);
+ m_status = APP_STATUS_IDLE;
return;
}
@@ -395,9 +413,9 @@ void CMainWindow::analyzeNextFile(void)
void CMainWindow::analyzeButtonClicked(void)
{
- if(m_process && (m_process->state() != QProcess::NotRunning))
+ if(!APPLICATION_IS_IDLE)
{
- qWarning("Process is still running!\n");
+ qWarning("Cannot process files at this time!\n");
return;
}
@@ -406,18 +424,19 @@ void CMainWindow::analyzeButtonClicked(void)
{
m_pendingFiles.clear();
m_pendingFiles << selectedFiles;
+ m_status = APP_STATUS_WORKING;
analyzeFiles();
}
}
void CMainWindow::saveButtonClicked(void)
{
- if(m_process && (m_process->state() != QProcess::NotRunning))
+ if(!APPLICATION_IS_IDLE)
{
- qWarning("Process is still running!\n");
+ qWarning("Cannot process files at this time!\n");
return;
}
-
+
const QString selectedFile = QFileDialog::getSaveFileName(this, tr("Select file to save..."), QString(), tr("Plain Text (*.txt)"));
if(!selectedFile.isEmpty())
{
@@ -437,9 +456,9 @@ void CMainWindow::saveButtonClicked(void)
void CMainWindow::copyToClipboardButtonClicked(void)
{
- if(m_process && (m_process->state() != QProcess::NotRunning))
+ if(!APPLICATION_IS_IDLE)
{
- qWarning("Process is still running!\n");
+ qWarning("Cannot process files at this time!\n");
return;
}
@@ -452,9 +471,9 @@ void CMainWindow::copyToClipboardButtonClicked(void)
void CMainWindow::clearButtonClicked(void)
{
- if(m_process && (m_process->state() != QProcess::NotRunning))
+ if(!APPLICATION_IS_IDLE)
{
- qWarning("Process is still running!\n");
+ qWarning("Cannot process files at this time!\n");
return;
}
@@ -551,6 +570,8 @@ void CMainWindow::processFinished(void)
ui->analyzeButton->setEnabled(true);
ui->exitButton->setEnabled(true);
ui->menuPreferences->setEnabled(true);
+
+ m_status = APP_STATUS_IDLE;
}
void CMainWindow::initShellExtension(void)
@@ -584,9 +605,9 @@ void CMainWindow::linkTriggered(void)
void CMainWindow::showAboutScreen(void)
{
- if(m_process && (m_process->state() != QProcess::NotRunning))
+ if(!APPLICATION_IS_IDLE)
{
- qWarning("Process is still running!\n");
+ qWarning("Cannot process files at this time!\n");
return;
}
@@ -645,6 +666,38 @@ void CMainWindow::updateSize(void)
}
}
+void CMainWindow::fileReceived(const QString &str)
+{
+ mixp_bring_to_front(this);
+
+ if(str.compare("?") != 0)
+ {
+ qDebug("Received file: %s", str.toUtf8().constData());
+
+ if((m_status != APP_STATUS_IDLE) && (m_status != APP_STATUS_AWAITING))
+ {
+ qWarning("Cannot process files at this time!\n");
+ return;
+ }
+
+ const QString absPath = QFileInfo(QDir::fromNativeSeparators(str)).absoluteFilePath();
+ QFileInfo fileInfo(absPath);
+ if(fileInfo.exists() && fileInfo.isFile())
+ {
+ m_pendingFiles << fileInfo.canonicalFilePath();
+ if(m_status == APP_STATUS_IDLE)
+ {
+ m_status = APP_STATUS_AWAITING;
+ QTimer::singleShot(FILE_RECEIVE_DELAY, this, SLOT(analyzeFiles()));
+ }
+ }
+ }
+ else
+ {
+ qDebug("Received ping from another instance!");
+ }
+}
+
////////////////////////////////////////////////////////////
// PRIVATE FUNCTIONS
////////////////////////////////////////////////////////////
diff --git a/src/MainWindow.h b/src/MainWindow.h
index f3e9035..447e285 100644
--- a/src/MainWindow.h
+++ b/src/MainWindow.h
@@ -32,6 +32,7 @@ class QProcess;
class QLabel;
class QFile;
class mixp_icon_t;
+class IPC;
//MainWindow class
class CMainWindow: public QMainWindow
@@ -39,7 +40,7 @@ class CMainWindow: public QMainWindow
Q_OBJECT
public:
- CMainWindow(const QString &tempFolder, QWidget *parent = 0);
+ CMainWindow(const QString &tempFolder, IPC *const ipc, QWidget *parent = 0);
~CMainWindow(void);
private slots:
@@ -56,6 +57,7 @@ private slots:
void updateSize(void);
void initShellExtension(void);
void updateShellExtension(bool checked);
+ void fileReceived(const QString &path);
protected:
virtual void showEvent(QShowEvent *event);
@@ -67,16 +69,27 @@ protected:
virtual void keyPressEvent(QKeyEvent *e);
private:
+ enum
+ {
+ APP_STATUS_STARTING = 0,
+ APP_STATUS_IDLE = 1,
+ APP_STATUS_AWAITING = 2,
+ APP_STATUS_WORKING = 3
+ }
+ status_t;
+
Ui::MainWindow *ui; //for Qt UIC
+ int m_status;
const QString &m_tempFolder;
- bool m_firstShow;
+
QFile *m_mediaInfoHandle;
QProcess *m_process;
QLabel *m_floatingLabel;
QStringList m_pendingFiles;
QStringList m_outputLines;
mixp_icon_t *m_icon;
+ IPC *const m_ipc;
const QList> m_htmlEscape;
diff --git a/src/Utils.cpp b/src/Utils.cpp
index b3ce35e..ad7f5d9 100644
--- a/src/Utils.cpp
+++ b/src/Utils.cpp
@@ -478,6 +478,26 @@ bool mixp_beep(int beepType)
}
}
+/*
+ * Bring the specifed window to the front
+ */
+bool mixp_bring_to_front(const QWidget *window)
+{
+ bool ret = false;
+
+ if(window)
+ {
+ for(int i = 0; (i < 5) && (!ret); i++)
+ {
+ ret = (SetForegroundWindow(window->winId()) != FALSE);
+ SwitchToThisWindow(window->winId(), TRUE);
+ }
+ LockSetForegroundWindow(LSFW_LOCK);
+ }
+
+ return ret;
+}
+
/*
* Registry root key
*/
diff --git a/src/Utils.h b/src/Utils.h
index 3c14eaa..dd03679 100644
--- a/src/Utils.h
+++ b/src/Utils.h
@@ -60,6 +60,7 @@ QDate mixp_get_current_date(void);
mixp_icon_t *mixp_set_window_icon(QWidget *window, const QIcon &icon, const bool bIsBigIcon);
void mixp_free_window_icon(mixp_icon_t *icon);
bool mixp_beep(int beepType);
+bool mixp_bring_to_front(const QWidget *window);
void mixp_shell_change_notification(void);
//Regsitry