diff --git a/LameXP_VS2013.vcxproj b/LameXP_VS2013.vcxproj index c2eafa38..010e3dd4 100644 --- a/LameXP_VS2013.vcxproj +++ b/LameXP_VS2013.vcxproj @@ -406,6 +406,7 @@ copy /Y "$(SolutionDir)\..\Prerequisites\VisualLeakDetector\bin\Win32\*.manifest + diff --git a/LameXP_VS2013.vcxproj.filters b/LameXP_VS2013.vcxproj.filters index 5c0eeba9..ea61492c 100644 --- a/LameXP_VS2013.vcxproj.filters +++ b/LameXP_VS2013.vcxproj.filters @@ -540,6 +540,9 @@ Generated Files\UIC + + Header Files\Misc + diff --git a/src/Config.h b/src/Config.h index 0d00671f..2355aa09 100644 --- a/src/Config.h +++ b/src/Config.h @@ -35,7 +35,7 @@ #define VER_LAMEXP_MINOR_LO 1 #define VER_LAMEXP_TYPE Beta #define VER_LAMEXP_PATCH 8 -#define VER_LAMEXP_BUILD 1628 +#define VER_LAMEXP_BUILD 1632 #define VER_LAMEXP_CONFG 1558 /////////////////////////////////////////////////////////////////////////////// diff --git a/src/Dialog_Processing.cpp b/src/Dialog_Processing.cpp index d1d9769c..78da7b8a 100644 --- a/src/Dialog_Processing.cpp +++ b/src/Dialog_Processing.cpp @@ -155,7 +155,7 @@ ProcessingDialog::ProcessingDialog(FileListModel *fileListModel, const AudioFile m_systemTray(new QSystemTrayIcon(QIcon(":/icons/cd_go.png"), this)), m_settings(settings), m_metaInfo(metaInfo), - m_shutdownFlag(shutdownFlag_None), + m_shutdownFlag(SHUTDOWN_FLAG_NONE), m_threadPool(NULL), m_diskObserver(NULL), m_cpuObserver(NULL), @@ -769,7 +769,7 @@ void ProcessingDialog::doneEncoding(void) { if(shutdownComputer()) { - m_shutdownFlag = m_settings->hibernateComputer() ? shutdownFlag_Hibernate : shutdownFlag_TurnPowerOff; + m_shutdownFlag = m_settings->hibernateComputer() ? SHUTDOWN_FLAG_HIBERNATE : SHUTDOWN_FLAG_POWER_OFF; accept(); } } diff --git a/src/Dialog_Processing.h b/src/Dialog_Processing.h index b8edf239..9a99bff0 100644 --- a/src/Dialog_Processing.h +++ b/src/Dialog_Processing.h @@ -45,11 +45,11 @@ class QElapsedTimer; class RAMObserverThread; class SettingsModel; -enum shutdownFlag_t +enum lamexp_shutdownFlag_t { - shutdownFlag_None = 0, - shutdownFlag_TurnPowerOff = 1, - shutdownFlag_Hibernate = 2 + SHUTDOWN_FLAG_NONE = 0, + SHUTDOWN_FLAG_POWER_OFF = 1, + SHUTDOWN_FLAG_HIBERNATE = 2 }; //UIC forward declartion diff --git a/src/IPCCommands.h b/src/IPCCommands.h new file mode 100644 index 00000000..8feea7bd --- /dev/null +++ b/src/IPCCommands.h @@ -0,0 +1,41 @@ +/////////////////////////////////////////////////////////////////////////////// +// LameXP - Audio Encoder Front-End +// Copyright (C) 2004-2014 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, but always including the *additional* +// restrictions defined in the "License.txt" file. +// +// 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 + +typedef enum +{ + IPC_CMD_NOOP = 0x0000, + IPC_CMD_PING = 0x0001, + IPC_CMD_ADD_FILE = 0x0002, + IPC_CMD_ADD_FOLDER = 0x0003, + IPC_CMD_TERMINATE = 0xFFFF +} +lamexp_ipc_command_t; + +typedef enum +{ + IPC_FLAG_NONE = 0x0000, + IPC_FLAG_ADD_RECURSIVE = 0x0001, + IPC_FLAG_FORCE = 0x8000, +} +lamexp_ipc_flag_t; diff --git a/src/Main.cpp b/src/Main.cpp index d7ed39cd..1914932d 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -50,15 +50,11 @@ #include /////////////////////////////////////////////////////////////////////////////// -// Main function +// Helper functions /////////////////////////////////////////////////////////////////////////////// -static int lamexp_main(int &argc, char **argv) +static void lamexp_print_logo(void) { - int iResult = -1; - int iShutdown = shutdownFlag_None; - bool bAccepted = true; - //Print version info qDebug("LameXP - Audio Encoder Front-End v%d.%02d %s (Build #%03d)", lamexp_version_major(), lamexp_version_minor(), lamexp_version_release(), lamexp_version_build()); qDebug("Copyright (c) 2004-%04d LoRd_MuldeR . Some rights reserved.", qMax(MUtils::Version::app_build_date().year(), MUtils::OS::current_date().year())); @@ -71,7 +67,7 @@ static int lamexp_main(int &argc, char **argv) //Print library version qDebug("This application is powerd by MUtils library v%u.%02u (%s, %s).\n", MUtils::Version::lib_version_major(), MUtils::Version::lib_version_minor(), MUTILS_UTF8(MUtils::Version::lib_build_date().toString(Qt::ISODate)), MUTILS_UTF8(MUtils::Version::lib_build_time().toString(Qt::ISODate))); - + //Print warning, if this is a "debug" build if(MUTILS_DEBUG) { @@ -79,7 +75,107 @@ static int lamexp_main(int &argc, char **argv) qWarning("DEBUG BUILD: DO NOT RELEASE THIS BINARY TO THE PUBLIC !!!"); qWarning("---------------------------------------------------------\n"); } +} + +static int lamexp_initialize_ipc(MUtils::IPCChannel *const ipcChannel) +{ + int iResult = 0; + + if((iResult = ipcChannel->initialize()) != MUtils::IPCChannel::RET_SUCCESS_MASTER) + { + if(iResult == MUtils::IPCChannel::RET_SUCCESS_SLAVE) + { + qDebug("LameXP is already running, connecting to running instance..."); + QScopedPointer messageProducerThread(new MessageProducerThread(ipcChannel)); + messageProducerThread->start(); + if(!messageProducerThread->wait(30000)) + { + qWarning("MessageProducer thread has encountered timeout -> going to kill!"); + messageProducerThread->terminate(); + messageProducerThread->wait(); + MUtils::OS::system_message_err(L"LameXP", L"LameXP is already running, but the running instance doesn't respond!"); + return -1; + } + return 0; + } + else + { + qFatal("The IPC initialization has failed!"); + return -1; + } + } + + return 1; +} + +static void lamexp_show_splash(const MUtils::CPUFetaures::cpu_info_t &cpuFeatures, SettingsModel *const settingsModel) +{ + QScopedPointer poInitializationThread(new InitializationThread(cpuFeatures)); + SplashScreen::showSplash(poInitializationThread.data()); + settingsModel->slowStartup(poInitializationThread->getSlowIndicator()); +} + +static int lamexp_main_loop_helper(MUtils::IPCChannel *const ipcChannel, FileListModel *const fileListModel, AudioFileModel_MetaInfo *const metaInfo, SettingsModel *const settingsModel, int &iShutdown) +{ + int iResult = -1; + bool bAccepted = true; + + //Create main window + QScopedPointer poMainWindow(new MainWindow(ipcChannel, fileListModel, metaInfo, settingsModel)); + + //Main application loop + while(bAccepted && (iShutdown <= SHUTDOWN_FLAG_NONE)) + { + //Show main window + poMainWindow->show(); + iResult = qApp->exec(); + bAccepted = poMainWindow->isAccepted(); + + //Sync settings + settingsModel->syncNow(); + + //Show processing dialog + if(bAccepted && (fileListModel->rowCount() > 0)) + { + ProcessingDialog *processingDialog = new ProcessingDialog(fileListModel, metaInfo, settingsModel); + processingDialog->exec(); + iShutdown = processingDialog->getShutdownFlag(); + MUTILS_DELETE(processingDialog); + } + } + + return iResult; +} + +static int lamexp_main_loop(const MUtils::CPUFetaures::cpu_info_t &cpuFeatures, MUtils::IPCChannel *const ipcChannel, int &iShutdown) +{ + //Create models + QScopedPointer fileListModel(new FileListModel() ); + QScopedPointer metaInfo (new AudioFileModel_MetaInfo()); + QScopedPointer settingsModel(new SettingsModel() ); + + //Show splash screen + lamexp_show_splash(cpuFeatures, settingsModel.data()); + + //Validate settings + settingsModel->validate(); + + //Main processing loop + return lamexp_main_loop_helper(ipcChannel, fileListModel.data(), metaInfo.data(), settingsModel.data(), iShutdown); +} + +/////////////////////////////////////////////////////////////////////////////// +// Main function +/////////////////////////////////////////////////////////////////////////////// + +static int lamexp_main(int &argc, char **argv) +{ + int iResult = -1; + int iShutdown = SHUTDOWN_FLAG_NONE; + //Print logo + lamexp_print_logo(); + //Get CLI arguments const QStringList &arguments = MUtils::OS::arguments(); @@ -125,34 +221,10 @@ static int lamexp_main(int &argc, char **argv) } //Initialize IPC - MUtils::IPCChannel *ipcChannel = new MUtils::IPCChannel("LameXP", "MultiInstanceHandling"); - if((iResult = ipcChannel->initialize()) != MUtils::IPC_RET_SUCCESS_MASTER) + QScopedPointer ipcChannel(new MUtils::IPCChannel("lamexp-v4", lamexp_version_build(), "instance")); + if((iResult = lamexp_initialize_ipc(ipcChannel.data())) < 1) { - if(iResult == MUtils::IPC_RET_SUCCESS_SLAVE) - { - qDebug("LameXP is already running, connecting to running instance..."); - MessageProducerThread *messageProducerThread = new MessageProducerThread(ipcChannel); - messageProducerThread->start(); - if(!messageProducerThread->wait(30000)) - { - messageProducerThread->terminate(); - QMessageBox messageBox(QMessageBox::Critical, "LameXP", "LameXP is already running, but the running instance doesn't respond!", QMessageBox::NoButton, NULL, Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint | Qt::WindowStaysOnTopHint); - messageBox.exec(); - messageProducerThread->wait(); - MUTILS_DELETE(messageProducerThread); - MUTILS_DELETE(ipcChannel); - lamexp_finalization(); - return EXIT_FAILURE; - } - MUTILS_DELETE(messageProducerThread); - } - else - { - qFatal("The IPC initialization has failed!"); - } - MUTILS_DELETE(ipcChannel); - lamexp_finalization(); - return EXIT_SUCCESS; + return (iResult == 0) ? EXIT_SUCCESS : EXIT_FAILURE; } //Kill application? @@ -160,7 +232,6 @@ static int lamexp_main(int &argc, char **argv) { if(!arguments[i].compare("--kill", Qt::CaseInsensitive) || !arguments[i].compare("--force-kill", Qt::CaseInsensitive)) { - MUTILS_DELETE(ipcChannel); lamexp_finalization(); return EXIT_SUCCESS; } @@ -175,61 +246,19 @@ static int lamexp_main(int &argc, char **argv) //Taskbar init WinSevenTaskbar::init(); - //Create models - FileListModel *fileListModel = new FileListModel(); - AudioFileModel_MetaInfo *metaInfo = new AudioFileModel_MetaInfo(); - SettingsModel *settingsModel = new SettingsModel(); - - //Show splash screen - InitializationThread *poInitializationThread = new InitializationThread(cpuFeatures); - SplashScreen::showSplash(poInitializationThread); - settingsModel->slowStartup(poInitializationThread->getSlowIndicator()); - MUTILS_DELETE(poInitializationThread); - - //Validate settings - settingsModel->validate(); - - //Create main window - MainWindow *poMainWindow = new MainWindow(ipcChannel, fileListModel, metaInfo, settingsModel); - //Main application loop - while(bAccepted && (iShutdown <= shutdownFlag_None)) - { - //Show main window - poMainWindow->show(); - iResult = qApp->exec(); - bAccepted = poMainWindow->isAccepted(); - - //Sync settings - settingsModel->syncNow(); - - //Show processing dialog - if(bAccepted && (fileListModel->rowCount() > 0)) - { - ProcessingDialog *processingDialog = new ProcessingDialog(fileListModel, metaInfo, settingsModel); - processingDialog->exec(); - iShutdown = processingDialog->getShutdownFlag(); - MUTILS_DELETE(processingDialog); - } - } - - //Free models - MUTILS_DELETE(poMainWindow); - MUTILS_DELETE(fileListModel); - MUTILS_DELETE(metaInfo); - MUTILS_DELETE(settingsModel); + iResult = lamexp_main_loop(cpuFeatures, ipcChannel.data(), iShutdown); //Taskbar un-init WinSevenTaskbar::uninit(); - MUTILS_DELETE(ipcChannel); //Final clean-up qDebug("Shutting down, please wait...\n"); //Shotdown computer - if(iShutdown > shutdownFlag_None) + if(iShutdown > SHUTDOWN_FLAG_NONE) { - if(!MUtils::OS::shutdown_computer(QApplication::applicationFilePath(), 12, true, (iShutdown == shutdownFlag_Hibernate))) + if(!MUtils::OS::shutdown_computer(QApplication::applicationFilePath(), 12, true, (iShutdown == SHUTDOWN_FLAG_HIBERNATE))) { QMessageBox messageBox(QMessageBox::Critical, "LameXP", "Sorry, LameXP was unable to shutdown your computer!", QMessageBox::NoButton, NULL, Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint | Qt::WindowStaysOnTopHint); } diff --git a/src/Thread_MessageHandler.cpp b/src/Thread_MessageHandler.cpp index 245220b1..f0b02c6f 100644 --- a/src/Thread_MessageHandler.cpp +++ b/src/Thread_MessageHandler.cpp @@ -24,6 +24,7 @@ //Internal #include "Global.h" +#include "IPCCommands.h" //MUtils #include @@ -36,6 +37,8 @@ //CRL #include +#define TEST_FLAG(X) ((flags & (X)) == (X)) + //////////////////////////////////////////////////////////// // Constructor //////////////////////////////////////////////////////////// @@ -45,7 +48,7 @@ MessageHandlerThread::MessageHandlerThread(MUtils::IPCChannel *const ipcChannel) m_ipcChannel(ipcChannel) { m_aborted = false; - m_parameter = new char[4096]; + m_parameter = new char[MUtils::IPCChannel::MAX_MESSAGE_LEN]; } MessageHandlerThread::~MessageHandlerThread(void) @@ -60,33 +63,35 @@ void MessageHandlerThread::run() while(!m_aborted) { - unsigned int command = 0; - m_ipcChannel->read(command, m_parameter, 4096); - if(!command) continue; + unsigned int command = 0, flags = 0; + if(!m_ipcChannel->read(command, flags, m_parameter, MUtils::IPCChannel::MAX_MESSAGE_LEN)) + { + qWarning("Failed to read next IPC message!"); + break; + } + + if(command == IPC_CMD_NOOP) + { + continue; + } switch(command) { - case 1: + case IPC_CMD_PING: + emit otherInstanceDetected(); + break; + case IPC_CMD_ADD_FILE: emit fileReceived(QString::fromUtf8(m_parameter)); break; - case 2: - emit folderReceived(QString::fromUtf8(m_parameter), false); + case IPC_CMD_ADD_FOLDER: + emit folderReceived(QString::fromUtf8(m_parameter), TEST_FLAG(IPC_FLAG_ADD_RECURSIVE)); break; - case 3: - emit folderReceived(QString::fromUtf8(m_parameter), true); - break; - case 666: - if(!_stricmp(m_parameter, "Force!")) + case IPC_CMD_TERMINATE: + if(TEST_FLAG(IPC_FLAG_FORCE)) { _exit(-2); } - else - { - emit killSignalReceived(); - } - break; - case UINT_MAX: - emit otherInstanceDetected(); + emit killSignalReceived(); break; default: qWarning("Received an unknown IPC message! (command=%u)", command); @@ -100,7 +105,7 @@ void MessageHandlerThread::stop(void) if(!m_aborted) { m_aborted = true; - m_ipcChannel->send(0, NULL); + m_ipcChannel->send(0, 0, NULL); } } diff --git a/src/Thread_MessageProducer.cpp b/src/Thread_MessageProducer.cpp index 0a4bbcc9..828a5c86 100644 --- a/src/Thread_MessageProducer.cpp +++ b/src/Thread_MessageProducer.cpp @@ -24,6 +24,7 @@ //Internal #include "Global.h" +#include "IPCCommands.h" //MUtils #include @@ -63,12 +64,18 @@ void MessageProducerThread::run() { if(!arguments[i].compare("--kill", Qt::CaseInsensitive)) { - m_ipcChannel->send(666, NULL); + if(!m_ipcChannel->send(IPC_CMD_TERMINATE, IPC_FLAG_NONE, NULL)) + { + qWarning("Failed to send IPC message!"); + } return; } if(!arguments[i].compare("--force-kill", Qt::CaseInsensitive)) { - m_ipcChannel->send(666, "Force!"); + if(!m_ipcChannel->send(IPC_CMD_TERMINATE, IPC_FLAG_FORCE, NULL)) + { + qWarning("Failed to send IPC message!"); + } return; } } @@ -80,7 +87,10 @@ void MessageProducerThread::run() QFileInfo file = QFileInfo(arguments[++i]); if(file.exists() && file.isFile()) { - m_ipcChannel->send(1, MUTILS_UTF8(file.canonicalFilePath())); + if(!m_ipcChannel->send(IPC_CMD_ADD_FILE, IPC_FLAG_NONE, MUTILS_UTF8(file.canonicalFilePath()))) + { + qWarning("Failed to send IPC message!"); + } } bSentFiles = true; } @@ -89,7 +99,10 @@ void MessageProducerThread::run() QDir dir = QDir(arguments[++i]); if(dir.exists()) { - m_ipcChannel->send(2, MUTILS_UTF8(dir.canonicalPath())); + if(!m_ipcChannel->send(IPC_CMD_ADD_FOLDER, IPC_FLAG_NONE, MUTILS_UTF8(dir.canonicalPath()))) + { + qWarning("Failed to send IPC message!"); + } } bSentFiles = true; } @@ -98,7 +111,10 @@ void MessageProducerThread::run() QDir dir = QDir(arguments[++i]); if(dir.exists()) { - m_ipcChannel->send(3, MUTILS_UTF8(dir.canonicalPath())); + if(!m_ipcChannel->send(IPC_CMD_ADD_FOLDER, IPC_FLAG_ADD_RECURSIVE, MUTILS_UTF8(dir.canonicalPath()))) + { + qWarning("Failed to send IPC message!"); + } } bSentFiles = true; } @@ -106,7 +122,10 @@ void MessageProducerThread::run() if(!bSentFiles) { - m_ipcChannel->send(UINT_MAX, "Use running instance!"); + if(!m_ipcChannel->send(IPC_CMD_PING, IPC_FLAG_NONE, "Use running instance!")) + { + qWarning("Failed to send IPC message!"); + } } } diff --git a/src/Thread_MessageProducer.h b/src/Thread_MessageProducer.h index a6d3c221..4181cb3a 100644 --- a/src/Thread_MessageProducer.h +++ b/src/Thread_MessageProducer.h @@ -36,6 +36,7 @@ class MessageProducerThread: public QThread public: MessageProducerThread(MUtils::IPCChannel *const ipcChannel); ~MessageProducerThread(void); + void run(); protected: