Implemented IPC based on shared memory and semaphores

This commit is contained in:
LoRd_MuldeR 2010-11-08 19:29:36 +01:00
parent 5ac1c127f1
commit 8e013b6aff
9 changed files with 478 additions and 163 deletions

View File

@ -207,6 +207,10 @@
RelativePath=".\src\Dialog_WorkingBanner.cpp" RelativePath=".\src\Dialog_WorkingBanner.cpp"
> >
</File> </File>
<File
RelativePath=".\src\Genres.cpp"
>
</File>
<File <File
RelativePath=".\src\Global.cpp" RelativePath=".\src\Global.cpp"
> >
@ -239,6 +243,10 @@
RelativePath=".\src\Thread_Initialization.cpp" RelativePath=".\src\Thread_Initialization.cpp"
> >
</File> </File>
<File
RelativePath=".\src\Thread_MessageHandler.cpp"
>
</File>
</Filter> </Filter>
<Filter <Filter
Name="Header Files" Name="Header Files"
@ -461,6 +469,30 @@
/> />
</FileConfiguration> </FileConfiguration>
</File> </File>
<File
RelativePath=".\src\Thread_MessageHandler.h"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCustomBuildTool"
Description="MOC &quot;$(SolutionDir)tmp\MOC_$(SafeInputName).cpp&quot;"
CommandLine="&quot;$(QTDIR)\bin\moc.exe&quot; -o &quot;$(SolutionDir)tmp\MOC_$(SafeInputName).cpp&quot; &quot;$(InputPath)&quot;"
Outputs="&quot;$(SolutionDir)tmp\MOC_$(SafeInputName).cpp&quot;"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCustomBuildTool"
Description="MOC &quot;$(SolutionDir)tmp\MOC_$(SafeInputName).cpp&quot;"
CommandLine="&quot;$(QTDIR)\bin\moc.exe&quot; -o &quot;$(SolutionDir)tmp\MOC_$(SafeInputName).cpp&quot; &quot;$(InputPath)&quot;"
Outputs="&quot;$(SolutionDir)tmp\MOC_$(SafeInputName).cpp&quot;"
/>
</FileConfiguration>
</File>
</Filter> </Filter>
<Filter <Filter
Name="Generated Files" Name="Generated Files"
@ -499,6 +531,10 @@
RelativePath=".\tmp\MOC_Thread_Initialization.cpp" RelativePath=".\tmp\MOC_Thread_Initialization.cpp"
> >
</File> </File>
<File
RelativePath=".\tmp\MOC_Thread_MessageHandler.cpp"
>
</File>
<File <File
RelativePath=".\tmp\RCC_Icons.cpp" RelativePath=".\tmp\RCC_Icons.cpp"
> >

View File

@ -27,6 +27,7 @@
#include "Dialog_WorkingBanner.h" #include "Dialog_WorkingBanner.h"
#include "Dialog_MetaInfo.h" #include "Dialog_MetaInfo.h"
#include "Thread_FileAnalyzer.h" #include "Thread_FileAnalyzer.h"
#include "Thread_MessageHandler.h"
//Qt includes //Qt includes
#include <QMessageBox> #include <QMessageBox>
@ -140,6 +141,10 @@ MainWindow::MainWindow(QWidget *parent)
//Create banner //Create banner
m_banner = new WorkingBanner(this); m_banner = new WorkingBanner(this);
//Create message handler thread
m_messageHandler = new MessageHandlerThread();
m_messageHandler->start();
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -161,10 +166,59 @@ MainWindow::~MainWindow(void)
/*NONE*/ /*NONE*/
////////////////////////////////////////////////////////////
// EVENTS
////////////////////////////////////////////////////////////
void MainWindow::showEvent(QShowEvent *event)
{
QTimer::singleShot(0, this, SLOT(windowShown()));
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Slots // Slots
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/*
* Window shown
*/
void MainWindow::windowShown(void)
{
QStringList fileList;
QStringList arguments = QApplication::arguments();
qDebug("Main window is showing");
for(int i = 0; i < arguments.count() - 1; i++)
{
if(!arguments[i].compare("--add", Qt::CaseInsensitive))
{
QFileInfo currentFile(arguments[++i].trimmed());
qDebug("Adding file from CLI: %s", currentFile.absoluteFilePath().toUtf8().constData());
if(currentFile.exists())
{
fileList << currentFile.absoluteFilePath();
}
else
{
qWarning("File doesn't exist: %s", currentFile.absoluteFilePath().toUtf8().constData());
}
}
}
if(fileList.count() > 0)
{
FileAnalyzer *analyzer = new FileAnalyzer(fileList);
connect(analyzer, SIGNAL(fileSelected(QString)), m_banner, SLOT(setText(QString)), Qt::QueuedConnection);
connect(analyzer, SIGNAL(fileAnalyzed(AudioFileModel)), m_fileListModel, SLOT(addFile(AudioFileModel)), Qt::QueuedConnection);
m_banner->show("Adding file(s), please wait...", analyzer);
LAMEXP_DELETE(analyzer);
sourceFileView->scrollToBottom();
m_banner->close();
}
}
/* /*
* About button * About button
*/ */

View File

@ -28,6 +28,7 @@
//Class declarations //Class declarations
class QFileSystemModel; class QFileSystemModel;
class WorkingBanner; class WorkingBanner;
class MessageHandlerThread;
class MainWindow: public QMainWindow, private Ui::MainWindow class MainWindow: public QMainWindow, private Ui::MainWindow
{ {
@ -38,6 +39,7 @@ public:
~MainWindow(void); ~MainWindow(void);
private slots: private slots:
void windowShown(void);
void aboutButtonClicked(void); void aboutButtonClicked(void);
void encodeButtonClicked(void); void encodeButtonClicked(void);
void addFilesButtonClicked(void); void addFilesButtonClicked(void);
@ -58,10 +60,14 @@ private slots:
void visitHomepageActionActivated(void); void visitHomepageActionActivated(void);
void openFolderActionActivated(void); void openFolderActionActivated(void);
protected:
void showEvent(QShowEvent *event);
private: private:
FileListModel *m_fileListModel; FileListModel *m_fileListModel;
QFileSystemModel *m_fileSystemModel; QFileSystemModel *m_fileSystemModel;
QActionGroup *m_tabActionGroup; QActionGroup *m_tabActionGroup;
QActionGroup *m_styleActionGroup; QActionGroup *m_styleActionGroup;
WorkingBanner *m_banner; WorkingBanner *m_banner;
MessageHandlerThread *m_messageHandler;
}; };

175
src/Genres.cpp Normal file
View File

@ -0,0 +1,175 @@
///////////////////////////////////////////////////////////////////////////////
// LameXP - Audio Encoder Front-End
// Copyright (C) 2004-2010 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 <stdlib.h>
extern const char *g_lamexp_generes[] =
{
"Blues",
"Classic Rock",
"Country",
"Dance",
"Disco",
"Funk",
"Grunge",
"Hip-Hop",
"Jazz",
"Metal",
"New Age",
"Oldies",
"Other",
"Pop",
"R&B",
"Rap",
"Reggae",
"Rock",
"Techno",
"Industrial",
"Alternative",
"Ska",
"Death Metal",
"Pranks",
"Soundtrack",
"Euro-Techno",
"Ambient",
"Trip-Hop",
"Vocal",
"Jazz+Funk",
"Fusion",
"Trance",
"Classical",
"Instrumental",
"Acid",
"House",
"Game",
"Sound Clip",
"Gospel",
"Noise",
"Alternative Rock",
"Bass",
"Soul",
"Punk",
"Space",
"Meditative",
"Instrumental Pop",
"Instrumental Rock",
"Ethnic",
"Gothic",
"Darkwave",
"Techno-Industrial",
"Electronic",
"Pop-Folk",
"Eurodance",
"Dream",
"Southern Rock",
"Comedy",
"Cult",
"Gangsta",
"Top 40",
"Christian Rap",
"Pop/Funk",
"Jungle",
"Native US",
"Cabaret",
"New Wave",
"Psychadelic",
"Rave",
"Showtunes",
"Trailer",
"Lo-Fi",
"Tribal",
"Acid Punk",
"Acid Jazz",
"Polka",
"Retro",
"Musical",
"Rock & Roll",
"Hard Rock",
"Folk",
"Folk-Rock",
"National Folk",
"Swing",
"Fast Fusion",
"Bebob",
"Latin",
"Revival",
"Celtic",
"Bluegrass",
"Avantgarde",
"Gothic Rock",
"Progressive Rock",
"Psychedelic Rock",
"Symphonic Rock",
"Slow Rock",
"Big Band",
"Chorus",
"Easy Listening",
"Acoustic",
"Humour",
"Speech",
"Chanson",
"Opera",
"Chamber Music",
"Sonata",
"Symphony",
"Booty Bass",
"Primus",
"Porn Groove",
"Satire",
"Slow Jam",
"Club",
"Tango",
"Samba",
"Folklore",
"Ballad",
"Power Ballad",
"Rhytmic Soul",
"Freestyle",
"Duet",
"Punk Rock",
"Drum Solo",
"Acapella",
"Euro-House",
"Dance Hall",
"Goa",
"Drum & Bass",
"Club-House",
"Hardcore",
"Terror",
"Indie",
"BritPop",
"Negerpunk",
"Polsk Punk",
"Beat",
"Christian Gangsta",
"Heavy Metal",
"Black Metal",
"Crossover",
"Contemporary C",
"Christian Rock",
"Merengue",
"Salsa",
"Thrash Metal",
"Anime",
"JPop",
"SynthPop",
NULL
};

View File

@ -19,155 +19,4 @@
// http://www.gnu.org/licenses/gpl-2.0.txt // http://www.gnu.org/licenses/gpl-2.0.txt
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
const static char *g_lamexp_generes[] = extern const char *g_lamexp_generes[];
{
"Blues",
"Classic Rock",
"Country",
"Dance",
"Disco",
"Funk",
"Grunge",
"Hip-Hop",
"Jazz",
"Metal",
"New Age",
"Oldies",
"Other",
"Pop",
"R&B",
"Rap",
"Reggae",
"Rock",
"Techno",
"Industrial",
"Alternative",
"Ska",
"Death Metal",
"Pranks",
"Soundtrack",
"Euro-Techno",
"Ambient",
"Trip-Hop",
"Vocal",
"Jazz+Funk",
"Fusion",
"Trance",
"Classical",
"Instrumental",
"Acid",
"House",
"Game",
"Sound Clip",
"Gospel",
"Noise",
"Alternative Rock",
"Bass",
"Soul",
"Punk",
"Space",
"Meditative",
"Instrumental Pop",
"Instrumental Rock",
"Ethnic",
"Gothic",
"Darkwave",
"Techno-Industrial",
"Electronic",
"Pop-Folk",
"Eurodance",
"Dream",
"Southern Rock",
"Comedy",
"Cult",
"Gangsta",
"Top 40",
"Christian Rap",
"Pop/Funk",
"Jungle",
"Native US",
"Cabaret",
"New Wave",
"Psychadelic",
"Rave",
"Showtunes",
"Trailer",
"Lo-Fi",
"Tribal",
"Acid Punk",
"Acid Jazz",
"Polka",
"Retro",
"Musical",
"Rock & Roll",
"Hard Rock",
"Folk",
"Folk-Rock",
"National Folk",
"Swing",
"Fast Fusion",
"Bebob",
"Latin",
"Revival",
"Celtic",
"Bluegrass",
"Avantgarde",
"Gothic Rock",
"Progressive Rock",
"Psychedelic Rock",
"Symphonic Rock",
"Slow Rock",
"Big Band",
"Chorus",
"Easy Listening",
"Acoustic",
"Humour",
"Speech",
"Chanson",
"Opera",
"Chamber Music",
"Sonata",
"Symphony",
"Booty Bass",
"Primus",
"Porn Groove",
"Satire",
"Slow Jam",
"Club",
"Tango",
"Samba",
"Folklore",
"Ballad",
"Power Ballad",
"Rhytmic Soul",
"Freestyle",
"Duet",
"Punk Rock",
"Drum Solo",
"Acapella",
"Euro-House",
"Dance Hall",
"Goa",
"Drum & Bass",
"Club-House",
"Hardcore",
"Terror",
"Indie",
"BritPop",
"Negerpunk",
"Polsk Punk",
"Beat",
"Christian Gangsta",
"Heavy Metal",
"Black Metal",
"Crossover",
"Contemporary C",
"Christian Rock",
"Merengue",
"Salsa",
"Thrash Metal",
"Anime",
"JPop",
"SynthPop",
NULL
};

View File

@ -34,6 +34,7 @@
#include <QSharedMemory> #include <QSharedMemory>
#include <QSysInfo> #include <QSysInfo>
#include <QStringList> #include <QStringList>
#include <QSystemSemaphore>
//LameXP includes //LameXP includes
#include "Resource.h" #include "Resource.h"
@ -49,6 +50,18 @@
#include <Psapi.h> #include <Psapi.h>
#endif //_DEBUG #endif //_DEBUG
///////////////////////////////////////////////////////////////////////////////
// TYPES
///////////////////////////////////////////////////////////////////////////////
typedef struct
{
unsigned int command;
unsigned int reserved_1;
unsigned int reserved_2;
char parameter[4096];
} lamexp_ipc_t;
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// GLOBAL VARS // GLOBAL VARS
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@ -73,6 +86,10 @@ static QMap<QString, LockedFile*> g_lamexp_tool_registry;
//Shared memory //Shared memory
static const char *g_lamexp_sharedmem_uuid = "{21A68A42-6923-43bb-9CF6-64BF151942EE}"; static const char *g_lamexp_sharedmem_uuid = "{21A68A42-6923-43bb-9CF6-64BF151942EE}";
static QSharedMemory *g_lamexp_sharedmem_ptr = NULL; static QSharedMemory *g_lamexp_sharedmem_ptr = NULL;
static const char *g_lamexp_semaphore_read_uuid = "{7A605549-F58C-4d78-B4E5-06EFC34F405B}";
static QSystemSemaphore *g_lamexp_semaphore_read_ptr = NULL;
static const char *g_lamexp_semaphore_write_uuid = "{60AA8D04-F6B8-497d-81EB-0F600F4A65B5}";
static QSystemSemaphore *g_lamexp_semaphore_write_ptr = NULL;
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// GLOBAL FUNCTIONS // GLOBAL FUNCTIONS
@ -245,35 +262,120 @@ bool lamexp_init_qt(int argc, char* argv[])
*/ */
bool lamexp_check_instances(void) bool lamexp_check_instances(void)
{ {
if(g_lamexp_sharedmem_ptr) if(g_lamexp_sharedmem_ptr && g_lamexp_semaphore_read_ptr && g_lamexp_semaphore_write_ptr)
{ {
return true; return true;
} }
QSharedMemory *sharedMemory = new QSharedMemory(g_lamexp_sharedmem_uuid, NULL); g_lamexp_semaphore_read_ptr = new QSystemSemaphore(g_lamexp_semaphore_read_uuid, 0);
g_lamexp_semaphore_write_ptr = new QSystemSemaphore(g_lamexp_semaphore_write_uuid, 0);
if(!sharedMemory->create(1048576))
if(g_lamexp_semaphore_read_ptr->error() != QSystemSemaphore::NoError)
{ {
if(sharedMemory->error() == QSharedMemory::AlreadyExists) QString errorMessage = g_lamexp_semaphore_read_ptr->errorString();
LAMEXP_DELETE(g_lamexp_semaphore_read_ptr);
LAMEXP_DELETE(g_lamexp_semaphore_write_ptr);
qFatal("Failed to create system smaphore: %s", errorMessage.toUtf8().constData());
return false;
}
if(g_lamexp_semaphore_write_ptr->error() != QSystemSemaphore::NoError)
{
QString errorMessage = g_lamexp_semaphore_write_ptr->errorString();
LAMEXP_DELETE(g_lamexp_semaphore_read_ptr);
LAMEXP_DELETE(g_lamexp_semaphore_write_ptr);
qFatal("Failed to create system smaphore: %s", errorMessage.toUtf8().constData());
return false;
}
g_lamexp_sharedmem_ptr = new QSharedMemory(g_lamexp_sharedmem_uuid, NULL);
if(!g_lamexp_sharedmem_ptr->create(sizeof(lamexp_ipc_t)))
{
if(g_lamexp_sharedmem_ptr->error() == QSharedMemory::AlreadyExists)
{ {
LAMEXP_DELETE(sharedMemory); g_lamexp_sharedmem_ptr->attach();
if(g_lamexp_sharedmem_ptr->error() == QSharedMemory::NoError)
{
lamexp_ipc_send(42, "Wurst schmeckt uns!");
}
else
{
qWarning("Failed to attach to the existing shared memory!");
}
qWarning("Another instance of LameXP is already running on this computer!"); qWarning("Another instance of LameXP is already running on this computer!");
QMessageBox::warning(NULL, "LameXP", "LameXP is already running. Please use the running instance!"); QMessageBox::warning(NULL, "LameXP", "LameXP is already running. Please use the running instance!");
return false;
} }
else else
{ {
QString errorMessage = sharedMemory->errorString(); QString errorMessage = g_lamexp_sharedmem_ptr->errorString();
LAMEXP_DELETE(sharedMemory);
qFatal("Failed to create shared memory: %s", errorMessage.toUtf8().constData()); qFatal("Failed to create shared memory: %s", errorMessage.toUtf8().constData());
return false;
} }
LAMEXP_DELETE(g_lamexp_semaphore_read_ptr);
LAMEXP_DELETE(g_lamexp_semaphore_write_ptr);
LAMEXP_DELETE(g_lamexp_sharedmem_ptr);
return false;
} }
g_lamexp_sharedmem_ptr = sharedMemory; memset(g_lamexp_sharedmem_ptr->data(), 0, sizeof(lamexp_ipc_t));
g_lamexp_semaphore_write_ptr->release();
return true; return true;
} }
/*
* IPC send message
*/
void lamexp_ipc_send(unsigned int command, const char* message)
{
if(!g_lamexp_sharedmem_ptr || !g_lamexp_semaphore_read_ptr || !g_lamexp_semaphore_write_ptr)
{
throw "Shared memory for IPC not initialized yet.";
}
lamexp_ipc_t *lamexp_ipc = new lamexp_ipc_t;
memset(lamexp_ipc, 0, sizeof(lamexp_ipc_t));
lamexp_ipc->command = command;
strcpy_s(lamexp_ipc->parameter, 4096, message);
g_lamexp_semaphore_write_ptr->acquire();
memcpy(g_lamexp_sharedmem_ptr->data(), lamexp_ipc, sizeof(lamexp_ipc_t));
g_lamexp_semaphore_read_ptr->release();
LAMEXP_DELETE(lamexp_ipc);
}
/*
* IPC read message
*/
void lamexp_ipc_read(unsigned int *command, char* message, size_t buffSize)
{
*command = 0;
message[0] = '\0';
if(!g_lamexp_sharedmem_ptr || !g_lamexp_semaphore_read_ptr || !g_lamexp_semaphore_write_ptr)
{
throw "Shared memory for IPC not initialized yet.";
}
lamexp_ipc_t *lamexp_ipc = new lamexp_ipc_t;
memset(lamexp_ipc, 0, sizeof(lamexp_ipc_t));
g_lamexp_semaphore_read_ptr->acquire();
memcpy(lamexp_ipc, g_lamexp_sharedmem_ptr->data(), sizeof(lamexp_ipc_t));
g_lamexp_semaphore_write_ptr->release();
if(!(lamexp_ipc->reserved_1 || lamexp_ipc->reserved_2))
{
*command = lamexp_ipc->command;
strcpy_s(message, buffSize, lamexp_ipc->parameter);
}
else
{
qWarning("Malformed IPC message, will be ignored");
}
LAMEXP_DELETE(lamexp_ipc);
}
/* /*
* Get LameXP temp folder * Get LameXP temp folder
*/ */
@ -361,6 +463,8 @@ void lamexp_finalization(void)
//Detach from shared memory //Detach from shared memory
if(g_lamexp_sharedmem_ptr) g_lamexp_sharedmem_ptr->detach(); if(g_lamexp_sharedmem_ptr) g_lamexp_sharedmem_ptr->detach();
LAMEXP_DELETE(g_lamexp_sharedmem_ptr); LAMEXP_DELETE(g_lamexp_sharedmem_ptr);
LAMEXP_DELETE(g_lamexp_semaphore_read_ptr);
LAMEXP_DELETE(g_lamexp_semaphore_write_ptr);
} }
/* /*

View File

@ -52,6 +52,8 @@ void lamexp_register_tool(const QString &toolName, LockedFile *file);
const QString lamexp_lookup_tool(const QString &toolName); const QString lamexp_lookup_tool(const QString &toolName);
void lamexp_finalization(void); void lamexp_finalization(void);
const QString &lamexp_temp_folder(void); const QString &lamexp_temp_folder(void);
void lamexp_ipc_read(unsigned int *command, char* message, size_t buffSize);
void lamexp_ipc_send(unsigned int command, const char* message);
//Auxiliary functions //Auxiliary functions
bool lamexp_clean_folder(const QString folderPath); bool lamexp_clean_folder(const QString folderPath);

View File

@ -0,0 +1,56 @@
///////////////////////////////////////////////////////////////////////////////
// LameXP - Audio Encoder Front-End
// Copyright (C) 2004-2010 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_MessageHandler.h"
#include "Global.h"
#include <QSharedMemory>
#include <QSystemSemaphore>
////////////////////////////////////////////////////////////
// Constructor
////////////////////////////////////////////////////////////
MessageHandlerThread::MessageHandlerThread(void)
{
}
void MessageHandlerThread::run()
{
unsigned int command = 0;
char *parameter = new char[4096];
while(true)
{
qDebug("MessageHandlerThread: Waiting...");
lamexp_ipc_read(&command, parameter, 4096);
qDebug("MessageHandlerThread: command=%u, parameter='%s'", command, parameter);
}
delete [] parameter;
}
////////////////////////////////////////////////////////////
// EVENTS
////////////////////////////////////////////////////////////
/*NONE*/

View File

@ -0,0 +1,33 @@
///////////////////////////////////////////////////////////////////////////////
// LameXP - Audio Encoder Front-End
// Copyright (C) 2004-2010 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 <QThread>
class MessageHandlerThread: public QThread
{
Q_OBJECT
public:
MessageHandlerThread(void);
void run();
};