diff --git a/gui/MainWindow.ui b/gui/MainWindow.ui index bfdc0520..3569924d 100644 --- a/gui/MainWindow.ui +++ b/gui/MainWindow.ui @@ -382,6 +382,9 @@ + + true + QFrame::StyledPanel @@ -769,8 +772,9 @@ - - + + + @@ -909,20 +913,28 @@ Cleanlooks - + true - Windows + Windows Vista ("Aero") - + true - Classic + Windows Classic + + + + + true + + + Windows XP ("Luna") @@ -951,6 +963,10 @@ + + + + diff --git a/src/Dialog_MainWindow.cpp b/src/Dialog_MainWindow.cpp index 6330231a..6a8a59a5 100644 --- a/src/Dialog_MainWindow.cpp +++ b/src/Dialog_MainWindow.cpp @@ -124,8 +124,9 @@ MainWindow::MainWindow(QWidget *parent) m_styleActionGroup = new QActionGroup(this); m_styleActionGroup->addAction(actionStylePlastique); m_styleActionGroup->addAction(actionStyleCleanlooks); - m_styleActionGroup->addAction(actionStyleWindows); - m_styleActionGroup->addAction(actionStyleClassic); + m_styleActionGroup->addAction(actionStyleWindowsVista); + m_styleActionGroup->addAction(actionStyleWindowsXP); + m_styleActionGroup->addAction(actionStyleWindowsClassic); actionStylePlastique->setChecked(true); connect(m_styleActionGroup, SIGNAL(triggered(QAction*)), this, SLOT(styleActionActivated(QAction*))); @@ -144,6 +145,11 @@ MainWindow::MainWindow(QWidget *parent) //Create message handler thread m_messageHandler = new MessageHandlerThread(); + m_delayedFileList = new QStringList(); + m_delayedFileTimer = new QTimer(); + connect(m_messageHandler, SIGNAL(otherInstanceDetected()), this, SLOT(notifyOtherInstance()), Qt::QueuedConnection); + connect(m_messageHandler, SIGNAL(fileReceived(QString)), this, SLOT(addFileDelayed(QString)), Qt::QueuedConnection); + connect(m_delayedFileTimer, SIGNAL(timeout()), this, SLOT(handleDelayedFiles())); m_messageHandler->start(); } @@ -153,11 +159,20 @@ MainWindow::MainWindow(QWidget *parent) MainWindow::~MainWindow(void) { + while(m_messageHandler->isRunning()) + { + m_messageHandler->stop(); + m_messageHandler->wait(); + } + LAMEXP_DELETE(m_tabActionGroup); LAMEXP_DELETE(m_styleActionGroup); LAMEXP_DELETE(m_fileListModel); LAMEXP_DELETE(m_banner); LAMEXP_DELETE(m_fileSystemModel); + LAMEXP_DELETE(m_messageHandler); + LAMEXP_DELETE(m_delayedFileList); + LAMEXP_DELETE(m_delayedFileTimer); } //////////////////////////////////////////////////////////// @@ -184,9 +199,7 @@ void MainWindow::showEvent(QShowEvent *event) */ void MainWindow::windowShown(void) { - QStringList fileList; QStringList arguments = QApplication::arguments(); - qDebug("Main window is showing"); for(int i = 0; i < arguments.count() - 1; i++) { @@ -196,7 +209,7 @@ void MainWindow::windowShown(void) qDebug("Adding file from CLI: %s", currentFile.absoluteFilePath().toUtf8().constData()); if(currentFile.exists()) { - fileList << currentFile.absoluteFilePath(); + m_delayedFileList->append(currentFile.absoluteFilePath()); } else { @@ -205,17 +218,9 @@ void MainWindow::windowShown(void) } } - if(fileList.count() > 0) + if(!m_delayedFileList->isEmpty() && !m_delayedFileTimer->isActive()) { - 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(); + m_delayedFileTimer->start(5000); } } @@ -318,6 +323,13 @@ void MainWindow::aboutButtonClicked(void) */ void MainWindow::encodeButtonClicked(void) { + if(m_delayedFileTimer->isActive()) + { + + MessageBeep(MB_ICONERROR); + return; + } + QMessageBox::warning(this, "LameXP", "Not implemented yet, please try again with a later version!"); } @@ -505,8 +517,9 @@ void MainWindow::styleActionActivated(QAction *action) { if(action == actionStylePlastique) QApplication::setStyle(new QPlastiqueStyle()); else if(action == actionStyleCleanlooks) QApplication::setStyle(new QCleanlooksStyle()); - else if(action == actionStyleWindows) QApplication::setStyle(new QWindowsVistaStyle()); - else if(action == actionStyleClassic) QApplication::setStyle(new QWindowsStyle()); + else if(action == actionStyleWindowsVista) QApplication::setStyle(new QWindowsVistaStyle()); + else if(action == actionStyleWindowsXP) QApplication::setStyle(new QWindowsXPStyle()); + else if(action == actionStyleWindowsClassic) QApplication::setStyle(new QWindowsStyle()); } /* @@ -519,7 +532,6 @@ void MainWindow::outputFolderViewClicked(const QModelIndex &index) outputFolderLabel->setText(selectedDir); } - /* * Goto desktop button */ @@ -622,3 +634,59 @@ void MainWindow::checkUpdatesActionActivated(void) QMessageBox::information(this, "Update Check", "Your version of LameXP is still up-to-date. There are no updates available.\nPlease remember to check for updates at regular intervals!"); } +/* + * Other instance detected + */ +void MainWindow::notifyOtherInstance(void) +{ + if(!m_banner->isVisible()) + { + QMessageBox msgBox(QMessageBox::Warning, "Already running", "LameXP is already running, please use the running instance!", QMessageBox::NoButton, this, Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint | Qt::WindowStaysOnTopHint); + msgBox.exec(); + } +} + +/* + * Add file from another instance + */ +void MainWindow::addFileDelayed(const QString &filePath) +{ + m_delayedFileTimer->stop(); + qDebug("Received file: %s", filePath.toUtf8().constData()); + m_delayedFileList->append(filePath); + m_delayedFileTimer->start(5000); +} + +/* + * Add all pending files + */ +void MainWindow::handleDelayedFiles(void) +{ + if(m_banner->isVisible()) + { + return; + } + + m_delayedFileTimer->stop(); + + if(m_delayedFileList->isEmpty()) + { + return; + } + + QStringList selectedFiles; + while(!m_delayedFileList->isEmpty()) + { + selectedFiles << QFileInfo(m_delayedFileList->takeFirst()).absoluteFilePath(); + } + + FileAnalyzer *analyzer = new FileAnalyzer(selectedFiles); + 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(); +} diff --git a/src/Dialog_MainWindow.h b/src/Dialog_MainWindow.h index aaec4e40..af05c946 100644 --- a/src/Dialog_MainWindow.h +++ b/src/Dialog_MainWindow.h @@ -59,6 +59,9 @@ private slots: void checkUpdatesActionActivated(void); void visitHomepageActionActivated(void); void openFolderActionActivated(void); + void notifyOtherInstance(void); + void addFileDelayed(const QString &filePath); + void handleDelayedFiles(void); protected: void showEvent(QShowEvent *event); @@ -70,4 +73,6 @@ private: QActionGroup *m_styleActionGroup; WorkingBanner *m_banner; MessageHandlerThread *m_messageHandler; + QStringList *m_delayedFileList; + QTimer *m_delayedFileTimer; }; diff --git a/src/Global.cpp b/src/Global.cpp index 6e90f692..e238eae3 100644 --- a/src/Global.cpp +++ b/src/Global.cpp @@ -258,13 +258,13 @@ bool lamexp_init_qt(int argc, char* argv[]) } /* - * Check for running instances of LameXP + * Initialize IPC */ -bool lamexp_check_instances(void) +int lamexp_init_ipc(void) { if(g_lamexp_sharedmem_ptr && g_lamexp_semaphore_read_ptr && g_lamexp_semaphore_write_ptr) { - return true; + return 0; } g_lamexp_semaphore_read_ptr = new QSystemSemaphore(g_lamexp_semaphore_read_uuid, 0); @@ -276,7 +276,7 @@ bool lamexp_check_instances(void) 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; + return -1; } if(g_lamexp_semaphore_write_ptr->error() != QSystemSemaphore::NoError) { @@ -284,7 +284,7 @@ bool lamexp_check_instances(void) 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; + return -1; } g_lamexp_sharedmem_ptr = new QSharedMemory(g_lamexp_sharedmem_uuid, NULL); @@ -296,30 +296,27 @@ bool lamexp_check_instances(void) g_lamexp_sharedmem_ptr->attach(); if(g_lamexp_sharedmem_ptr->error() == QSharedMemory::NoError) { - lamexp_ipc_send(42, "Wurst schmeckt uns!"); + return 1; } else { - qWarning("Failed to attach to the existing shared memory!"); + QString errorMessage = g_lamexp_sharedmem_ptr->errorString(); + qFatal("Failed to attach to shared memory: %s", errorMessage.toUtf8().constData()); + return -1; } - 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()); + return -1; } - 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; + return 0; } /* @@ -337,9 +334,12 @@ void lamexp_ipc_send(unsigned int command, const char* message) 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(); + if(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); } @@ -359,23 +359,48 @@ void lamexp_ipc_read(unsigned int *command, char* message, size_t buffSize) 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)) + if(g_lamexp_semaphore_read_ptr->acquire()) { - *command = lamexp_ipc->command; - strcpy_s(message, buffSize, lamexp_ipc->parameter); - } - else - { - qWarning("Malformed IPC message, will be ignored"); + 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); } +/* + * Communicate with running instance + */ +void lamexp_handle_multiple_instanced(void) +{ + QStringList arguments = QApplication::arguments(); + bool bSentFiles = false; + + for(int i = 0; i < arguments.count() - 1; i++) + { + if(!arguments[i].compare("--add", Qt::CaseInsensitive)) + { + lamexp_ipc_send(1, arguments[++i].toUtf8().constData()); + bSentFiles = true; + } + } + + if(!bSentFiles) + { + lamexp_ipc_send(UINT_MAX, "Use running instance!"); + } +} + /* * Get LameXP temp folder */ diff --git a/src/Global.h b/src/Global.h index 6933ebc3..334a1fd5 100644 --- a/src/Global.h +++ b/src/Global.h @@ -47,7 +47,8 @@ bool lamexp_version_demo(void); //Public functions void lamexp_init_console(int argc, char* argv[]); bool lamexp_init_qt(int argc, char* argv[]); -bool lamexp_check_instances(void); +int lamexp_init_ipc(void); +void lamexp_handle_multiple_instanced(void); void lamexp_register_tool(const QString &toolName, LockedFile *file); const QString lamexp_lookup_tool(const QString &toolName); void lamexp_finalization(void); diff --git a/src/Main.cpp b/src/Main.cpp index b305ee59..0d0f0ae8 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -68,8 +68,18 @@ int lamexp_main(int argc, char* argv[]) } } - //Check for multiple instances - if(!lamexp_check_instances()) return 0; + //Check for multiple instances of LameXP + int iResult = lamexp_init_ipc(); + if(iResult > 0) + { + qDebug("LameXP is already running, connecting to running instance..."); + lamexp_handle_multiple_instanced(); + return 0; + } + else if(iResult < 0) + { + return -1; + } //Show splash screen InitializationThread *poInitializationThread = new InitializationThread(); @@ -79,7 +89,7 @@ int lamexp_main(int argc, char* argv[]) //Show main window MainWindow *poMainWindow = new MainWindow(); poMainWindow->show(); - int iResult = QApplication::instance()->exec(); + iResult = QApplication::instance()->exec(); LAMEXP_DELETE(poMainWindow); //Final clean-up diff --git a/src/Thread_MessageHandler.cpp b/src/Thread_MessageHandler.cpp index 21074fa6..6bd09de3 100644 --- a/src/Thread_MessageHandler.cpp +++ b/src/Thread_MessageHandler.cpp @@ -25,6 +25,9 @@ #include #include +#include + +#include //////////////////////////////////////////////////////////// // Constructor @@ -32,21 +35,49 @@ MessageHandlerThread::MessageHandlerThread(void) { + m_aborted = false; + m_parameter = new char[4096]; +} + +MessageHandlerThread::~MessageHandlerThread(void) +{ + delete [] m_parameter; } void MessageHandlerThread::run() { - unsigned int command = 0; - char *parameter = new char[4096]; - - while(true) + m_aborted = false; + setTerminationEnabled(true); + + while(!m_aborted) { - qDebug("MessageHandlerThread: Waiting..."); - lamexp_ipc_read(&command, parameter, 4096); - qDebug("MessageHandlerThread: command=%u, parameter='%s'", command, parameter); + unsigned int command = 0; + lamexp_ipc_read(&command, m_parameter, 4096); + if(!command) continue; + + switch(command) + { + case 1: + emit fileReceived(QString::fromUtf8(m_parameter)); + break; + case UINT_MAX: + emit otherInstanceDetected(); + break; + default: + qWarning("Received an unknown IPC message! (command=%u)", command); + break; + } + } +} + +void MessageHandlerThread::stop(void) +{ + if(!m_aborted) + { + m_aborted = true; + lamexp_ipc_send(0, ""); } - delete [] parameter; } //////////////////////////////////////////////////////////// diff --git a/src/Thread_MessageHandler.h b/src/Thread_MessageHandler.h index 6ffd07b4..c5cb4b34 100644 --- a/src/Thread_MessageHandler.h +++ b/src/Thread_MessageHandler.h @@ -29,5 +29,15 @@ class MessageHandlerThread: public QThread public: MessageHandlerThread(void); + ~MessageHandlerThread(void); void run(); + void stop(void); + +private: + char *m_parameter; + bool m_aborted; + +signals: + void otherInstanceDetected(void); + void fileReceived(const QString &filePath); };