Added support for handling multiple instances.
This commit is contained in:
parent
9a7ddf16c4
commit
ff3f5516d8
136
src/thread_ipc.cpp
Normal file
136
src/thread_ipc.cpp
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Simple x264 Launcher
|
||||||
|
// Copyright (C) 2004-2012 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
|
||||||
|
// the Free Software Foundation; either version 2 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License along
|
||||||
|
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
//
|
||||||
|
// http://www.gnu.org/licenses/gpl-2.0.txt
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "thread_ipc.h"
|
||||||
|
#include "global.h"
|
||||||
|
|
||||||
|
#include <QSystemSemaphore>
|
||||||
|
#include <QSharedMemory>
|
||||||
|
|
||||||
|
static const char* s_key[3] =
|
||||||
|
{
|
||||||
|
"{53F0CAC8-75BC-449A-91DF-2417B2867087}",
|
||||||
|
"{20BD6A5F-B510-4764-937D-EE6598271801}",
|
||||||
|
"{F09C3D10-EC27-4F4D-BF9C-9957A23B8A70}"
|
||||||
|
};
|
||||||
|
|
||||||
|
IPCThread::IPCThread(void)
|
||||||
|
{
|
||||||
|
m_ipcReady = m_firstInstance = m_abort = false;
|
||||||
|
|
||||||
|
m_semaphore_r = new QSystemSemaphore(QString::fromLatin1(s_key[0]), 0);
|
||||||
|
m_semaphore_w = new QSystemSemaphore(QString::fromLatin1(s_key[1]), 1);
|
||||||
|
m_sharedMem = new QSharedMemory(QString::fromLatin1(s_key[2]));
|
||||||
|
}
|
||||||
|
|
||||||
|
IPCThread::~IPCThread(void)
|
||||||
|
{
|
||||||
|
X264_DELETE(m_semaphore_r);
|
||||||
|
X264_DELETE(m_semaphore_w);
|
||||||
|
X264_DELETE(m_sharedMem);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IPCThread::initialize(bool *firstInstance)
|
||||||
|
{
|
||||||
|
if(!m_ipcReady)
|
||||||
|
{
|
||||||
|
if((m_semaphore_r->error() == 0) && (m_semaphore_w->error() == 0) && (m_sharedMem->error() == 0))
|
||||||
|
{
|
||||||
|
if(m_sharedMem->create(sizeof(DWORD), QSharedMemory::ReadWrite))
|
||||||
|
{
|
||||||
|
m_firstInstance = m_ipcReady = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(m_sharedMem->attach(QSharedMemory::ReadWrite))
|
||||||
|
{
|
||||||
|
m_ipcReady = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(firstInstance)
|
||||||
|
{
|
||||||
|
*firstInstance = m_firstInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_ipcReady;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IPCThread::notifyOtherInstance(void)
|
||||||
|
{
|
||||||
|
if(!m_firstInstance)
|
||||||
|
{
|
||||||
|
m_semaphore_w->acquire();
|
||||||
|
DWORD *pidPtr = reinterpret_cast<DWORD*>(m_sharedMem->data());
|
||||||
|
*pidPtr = GetCurrentProcessId();
|
||||||
|
m_semaphore_r->release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IPCThread::start(Priority priority)
|
||||||
|
{
|
||||||
|
m_abort = false;
|
||||||
|
|
||||||
|
if(!m_ipcReady)
|
||||||
|
{
|
||||||
|
throw "IPC not initialized yet !!!";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!m_firstInstance)
|
||||||
|
{
|
||||||
|
qWarning("This is NOT the first instance!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QThread::start(priority);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IPCThread::setAbort(void)
|
||||||
|
{
|
||||||
|
m_abort = true;
|
||||||
|
if(m_semaphore_r)
|
||||||
|
{
|
||||||
|
m_semaphore_r->release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IPCThread::run(void)
|
||||||
|
{
|
||||||
|
forever
|
||||||
|
{
|
||||||
|
if(!m_semaphore_r->acquire())
|
||||||
|
{
|
||||||
|
qWarning("IPCThread: System error !!!");
|
||||||
|
qWarning("IPCThread: %s\n", m_semaphore_r->errorString().toLatin1().constData());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(m_abort)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
const DWORD procId = *reinterpret_cast<const DWORD*>(m_sharedMem->constData());
|
||||||
|
m_semaphore_w->release();
|
||||||
|
emit instanceCreated(procId);
|
||||||
|
}
|
||||||
|
}
|
59
src/thread_ipc.h
Normal file
59
src/thread_ipc.h
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Simple x264 Launcher
|
||||||
|
// Copyright (C) 2004-2012 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
|
||||||
|
// the Free Software Foundation; either version 2 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License along
|
||||||
|
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
//
|
||||||
|
// http://www.gnu.org/licenses/gpl-2.0.txt
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "global.h"
|
||||||
|
#include <QThread>
|
||||||
|
|
||||||
|
class QSystemSemaphore;
|
||||||
|
class QSharedMemory;
|
||||||
|
|
||||||
|
class IPCThread : public QThread
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
IPCThread(void);
|
||||||
|
~IPCThread(void);
|
||||||
|
|
||||||
|
void setAbort(void);
|
||||||
|
bool initialize(bool *firstInstance = NULL);
|
||||||
|
void notifyOtherInstance(void);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void instanceCreated(DWORD pid);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void start(Priority priority = InheritPriority);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
volatile bool m_abort;
|
||||||
|
|
||||||
|
QSystemSemaphore *m_semaphore_r;
|
||||||
|
QSystemSemaphore *m_semaphore_w;
|
||||||
|
QSharedMemory *m_sharedMem;
|
||||||
|
|
||||||
|
bool m_ipcReady;
|
||||||
|
bool m_firstInstance;
|
||||||
|
|
||||||
|
virtual void run(void);
|
||||||
|
};
|
@ -22,7 +22,7 @@
|
|||||||
#define VER_X264_MAJOR 2
|
#define VER_X264_MAJOR 2
|
||||||
#define VER_X264_MINOR 0
|
#define VER_X264_MINOR 0
|
||||||
#define VER_X264_PATCH 2
|
#define VER_X264_PATCH 2
|
||||||
#define VER_X264_BUILD 222
|
#define VER_X264_BUILD 238
|
||||||
|
|
||||||
#define VER_X264_MINIMUM_REV 2146
|
#define VER_X264_MINIMUM_REV 2146
|
||||||
#define VER_X264_CURRENT_API 120
|
#define VER_X264_CURRENT_API 120
|
||||||
|
@ -72,6 +72,7 @@ MainWindow::MainWindow(const x264_cpu_t *const cpuFeatures)
|
|||||||
|
|
||||||
//Register meta types
|
//Register meta types
|
||||||
qRegisterMetaType<QUuid>("QUuid");
|
qRegisterMetaType<QUuid>("QUuid");
|
||||||
|
qRegisterMetaType<QUuid>("DWORD");
|
||||||
qRegisterMetaType<EncodeThread::JobStatus>("EncodeThread::JobStatus");
|
qRegisterMetaType<EncodeThread::JobStatus>("EncodeThread::JobStatus");
|
||||||
|
|
||||||
//Load preferences
|
//Load preferences
|
||||||
@ -82,6 +83,10 @@ MainWindow::MainWindow(const x264_cpu_t *const cpuFeatures)
|
|||||||
m_options = new OptionsModel();
|
m_options = new OptionsModel();
|
||||||
OptionsModel::loadTemplate(m_options, QString::fromLatin1(tpl_last));
|
OptionsModel::loadTemplate(m_options, QString::fromLatin1(tpl_last));
|
||||||
|
|
||||||
|
//Create IPC thread object
|
||||||
|
m_ipcThread = new IPCThread();
|
||||||
|
connect(m_ipcThread, SIGNAL(instanceCreated(DWORD)), this, SLOT(instanceCreated(DWORD)), Qt::QueuedConnection);
|
||||||
|
|
||||||
//Freeze minimum size
|
//Freeze minimum size
|
||||||
setMinimumSize(size());
|
setMinimumSize(size());
|
||||||
splitter->setSizes(QList<int>() << 16 << 196);
|
splitter->setSizes(QList<int>() << 16 << 196);
|
||||||
@ -177,6 +182,18 @@ MainWindow::~MainWindow(void)
|
|||||||
QFile *temp = m_toolsList.takeFirst();
|
QFile *temp = m_toolsList.takeFirst();
|
||||||
X264_DELETE(temp);
|
X264_DELETE(temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(m_ipcThread->isRunning())
|
||||||
|
{
|
||||||
|
m_ipcThread->setAbort();
|
||||||
|
if(!m_ipcThread->wait(5000))
|
||||||
|
{
|
||||||
|
m_ipcThread->terminate();
|
||||||
|
m_ipcThread->wait();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
X264_DELETE(m_ipcThread);
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@ -617,6 +634,18 @@ void MainWindow::init(void)
|
|||||||
|
|
||||||
updateLabelPos();
|
updateLabelPos();
|
||||||
|
|
||||||
|
//Check for a running instance
|
||||||
|
bool firstInstance = false;
|
||||||
|
if(m_ipcThread->initialize(&firstInstance))
|
||||||
|
{
|
||||||
|
if(!firstInstance)
|
||||||
|
{
|
||||||
|
m_ipcThread->notifyOtherInstance();
|
||||||
|
close(); qApp->exit(-1); return;
|
||||||
|
}
|
||||||
|
m_ipcThread->start();
|
||||||
|
}
|
||||||
|
|
||||||
//Check all binaries
|
//Check all binaries
|
||||||
while(!binaries.isEmpty())
|
while(!binaries.isEmpty())
|
||||||
{
|
{
|
||||||
@ -800,6 +829,24 @@ void MainWindow::handleDroppedFiles(void)
|
|||||||
qDebug("Leave from MainWindow::handleDroppedFiles!");
|
qDebug("Leave from MainWindow::handleDroppedFiles!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::instanceCreated(DWORD pid)
|
||||||
|
{
|
||||||
|
qDebug("Notification from other instance received!");
|
||||||
|
|
||||||
|
FLASHWINFO flashWinInfo;
|
||||||
|
memset(&flashWinInfo, 0, sizeof(FLASHWINFO));
|
||||||
|
flashWinInfo.cbSize = sizeof(FLASHWINFO);
|
||||||
|
flashWinInfo.hwnd = this->winId();
|
||||||
|
flashWinInfo.dwFlags = FLASHW_ALL;
|
||||||
|
flashWinInfo.dwTimeout = 125;
|
||||||
|
flashWinInfo.uCount = 5;
|
||||||
|
|
||||||
|
SwitchToThisWindow(this->winId(), TRUE);
|
||||||
|
SetForegroundWindow(this->winId());
|
||||||
|
qApp->processEvents();
|
||||||
|
FlashWindowEx(&flashWinInfo);
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// Event functions
|
// Event functions
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "uic_win_main.h"
|
#include "uic_win_main.h"
|
||||||
|
#include "thread_ipc.h"
|
||||||
#include "thread_encode.h"
|
#include "thread_encode.h"
|
||||||
#include "win_preferences.h"
|
#include "win_preferences.h"
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
@ -51,6 +52,7 @@ protected:
|
|||||||
private:
|
private:
|
||||||
bool m_firstShow;
|
bool m_firstShow;
|
||||||
QLabel *m_label;
|
QLabel *m_label;
|
||||||
|
IPCThread *m_ipcThread;
|
||||||
|
|
||||||
JobListModel *m_jobList;
|
JobListModel *m_jobList;
|
||||||
OptionsModel *m_options;
|
OptionsModel *m_options;
|
||||||
@ -76,6 +78,7 @@ private slots:
|
|||||||
void copyLogToClipboard(bool checked);
|
void copyLogToClipboard(bool checked);
|
||||||
void handleDroppedFiles(void);
|
void handleDroppedFiles(void);
|
||||||
void init(void);
|
void init(void);
|
||||||
|
void instanceCreated(DWORD pid);
|
||||||
void jobSelected(const QModelIndex & current, const QModelIndex & previous);
|
void jobSelected(const QModelIndex & current, const QModelIndex & previous);
|
||||||
void jobChangedData(const QModelIndex &top, const QModelIndex &bottom);
|
void jobChangedData(const QModelIndex &top, const QModelIndex &bottom);
|
||||||
void jobLogExtended(const QModelIndex & parent, int start, int end);
|
void jobLogExtended(const QModelIndex & parent, int start, int end);
|
||||||
|
@ -248,6 +248,14 @@ copy "$(SolutionDir)res\toolset\*.exe" "$(SolutionDir)bin\$(Configuration)\tools
|
|||||||
<ClInclude Include="src\model_options.h" />
|
<ClInclude Include="src\model_options.h" />
|
||||||
<ClInclude Include="src\targetver.h" />
|
<ClInclude Include="src\targetver.h" />
|
||||||
<ClInclude Include="src\taskbar7.h" />
|
<ClInclude Include="src\taskbar7.h" />
|
||||||
|
<CustomBuild Include="src\thread_ipc.h">
|
||||||
|
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">"$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\moc\moc_%(Filename).cpp" "%(FullPath)"</Command>
|
||||||
|
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">"$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\moc\moc_%(Filename).cpp" "%(FullPath)"</Command>
|
||||||
|
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">MOC "$(SolutionDir)tmp\moc\moc_%(Filename).cpp"</Message>
|
||||||
|
<Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">MOC "$(SolutionDir)tmp\moc\moc_%(Filename).cpp"</Message>
|
||||||
|
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)tmp\moc\moc_%(Filename).cpp;%(Outputs)</Outputs>
|
||||||
|
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)tmp\moc\moc_%(Filename).cpp;%(Outputs)</Outputs>
|
||||||
|
</CustomBuild>
|
||||||
<ClInclude Include="src\version.h" />
|
<ClInclude Include="src\version.h" />
|
||||||
<CustomBuild Include="src\win_main.h">
|
<CustomBuild Include="src\win_main.h">
|
||||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">"$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\moc\moc_%(Filename).cpp" "%(FullPath)"</Command>
|
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">"$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\moc\moc_%(Filename).cpp" "%(FullPath)"</Command>
|
||||||
@ -266,6 +274,7 @@ copy "$(SolutionDir)res\toolset\*.exe" "$(SolutionDir)bin\$(Configuration)\tools
|
|||||||
<ClCompile Include="src\thread_encode.cpp" />
|
<ClCompile Include="src\thread_encode.cpp" />
|
||||||
<ClCompile Include="src\global.cpp" />
|
<ClCompile Include="src\global.cpp" />
|
||||||
<ClCompile Include="src\main.cpp" />
|
<ClCompile Include="src\main.cpp" />
|
||||||
|
<ClCompile Include="src\thread_ipc.cpp" />
|
||||||
<ClCompile Include="src\win_addJob.cpp" />
|
<ClCompile Include="src\win_addJob.cpp" />
|
||||||
<ClCompile Include="src\win_editor.cpp" />
|
<ClCompile Include="src\win_editor.cpp" />
|
||||||
<ClCompile Include="src\win_help.cpp" />
|
<ClCompile Include="src\win_help.cpp" />
|
||||||
@ -274,6 +283,7 @@ copy "$(SolutionDir)res\toolset\*.exe" "$(SolutionDir)bin\$(Configuration)\tools
|
|||||||
<ClCompile Include="tmp\moc\moc_model_jobList.cpp" />
|
<ClCompile Include="tmp\moc\moc_model_jobList.cpp" />
|
||||||
<ClCompile Include="tmp\moc\moc_model_logFile.cpp" />
|
<ClCompile Include="tmp\moc\moc_model_logFile.cpp" />
|
||||||
<ClCompile Include="tmp\moc\moc_thread_encode.cpp" />
|
<ClCompile Include="tmp\moc\moc_thread_encode.cpp" />
|
||||||
|
<ClCompile Include="tmp\moc\moc_thread_ipc.cpp" />
|
||||||
<ClCompile Include="tmp\moc\moc_win_addJob.cpp" />
|
<ClCompile Include="tmp\moc\moc_win_addJob.cpp" />
|
||||||
<ClCompile Include="tmp\moc\moc_win_editor.cpp" />
|
<ClCompile Include="tmp\moc\moc_win_editor.cpp" />
|
||||||
<ClCompile Include="tmp\moc\moc_win_help.cpp" />
|
<ClCompile Include="tmp\moc\moc_win_help.cpp" />
|
||||||
|
@ -113,6 +113,12 @@
|
|||||||
<ClCompile Include="tmp\moc\moc_win_editor.cpp">
|
<ClCompile Include="tmp\moc\moc_win_editor.cpp">
|
||||||
<Filter>Generated Files</Filter>
|
<Filter>Generated Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\thread_ipc.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="tmp\moc\moc_thread_ipc.cpp">
|
||||||
|
<Filter>Generated Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<CustomBuild Include="src\win_main.h">
|
<CustomBuild Include="src\win_main.h">
|
||||||
@ -157,6 +163,9 @@
|
|||||||
<CustomBuild Include="src\win_editor.h">
|
<CustomBuild Include="src\win_editor.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</CustomBuild>
|
</CustomBuild>
|
||||||
|
<CustomBuild Include="src\thread_ipc.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</CustomBuild>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="x264_launcher.rc">
|
<ResourceCompile Include="x264_launcher.rc">
|
||||||
|
Loading…
Reference in New Issue
Block a user