From 8e013b6affded4df479cd5b494c9605c9139e4e6 Mon Sep 17 00:00:00 2001 From: lordmulder Date: Mon, 8 Nov 2010 19:29:36 +0100 Subject: [PATCH] Implemented IPC based on shared memory and semaphores --- LameXP.vcproj | 36 +++++++ src/Dialog_MainWindow.cpp | 54 +++++++++++ src/Dialog_MainWindow.h | 6 ++ src/Genres.cpp | 175 ++++++++++++++++++++++++++++++++++ src/Genres.h | 153 +---------------------------- src/Global.cpp | 126 +++++++++++++++++++++--- src/Global.h | 2 + src/Thread_MessageHandler.cpp | 56 +++++++++++ src/Thread_MessageHandler.h | 33 +++++++ 9 files changed, 478 insertions(+), 163 deletions(-) create mode 100644 src/Genres.cpp create mode 100644 src/Thread_MessageHandler.cpp create mode 100644 src/Thread_MessageHandler.h diff --git a/LameXP.vcproj b/LameXP.vcproj index 2fab5ce8..7763dca8 100644 --- a/LameXP.vcproj +++ b/LameXP.vcproj @@ -207,6 +207,10 @@ RelativePath=".\src\Dialog_WorkingBanner.cpp" > + + @@ -239,6 +243,10 @@ RelativePath=".\src\Thread_Initialization.cpp" > + + + + + + + + + + + + diff --git a/src/Dialog_MainWindow.cpp b/src/Dialog_MainWindow.cpp index 93f1ea83..6330231a 100644 --- a/src/Dialog_MainWindow.cpp +++ b/src/Dialog_MainWindow.cpp @@ -27,6 +27,7 @@ #include "Dialog_WorkingBanner.h" #include "Dialog_MetaInfo.h" #include "Thread_FileAnalyzer.h" +#include "Thread_MessageHandler.h" //Qt includes #include @@ -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 */ diff --git a/src/Dialog_MainWindow.h b/src/Dialog_MainWindow.h index 38fee2dd..aaec4e40 100644 --- a/src/Dialog_MainWindow.h +++ b/src/Dialog_MainWindow.h @@ -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; }; diff --git a/src/Genres.cpp b/src/Genres.cpp new file mode 100644 index 00000000..b94597cf --- /dev/null +++ b/src/Genres.cpp @@ -0,0 +1,175 @@ +/////////////////////////////////////////////////////////////////////////////// +// LameXP - Audio Encoder Front-End +// Copyright (C) 2004-2010 LoRd_MuldeR +// +// 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 + +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 +}; diff --git a/src/Genres.h b/src/Genres.h index 6de306c0..97c073bc 100644 --- a/src/Genres.h +++ b/src/Genres.h @@ -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[]; diff --git a/src/Global.cpp b/src/Global.cpp index a5dd8667..6e90f692 100644 --- a/src/Global.cpp +++ b/src/Global.cpp @@ -34,6 +34,7 @@ #include #include #include +#include //LameXP includes #include "Resource.h" @@ -49,6 +50,18 @@ #include #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 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,35 +262,120 @@ 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); - - if(!sharedMemory->create(1048576)) + 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(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!"); QMessageBox::warning(NULL, "LameXP", "LameXP is already running. Please use the running instance!"); - return false; } else { - QString errorMessage = sharedMemory->errorString(); - LAMEXP_DELETE(sharedMemory); + QString errorMessage = g_lamexp_sharedmem_ptr->errorString(); 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; } +/* + * 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 */ @@ -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); } /* diff --git a/src/Global.h b/src/Global.h index 6c2e1957..6933ebc3 100644 --- a/src/Global.h +++ b/src/Global.h @@ -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); diff --git a/src/Thread_MessageHandler.cpp b/src/Thread_MessageHandler.cpp new file mode 100644 index 00000000..21074fa6 --- /dev/null +++ b/src/Thread_MessageHandler.cpp @@ -0,0 +1,56 @@ +/////////////////////////////////////////////////////////////////////////////// +// LameXP - Audio Encoder Front-End +// Copyright (C) 2004-2010 LoRd_MuldeR +// +// 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 +#include + +//////////////////////////////////////////////////////////// +// 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*/ \ No newline at end of file diff --git a/src/Thread_MessageHandler.h b/src/Thread_MessageHandler.h new file mode 100644 index 00000000..6ffd07b4 --- /dev/null +++ b/src/Thread_MessageHandler.h @@ -0,0 +1,33 @@ +/////////////////////////////////////////////////////////////////////////////// +// LameXP - Audio Encoder Front-End +// Copyright (C) 2004-2010 LoRd_MuldeR +// +// 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 + +class MessageHandlerThread: public QThread +{ + Q_OBJECT + +public: + MessageHandlerThread(void); + void run(); +};