diff --git a/core/src/core.cpp b/core/src/core.cpp index 9bc9af64..b13b8f83 100644 --- a/core/src/core.cpp +++ b/core/src/core.cpp @@ -40,6 +40,7 @@ namespace core { ConfigManager configManager; ScriptManager scriptManager; ModuleManager moduleManager; + ModuleComManager modComManager; void setInputSampleRate(double samplerate) { // NOTE: Zoom controls won't work diff --git a/core/src/core.h b/core/src/core.h index f9b3be8b..b10e7d3e 100644 --- a/core/src/core.h +++ b/core/src/core.h @@ -3,11 +3,13 @@ #include #include #include +#include namespace core { SDRPP_EXPORT ConfigManager configManager; SDRPP_EXPORT ScriptManager scriptManager; SDRPP_EXPORT ModuleManager moduleManager; + SDRPP_EXPORT ModuleComManager modComManager; void setInputSampleRate(double samplerate); }; diff --git a/core/src/module_com.cpp b/core/src/module_com.cpp new file mode 100644 index 00000000..10bba023 --- /dev/null +++ b/core/src/module_com.cpp @@ -0,0 +1,51 @@ +#include + +bool ModuleComManager::registerInterface(std::string moduleName, std::string name, void (*handler)(int code, void* in, void* out, void* ctx), void* ctx) { + std::lock_guard lck(mtx); + if (interfaces.find(name) != interfaces.end()) { + spdlog::error("Tried creating module interface with an existing name: {0}", name); + return false; + } + ModuleComInterface iface; + iface.moduleName = moduleName; + iface.handler = handler; + iface.ctx = ctx; + interfaces[name] = iface; + return true; +} + +bool ModuleComManager::unregisterInterface(std::string name) { + std::lock_guard lck(mtx); + if (interfaces.find(name) == interfaces.end()) { + spdlog::error("Tried to erase module interface with unknown name: {0}", name); + return false; + } + interfaces.erase(name); + return true; +} + +bool ModuleComManager::interfaceExists(std::string name) { + std::lock_guard lck(mtx); + if (interfaces.find(name) == interfaces.end()) { return false; } + return true; +} + +std::string ModuleComManager::getModuleName(std::string name) { + std::lock_guard lck(mtx); + if (interfaces.find(name) == interfaces.end()) { + spdlog::error("Tried to call unknown module interface: {0}", name); + return ""; + } + return interfaces[name].moduleName; +} + +bool ModuleComManager::callInterface(std::string name, int code, void* in, void* out) { + std::lock_guard lck(mtx); + if (interfaces.find(name) == interfaces.end()) { + spdlog::error("Tried to call unknown module interface: {0}", name); + return false; + } + ModuleComInterface iface = interfaces[name]; + iface.handler(code, in, out, iface.ctx); + return true; +} \ No newline at end of file diff --git a/core/src/module_com.h b/core/src/module_com.h new file mode 100644 index 00000000..6729dc19 --- /dev/null +++ b/core/src/module_com.h @@ -0,0 +1,24 @@ +#pragma once +#include +#include +#include +#include + +struct ModuleComInterface { + std::string moduleName; + void* ctx; + void (*handler)(int code, void* in, void* out, void* ctx); +}; + +class ModuleComManager { +public: + bool registerInterface(std::string moduleName, std::string name, void (*handler)(int code, void* in, void* out, void* ctx), void* ctx); + bool unregisterInterface(std::string name); + bool interfaceExists(std::string name); + std::string getModuleName(std::string name); + bool callInterface(std::string name, int code, void* in, void* out); + +private: + std::mutex mtx; + std::map interfaces; +}; \ No newline at end of file diff --git a/discord_integration/CMakeLists.txt b/discord_integration/CMakeLists.txt index a1bfe7c3..e1d511d1 100644 --- a/discord_integration/CMakeLists.txt +++ b/discord_integration/CMakeLists.txt @@ -12,7 +12,7 @@ endif () add_subdirectory("discord-rpc") file(GLOB SRC "src/*.cpp") -include_directories("src/" "discord-rpc/include") +include_directories("src/" "discord-rpc/include" "../radio/src/") add_library(discord_integration SHARED ${SRC}) target_link_libraries(discord_integration PUBLIC sdrpp_core discord-rpc) diff --git a/discord_integration/src/main.cpp b/discord_integration/src/main.cpp index efaacc97..55c29c0e 100644 --- a/discord_integration/src/main.cpp +++ b/discord_integration/src/main.cpp @@ -6,29 +6,24 @@ #include #include #include +#include SDRPP_MOD_INFO { /* Name: */ "discord_integration", /* Description: */ "Discord Rich Presence module for SDR++", - /* Author: */ "Starman0620 & Ryzerth", + /* Author: */ "Starman0620;Ryzerth", /* Version: */ 0, 0, 2, /* Max instances */ 1 }; -DiscordRichPresence presence; -uint64_t lastFreq; -char* freq = new char[24]; - -// Threading -int workerCounter = 0; -std::thread workerThread; -bool workerRunning; +#define DISCORD_APP_ID "834590435708108860" class PresenceModule : public ModuleManager::Instance { public: PresenceModule(std::string name) { this->name = name; + // Change to timer start later on workerRunning = true; workerThread = std::thread(&PresenceModule::worker, this); @@ -36,17 +31,23 @@ public: } ~PresenceModule() { + // Change to timer stop later on workerRunning = false; if (workerThread.joinable()) { workerThread.join(); } } void enable() { + // Change to timer start later on workerRunning = true; + workerThread = std::thread(&PresenceModule::worker, this); enabled = true; } void disable() { + // Change to timer stop later on workerRunning = false; + if (workerThread.joinable()) { workerThread.join(); } + enabled = false; Discord_ClearPresence(); } @@ -59,6 +60,8 @@ private: // Main thread void worker() { + // TODO: Switch out for condition variable to terminate thread instantly + // OR even better, the new timer class that I still need to add while (workerRunning) { workerCounter++; if(workerCounter >= 1000) { @@ -69,36 +72,78 @@ private: } } - static void updatePresence() { - if (gui::freqSelect.frequency != lastFreq) { - presence.details = "Listening"; // This really doesn't need to be re-set each time but it'll remain since it will be used once proper status can be displayed - sprintf(freq, "%.2fMHz", (float)gui::freqSelect.frequency/1000000); + void updatePresence() { + double selectedFreq = gui::freqSelect.frequency; + std::string selectedName = gui::waterfall.selectedVFO; + if (selectedFreq != lastFreq) { + lastFreq = selectedFreq; + + strcpy(mode, "Raw"); + + if (core::modComManager.interfaceExists(selectedName)) { + if (core::modComManager.getModuleName(selectedName) == "radio") { + int modeNum; + core::modComManager.callInterface(selectedName, RADIO_IFACE_CMD_GET_MODE, NULL, &modeNum); + if (modeNum == RADIO_IFACE_MODE_NFM) { strcpy(mode, "NFM"); } + else if (modeNum == RADIO_IFACE_MODE_WFM) { strcpy(mode, "FM"); } + else if (modeNum == RADIO_IFACE_MODE_AM) { strcpy(mode, "AM"); } + else if (modeNum == RADIO_IFACE_MODE_DSB) { strcpy(mode, "DSB"); } + else if (modeNum == RADIO_IFACE_MODE_USB) { strcpy(mode, "USB"); } + else if (modeNum == RADIO_IFACE_MODE_CW) { strcpy(mode, "CW"); } + else if (modeNum == RADIO_IFACE_MODE_LSB) { strcpy(mode, "LSB"); } + } + } + + // Print out frequency to buffer + if (selectedFreq >= 1000000.0) { + sprintf(freq, "%.3lfMHz %s", selectedFreq / 1000000.0, mode); + } + else if (selectedFreq >= 1000.0) { + sprintf(freq, "%.3lfKHz %s", selectedFreq / 1000.0, mode); + } + else { + sprintf(freq, "%.3lfHz %s", selectedFreq, mode); + } + + // Fill in the rest of the details and send to discord + presence.details = "Listening to"; presence.state = freq; Discord_UpdatePresence(&presence); - lastFreq = gui::freqSelect.frequency; } } - static void startPresence() { + void startPresence() { // Discord initialization DiscordEventHandlers handlers; memset(&handlers, 0, sizeof(handlers)); memset(&presence, 0, sizeof(presence)); - Discord_Initialize("833485588954742864", &handlers, 1, ""); + Discord_Initialize(DISCORD_APP_ID, &handlers, 1, ""); // Set the first presence presence.details = "Initializing rich presence..."; presence.startTimestamp = time(0); - presence.largeImageKey = "image_large"; + presence.largeImageKey = "sdrpp_large"; Discord_UpdatePresence(&presence); } std::string name; bool enabled = true; + + // Rich Presence + DiscordRichPresence presence; + double lastFreq; + char* freq = new char[1024]; + char* mode = new char[1024]; + + // Threading + int workerCounter = 0; + std::thread workerThread; + bool workerRunning; + }; MOD_EXPORT void _INIT_() { - + // Nothing here } MOD_EXPORT ModuleManager::Instance* _CREATE_INSTANCE_(std::string name) { @@ -110,5 +155,5 @@ MOD_EXPORT void _DELETE_INSTANCE_(void* instance) { } MOD_EXPORT void _END_() { - + // Nothing here } \ No newline at end of file diff --git a/radio/src/main.cpp b/radio/src/main.cpp index dd41c398..8fabe838 100644 --- a/radio/src/main.cpp +++ b/radio/src/main.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #define CONCAT(a, b) ((std::string(a) + b).c_str()) @@ -63,6 +64,8 @@ public: stream.start(); gui::menu.registerEntry(name, menuHandler, this, this); + + core::modComManager.registerInterface("radio", name, moduleInterfaceHandler, this); } ~RadioModule() { @@ -155,6 +158,13 @@ private: } } + static void moduleInterfaceHandler(int code, void* in, void* out, void* ctx) { + RadioModule* _this = (RadioModule*)ctx; + if (code == RADIO_IFACE_CMD_GET_MODE) { + *(int*)out = _this->demodId; + } + } + void selectDemod(Demodulator* demod) { if (currentDemod != NULL) { currentDemod->stop(); } currentDemod = demod; diff --git a/radio/src/radio_interface.h b/radio/src/radio_interface.h new file mode 100644 index 00000000..b1122ee7 --- /dev/null +++ b/radio/src/radio_interface.h @@ -0,0 +1,16 @@ +#pragma once + +enum { + RADIO_IFACE_CMD_GET_MODE +}; + +enum { + RADIO_IFACE_MODE_NFM, + RADIO_IFACE_MODE_WFM, + RADIO_IFACE_MODE_AM, + RADIO_IFACE_MODE_DSB, + RADIO_IFACE_MODE_USB, + RADIO_IFACE_MODE_CW, + RADIO_IFACE_MODE_LSB, + RADIO_IFACE_MODE_RAW +}; \ No newline at end of file