From a1fbc790bf6aecf4fc71e95524b2a606adf355c9 Mon Sep 17 00:00:00 2001 From: f4exb Date: Sat, 18 Aug 2018 21:30:51 +0200 Subject: [PATCH] Added the SDRdaemon server executable --- CMakeLists.txt | 26 +++++ appdaemon/main.cpp | 115 +++++++++++++++++++++++ sdrbase/plugin/pluginmanager.cpp | 29 ++++-- sdrbase/plugin/pluginmanager.h | 2 + sdrdaemon/sdrdaemonmain.cpp | 19 ++-- sdrdaemon/sdrdaemonmain.h | 5 +- sdrdaemon/webapi/webapirequestmapper.cpp | 2 +- 7 files changed, 178 insertions(+), 20 deletions(-) create mode 100644 appdaemon/main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 1d39b60f0..ed0465ff0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -327,6 +327,31 @@ target_link_libraries(sdrangelbench target_compile_features(sdrangelbench PRIVATE cxx_generalized_initializers) # cmake >= 3.1.0 target_link_libraries(sdrangelbench Qt5::Multimedia) +############################################################################## +# SDRdaemon application + +set(sdrdaemonsrv_SOURCES + appdaemon/main.cpp +) + +add_executable(sdrdaemonsrv + ${sdrdaemonsrv_SOURCES} +) + +target_include_directories(sdrdaemonsrv + PUBLIC ${CMAKE_SOURCE_DIR}/sdrdaemon +) + +target_link_libraries(sdrdaemonsrv + sdrdaemon + sdrbase + logging + ${QT_LIBRARIES} +) + +target_compile_features(sdrdaemonsrv PRIVATE cxx_generalized_initializers) # cmake >= 3.1.0 +target_link_libraries(sdrdaemonsrv Qt5::Multimedia) + ############################################################################## if (BUILD_DEBIAN) @@ -360,6 +385,7 @@ endif(LIBUSB_FOUND AND UNIX) install(TARGETS sdrangel DESTINATION bin) install(TARGETS sdrangelsrv DESTINATION bin) install(TARGETS sdrangelbench DESTINATION bin) +install(TARGETS sdrdaemonsrv DESTINATION bin) #install(TARGETS sdrbase DESTINATION lib) #install files and directories diff --git a/appdaemon/main.cpp b/appdaemon/main.cpp new file mode 100644 index 000000000..6194726cf --- /dev/null +++ b/appdaemon/main.cpp @@ -0,0 +1,115 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2018 Edouard Griffiths, F4EXB. // +// // +// SDRdaemon instance // +// // +// SDRdaemon is a detached SDR front end that handles the interface with a // +// physical device and sends or receives the I/Q samples stream to or from a // +// SDRangel instance via UDP. It is controlled via a Web REST API. // +// // +// 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 as version 3 of the License, or // +// // +// 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 V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include + +#include +#include +#include + +#include "mainparser.h" +#include "loggerwithfile.h" +#include "sdrdaemonmain.h" +#include "dsp/dsptypes.h" + +void handler(int sig) { + fprintf(stderr, "quit the application by signal(%d).\n", sig); + QCoreApplication::quit(); +} + +void catchUnixSignals(const std::vector& quitSignals) { + sigset_t blocking_mask; + sigemptyset(&blocking_mask); + + for (std::vector::const_iterator it = quitSignals.begin(); it != quitSignals.end(); ++it) { + sigaddset(&blocking_mask, *it); + } + + struct sigaction sa; + sa.sa_handler = handler; + sa.sa_mask = blocking_mask; + sa.sa_flags = 0; + + for (std::vector::const_iterator it = quitSignals.begin(); it != quitSignals.end(); ++it) { + sigaction(*it, &sa, 0); + } +} + +static int runQtApplication(int argc, char* argv[], qtwebapp::LoggerWithFile *logger) +{ + QCoreApplication a(argc, argv); + + QCoreApplication::setOrganizationName("f4exb"); + QCoreApplication::setApplicationName("SDRdaemonSrv"); + QCoreApplication::setApplicationVersion("4.1.0"); + + int catchSignals[] = {SIGQUIT, SIGINT, SIGTERM, SIGHUP}; + std::vector vsig(catchSignals, catchSignals + sizeof(catchSignals) / sizeof(int)); + catchUnixSignals(vsig); + + MainParser parser; + parser.parse(a); + +#if QT_VERSION >= 0x050400 + qInfo("%s %s Qt %s %db %s %s DSP Rx:%db Tx:%db PID %lld", + qPrintable(QCoreApplication::applicationName()), + qPrintable(QCoreApplication::applicationVersion()), + qPrintable(QString(QT_VERSION_STR)), + QT_POINTER_SIZE*8, + qPrintable(QSysInfo::currentCpuArchitecture()), + qPrintable(QSysInfo::prettyProductName()), + SDR_RX_SAMP_SZ, + SDR_TX_SAMP_SZ, + QCoreApplication::applicationPid()); +#else + qInfo("%s %s Qt %s %db DSP Rx:%db Tx:%db PID %lld", + qPrintable(QCoreApplication::applicationName()), + qPrintable((QCoreApplication::>applicationVersion()), + qPrintable(QString(QT_VERSION_STR)), + QT_POINTER_SIZE*8, + SDR_RX_SAMP_SZ, + SDR_TX_SAMP_SZ, + QCoreApplication::applicationPid()); +#endif + + SDRDaemonMain m(logger, parser, &a); + + // This will cause the application to exit when SDRdaemon is finished + QObject::connect(&m, SIGNAL(finished()), &a, SLOT(quit())); + + return a.exec(); +} + +int main(int argc, char* argv[]) +{ + qtwebapp::LoggerWithFile *logger = new qtwebapp::LoggerWithFile(qApp); + logger->installMsgHandler(); + int res = runQtApplication(argc, argv, logger); + qWarning("SDRdaemon quit."); + return res; +} + + + + + diff --git a/sdrbase/plugin/pluginmanager.cpp b/sdrbase/plugin/pluginmanager.cpp index f94f9b481..17574b33e 100644 --- a/sdrbase/plugin/pluginmanager.cpp +++ b/sdrbase/plugin/pluginmanager.cpp @@ -55,9 +55,15 @@ PluginManager::~PluginManager() void PluginManager::loadPlugins(const QString& pluginsSubDir) { - QString applicationDirPath = QCoreApplication::instance()->applicationDirPath(); - QString applicationLibPath = applicationDirPath + "/../lib/" + pluginsSubDir; - QString applicationBuildPath = applicationDirPath + "/" + pluginsSubDir; + loadPluginsPart(pluginsSubDir); + loadPluginsFinal(); +} + +void PluginManager::loadPluginsPart(const QString& pluginsSubDir) +{ + QString applicationDirPath = QCoreApplication::instance()->applicationDirPath(); + QString applicationLibPath = applicationDirPath + "/../lib/" + pluginsSubDir; + QString applicationBuildPath = applicationDirPath + "/" + pluginsSubDir; qDebug() << "PluginManager::loadPlugins: " << qPrintable(applicationLibPath) << "," << qPrintable(applicationBuildPath); QDir pluginsLibDir = QDir(applicationLibPath); @@ -65,16 +71,19 @@ void PluginManager::loadPlugins(const QString& pluginsSubDir) loadPluginsDir(pluginsLibDir); loadPluginsDir(pluginsBuildDir); +} - qSort(m_plugins); +void PluginManager::loadPluginsFinal() +{ + qSort(m_plugins); - for (Plugins::const_iterator it = m_plugins.begin(); it != m_plugins.end(); ++it) - { - it->pluginInterface->initPlugin(&m_pluginAPI); - } + for (Plugins::const_iterator it = m_plugins.begin(); it != m_plugins.end(); ++it) + { + it->pluginInterface->initPlugin(&m_pluginAPI); + } - DeviceEnumerator::instance()->enumerateRxDevices(this); - DeviceEnumerator::instance()->enumerateTxDevices(this); + DeviceEnumerator::instance()->enumerateRxDevices(this); + DeviceEnumerator::instance()->enumerateTxDevices(this); } void PluginManager::registerRxChannel(const QString& channelIdURI, const QString& channelId, PluginInterface* plugin) diff --git a/sdrbase/plugin/pluginmanager.h b/sdrbase/plugin/pluginmanager.h index fafb25c34..e313563d9 100644 --- a/sdrbase/plugin/pluginmanager.h +++ b/sdrbase/plugin/pluginmanager.h @@ -43,6 +43,8 @@ public: PluginAPI *getPluginAPI() { return &m_pluginAPI; } void loadPlugins(const QString& pluginsSubDir); + void loadPluginsPart(const QString& pluginsSubDir); + void loadPluginsFinal(); const Plugins& getPlugins() const { return m_plugins; } // Callbacks from the plugins diff --git a/sdrdaemon/sdrdaemonmain.cpp b/sdrdaemon/sdrdaemonmain.cpp index db2567772..6e26ee02e 100644 --- a/sdrdaemon/sdrdaemonmain.cpp +++ b/sdrdaemon/sdrdaemonmain.cpp @@ -24,6 +24,7 @@ #include #include +#include "mainparser.h" #include "dsp/dspengine.h" #include "dsp/dspdevicesourceengine.h" #include "plugin/pluginmanager.h" @@ -44,12 +45,14 @@ SDRDaemonMain::SDRDaemonMain(qtwebapp::LoggerWithFile *logger, const MainParser& m_dspEngine(DSPEngine::instance()), m_lastEngineState(DSPDeviceSourceEngine::StNotStarted) { - qDebug() << "SDRdaemon::SDRdaemon: start"; + qDebug() << "SDRDaemonMain::SDRDaemonMain: start"; m_instance = this; m_pluginManager = new PluginManager(this); - m_pluginManager->loadPlugins(QString("pluginssrv")); + m_pluginManager->loadPluginsPart(QString("pluginssrv/samplesink")); + m_pluginManager->loadPluginsPart(QString("pluginssrv/samplesource")); + m_pluginManager->loadPluginsFinal(); connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleMessages()), Qt::QueuedConnection); m_masterTimer.start(50); @@ -59,9 +62,9 @@ SDRDaemonMain::SDRDaemonMain(qtwebapp::LoggerWithFile *logger, const MainParser& QString applicationDirPath = QCoreApplication::instance()->applicationDirPath(); if (QResource::registerResource(applicationDirPath + "/sdrbase.rcc")) { - qDebug("MainCore::MainCore: registered resource file %s/%s", qPrintable(applicationDirPath), "sdrbase.rcc"); + qDebug("SDRDaemonMain::SDRDaemonMain: registered resource file %s/%s", qPrintable(applicationDirPath), "sdrbase.rcc"); } else { - qWarning("MainCore::MainCore: could not register resource file %s/%s", qPrintable(applicationDirPath), "sdrbase.rcc"); + qWarning("SDRDaemonMain::SDRDaemonMain: could not register resource file %s/%s", qPrintable(applicationDirPath), "sdrbase.rcc"); } m_apiAdapter = new WebAPIAdapterDaemon(*this); @@ -70,7 +73,7 @@ SDRDaemonMain::SDRDaemonMain(qtwebapp::LoggerWithFile *logger, const MainParser& m_apiServer = new SDRDaemon::WebAPIServer(parser.getServerAddress(), parser.getServerPort(), m_requestMapper); m_apiServer->start(); - qDebug() << "SDRdaemon::SDRdaemon: end"; + qDebug() << "SDRDaemonMain::SDRDaemonMain: end"; } SDRDaemonMain::~SDRDaemonMain() @@ -83,13 +86,13 @@ SDRDaemonMain::~SDRDaemonMain() delete m_pluginManager; - qDebug() << "SDRdaemon::~SDRdaemon: end"; + qDebug() << "SDRDaemonMain::~SDRdaemon: end"; delete m_logger; } void SDRDaemonMain::loadSettings() { - qDebug() << "SDRdaemon::loadSettings"; + qDebug() << "SDRDaemonMain::loadSettings"; m_settings.load(); setLoggingOptions(); @@ -155,7 +158,7 @@ void SDRDaemonMain::handleMessages() while ((message = m_inputMessageQueue.pop()) != 0) { - qDebug("SDRdaemon::handleMessages: message: %s", message->getIdentifier()); + qDebug("SDRDaemonMain::handleMessages: message: %s", message->getIdentifier()); handleMessage(*message); delete message; } diff --git a/sdrdaemon/sdrdaemonmain.h b/sdrdaemon/sdrdaemonmain.h index 1d9fe0862..3ca10d0d6 100644 --- a/sdrdaemon/sdrdaemonmain.h +++ b/sdrdaemon/sdrdaemonmain.h @@ -26,7 +26,6 @@ #include #include -#include "mainparser.h" #include "sdrdaemonsettings.h" #include "util/messagequeue.h" @@ -39,6 +38,7 @@ namespace qtwebapp { class LoggerWithFile; } +class MainParser; class DSPEngine; class PluginManager; class Message; @@ -51,6 +51,9 @@ public: ~SDRDaemonMain(); static SDRDaemonMain *getInstance() { return m_instance; } // Main Core is de facto a singleton so this just returns its reference +signals: + void finished(); + private: static SDRDaemonMain *m_instance; qtwebapp::LoggerWithFile *m_logger; diff --git a/sdrdaemon/webapi/webapirequestmapper.cpp b/sdrdaemon/webapi/webapirequestmapper.cpp index 3b2a6eb7f..c8b2cd807 100644 --- a/sdrdaemon/webapi/webapirequestmapper.cpp +++ b/sdrdaemon/webapi/webapirequestmapper.cpp @@ -81,7 +81,7 @@ void WebAPIRequestMapper::service(qtwebapp::HttpRequest& request, qtwebapp::Http return; } - if (path.startsWith("/sdrangel")) + if (path.startsWith("/sdrangel") && (path != "/sdrangel_logo.png")) { SWGSDRangel::SWGErrorResponse errorResponse; response.setStatus(501,"Not implemented");