From 77d67f7d2e4f038f82d89729b3a2e49ab2f496fd Mon Sep 17 00:00:00 2001 From: MuldeR Date: Sat, 2 May 2015 21:04:23 +0200 Subject: [PATCH] Replaced the old IPC code with the MUtils IPC functions. --- MediaInfoXP.sln | 4 - MediaInfoXP.vcxproj | 2 + src/Config.h | 2 +- src/IPC.cpp | 239 ++++------------------------------------- src/IPC.h | 77 ++++++------- src/Main.cpp | 98 ++++++----------- src/MainWindow.cpp | 123 ++++++++++----------- src/MainWindow.h | 25 +++-- src/ShellExtension.cpp | 2 +- 9 files changed, 158 insertions(+), 414 deletions(-) diff --git a/MediaInfoXP.sln b/MediaInfoXP.sln index aa4bf36..6d73347 100644 --- a/MediaInfoXP.sln +++ b/MediaInfoXP.sln @@ -11,20 +11,16 @@ Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Release_Static|Win32 = Release_Static|Win32 - Release|Win32 = Release|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {DCDCCABB-970A-4337-B5BB-7838EE72FE80}.Debug|Win32.ActiveCfg = Debug|Win32 {DCDCCABB-970A-4337-B5BB-7838EE72FE80}.Debug|Win32.Build.0 = Debug|Win32 {DCDCCABB-970A-4337-B5BB-7838EE72FE80}.Release_Static|Win32.ActiveCfg = Release_Static|Win32 {DCDCCABB-970A-4337-B5BB-7838EE72FE80}.Release_Static|Win32.Build.0 = Release_Static|Win32 - {DCDCCABB-970A-4337-B5BB-7838EE72FE80}.Release|Win32.ActiveCfg = Release_Static|Win32 {55405FE1-149F-434C-9D72-4B64348D2A08}.Debug|Win32.ActiveCfg = Debug|Win32 {55405FE1-149F-434C-9D72-4B64348D2A08}.Debug|Win32.Build.0 = Debug|Win32 {55405FE1-149F-434C-9D72-4B64348D2A08}.Release_Static|Win32.ActiveCfg = Release_Static|Win32 {55405FE1-149F-434C-9D72-4B64348D2A08}.Release_Static|Win32.Build.0 = Release_Static|Win32 - {55405FE1-149F-434C-9D72-4B64348D2A08}.Release|Win32.ActiveCfg = Release|Win32 - {55405FE1-149F-434C-9D72-4B64348D2A08}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/MediaInfoXP.vcxproj b/MediaInfoXP.vcxproj index 82053f8..fd59699 100644 --- a/MediaInfoXP.vcxproj +++ b/MediaInfoXP.vcxproj @@ -57,11 +57,13 @@ Disabled WIN32;_DEBUG;_CONSOLE;QT_GUI_LIB;QT_CORE_LIB;QT_THREAD_SUPPORT;QT_DLL;QT_DEBUG;%(PreprocessorDefinitions) $(QTDIR)\include;$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(SolutionDir)\..\MUtilities\include;$(SolutionDir)\tmp\$(ProjectName);%(AdditionalIncludeDirectories) + NoExtensions Console true $(SolutionDir)\..\Prerequisites\Qt4\MSVC-2013\Debug\lib;$(SolutionDir)\..\Prerequisites\Qt4\MSVC-2013\Debug\plugins\imageformats;$(SolutionDir)\..\Prerequisites\EncodePointer\lib;%(AdditionalLibraryDirectories) + QtCored4.lib;QtGuid4.lib;QtSvgd4.lib;Winmm.lib;imm32.lib;ws2_32.lib;Shlwapi.lib;Wininet.lib;PowrProf.lib;psapi.lib;Sensapi.lib;%(AdditionalDependencies) diff --git a/src/Config.h b/src/Config.h index 2374223..21df2ab 100644 --- a/src/Config.h +++ b/src/Config.h @@ -21,7 +21,7 @@ //Version static unsigned int mixp_versionMajor = 2; -static unsigned int mixp_versionMinor = 14; +static unsigned int mixp_versionMinor = 15; //MediaInfo Version static unsigned int mixp_miVersionMajor = 0; diff --git a/src/IPC.cpp b/src/IPC.cpp index b2f0c0c..81e525e 100644 --- a/src/IPC.cpp +++ b/src/IPC.cpp @@ -23,6 +23,7 @@ //MUtils #include "MUtils/Global.h" +#include "MUtils/IPCChannel.h" //Qt #include @@ -48,9 +49,9 @@ mixp_ipc_t; // Send Thread /////////////////////////////////////////////////////////////////////////////// -IPCSendThread::IPCSendThread(IPC *ipc, const QString &str) +IPCSendThread::IPCSendThread(MUtils::IPCChannel *const ipc, const quint32 &command, const QString &message) : - m_ipc(ipc), m_str(str) + m_ipc(ipc), m_command(command), m_message(message) { m_result = false; } @@ -59,10 +60,11 @@ void IPCSendThread::run(void) { try { - m_result = m_ipc->pushStr(m_str); + m_result = m_ipc->send(m_command, 0, QStringList() << m_message); } catch(...) { + qWarning("Exception in IPC receive thread!"); m_result = false; } } @@ -72,7 +74,7 @@ void IPCSendThread::run(void) // Receive Thread /////////////////////////////////////////////////////////////////////////////// -IPCReceiveThread::IPCReceiveThread(IPC *ipc) +IPCReceiveThread::IPCReceiveThread(MUtils::IPCChannel *const ipc) : m_ipc(ipc) { @@ -95,192 +97,34 @@ void IPCReceiveThread::receiveLoop(void) { while(!m_stopped) { - QString temp; - if(m_ipc->popStr(temp)) + quint32 command, flags; + QStringList params; + if(m_ipc->read(command, flags, params)) { - if(!temp.isEmpty()) + if((command != IPC::COMMAND_NONE) && (!params.isEmpty())) { - emit receivedStr(temp); + emit received(command, params.first()); } } } } +void IPCReceiveThread::stop(void) +{ + if(!m_stopped) + { + m_stopped = true; + IPC::sendAsync(m_ipc, IPC::COMMAND_NONE, "exit"); + } +} + /////////////////////////////////////////////////////////////////////////////// // IPC Class /////////////////////////////////////////////////////////////////////////////// -IPC::IPC(void) +bool IPC::sendAsync(MUtils::IPCChannel *const ipc, const quint32 &command, const QString &message, const quint32 &timeout) { - m_initialized = -1; - m_sharedMemory = NULL; - m_semaphoreWr = NULL; - m_semaphoreRd = NULL; - m_recvThread = NULL; -} - -IPC::~IPC(void) -{ - if(m_recvThread && m_recvThread->isRunning()) - { - qWarning("Receive thread still running -> terminating!"); - m_recvThread->terminate(); - m_recvThread->wait(); - } - - MUTILS_DELETE(m_recvThread); - MUTILS_DELETE(m_sharedMemory); - MUTILS_DELETE(m_semaphoreWr); - MUTILS_DELETE(m_semaphoreRd); -} - -int IPC::initialize(void) -{ - if(m_initialized >= 0) - { - return m_initialized; - } - - m_semaphoreWr = new QSystemSemaphore(s_key_sema_wr, MAX_ENTRIES); - m_semaphoreRd = new QSystemSemaphore(s_key_sema_rd, 0); - - if((m_semaphoreWr->error() != QSystemSemaphore::NoError) || (m_semaphoreRd->error() != QSystemSemaphore::NoError)) - { - qWarning("IPC: Failed to created system semaphores!"); - return -1; - } - - m_sharedMemory = new QSharedMemory(s_key_smemory, this); - - if(m_sharedMemory->create(sizeof(mixp_ipc_t))) - { - memset(m_sharedMemory->data(), 0, sizeof(mixp_ipc_t)); - m_initialized = 1; - return 1; - } - - if(m_sharedMemory->error() == QSharedMemory::AlreadyExists) - { - qDebug("Not the first instance -> attaching to existing shared memory"); - if(m_sharedMemory->attach()) - { - m_initialized = 0; - return 0; - } - } - - qWarning("IPC: Failed to attach to the shared memory!"); - return -1; -} - -bool IPC::pushStr(const QString &str) -{ - if(m_initialized < 0) - { - qWarning("Error: IPC not initialized yet!"); - return false; - } - - if(!m_semaphoreWr->acquire()) - { - qWarning("IPC: Failed to acquire semaphore!"); - return false; - } - - if(!m_sharedMemory->lock()) - { - qWarning("IPC: Failed to lock shared memory!"); - return false; - } - - bool success = true; - - try - { - mixp_ipc_t *memory = (mixp_ipc_t*) m_sharedMemory->data(); - if(memory->counter < MAX_ENTRIES) - { - wcsncpy_s(memory->data[memory->posWr], MAX_STR_LEN, (wchar_t*)str.utf16(), _TRUNCATE); - memory->posWr = (memory->posWr + 1) % MAX_ENTRIES; - memory->counter++; - } - else - { - qWarning("IPC: Shared memory is full -> cannot push string!"); - success = false; - } - } - catch(...) - { - /*ignore any exception*/ - } - - m_sharedMemory->unlock(); - - if(success) - { - m_semaphoreRd->release(); - } - - return success; -} - -bool IPC::popStr(QString &str) -{ - if(m_initialized < 0) - { - qWarning("Error: IPC not initialized yet!"); - return false; - } - - if(!m_semaphoreRd->acquire()) - { - qWarning("IPC: Failed to acquire semaphore!"); - return false; - } - - if(!m_sharedMemory->lock()) - { - qWarning("IPC: Failed to lock shared memory!"); - return false; - } - - bool success = true; - - try - { - mixp_ipc_t *memory = (mixp_ipc_t*) m_sharedMemory->data(); - if(memory->counter > 0) - { - memory->data[memory->posRd][MAX_STR_LEN-1] = L'\0'; - str = QString::fromUtf16((const ushort*)memory->data[memory->posRd]); - memory->posRd = (memory->posRd + 1) % MAX_ENTRIES; - memory->counter--; - } - else - { - qWarning("IPC: Shared memory is empty -> cannot pop string!"); - success = false; - } - } - catch(...) - { - /*ignore any exception*/ - } - - m_sharedMemory->unlock(); - - if(success) - { - m_semaphoreWr->release(); - } - - return success; -} - -bool IPC::sendAsync(const QString &str, const int timeout) -{ - IPCSendThread sendThread(this, str); + IPCSendThread sendThread(ipc, command, message); sendThread.start(); if(!sendThread.wait(timeout)) @@ -293,42 +137,3 @@ bool IPC::sendAsync(const QString &str, const int timeout) return sendThread.result(); } - -void IPC::startListening(void) -{ - if(!m_recvThread) - { - m_recvThread = new IPCReceiveThread(this); - connect(m_recvThread, SIGNAL(receivedStr(QString)), this, SIGNAL(receivedStr(QString)), Qt::QueuedConnection); - } - - if(!m_recvThread->isRunning()) - { - m_recvThread->start(); - } - else - { - qWarning("Receive thread was already running!"); - } - -} - -void IPC::stopListening(void) -{ - if(m_recvThread && m_recvThread->isRunning()) - { - m_recvThread->stop(); - m_semaphoreRd->release(); - - if(!m_recvThread->wait(5000)) - { - qWarning("Receive thread seems deadlocked -> terminating!"); - m_recvThread->terminate(); - m_recvThread->wait(); - } - } - else - { - qWarning("Receive thread was not running!"); - } -} diff --git a/src/IPC.h b/src/IPC.h index 8585747..2d2a050 100644 --- a/src/IPC.h +++ b/src/IPC.h @@ -23,78 +23,63 @@ #include -class QSharedMemory; -class QSystemSemaphore; -class IPCSendThread; -class IPCReceiveThread; - -class IPC : public QObject +namespace MUtils { - Q_OBJECT - friend class IPCReceiveThread; - friend class IPCSendThread; - -public: - IPC(void); - ~IPC(void); - - int initialize(void); - bool sendAsync(const QString &str, const int timeout = 5000); - -public slots: - void startListening(void); - void stopListening(void); - -signals: - void receivedStr(const QString &str); - -protected: - bool popStr(QString &str); - bool pushStr(const QString &str); - - int m_initialized; - - QSharedMemory *m_sharedMemory; - QSystemSemaphore *m_semaphoreRd; - QSystemSemaphore *m_semaphoreWr; - IPCReceiveThread *m_recvThread; -}; + class IPCChannel; +} /////////////////////////////////////////////////////////////////////////////// class IPCSendThread : public QThread { Q_OBJECT - friend class IPC; -protected: - IPCSendThread(IPC *ipc, const QString &str); +public: + IPCSendThread(MUtils::IPCChannel *const ipc, const quint32 &command, const QString &message); inline bool result(void) { return m_result; } virtual void run(void); private: volatile bool m_result; - IPC *const m_ipc; - const QString m_str; + MUtils::IPCChannel *const m_ipc; + const quint32 m_command; + const QString m_message; }; class IPCReceiveThread : public QThread { Q_OBJECT - friend class IPC; + +public: + IPCReceiveThread(MUtils::IPCChannel *const ipc); + void stop(void); protected: - IPCReceiveThread(IPC *ipc); - inline void stop(void) { m_stopped = true; } - virtual void run(void); signals: - void receivedStr(const QString &str); + void received(const quint32 &command, const QString &message); private: void receiveLoop(void); volatile bool m_stopped; - IPC *const m_ipc; + MUtils::IPCChannel *const m_ipc; +}; + +class IPC +{ +public: + enum + { + COMMAND_NONE = 0, + COMMAND_PING = 1, + COMMAND_OPEN = 2 + } + ipc_command_t; + + static bool sendAsync(MUtils::IPCChannel *const ipc, const quint32 &command, const QString &message, const quint32 &timeout = 5000); + +private: + IPC(void) { throw 666; } }; diff --git a/src/Main.cpp b/src/Main.cpp index 802be56..666f733 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -21,26 +21,14 @@ //MUTils #include +#include #include - -//StdLib -#include -#include -#include -#include -#include - -#pragma intrinsic(_InterlockedExchange) +#include //Qt #include #include - -//Win32 -#define WIN32_LEAN_AND_MEAN -#include -#include -#include +#include #ifdef QT_NODLL #include @@ -54,34 +42,28 @@ #include "IPC.h" /////////////////////////////////////////////////////////////////////////////// -// Debug Console +// Multi-instance handling /////////////////////////////////////////////////////////////////////////////// -bool g_bHaveConsole = false; - -static void init_console(void) +static void mixp_handle_multi_instance(MUtils::IPCChannel *const ipcChannel) { - if(AllocConsole()) + bool bHaveFile = false; + + //We are *not* the first instance -> pass all file names to the running instance + const MUtils::OS::ArgumentMap arguments = MUtils::OS::arguments(); + const QStringList files = arguments.values("open"); + for(QStringList::ConstIterator iter = files.constBegin(); iter != files.constEnd(); iter++) { - int hCrtStdOut = _open_osfhandle((intptr_t) GetStdHandle(STD_OUTPUT_HANDLE), _O_WRONLY); - int hCrtStdErr = _open_osfhandle((intptr_t) GetStdHandle(STD_ERROR_HANDLE), _O_WRONLY); - FILE *hfStdOut = (hCrtStdOut >= 0) ? _fdopen(hCrtStdOut, "wb") : NULL; - FILE *hfStdErr = (hCrtStdErr >= 0) ? _fdopen(hCrtStdErr, "wb") : NULL; - if(hfStdOut) { *stdout = *hfStdOut; std::cout.rdbuf(new std::filebuf(hfStdOut)); } - if(hfStdErr) { *stderr = *hfStdErr; std::cerr.rdbuf(new std::filebuf(hfStdErr)); } - - HWND hwndConsole = GetConsoleWindow(); - if((hwndConsole != NULL) && (hwndConsole != INVALID_HANDLE_VALUE)) + if(IPC::sendAsync(ipcChannel, IPC::COMMAND_OPEN, *iter)) { - HMENU hMenu = GetSystemMenu(hwndConsole, 0); - EnableMenuItem(hMenu, SC_CLOSE, MF_BYCOMMAND | MF_GRAYED); - RemoveMenu(hMenu, SC_CLOSE, MF_BYCOMMAND); - SetWindowPos(hwndConsole, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED); - SetWindowLong(hwndConsole, GWL_STYLE, GetWindowLong(hwndConsole, GWL_STYLE) & (~WS_MAXIMIZEBOX) & (~WS_MINIMIZEBOX)); - SetWindowPos(hwndConsole, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED); + bHaveFile = true; } + } - g_bHaveConsole = true; + //If no file was sent, we will at least try to bring the other instance to front + if(!bHaveFile) + { + IPC::sendAsync(ipcChannel, IPC::COMMAND_PING, "?"); } } @@ -103,36 +85,19 @@ static int mixp_main(int &argc, char **argv) QScopedPointer application(new QApplication(argc, argv)); //Create IPC - QScopedPointer ipc(new IPC()); - - //Is this the *first* instance? - if(ipc->initialize() == 0) + QScopedPointer ipcChannel(new MUtils::IPCChannel("mediainfo-xp", qHash(QString("%0@%1").arg(QString::fromLatin1(mixp_buildDate), QString::fromLatin1(mixp_buildTime))), "instance")); + const int ipcMode = ipcChannel->initialize(); + if((ipcMode != MUtils::IPCChannel::RET_SUCCESS_MASTER) && (ipcMode != MUtils::IPCChannel::RET_SUCCESS_SLAVE)) { - //We are *not* the first instance -> pass all file names to the running instance - const QStringList arguments = qApp->arguments(); - bool bHaveFile = false; - for(QStringList::ConstIterator iter = arguments.constBegin(); iter != arguments.constEnd(); iter++) - { - if(QString::compare(*iter, "--open", Qt::CaseInsensitive) == 0) - { - if(++iter != arguments.constEnd()) - { - if(ipc->sendAsync(*iter)) - { - bHaveFile = true; - continue; - } - } - break; - } - } - //If no file was sent, we will at least try to bring the other instance to front - if(!bHaveFile) - { - ipc->sendAsync("?"); - } + qFatal("The IPC initialization has failed!"); + return EXIT_FAILURE; + } - return 42; + //Handle multiple instances + if(ipcMode == MUtils::IPCChannel::RET_SUCCESS_SLAVE) + { + mixp_handle_multi_instance(ipcChannel.data()); + return EXIT_SUCCESS; } //Get temp folder @@ -140,15 +105,12 @@ static int mixp_main(int &argc, char **argv) qDebug("TEMP folder is:\n%s\n", QDir::toNativeSeparators(tempFolder).toUtf8().constData()); //Create main window - QScopedPointer mainWindow(new CMainWindow(tempFolder, ipc.data())); + QScopedPointer mainWindow(new CMainWindow(tempFolder, ipcChannel.data())); mainWindow->show(); //Run application const int exit_code = application->exec(); qDebug("\nTime to say goodbye... (%d)\n", exit_code); - - //Stop IPC - ipc->stopListening(); return exit_code; } diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index 9d781d3..6b285d0 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -82,11 +82,11 @@ static const int FILE_RECEIVE_DELAY = 1750; // Constructor //////////////////////////////////////////////////////////// -CMainWindow::CMainWindow(const QString &tempFolder, IPC *const ipc, QWidget *parent) +CMainWindow::CMainWindow(const QString &tempFolder, MUtils::IPCChannel *const ipc, QWidget *parent) : QMainWindow(parent), m_tempFolder(tempFolder), - m_ipc(ipc), + m_ipcThread(new IPCReceiveThread(ipc)), m_htmlEscape(HTML_ESCAPE()), m_status(APP_STATUS_STARTING), ui(new Ui::MainWindow) @@ -100,23 +100,23 @@ CMainWindow::CMainWindow(const QString &tempFolder, IPC *const ipc, QWidget *par MUtils::GUI::set_window_icon(this, QIcon(":/res/logo.png"), true); //Setup links - ui->actionLink_MuldeR->setData(QVariant(QString::fromLatin1(LINK_MULDER))); + ui->actionLink_MuldeR ->setData(QVariant(QString::fromLatin1(LINK_MULDER))); ui->actionLink_MediaInfo->setData(QVariant(QString::fromLatin1(LINK_MEDIAINFO))); - ui->actionLink_Discuss->setData(QVariant(QString::fromLatin1(LINK_DISCUSS))); + ui->actionLink_Discuss ->setData(QVariant(QString::fromLatin1(LINK_DISCUSS))); //Setup connections - connect(ui->analyzeButton, SIGNAL(clicked()), this, SLOT(analyzeButtonClicked())); - connect(ui->actionOpen, SIGNAL(triggered()), this, SLOT(analyzeButtonClicked())); - connect(ui->actionSave, SIGNAL(triggered()), this, SLOT(saveButtonClicked())); - connect(ui->actionCopyToClipboard, SIGNAL(triggered()), this, SLOT(copyToClipboardButtonClicked())); - connect(ui->actionClear, SIGNAL(triggered()), this, SLOT(clearButtonClicked())); - connect(ui->actionLink_MuldeR, SIGNAL(triggered()), this, SLOT(linkTriggered())); - connect(ui->actionLink_MediaInfo, SIGNAL(triggered()), this, SLOT(linkTriggered())); - connect(ui->actionLink_Discuss, SIGNAL(triggered()), this, SLOT(linkTriggered())); - connect(ui->actionAbout, SIGNAL(triggered()), this, SLOT(showAboutScreen())); - connect(ui->actionShellExtension, SIGNAL(toggled(bool)), this, SLOT(updateShellExtension(bool))); - connect(ui->actionLineWrapping, SIGNAL(toggled(bool)), this, SLOT(updateLineWrapping(bool))); - connect(m_ipc, SIGNAL(receivedStr(QString)), this, SLOT(fileReceived(QString))); + connect(ui->analyzeButton, SIGNAL(clicked()), this, SLOT(analyzeButtonClicked())); + connect(ui->actionOpen, SIGNAL(triggered()), this, SLOT(analyzeButtonClicked())); + connect(ui->actionSave, SIGNAL(triggered()), this, SLOT(saveButtonClicked())); + connect(ui->actionCopyToClipboard, SIGNAL(triggered()), this, SLOT(copyToClipboardButtonClicked())); + connect(ui->actionClear, SIGNAL(triggered()), this, SLOT(clearButtonClicked())); + connect(ui->actionLink_MuldeR, SIGNAL(triggered()), this, SLOT(linkTriggered())); + connect(ui->actionLink_MediaInfo, SIGNAL(triggered()), this, SLOT(linkTriggered())); + connect(ui->actionLink_Discuss, SIGNAL(triggered()), this, SLOT(linkTriggered())); + connect(ui->actionAbout, SIGNAL(triggered()), this, SLOT(showAboutScreen())); + connect(ui->actionShellExtension, SIGNAL(toggled(bool)), this, SLOT(updateShellExtension(bool))); + connect(ui->actionLineWrapping, SIGNAL(toggled(bool)), this, SLOT(updateLineWrapping(bool))); + connect(m_ipcThread.data(), SIGNAL(received(quint32, QString)), this, SLOT(received(quint32, QString))); ui->versionLabel->installEventFilter(this); //Context menu @@ -124,7 +124,7 @@ CMainWindow::CMainWindow(const QString &tempFolder, IPC *const ipc, QWidget *par ui->textBrowser->insertActions(0, ui->menuFile->actions()); //Create label - m_floatingLabel = new QLabel(ui->textBrowser); + m_floatingLabel.reset(new QLabel(ui->textBrowser)); m_floatingLabel->setText(QString::fromLatin1(STATUS_BLNK)); m_floatingLabel->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); m_floatingLabel->show(); @@ -132,10 +132,6 @@ CMainWindow::CMainWindow(const QString &tempFolder, IPC *const ipc, QWidget *par SET_FONT_BOLD(m_floatingLabel, true); m_floatingLabel->setContextMenuPolicy(Qt::ActionsContextMenu); m_floatingLabel->insertActions(0, ui->textBrowser->actions()); - - //Clear - m_mediaInfoHandle = NULL; - m_process = NULL; //Randomize qsrand((uint) time(NULL)); @@ -147,13 +143,21 @@ CMainWindow::CMainWindow(const QString &tempFolder, IPC *const ipc, QWidget *par CMainWindow::~CMainWindow(void) { - if(m_mediaInfoHandle) + if(!m_ipcThread.isNull()) + { + m_ipcThread->stop(); + if(!m_ipcThread->wait(5000)) + { + qWarning("IPC thread doesn't respond -> terminating!"); + m_ipcThread->terminate(); + m_ipcThread->wait(); + } + } + + if(!m_mediaInfoHandle.isNull()) { m_mediaInfoHandle->remove(); - MUTILS_DELETE(m_mediaInfoHandle); } - MUTILS_DELETE(m_process); - MUTILS_DELETE(m_floatingLabel); } //////////////////////////////////////////////////////////// @@ -178,21 +182,14 @@ void CMainWindow::showEvent(QShowEvent *event) if(m_status == APP_STATUS_STARTING) { - const QStringList arguments = qApp->arguments(); - for(QStringList::ConstIterator iter = arguments.constBegin(); iter != arguments.constEnd(); iter++) + const MUtils::OS::ArgumentMap arguments = MUtils::OS::arguments(); + const QStringList files = arguments.values("open"); + for(QStringList::ConstIterator iter = files.constBegin(); iter != files.constEnd(); iter++) { - if(QString::compare(*iter, "--open", Qt::CaseInsensitive) == 0) + QFileInfo currentFile = QFileInfo(*iter); + if(currentFile.exists() && currentFile.isFile()) { - if(++iter != arguments.constEnd()) - { - QFileInfo currentFile = QFileInfo(*iter); - if(currentFile.exists() && currentFile.isFile()) - { - m_pendingFiles << currentFile.canonicalFilePath(); - } - continue; - } - break; + m_pendingFiles << currentFile.canonicalFilePath(); } } if(!m_pendingFiles.empty()) @@ -201,9 +198,9 @@ void CMainWindow::showEvent(QShowEvent *event) QTimer::singleShot(FILE_RECEIVE_DELAY, this, SLOT(analyzeFiles())); } - QTimer::singleShot(125, m_ipc, SLOT(startListening())); QTimer::singleShot(250, this, SLOT(initShellExtension())); - + m_ipcThread->start(); + if(m_status == APP_STATUS_STARTING) { m_status = APP_STATUS_IDLE; @@ -313,15 +310,15 @@ void CMainWindow::analyzeFiles(void) } //Create process, if not done yet - if(!m_process) + if(m_process.isNull()) { - m_process = new QProcess(); + m_process.reset(new QProcess()); m_process->setProcessChannelMode(QProcess::MergedChannels); m_process->setReadChannel(QProcess::StandardOutput); - connect(m_process, SIGNAL(readyReadStandardError()), this, SLOT(outputAvailable())); - connect(m_process, SIGNAL(readyReadStandardOutput()), this, SLOT(outputAvailable())); - connect(m_process, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(processFinished())); - connect(m_process, SIGNAL(error(QProcess::ProcessError)), this, SLOT(processFinished())); + connect(m_process.data(), SIGNAL(readyReadStandardError()), this, SLOT(outputAvailable())); + connect(m_process.data(), SIGNAL(readyReadStandardOutput()), this, SLOT(outputAvailable())); + connect(m_process.data(), SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(processFinished())); + connect(m_process.data(), SIGNAL(error(QProcess::ProcessError)), this, SLOT(processFinished())); } //Still running? @@ -686,13 +683,16 @@ void CMainWindow::updateSize(void) } } -void CMainWindow::fileReceived(const QString &str) +void CMainWindow::received(const quint32 &command, const QString &message) { - MUtils::GUI::bring_to_front(this); - - if(str.compare("?") != 0) + if((command == IPC::COMMAND_PING) || (command == IPC::COMMAND_OPEN)) { - qDebug("Received file: %s", str.toUtf8().constData()); + MUtils::GUI::bring_to_front(this); + } + + if((command == IPC::COMMAND_OPEN) && (!message.isEmpty())) + { + qDebug("Received file: %s", message.toUtf8().constData()); if((m_status != APP_STATUS_IDLE) && (m_status != APP_STATUS_AWAITING)) { @@ -700,7 +700,7 @@ void CMainWindow::fileReceived(const QString &str) return; } - const QString absPath = QFileInfo(QDir::fromNativeSeparators(str)).absoluteFilePath(); + const QString absPath = QFileInfo(QDir::fromNativeSeparators(message)).absoluteFilePath(); QFileInfo fileInfo(absPath); if(fileInfo.exists() && fileInfo.isFile()) { @@ -712,10 +712,6 @@ void CMainWindow::fileReceived(const QString &str) } } } - else - { - qDebug("Received ping from another instance!"); - } } //////////////////////////////////////////////////////////// @@ -752,19 +748,18 @@ QString CMainWindow::getMediaInfoPath(void) } //Validate file content, if already extracted - if(m_mediaInfoHandle) + if(!m_mediaInfoHandle.isNull()) { - if(VALIDATE_MEDIAINFO(m_mediaInfoHandle)) + if(VALIDATE_MEDIAINFO(m_mediaInfoHandle.data())) { return m_mediaInfoHandle->fileName(); } m_mediaInfoHandle->remove(); - MUTILS_DELETE(m_mediaInfoHandle); } //Extract MediaInfo binary now! qDebug("MediaInfo binary not existing yet, going to extract now...\n"); - m_mediaInfoHandle = new QFile(QString("%1/MediaInfo_%2.exe").arg(m_tempFolder, QString().sprintf("%04x", qrand() % 0xFFFF))); + m_mediaInfoHandle.reset(new QFile(QString("%1/MediaInfo_%2.exe").arg(m_tempFolder, QString().sprintf("%04x", qrand() % 0xFFFF)))); if(m_mediaInfoHandle->open(QIODevice::ReadWrite | QIODevice::Truncate)) { if(m_mediaInfoHandle->write(reinterpret_cast(mediaInfoRes.data()), mediaInfoRes.size()) == mediaInfoRes.size()) @@ -775,31 +770,27 @@ QString CMainWindow::getMediaInfoPath(void) { qWarning("Failed to open MediaInfo binary for reading!\n"); m_mediaInfoHandle->remove(); - MUTILS_DELETE(m_mediaInfoHandle); } } else { qWarning("Failed to write data to MediaInfo binary file!\n"); m_mediaInfoHandle->remove(); - MUTILS_DELETE(m_mediaInfoHandle); } } else { qWarning("Failed to open MediaInfo binary for writing!\n"); - MUTILS_DELETE(m_mediaInfoHandle); } //Validate file content, after it has been extracted - if(m_mediaInfoHandle) + if(!m_mediaInfoHandle.isNull()) { - if(VALIDATE_MEDIAINFO(m_mediaInfoHandle)) + if(VALIDATE_MEDIAINFO(m_mediaInfoHandle.data())) { return m_mediaInfoHandle->fileName(); } m_mediaInfoHandle->remove(); - MUTILS_DELETE(m_mediaInfoHandle); } return QString(); diff --git a/src/MainWindow.h b/src/MainWindow.h index 2f7d29e..5e2929b 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -25,14 +25,18 @@ #include //UIC forward declartion -namespace Ui { +namespace Ui +{ class MainWindow; } +namespace MUtils +{ + class IPCChannel; +} class QProcess; class QLabel; class QFile; -class mixp_icon_t; -class IPC; +class IPCReceiveThread; //MainWindow class class CMainWindow: public QMainWindow @@ -40,7 +44,7 @@ class CMainWindow: public QMainWindow Q_OBJECT public: - CMainWindow(const QString &tempFolder, IPC *const ipc, QWidget *parent = 0); + CMainWindow(const QString &tempFolder, MUtils::IPCChannel *const ipc, QWidget *parent = 0); ~CMainWindow(void); private slots: @@ -58,7 +62,7 @@ private slots: void initShellExtension(void); void updateShellExtension(bool checked); void updateLineWrapping(bool checked); - void fileReceived(const QString &path); + void received(const quint32 &command, const QString &message); protected: virtual void showEvent(QShowEvent *event); @@ -85,14 +89,13 @@ private: int m_status; const QString &m_tempFolder; - QFile *m_mediaInfoHandle; - QProcess *m_process; - QLabel *m_floatingLabel; + QScopedPointer m_ipcThread; + QScopedPointer m_mediaInfoHandle; + QScopedPointer m_process; + QScopedPointer m_floatingLabel; QStringList m_pendingFiles; QStringList m_outputLines; - mixp_icon_t *m_icon; - IPC *const m_ipc; - + const QList> m_htmlEscape; QString getMediaInfoPath(void); diff --git a/src/ShellExtension.cpp b/src/ShellExtension.cpp index 0779cdf..28cc9b1 100644 --- a/src/ShellExtension.cpp +++ b/src/ShellExtension.cpp @@ -52,7 +52,7 @@ bool ShellExtension::setEnabled(bool enabled) if(MUtils::Registry::reg_value_write(MUtils::Registry::root_user, MIXP_REGISTRY_KEY, QString(), tr("Analyze file with MediaInfoXP"))) { const QString appPath = QDir::toNativeSeparators(QApplication::applicationFilePath()); - const QString command = QString().sprintf("\"%ls\" --open \"%%1\"", appPath.utf16()); + const QString command = QString().sprintf("\"%ls\" --open=\"%%1\"", appPath.utf16()); if(MUtils::Registry::reg_value_write(MUtils::Registry::root_user, MIXP_REGISTRY_KEY"\\command", QString(), command)) { if(MUtils::Registry::reg_value_write(MUtils::Registry::root_user, MIXP_REGISTRY_KEY, MIXP_REGISTRY_VAL, 1))