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"
>
</File>
<File
RelativePath=".\src\Genres.cpp"
>
</File>
<File
RelativePath=".\src\Global.cpp"
>
@ -239,6 +243,10 @@
RelativePath=".\src\Thread_Initialization.cpp"
>
</File>
<File
RelativePath=".\src\Thread_MessageHandler.cpp"
>
</File>
</Filter>
<Filter
Name="Header Files"
@ -461,6 +469,30 @@
/>
</FileConfiguration>
</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
Name="Generated Files"
@ -499,6 +531,10 @@
RelativePath=".\tmp\MOC_Thread_Initialization.cpp"
>
</File>
<File
RelativePath=".\tmp\MOC_Thread_MessageHandler.cpp"
>
</File>
<File
RelativePath=".\tmp\RCC_Icons.cpp"
>

View File

@ -27,6 +27,7 @@
#include "Dialog_WorkingBanner.h"
#include "Dialog_MetaInfo.h"
#include "Thread_FileAnalyzer.h"
#include "Thread_MessageHandler.h"
//Qt includes
#include <QMessageBox>
@ -140,6 +141,10 @@ MainWindow::MainWindow(QWidget *parent)
//Create banner
m_banner = new WorkingBanner(this);
//Create message handler thread
m_messageHandler = new MessageHandlerThread();
m_messageHandler->start();
}
////////////////////////////////////////////////////////////
@ -161,10 +166,59 @@ MainWindow::~MainWindow(void)
/*NONE*/
////////////////////////////////////////////////////////////
// EVENTS
////////////////////////////////////////////////////////////
void MainWindow::showEvent(QShowEvent *event)
{
QTimer::singleShot(0, this, SLOT(windowShown()));
}
////////////////////////////////////////////////////////////
// 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
*/

View File

@ -28,6 +28,7 @@
//Class declarations
class QFileSystemModel;
class WorkingBanner;
class MessageHandlerThread;
class MainWindow: public QMainWindow, private Ui::MainWindow
{
@ -38,6 +39,7 @@ public:
~MainWindow(void);
private slots:
void windowShown(void);
void aboutButtonClicked(void);
void encodeButtonClicked(void);
void addFilesButtonClicked(void);
@ -58,10 +60,14 @@ private slots:
void visitHomepageActionActivated(void);
void openFolderActionActivated(void);
protected:
void showEvent(QShowEvent *event);
private:
FileListModel *m_fileListModel;
QFileSystemModel *m_fileSystemModel;
QActionGroup *m_tabActionGroup;
QActionGroup *m_styleActionGroup;
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
///////////////////////////////////////////////////////////////////////////////
const static 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
};
extern const char *g_lamexp_generes[];

View File

@ -34,6 +34,7 @@
#include <QSharedMemory>
#include <QSysInfo>
#include <QStringList>
#include <QSystemSemaphore>
//LameXP includes
#include "Resource.h"
@ -49,6 +50,18 @@
#include <Psapi.h>
#endif //_DEBUG
///////////////////////////////////////////////////////////////////////////////
// TYPES
///////////////////////////////////////////////////////////////////////////////
typedef struct
{
unsigned int command;
unsigned int reserved_1;
unsigned int reserved_2;
char parameter[4096];
} lamexp_ipc_t;
///////////////////////////////////////////////////////////////////////////////
// GLOBAL VARS
///////////////////////////////////////////////////////////////////////////////
@ -73,6 +86,10 @@ static QMap<QString, LockedFile*> g_lamexp_tool_registry;
//Shared memory
static const char *g_lamexp_sharedmem_uuid = "{21A68A42-6923-43bb-9CF6-64BF151942EE}";
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
@ -245,33 +262,118 @@ bool lamexp_init_qt(int argc, char* argv[])
*/
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;
}
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)
{
LAMEXP_DELETE(sharedMemory);
qWarning("Another instance of LameXP is already running on this computer!");
QMessageBox::warning(NULL, "LameXP", "LameXP is already running. Please use the running instance!");
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)
{
g_lamexp_sharedmem_ptr->attach();
if(g_lamexp_sharedmem_ptr->error() == QSharedMemory::NoError)
{
lamexp_ipc_send(42, "Wurst schmeckt uns!");
}
else
{
QString errorMessage = sharedMemory->errorString();
LAMEXP_DELETE(sharedMemory);
qWarning("Failed to attach to the existing shared memory!");
}
qWarning("Another instance of LameXP is already running on this computer!");
QMessageBox::warning(NULL, "LameXP", "LameXP is already running. Please use the running instance!");
}
else
{
QString errorMessage = g_lamexp_sharedmem_ptr->errorString();
qFatal("Failed to create shared memory: %s", errorMessage.toUtf8().constData());
}
LAMEXP_DELETE(g_lamexp_semaphore_read_ptr);
LAMEXP_DELETE(g_lamexp_semaphore_write_ptr);
LAMEXP_DELETE(g_lamexp_sharedmem_ptr);
return false;
}
memset(g_lamexp_sharedmem_ptr->data(), 0, sizeof(lamexp_ipc_t));
g_lamexp_semaphore_write_ptr->release();
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.";
}
g_lamexp_sharedmem_ptr = sharedMemory;
return true;
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);
}
/*
@ -361,6 +463,8 @@ void lamexp_finalization(void)
//Detach from shared memory
if(g_lamexp_sharedmem_ptr) g_lamexp_sharedmem_ptr->detach();
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);
void lamexp_finalization(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
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();
};