diff --git a/CMakeLists.txt b/CMakeLists.txt index c9157751..0816499c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -278,7 +278,6 @@ install(TARGETS dvmhost DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) install(TARGETS dvmcmd DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) install(TARGETS dvmfne DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) if (ENABLE_TUI_SUPPORT AND (NOT DISABLE_TUI_APPS)) -install(TARGETS dvmmon DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) install(TARGETS sysview DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) install(TARGETS tged DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) endif (ENABLE_TUI_SUPPORT AND (NOT DISABLE_TUI_APPS)) @@ -302,7 +301,6 @@ if (NOT TARGET strip) COMMAND arm-linux-gnueabihf-strip -s dvmhost COMMAND arm-linux-gnueabihf-strip -s dvmfne COMMAND arm-linux-gnueabihf-strip -s dvmcmd - COMMAND arm-linux-gnueabihf-strip -s dvmmon COMMAND arm-linux-gnueabihf-strip -s sysview COMMAND arm-linux-gnueabihf-strip -s tged COMMAND arm-linux-gnueabihf-strip -s peered @@ -322,7 +320,6 @@ if (NOT TARGET strip) COMMAND aarch64-linux-gnu-strip -s dvmhost COMMAND aarch64-linux-gnu-strip -s dvmfne COMMAND aarch64-linux-gnu-strip -s dvmcmd - COMMAND aarch64-linux-gnu-strip -s dvmmon COMMAND aarch64-linux-gnu-strip -s sysview COMMAND aarch64-linux-gnu-strip -s tged COMMAND aarch64-linux-gnu-strip -s peered @@ -342,7 +339,6 @@ if (NOT TARGET strip) COMMAND strip -s dvmhost COMMAND strip -s dvmfne COMMAND strip -s dvmcmd - COMMAND strip -s dvmmon COMMAND strip -s sysview COMMAND strip -s tged COMMAND strip -s peered @@ -378,7 +374,6 @@ if (NOT TARGET tarball) COMMAND touch ${CMAKE_INSTALL_PREFIX_TARBALL}/dvm/log/INCLUDE_DIRECTORY COMMAND cp -v dvmhost ${CMAKE_INSTALL_PREFIX_TARBALL}/dvm/bin COMMAND cp -v dvmcmd ${CMAKE_INSTALL_PREFIX_TARBALL}/dvm/bin - COMMAND cp -v dvmmon ${CMAKE_INSTALL_PREFIX_TARBALL}/dvm/bin COMMAND cp -v sysview ${CMAKE_INSTALL_PREFIX_TARBALL}/dvm/bin COMMAND cp -v tged ${CMAKE_INSTALL_PREFIX_TARBALL}/dvm/bin COMMAND cp -v peered ${CMAKE_INSTALL_PREFIX_TARBALL}/dvm/bin @@ -459,7 +454,6 @@ if (NOT TARGET tarball_notools) COMMAND touch ${CMAKE_INSTALL_PREFIX_TARBALL}/dvm/log/INCLUDE_DIRECTORY COMMAND cp -v dvmhost ${CMAKE_INSTALL_PREFIX_TARBALL}/dvm/bin COMMAND cp -v dvmcmd ${CMAKE_INSTALL_PREFIX_TARBALL}/dvm/bin - COMMAND cp -v dvmmon ${CMAKE_INSTALL_PREFIX_TARBALL}/dvm/bin COMMAND cp -v sysview ${CMAKE_INSTALL_PREFIX_TARBALL}/dvm/bin COMMAND cp -v tged ${CMAKE_INSTALL_PREFIX_TARBALL}/dvm/bin COMMAND cp -v peered ${CMAKE_INSTALL_PREFIX_TARBALL}/dvm/bin @@ -537,7 +531,6 @@ add_custom_target(old_install COMMAND mkdir -p ${CMAKE_LEGACY_INSTALL_PREFIX}/schema COMMAND install -m 755 dvmhost ${CMAKE_LEGACY_INSTALL_PREFIX}/bin COMMAND install -m 755 dvmcmd ${CMAKE_LEGACY_INSTALL_PREFIX}/bin - COMMAND install -m 755 dvmmon ${CMAKE_LEGACY_INSTALL_PREFIX}/bin COMMAND install -m 755 sysview ${CMAKE_LEGACY_INSTALL_PREFIX}/bin COMMAND install -m 755 tged ${CMAKE_LEGACY_INSTALL_PREFIX}/bin COMMAND install -m 755 peered ${CMAKE_LEGACY_INSTALL_PREFIX}/bin diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2e748572..fd59b8f8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -83,16 +83,6 @@ endif (COMPILE_WIN32) target_link_libraries(dvmfne PRIVATE common ${OPENSSL_LIBRARIES} ${LIBDW_LIBRARY} asio::asio Threads::Threads) target_include_directories(dvmfne PRIVATE ${OPENSSL_INCLUDE_DIR} ${LIBDW_INCLUDE_DIR} src src/fne) -# -## dvmmon -# -if (ENABLE_TUI_SUPPORT AND (NOT DISABLE_TUI_APPS)) - include(src/monitor/CMakeLists.txt) - add_executable(dvmmon ${common_INCLUDE} ${dvmmon_SRC}) - target_link_libraries(dvmmon PRIVATE common ${OPENSSL_LIBRARIES} ${LIBDW_LIBRARY} asio::asio finalcut Threads::Threads) - target_include_directories(dvmmon PRIVATE ${OPENSSL_INCLUDE_DIR} ${LIBDW_INCLUDE_DIR} src src/host src/monitor) -endif (ENABLE_TUI_SUPPORT AND (NOT DISABLE_TUI_APPS)) - # ## sysview # diff --git a/src/monitor/CMakeLists.txt b/src/monitor/CMakeLists.txt deleted file mode 100644 index ee9774e5..00000000 --- a/src/monitor/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -#/* -# * Digital Voice Modem - Host Monitor Software -# * GPLv2 Open Source. Use is subject to license terms. -# * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# * -# * Copyright (C) 2024 Bryan Biedenkapp, N2PLL -# * -# */ -file(GLOB dvmmon_SRC - "src/host/modem/Modem.h" - - "src/remote/RESTClient.cpp" - "src/remote/RESTClient.h" - - "src/monitor/*.h" - "src/monitor/*.cpp" -) diff --git a/src/monitor/Defines.h b/src/monitor/Defines.h deleted file mode 100644 index 46f2d81b..00000000 --- a/src/monitor/Defines.h +++ /dev/null @@ -1,34 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Digital Voice Modem - Host Monitor Software - * GPLv2 Open Source. Use is subject to license terms. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright (C) 2023 Bryan Biedenkapp, N2PLL - * - */ -/** - * @defgroup monitor Host Monitor Software (dvmmon) - * @brief Digital Voice Modem - Host Monitor Software - * @details Montior software that connects to the DVM hosts and is a quick TUI for monitoring activity on them. - * @ingroup monitor - * - * @file Defines.h - * @ingroup monitor - */ -#if !defined(__DEFINES_H__) -#define __DEFINES_H__ - -#include "common/Defines.h" -#include "common/GitHash.h" - -// --------------------------------------------------------------------------- -// Constants -// --------------------------------------------------------------------------- - -#undef __PROG_NAME__ -#define __PROG_NAME__ "Digital Voice Modem (DVM) Monitor" -#undef __EXE_NAME__ -#define __EXE_NAME__ "dvmmon" - -#endif // __DEFINES_H__ diff --git a/src/monitor/FDblDialog.h b/src/monitor/FDblDialog.h deleted file mode 100644 index 3b0efaee..00000000 --- a/src/monitor/FDblDialog.h +++ /dev/null @@ -1,87 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Digital Voice Modem - Host Monitor Software - * GPLv2 Open Source. Use is subject to license terms. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright (C) 2024 Bryan Biedenkapp, N2PLL - * - */ -/** - * @file FDblDialog.h - * @ingroup monitor - */ -#if !defined(__F_DBL_DIALOG_H__) -#define __F_DBL_DIALOG_H__ - -#include "common/Defines.h" - -#include -using namespace finalcut; - -// --------------------------------------------------------------------------- -// Class Declaration -// --------------------------------------------------------------------------- - -/** - * @brief This class implements the double-border dialog. - * @ingroup monitor - */ -class HOST_SW_API FDblDialog : public finalcut::FDialog { -public: - /** - * @brief Initializes a new instance of the FDblDialog class. - * @param widget - */ - explicit FDblDialog(FWidget* widget = nullptr) : finalcut::FDialog{widget} - { - /* stub */ - } - -protected: - /** - * @brief - */ - void drawBorder() override - { - if (!hasBorder()) - return; - - setColor(); - - FRect box{{1, 2}, getSize()}; - box.scaleBy(0, -1); - - FRect rect = box; - if (rect.x1_ref() > rect.x2_ref()) - std::swap(rect.x1_ref(), rect.x2_ref()); - - if (rect.y1_ref() > rect.y2_ref()) - std::swap(rect.y1_ref(), rect.y2_ref()); - - rect.x1_ref() = std::max(rect.x1_ref(), 1); - rect.y1_ref() = std::max(rect.y1_ref(), 1); - rect.x2_ref() = std::min(rect.x2_ref(), rect.x1_ref() + int(getWidth()) - 1); - rect.y2_ref() = std::min(rect.y2_ref(), rect.y1_ref() + int(getHeight()) - 1); - - if (box.getWidth() < 3) - return; - - // Use box-drawing characters to draw a border - constexpr std::array box_char - {{ - static_cast(0x2554), // ╔ - static_cast(0x2550), // ═ - static_cast(0x2557), // ╗ - static_cast(0x2551), // ║ - static_cast(0x2551), // ║ - static_cast(0x255A), // ╚ - static_cast(0x2550), // ═ - static_cast(0x255D) // ╝ - }}; - - drawGenericBox(this, box, box_char); - } -}; - -#endif // __F_DBL_DIALOG_H__ diff --git a/src/monitor/InhibitSubscriberWnd.h b/src/monitor/InhibitSubscriberWnd.h deleted file mode 100644 index 76204faf..00000000 --- a/src/monitor/InhibitSubscriberWnd.h +++ /dev/null @@ -1,146 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Digital Voice Modem - Host Monitor Software - * GPLv2 Open Source. Use is subject to license terms. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright (C) 2023 Bryan Biedenkapp, N2PLL - * - */ -/** - * @file InhibitSubscriberWnd.h - * @ingroup monitor - */ -#if !defined(__INHIBIT_SUBSCRIBER_WND_H__) -#define __INHIBIT_SUBSCRIBER_WND_H__ - -#include "TransmitWndBase.h" - -#include -using namespace finalcut; - -// --------------------------------------------------------------------------- -// Class Declaration -// --------------------------------------------------------------------------- - -/** - * @brief This class implements the inhibit subscriber window. - * @ingroup monitor - */ -class HOST_SW_API InhibitSubscriberWnd final : public TransmitWndBase { -public: - /** - * @brief Initializes a new instance of the InhibitSubscriberWnd class. - * @param channel Channel data. - * @param widget - */ - explicit InhibitSubscriberWnd(lookups::VoiceChData channel, FWidget* widget = nullptr) : TransmitWndBase{channel, widget} - { - /* stub */ - } - -private: - FLabel m_dialogLabel{"Inhibit Subscriber", this}; - - FLabel m_subscriberLabel{"Subscriber ID: ", this}; - FSpinBox m_subscriber{this}; - - /** - * @brief Initializes the window layout. - */ - void initLayout() override - { - FDialog::setText("Inhibit Subscriber"); - FDialog::setSize(FSize{60, 16}); - - TransmitWndBase::initLayout(); - } - - /** - * @brief Initializes window controls. - */ - void initControls() override - { - TransmitWndBase::initControls(); - - if (m_hideModeSelect) { - FDialog::setSize(FSize{60, 12}); - resizeControls(); - } - - // subscriber entry - { - if (!m_hideModeSelect) { - m_dialogLabel.setGeometry(FPoint(6, 6), FSize(20, 2)); - } - else { - m_dialogLabel.setGeometry(FPoint(6, 2), FSize(20, 2)); - } - m_dialogLabel.setEmphasis(); - m_dialogLabel.setAlignment(Align::Center); - - if (!m_hideModeSelect) { - m_subscriberLabel.setGeometry(FPoint(2, 8), FSize(25, 1)); - m_subscriber.setGeometry(FPoint(28, 8), FSize(20, 1)); - } - else { - m_subscriberLabel.setGeometry(FPoint(2, 4), FSize(25, 1)); - m_subscriber.setGeometry(FPoint(28, 4), FSize(20, 1)); - } - m_subscriber.setRange(0, 16777211); - m_subscriber.setValue(1); - m_subscriber.setShadow(false); - m_subscriber.addCallback("changed", [&]() { - if (m_subscriber.getValue() >= 1 && m_subscriber.getValue() <= 16777211) { - m_txButton.setEnable(true); - } - else { - m_txButton.setEnable(false); - } - - redraw(); - }); - } - - m_dialogLabel.redraw(); - m_subscriberLabel.redraw(); - redraw(); - } - - /** - * @brief Helper to transmit. - */ - void setTransmit() override - { - std::string method = PUT_DMR_RID; - json::object req = json::object(); - req["command"].set(RID_CMD_INHIBIT); - uint32_t dstId = m_subscriber.getValue(); - req["dstId"].set(dstId); - - switch (m_mode) { - case modem::STATE_DMR: - { - uint8_t slot = m_dmrSlot.getValue(); - req["slot"].set(slot); - } - break; - case modem::STATE_P25: - { - method = PUT_P25_RID; - } - break; - case modem::STATE_NXDN: - return; - } - - // callback REST API - int ret = RESTClient::send(m_selectedCh.address(), m_selectedCh.port(), m_selectedCh.password(), - HTTP_PUT, method, req, m_selectedCh.ssl(), g_debug); - if (ret != restapi::http::HTTPPayload::StatusType::OK) { - ::LogError(LOG_HOST, "failed to send request %s to %s:%u", method.c_str(), m_selectedCh.address().c_str(), m_selectedCh.port()); - } - } -}; - -#endif // __INHIBIT_SUBSCRIBER_WND_H__ \ No newline at end of file diff --git a/src/monitor/LogDisplayWnd.h b/src/monitor/LogDisplayWnd.h deleted file mode 100644 index abc19a69..00000000 --- a/src/monitor/LogDisplayWnd.h +++ /dev/null @@ -1,135 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Digital Voice Modem - Host Monitor Software - * GPLv2 Open Source. Use is subject to license terms. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright (C) 2023 Bryan Biedenkapp, N2PLL - * - */ -/** - * @file LogDisplayWnd.h - * @ingroup monitor - */ -#if !defined(__LOG_DISPLAY_WND_H__) -#define __LOG_DISPLAY_WND_H__ - -#include -using namespace finalcut; - -// --------------------------------------------------------------------------- -// Class Declaration -// --------------------------------------------------------------------------- - -/** - * @brief This class implements the log display window. - * @ingroup monitor - */ -class HOST_SW_API LogDisplayWnd final : public finalcut::FDialog, public std::ostringstream { -public: - /** - * @brief Initializes a new instance of the LogDisplayWnd class. - * @param widget - */ - explicit LogDisplayWnd(FWidget* widget = nullptr) : FDialog{widget} - { - m_scrollText.ignorePadding(); - - m_timerId = addTimer(250); // starts the timer every 250 milliseconds - } - /** - * @brief Copy constructor. - */ - LogDisplayWnd(const LogDisplayWnd&) = delete; - /** - * @brief Move constructor. - */ - LogDisplayWnd(LogDisplayWnd&&) noexcept = delete; - /** - * @brief Finalizes an instance of the LogDisplayWnd class. - */ - ~LogDisplayWnd() noexcept override = default; - - /** - * @brief Disable copy assignment operator (=). - */ - auto operator= (const LogDisplayWnd&) -> LogDisplayWnd& = delete; - /** - * @brief Disable move assignment operator (=). - */ - auto operator= (LogDisplayWnd&&) noexcept -> LogDisplayWnd& = delete; - -private: - FTextView m_scrollText{this}; - int m_timerId; - - /** - * @brief Initializes the window layout. - */ - void initLayout() override - { - using namespace std::string_literals; - auto lightning = "\u26a1"; - FDialog::setText("System Log"s + lightning); - - const auto& rootWidget = getRootWidget(); - - FDialog::setGeometry(FPoint{(int)(rootWidget->getClientWidth() - 81), (int)(rootWidget->getClientHeight() - 20)}, FSize{80, 20}); - FDialog::setMinimumSize(FSize{80, 20}); - FDialog::setResizeable(true); - FDialog::setMinimizable(true); - FDialog::setTitlebarButtonVisibility(true); - FDialog::setShadow(); - - minimizeWindow(); - - m_scrollText.setGeometry(FPoint{1, 2}, FSize{getWidth(), getHeight() - 1}); - - FDialog::initLayout(); - } - - /** - * @brief Adjusts window size. - */ - void adjustSize() override - { - FDialog::adjustSize(); - - m_scrollText.setGeometry(FPoint{1, 2}, FSize{getWidth(), getHeight() - 1}); - } - - /* - ** Event Handlers - */ - - /** - * @brief Event that occurs when the window is closed. - * @param e Close Event - */ - void onClose(FCloseEvent* e) override - { - minimizeWindow(); - } - - /** - * @brief Event that occurs on interval by timer. - * @param timer Timer Event - */ - void onTimer(FTimerEvent* timer) override - { - if (timer != nullptr) { - if (timer->getTimerId() == m_timerId) { - if (str().empty()) { - return; - } - - m_scrollText.append(str()); - str(""); - m_scrollText.scrollToEnd(); - redraw(); - } - } - } -}; - -#endif // __LOG_DISPLAY_WND_H__ \ No newline at end of file diff --git a/src/monitor/MonitorApplication.h b/src/monitor/MonitorApplication.h deleted file mode 100644 index 54982355..00000000 --- a/src/monitor/MonitorApplication.h +++ /dev/null @@ -1,214 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Digital Voice Modem - Host Monitor Software - * GPLv2 Open Source. Use is subject to license terms. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright (C) 2023 Bryan Biedenkapp, N2PLL - * - */ -/** - * @file MonitorApplication.h - * @ingroup monitor - */ -#if !defined(__MONITOR_APPLICATION_H__) -#define __MONITOR_APPLICATION_H__ - -#include "common/Log.h" -#include "MonitorMain.h" -#include "MonitorMainWnd.h" - -#include -using namespace finalcut; - -// --------------------------------------------------------------------------- -// Class Declaration -// --------------------------------------------------------------------------- - -/** - * @brief This class implements a color theme for a finalcut application. - * @ingroup setup - */ -class HOST_SW_API dvmColorTheme final : public FWidgetColors -{ -public: - /** - * @brief Initializes a new instance of the dvmColorTheme class. - */ - dvmColorTheme() - { - dvmColorTheme::setColorTheme(); - } - - /** - * @brief Finalizes a instance of the dvmColorTheme class. - */ - ~dvmColorTheme() noexcept override = default; - - /** - * @brief Get the Class Name object - * @return FString - */ - auto getClassName() const -> FString override { return "dvmColorTheme"; } - /** - * @brief Set the Color Theme object - */ - void setColorTheme() override - { - term_fg = FColor::White; - term_bg = FColor::DarkGray; - - list_fg = FColor::Black; - list_bg = FColor::LightGray; - selected_list_fg = FColor::Red; - selected_list_bg = FColor::LightGray; - - dialog_fg = FColor::Black; - dialog_resize_fg = FColor::LightBlue; - dialog_emphasis_fg = FColor::Blue; - dialog_bg = FColor::LightGray; - - error_box_fg = FColor::LightRed; - error_box_emphasis_fg = FColor::Yellow; - error_box_bg = FColor::Black; - - tooltip_fg = FColor::White; - tooltip_bg = FColor::Black; - - shadow_fg = FColor::Black; - shadow_bg = FColor::LightGray; // only for transparent shadow - - current_element_focus_fg = FColor::White; - current_element_focus_bg = FColor::Blue; - current_element_fg = FColor::LightGray; - current_element_bg = FColor::DarkGray; - - current_inc_search_element_fg = FColor::LightRed; - - selected_current_element_focus_fg = FColor::LightRed; - selected_current_element_focus_bg = FColor::Cyan; - selected_current_element_fg = FColor::Red; - selected_current_element_bg = FColor::Cyan; - - label_fg = FColor::Black; - label_bg = FColor::LightGray; - label_inactive_fg = FColor::DarkGray; - label_inactive_bg = FColor::LightGray; - label_hotkey_fg = FColor::Red; - label_hotkey_bg = FColor::LightGray; - label_emphasis_fg = FColor::Blue; - label_ellipsis_fg = FColor::DarkGray; - - inputfield_active_focus_fg = FColor::Yellow; - inputfield_active_focus_bg = FColor::Blue; - inputfield_active_fg = FColor::LightGray; - inputfield_active_bg = FColor::Blue; - inputfield_inactive_fg = FColor::Black; - inputfield_inactive_bg = FColor::DarkGray; - - toggle_button_active_focus_fg = FColor::Yellow; - toggle_button_active_focus_bg = FColor::Blue; - toggle_button_active_fg = FColor::LightGray; - toggle_button_active_bg = FColor::Blue; - toggle_button_inactive_fg = FColor::Black; - toggle_button_inactive_bg = FColor::DarkGray; - - button_active_focus_fg = FColor::Yellow; - button_active_focus_bg = FColor::Blue; - button_active_fg = FColor::White; - button_active_bg = FColor::Blue; - button_inactive_fg = FColor::Black; - button_inactive_bg = FColor::DarkGray; - button_hotkey_fg = FColor::Yellow; - - titlebar_active_fg = FColor::Blue; - titlebar_active_bg = FColor::White; - titlebar_inactive_fg = FColor::Blue; - titlebar_inactive_bg = FColor::LightGray; - titlebar_button_fg = FColor::Yellow; - titlebar_button_bg = FColor::LightBlue; - titlebar_button_focus_fg = FColor::LightGray; - titlebar_button_focus_bg = FColor::Black; - - menu_active_focus_fg = FColor::Black; - menu_active_focus_bg = FColor::White; - menu_active_fg = FColor::White; - menu_active_bg = FColor::Cyan; - menu_inactive_fg = FColor::DarkGray; - menu_inactive_bg = FColor::Cyan; - menu_hotkey_fg = FColor::Yellow; - menu_hotkey_bg = FColor::Cyan; - - statusbar_fg = FColor::White; - statusbar_bg = FColor::Blue; - statusbar_hotkey_fg = FColor::Yellow; - statusbar_hotkey_bg = FColor::Blue; - statusbar_separator_fg = FColor::White; - statusbar_active_fg = FColor::Black; - statusbar_active_bg = FColor::LightGray; - statusbar_active_hotkey_fg = FColor::Blue; - statusbar_active_hotkey_bg = FColor::LightGray; - - scrollbar_fg = FColor::Cyan; - scrollbar_bg = FColor::DarkGray; - scrollbar_button_fg = FColor::Yellow; - scrollbar_button_bg = FColor::DarkGray; - scrollbar_button_inactive_fg = FColor::LightGray; - scrollbar_button_inactive_bg = FColor::Black; - - progressbar_fg = FColor::Yellow; - progressbar_bg = FColor::Blue; - } -}; - -// --------------------------------------------------------------------------- -// Class Declaration -// --------------------------------------------------------------------------- - -/** - * @brief This class implements the finalcut application. - * @ingroup monitor - */ -class HOST_SW_API MonitorApplication final : public finalcut::FApplication { -public: - /** - * @brief Initializes a new instance of the MonitorApplication class. - * @param argc Passed argc. - * @param argv Passed argv. - */ - explicit MonitorApplication(const int& argc, char** argv) : FApplication{argc, argv} - { - m_statusRefreshTimer = addTimer(1000); - } - -protected: - /** - * @brief Process external user events. - */ - void processExternalUserEvent() override - { - /* stub */ - } - - /* - ** Event Handlers - */ - - /** - * @brief Event that occurs on interval by timer. - * @param timer Timer Event - */ - void onTimer(FTimerEvent* timer) override - { - if (timer != nullptr) { - if (timer->getTimerId() == m_statusRefreshTimer) { - /* stub */ - } - } - } - -private: - int m_statusRefreshTimer; -}; - -#endif // __MONITOR_APPLICATION_H__ \ No newline at end of file diff --git a/src/monitor/MonitorMain.cpp b/src/monitor/MonitorMain.cpp deleted file mode 100644 index 35a58c97..00000000 --- a/src/monitor/MonitorMain.cpp +++ /dev/null @@ -1,245 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Digital Voice Modem - Host Monitor Software - * GPLv2 Open Source. Use is subject to license terms. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright (C) 2023 Bryan Biedenkapp, N2PLL - * - */ -#include "Defines.h" -#include "common/yaml/Yaml.h" -#include "common/Log.h" -#include "MonitorMain.h" -#include "MonitorApplication.h" -#include "MonitorMainWnd.h" - -using namespace lookups; - -#include -#include -#include -#include - -// --------------------------------------------------------------------------- -// Macros -// --------------------------------------------------------------------------- - -#define IS(s) (::strcmp(argv[i], s) == 0) - -// --------------------------------------------------------------------------- -// Global Variables -// --------------------------------------------------------------------------- - -std::string g_progExe = std::string(__EXE_NAME__); -std::string g_iniFile = std::string(DEFAULT_CONF_FILE); -yaml::Node g_conf; -bool g_debug = false; - -bool g_hideLoggingWnd = false; - -lookups::IdenTableLookup* g_idenTable = nullptr; - -// --------------------------------------------------------------------------- -// Global Functions -// --------------------------------------------------------------------------- - -/* Helper to print a fatal error message and exit. */ - -void fatal(const char* msg, ...) -{ - char buffer[400U]; - ::memset(buffer, 0x20U, 400U); - - va_list vl; - va_start(vl, msg); - - ::vsprintf(buffer, msg, vl); - - va_end(vl); - - ::fprintf(stderr, "%s: FATAL PANIC; %s\n", g_progExe.c_str(), buffer); - exit(EXIT_FAILURE); -} - -/* Helper to pring usage the command line arguments. (And optionally an error.) */ - -void usage(const char* message, const char* arg) -{ - ::fprintf(stdout, __PROG_NAME__ " %s (built %s)\r\n", __VER__, __BUILD__); - ::fprintf(stdout, "Copyright (c) 2017-2026 Bryan Biedenkapp, N2PLL and DVMProject (https://github.com/dvmproject) Authors.\n"); - ::fprintf(stdout, "Portions Copyright (c) 2015-2021 by Jonathan Naylor, G4KLX and others\n\n"); - if (message != nullptr) { - ::fprintf(stderr, "%s: ", g_progExe.c_str()); - ::fprintf(stderr, message, arg); - ::fprintf(stderr, "\n\n"); - } - - ::fprintf(stdout, - "usage: %s [-dvh]" - "[--hide-log]" - "[-c ]" - "\n\n" - " -d enable debug\n" - " -v show version information\n" - " -h show this screen\n" - "\n" - " --hide-log hide interactive logging window on startup\n" - "\n" - " -c specifies the monitor configuration file to use\n" - "\n" - " -- stop handling options\n", - g_progExe.c_str()); - - exit(EXIT_FAILURE); -} - -/* Helper to validate the command line arguments. */ - -int checkArgs(int argc, char* argv[]) -{ - int i, p = 0; - - // iterate through arguments - for (i = 1; i <= argc; i++) - { - if (argv[i] == nullptr) { - break; - } - - if (*argv[i] != '-') { - continue; - } - else if (IS("--")) { - ++p; - break; - } - else if (IS("-c")) { - if (argc-- <= 0) - usage("error: %s", "must specify the monitor configuration file to use"); - g_iniFile = std::string(argv[++i]); - - if (g_iniFile.empty()) - usage("error: %s", "monitor configuration file cannot be blank!"); - - p += 2; - } - else if (IS("--hide-log")) { - ++p; - g_hideLoggingWnd = true; - } - else if (IS("-d")) { - ++p; - g_debug = true; - } - else if (IS("-v")) { - ::fprintf(stdout, __PROG_NAME__ " %s (built %s)\r\n", __VER__, __BUILD__); - ::fprintf(stdout, "Copyright (c) 2017-2026 Bryan Biedenkapp, N2PLL and DVMProject (https://github.com/dvmproject) Authors.\n"); - ::fprintf(stdout, "Portions Copyright (c) 2015-2021 by Jonathan Naylor, G4KLX and others\n\n"); - if (argc == 2) - exit(EXIT_SUCCESS); - } - else if (IS("-h")) { - usage(nullptr, nullptr); - if (argc == 2) - exit(EXIT_SUCCESS); - } - else { - usage("unrecognized option `%s'", argv[i]); - } - } - - if (p < 0 || p > argc) { - p = 0; - } - - return ++p; -} - -// --------------------------------------------------------------------------- -// Program Entry Point -// --------------------------------------------------------------------------- - -int main(int argc, char** argv) -{ - if (argv[0] != nullptr && *argv[0] != 0) - g_progExe = std::string(argv[0]); - - if (argc > 1) { - // check arguments - int i = checkArgs(argc, argv); - if (i < argc) { - argc -= i; - argv += i; - } - else { - argc--; - argv++; - } - } - - // initialize system logging - bool ret = ::LogInitialise("", "", 0U, 1U); - if (!ret) { - ::fprintf(stderr, "unable to open the log file\n"); - return 1; - } - - ::LogInfo(__PROG_NAME__ " " __VER__ " (built " __BUILD__ ")\r\n" \ - "Copyright (c) 2017-2026 Bryan Biedenkapp, N2PLL and DVMProject (https://github.com/dvmproject) Authors.\r\n" \ - "Portions Copyright (c) 2015-2021 by Jonathan Naylor, G4KLX and others\r\n" \ - ">> Host Monitor\r\n"); - - try { - ret = yaml::Parse(g_conf, g_iniFile.c_str()); - if (!ret) { - ::fatal("cannot read the configuration file, %s\n", g_iniFile.c_str()); - } - } - catch (yaml::OperationException const& e) { - ::fatal("cannot read the configuration file - %s (%s)", g_iniFile.c_str(), e.message()); - } - - finalcut::FApplication::setColorTheme(); - - // setup the finalcut tui - MonitorApplication app{argc, argv}; - - MonitorMainWnd wnd{&app}; - finalcut::FWidget::setMainWidget(&wnd); - - // try to load bandplan identity table - std::string idenLookupFile = g_conf["iden_table"]["file"].as(); - uint32_t idenReloadTime = g_conf["iden_table"]["time"].as(0U); - - if (idenLookupFile.length() <= 0U) { - ::LogError(LOG_HOST, "No bandplan identity table? This must be defined!"); - return 1; - } - - yaml::Node& voiceChList = g_conf["channels"]; - if (voiceChList.size() == 0U) { - ::LogError(LOG_HOST, "No channels defined to monitor? This must be defined!"); - return 1; - } - - g_logDisplayLevel = 0U; - - LogInfo("Iden Table Lookups"); - LogInfo(" File: %s", idenLookupFile.length() > 0U ? idenLookupFile.c_str() : "None"); - if (idenReloadTime > 0U) - LogInfo(" Reload: %u mins", idenReloadTime); - - g_idenTable = new IdenTableLookup(idenLookupFile, idenReloadTime); - g_idenTable->read(); - - // show and start the application - wnd.show(); - - app.resetColors(); - app.redraw(); - - int _errno = app.exec(); - ::LogFinalise(); - return _errno; -} diff --git a/src/monitor/MonitorMain.h b/src/monitor/MonitorMain.h deleted file mode 100644 index 6d5b9170..00000000 --- a/src/monitor/MonitorMain.h +++ /dev/null @@ -1,53 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Digital Voice Modem - Host Monitor Software - * GPLv2 Open Source. Use is subject to license terms. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright (C) 2023 Bryan Biedenkapp, N2PLL - * - */ -/** - * @file MonitorMain.h - * @ingroup monitor - * @file MonitorMain.cpp - * @ingroup monitor - */ -#if !defined(__MONITOR_MAIN_H__) -#define __MONITOR_MAIN_H__ - -#include "Defines.h" -#include "common/lookups/IdenTableLookup.h" -#include "common/yaml/Yaml.h" - -#include - -// --------------------------------------------------------------------------- -// Constants -// --------------------------------------------------------------------------- - -#undef __PROG_NAME__ -#define __PROG_NAME__ "Digital Voice Modem (DVM) Monitor Tool" -#undef __EXE_NAME__ -#define __EXE_NAME__ "dvmmon" - -// --------------------------------------------------------------------------- -// Externs -// --------------------------------------------------------------------------- - -/** @brief */ -extern std::string g_progExe; -/** @brief */ -extern std::string g_iniFile; -/** @brief */ -extern yaml::Node g_conf; -/** @brief */ -extern bool g_debug; - -/** @brief */ -extern bool g_hideLoggingWnd; - -/** @brief */ -extern lookups::IdenTableLookup* g_idenTable; - -#endif // __MONITOR_MAIN_H__ diff --git a/src/monitor/MonitorMainWnd.h b/src/monitor/MonitorMainWnd.h deleted file mode 100644 index d438b24e..00000000 --- a/src/monitor/MonitorMainWnd.h +++ /dev/null @@ -1,284 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Digital Voice Modem - Host Monitor Software - * GPLv2 Open Source. Use is subject to license terms. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright (C) 2023 Bryan Biedenkapp, N2PLL - * - */ -/** - * @file MonitorMainWnd.h - * @ingroup monitor - */ -#if !defined(__MONITOR_WND_H__) -#define __MONITOR_WND_H__ - -#include "common/lookups/AffiliationLookup.h" -#include "common/Log.h" -#include "common/Thread.h" - -using namespace lookups; - -#include -using namespace finalcut; -#undef null - -#include "MonitorMain.h" - -#include "LogDisplayWnd.h" -#include "NodeStatusWnd.h" -#include "SelectedNodeWnd.h" -#include "PageSubscriberWnd.h" -#include "RadioCheckSubscriberWnd.h" -#include "InhibitSubscriberWnd.h" -#include "UninhibitSubscriberWnd.h" - -#include - -// --------------------------------------------------------------------------- -// Class Prototypes -// --------------------------------------------------------------------------- - -class HOST_SW_API MonitorApplication; - -// --------------------------------------------------------------------------- -// Class Declaration -// --------------------------------------------------------------------------- - -/** - * @brief This class implements the root window control. - * @ingroup monitor - */ -class HOST_SW_API MonitorMainWnd final : public finalcut::FWidget { -public: - /** - * @brief Initializes a new instance of the MonitorMainWnd class. - * @param widget - */ - explicit MonitorMainWnd(FWidget* widget = nullptr) : FWidget{widget} - { - log_internal::SetInternalOutputStream(m_logWnd); - - // file menu - m_quitItem.addAccelerator(FKey::Meta_x); // Meta/Alt + X - m_quitItem.addCallback("clicked", getFApplication(), &FApplication::cb_exitApp, this); - m_keyF3.addCallback("activate", getFApplication(), &FApplication::cb_exitApp, this); - - // command menu - m_pageSU.addCallback("clicked", this, [&]() { - PageSubscriberWnd wnd{m_selectedCh, this}; - wnd.show(); - }); - m_keyF5.addCallback("activate", this, [&]() { - PageSubscriberWnd wnd{m_selectedCh, this}; - wnd.show(); - }); - m_radioCheckSU.addCallback("clicked", this, [&]() { - RadioCheckSubscriberWnd wnd{m_selectedCh, this}; - wnd.show(); - }); - m_cmdMenuSeparator1.setSeparator(); - m_inhibitSU.addCallback("clicked", this, [&]() { - InhibitSubscriberWnd wnd{m_selectedCh, this}; - wnd.show(); - }); - m_keyF7.addCallback("activate", this, [&]() { - InhibitSubscriberWnd wnd{m_selectedCh, this}; - wnd.show(); - }); - m_uninhibitSU.addCallback("clicked", this, [&]() { - UninhibitSubscriberWnd wnd{m_selectedCh, this}; - wnd.show(); - }); - m_keyF8.addCallback("activate", this, [&]() { - UninhibitSubscriberWnd wnd{m_selectedCh, this}; - wnd.show(); - }); - - // help menu - m_aboutItem.addCallback("clicked", this, [&]() { - const FString line(2, UniChar::BoxDrawingsHorizontal); - FMessageBox info("About", line + __PROG_NAME__ + line + L"\n\n" - L"" + __BANNER__ + L"\n" - L"Version " + __VER__ + L"\n\n" - L"Copyright (c) 2017-2026 Bryan Biedenkapp, N2PLL and DVMProject (https://github.com/dvmproject) Authors." + L"\n" - L"Portions Copyright (c) 2015-2021 by Jonathan Naylor, G4KLX and others", - FMessageBox::ButtonType::Ok, FMessageBox::ButtonType::Reject, FMessageBox::ButtonType::Reject, this); - info.setCenterText(); - info.show(); - }); - } - - /** - * @brief Helper to get the currently selected channel. - * @returns lookups::VoiceChData Currently selected channel. - */ - lookups::VoiceChData getSelectedCh() { return m_selectedCh; } - -private: - friend class MonitorApplication; - - LogDisplayWnd m_logWnd{this}; - SelectedNodeWnd m_selectWnd{this}; - std::vector m_nodes; - uint32_t m_activeNodeId = 0U; - - lookups::VoiceChData m_selectedCh; - - FString m_line{13, UniChar::BoxDrawingsHorizontal}; - - FMenuBar m_menuBar{this}; - - FMenu m_fileMenu{"&File", &m_menuBar}; - FMenuItem m_quitItem{"&Quit", &m_fileMenu}; - - FMenu m_cmdMenu{"&Commands", &m_menuBar}; - FMenuItem m_pageSU{"&Page Subscriber", &m_cmdMenu}; - FMenuItem m_radioCheckSU{"Radio &Check Subscriber", &m_cmdMenu}; - FMenuItem m_cmdMenuSeparator1{&m_cmdMenu}; - FMenuItem m_inhibitSU{"&Inhibit Subscriber", &m_cmdMenu}; - FMenuItem m_uninhibitSU{"&Uninhibit Subscriber", &m_cmdMenu}; - - FMenu m_helpMenu{"&Help", &m_menuBar}; - FMenuItem m_aboutItem{"&About", &m_helpMenu}; - - FStatusBar m_statusBar{this}; - FStatusKey m_keyF3{FKey::F3, "Quit", &m_statusBar}; - FStatusKey m_keyF5{FKey::F5, "Page Subscriber", &m_statusBar}; - FStatusKey m_keyF7{FKey::F7, "Inhibit Subscriber", &m_statusBar}; - FStatusKey m_keyF8{FKey::F8, "Uninhibit Subscriber", &m_statusBar}; - - /** - * @brief Helper to initialize the individual channel display elements. - */ - void intializeNodeDisplay() - { - const auto& rootWidget = getRootWidget(); - const int defaultOffsX = 2; - int offsX = defaultOffsX, offsY = 8; - - int maxWidth = 77; - if (rootWidget) { - maxWidth = rootWidget->getClientWidth() - 3; - } - - /* - ** Channels - */ - yaml::Node& voiceChList = g_conf["channels"]; - - if (voiceChList.size() != 0U) { - for (size_t i = 0; i < voiceChList.size(); i++) { - yaml::Node& channel = voiceChList[i]; - - std::string restApiAddress = channel["restAddress"].as("127.0.0.1"); - uint16_t restApiPort = (uint16_t)channel["restPort"].as(REST_API_DEFAULT_PORT); - std::string restApiPassword = channel["restPassword"].as(); - bool restSsl = channel["restSsl"].as(false); - - ::LogInfoEx(LOG_HOST, "Channel REST API Adddress %s:%u", restApiAddress.c_str(), restApiPort); - - VoiceChData data = VoiceChData(0U, 0U, restApiAddress, restApiPort, restApiPassword, restSsl); - - NodeStatusWnd* wnd = new NodeStatusWnd(this); - wnd->setChData(data); - - // set control position - if (offsX + NODE_STATUS_WIDTH > maxWidth) { - offsY += NODE_STATUS_HEIGHT + 2; - offsX = defaultOffsX; - } - - wnd->setGeometry(FPoint{offsX, offsY}, FSize{NODE_STATUS_WIDTH, NODE_STATUS_HEIGHT}); - - wnd->addCallback("update-selected", this, [&](NodeStatusWnd* wnd) { - std::stringstream ss; - ss << (uint32_t)(wnd->getChannelId()) << "-" << wnd->getChannelNo() << " / " - << wnd->getChData().address() << ":" << wnd->getChData().port() << " / " - << "Peer ID " << (uint32_t)(wnd->getPeerId()); - - m_selectWnd.setSelectedText(ss.str()); - m_selectedCh = wnd->getChData(); - - auto it = std::find(m_nodes.begin(), m_nodes.end(), wnd); - if (it != m_nodes.end()) { - uint32_t i = it - m_nodes.begin(); - m_activeNodeId = i; - } - }, wnd); - - offsX += NODE_STATUS_WIDTH + 2; - m_nodes.push_back(wnd); - } - } - - // display all the node windows - for (auto* wnd : m_nodes) { - wnd->setModal(false); - wnd->show(); - - wnd->lowerWindow(); - wnd->deactivateWindow(); - } - - // raise and activate first window - m_nodes.at(0)->raiseWindow(); - m_nodes.at(0)->activateWindow(); - - redraw(); - } - - /* - ** Event Handlers - */ - - /** - * @brief Event that occurs on keyboard key press. - * @param e Keyboard Event. - */ - void onKeyPress(finalcut::FKeyEvent* e) override - { - const FKey key = e->key(); - if (key == FKey::Tab) { - // lower and deactivate current window - m_nodes.at(m_activeNodeId)->lowerWindow(); - m_nodes.at(m_activeNodeId)->deactivateWindow(); - - m_activeNodeId++; - if (m_activeNodeId >= m_nodes.size()) { - m_activeNodeId = 0U; - } - - // raise and activate window - m_nodes.at(m_activeNodeId)->raiseWindow(); - m_nodes.at(m_activeNodeId)->activateWindow(); - } - } - - /** - * @brief Event that occurs when the window is shown. - * @param e Show Event - */ - void onShow(FShowEvent* e) override - { - intializeNodeDisplay(); - if (g_hideLoggingWnd) { - const auto& rootWidget = getRootWidget(); - m_logWnd.setGeometry(FPoint{(int)(rootWidget->getClientWidth() - 81), (int)(rootWidget->getClientHeight() - 1)}, FSize{80, 20}); - - m_logWnd.minimizeWindow(); - } - } - - /** - * @brief Event that occurs when the window is closed. - * @param e Close Event - */ - void onClose(FCloseEvent* e) override - { - FApplication::closeConfirmationDialog(this, e); - } -}; - -#endif // __MONITOR_WND_H__ \ No newline at end of file diff --git a/src/monitor/NodeStatusWnd.h b/src/monitor/NodeStatusWnd.h deleted file mode 100644 index a4884ca1..00000000 --- a/src/monitor/NodeStatusWnd.h +++ /dev/null @@ -1,522 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Digital Voice Modem - Host Monitor Software - * GPLv2 Open Source. Use is subject to license terms. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright (C) 2023 Bryan Biedenkapp, N2PLL - * - */ -/** - * @file NodeStatusWnd.h - * @ingroup monitor - */ -#if !defined(__NODE_STATUS_WND_H__) -#define __NODE_STATUS_WND_H__ - -#include "common/lookups/AffiliationLookup.h" -#include "host/restapi/RESTDefines.h" -#include "host/modem/Modem.h" -#include "remote/RESTClient.h" - -#include "MonitorMainWnd.h" - -#include -using namespace finalcut; - -// --------------------------------------------------------------------------- -// Constants -// --------------------------------------------------------------------------- - -#define NODE_STATUS_WIDTH 28 -#define NODE_STATUS_HEIGHT 8 -#define NODE_UPDATE_FAIL_CNT 4 - -// --------------------------------------------------------------------------- -// Class Declaration -// --------------------------------------------------------------------------- - -/** - * @brief This class implements the node status display window. - * @ingroup monitor - */ -class HOST_SW_API NodeStatusWnd final : public finalcut::FDialog { -public: - /** - * @brief Initializes a new instance of the NodeStatusWnd class. - * @param widget - */ - explicit NodeStatusWnd(FWidget* widget = nullptr) : FDialog{widget} - { - m_timerId = addTimer(250); // starts the timer every 250 milliseconds - m_reconnectTimerId = addTimer(15000); // starts the timer every 10 seconds - } - /** - * @brief Copy constructor. - */ - NodeStatusWnd(const NodeStatusWnd&) = delete; - /** - * @brief Move constructor. - */ - NodeStatusWnd(NodeStatusWnd&&) noexcept = delete; - /** - * @brief Finalizes an instance of the NodeStatusWnd class. - */ - ~NodeStatusWnd() noexcept override = default; - - /** - * @brief Disable copy assignment operator (=). - */ - auto operator= (const NodeStatusWnd&) -> NodeStatusWnd& = delete; - /** - * @brief Disable move assignment operator (=). - */ - auto operator= (NodeStatusWnd&&) noexcept -> NodeStatusWnd& = delete; - - /** - * @brief Disable set X coordinate. - */ - void setX(int, bool = true) override { } - /** - * @brief Disable set Y coordinate. - */ - void setY(int, bool = true) override { } - /** - * @brief Disable set position. - */ - void setPos(const FPoint&, bool = true) override { } - - /** - * @brief Gets the channel ID. - * @returns uint8_t Channel ID. - */ - uint8_t getChannelId() const { return m_channelId; } - /** - * @brief Gets the channel number. - * @returns uint32_t Channel Number. - */ - uint32_t getChannelNo() const { return m_channelNo; } - /** - * @brief Gets the channel data. - * @returns lookups::VoiceChData Channel Data. - */ - lookups::VoiceChData getChData() { return m_chData; } - /** - * @brief Sets the channel data. - * @param chData Channel Data. - */ - void setChData(lookups::VoiceChData chData) { m_chData = chData; } - /** - * @brief Gets the peer ID. - * @param uint32_t Peer ID. - */ - uint32_t getPeerId() const { return m_peerId; } - -private: - int m_timerId; - int m_reconnectTimerId; - - uint8_t m_failCnt = 0U; - bool m_failed; - bool m_control; - bool m_tx; - - FString m_tbText{}; // title bar text - - lookups::VoiceChData m_chData; - uint8_t m_channelId; - uint32_t m_channelNo; - uint32_t m_peerId; - - FLabel m_modeStr{this}; - FLabel m_peerIdStr{this}; - - FLabel m_channelNoLabel{"Ch. No.: ", this}; - FLabel m_chanNo{this}; - - FLabel m_txFreqLabel{"Tx: ", this}; - FLabel m_txFreq{this}; - FLabel m_rxFreqLabel{"Rx: ", this}; - FLabel m_rxFreq{this}; - - FLabel m_lastDstLabel{"Last Dst: ", this}; - FLabel m_lastDst{this}; - FLabel m_lastSrcLabel{"Last Src: ", this}; - FLabel m_lastSrc{this}; - - /** - * @brief Initializes the window layout. - */ - void initLayout() override - { - FDialog::setMinimumSize(FSize{NODE_STATUS_WIDTH, NODE_STATUS_HEIGHT}); - - FDialog::setResizeable(false); - FDialog::setMinimizable(false); - FDialog::setTitlebarButtonVisibility(false); - FDialog::setShadow(false); - FDialog::setModal(false); - - m_failed = true; - m_tbText = "UNKNOWN"; - - initControls(); - - FDialog::initLayout(); - } - - /** - * @brief Draws the window. - */ - void draw() override - { - FDialog::draw(); - - setColor(); - - const auto& wc = getColorTheme(); - setForegroundColor(wc->dialog_fg); - setBackgroundColor(wc->dialog_bg); - - if (m_failed) { - m_tbText = "FAILED"; - setColor(FColor::LightGray, FColor::LightRed); - } - else if (m_control) { - setColor(FColor::LightGray, FColor::Purple1); - } - else if (m_tx) { - setColor(FColor::LightGray, FColor::LightGreen); - } - else { - setColor(FColor::LightGray, FColor::Black); - } - - finalcut::drawBorder(this, FRect(FPoint{1, 1}, FPoint{NODE_STATUS_WIDTH, NODE_STATUS_HEIGHT + 1})); - - if (FVTerm::getFOutput()->isMonochron()) - setReverse(true); - - drawTitleBar(); - setCursorPos({2, int(getHeight()) - 1}); - - if (FVTerm::getFOutput()->isMonochron()) - setReverse(false); - } - - /** - * @brief - */ - void drawTitleBar() - { - print() << FPoint{2, 1}; - - // Fill with spaces (left of the title) - if (FVTerm::getFOutput()->getMaxColor() < 16) - setBold(); - - if (!m_tx) { - if (m_failed) { - setColor(FColor::Black, FColor::LightRed); - } - else if (m_control) { - setColor(FColor::LightGray, FColor::Purple1); - } - else { - setColor(FColor::Black, FColor::White); - } - } else { - setColor(FColor::Black, FColor::LightGreen); - } - - const auto width = getWidth(); - auto textWidth = getColumnWidth(m_tbText); - std::size_t leadingSpace{0}; - - if (width > textWidth) - leadingSpace = ((width - textWidth) / 2) - 1; - - // Print leading whitespace - print(FString(leadingSpace, L' ')); - - // Print title bar text - if (!m_tbText.isEmpty()) { - if (textWidth <= width) - print(m_tbText); - else { - // Print ellipsis - const auto len = getLengthFromColumnWidth(m_tbText, width - 2); - print(m_tbText.left(len)); - print(".."); - textWidth = len + 2; - } - } - - // Print trailing whitespace - std::size_t trailingSpace = (width - leadingSpace - textWidth) - 2; - print(FString(trailingSpace, L' ')); - - if (FVTerm::getFOutput()->getMaxColor() < 16) - unsetBold(); - } - - /** - * @brief Initializes window controls. - */ - void initControls() - { - m_modeStr.setGeometry(FPoint(23, 1), FSize(4, 1)); - m_modeStr.setAlignment(Align::Right); - m_modeStr.setEmphasis(); - - m_peerIdStr.setGeometry(FPoint(18, 2), FSize(9, 1)); - m_peerIdStr.setAlignment(Align::Right); - m_peerIdStr.setEmphasis(); - - // channel number - { - m_channelNoLabel.setGeometry(FPoint(1, 1), FSize(10, 1)); - - m_chanNo.setGeometry(FPoint(11, 1), FSize(8, 1)); - m_chanNo.setText(""); - } - - // channel frequency - { - m_txFreqLabel.setGeometry(FPoint(1, 2), FSize(4, 1)); - m_txFreq.setGeometry(FPoint(6, 2), FSize(9, 1)); - m_txFreq.setText(""); - - m_rxFreqLabel.setGeometry(FPoint(1, 3), FSize(4, 1)); - m_rxFreq.setGeometry(FPoint(6, 3), FSize(9, 1)); - m_rxFreq.setText(""); - } - - // last TG - { - m_lastDstLabel.setGeometry(FPoint(1, 4), FSize(11, 1)); - - m_lastDst.setGeometry(FPoint(13, 4), FSize(8, 1)); - m_lastDst.setText("None"); - } - - // last source - { - m_lastSrcLabel.setGeometry(FPoint(1, 5), FSize(11, 1)); - - m_lastSrc.setGeometry(FPoint(13, 5), FSize(8, 1)); - m_lastSrc.setText("None"); - } - } - - /** - * @brief Helper to calculate the Tx/Rx frequencies of a channel. - */ - void calculateRxTx() - { - IdenTable entry = g_idenTable->find(m_channelId); - if (entry.baseFrequency() == 0U) { - ::LogError(LOG_HOST, "Channel Id %u has an invalid base frequency.", m_channelId); - } - - if (entry.txOffsetMhz() == 0U) { - ::LogError(LOG_HOST, "Channel Id %u has an invalid Tx offset.", m_channelId); - } - - m_chanNo.setText(__INT_STR(m_channelId) + "-" + __INT_STR(m_channelNo)); - - uint32_t calcSpace = (uint32_t)(entry.chSpaceKhz() / 0.125); - float calcTxOffset = entry.txOffsetMhz() * 1000000.0; - - uint32_t rxFrequency = (uint32_t)((entry.baseFrequency() + ((calcSpace * 125) * m_channelNo)) + (int32_t)calcTxOffset); - uint32_t txFrequency = (uint32_t)((entry.baseFrequency() + ((calcSpace * 125) * m_channelNo))); - - std::stringstream ss; - ss << std::fixed << std::setprecision(5) << (double)(txFrequency / 1000000.0); - - m_txFreq.setText(ss.str()); - - ss.str(std::string()); - ss << std::fixed << std::setprecision(5) << (double)(rxFrequency / 1000000.0); - - m_rxFreq.setText(ss.str()); - - if (isWindowActive()) { - emitCallback("update-selected"); - } - } - - /* - ** Event Handlers - */ - - /** - * @brief Event that occurs when the window is raised. - * @param e Event. - */ - void onWindowRaised(FEvent* e) override - { - FDialog::onWindowLowered(e); - emitCallback("update-selected"); - } - - /** - * @brief Event that occurs on interval by timer. - * @param timer Timer Event - */ - void onTimer(FTimerEvent* timer) override - { - if (timer != nullptr) { - // update timer - if (timer->getTimerId() == m_timerId) { - if (!m_failed) { - // callback REST API to get status of the channel we represent - json::object req = json::object(); - json::object rsp = json::object(); - - int ret = RESTClient::send(m_chData.address(), m_chData.port(), m_chData.password(), - HTTP_GET, GET_STATUS, req, rsp, m_chData.ssl(), g_debug); - if (ret != restapi::http::HTTPPayload::StatusType::OK) { - ::LogError(LOG_HOST, "failed to get status for %s:%u, chNo = %u", m_chData.address().c_str(), m_chData.port(), m_channelNo); - ++m_failCnt; - if (m_failCnt > NODE_UPDATE_FAIL_CNT) { - m_failed = true; - m_tbText = std::string("FAILED"); - } - } - else { - try { - m_failCnt = 0U; - - uint8_t mode = rsp["state"].get(); - switch (mode) { - case modem::STATE_DMR: - m_modeStr.setText("DMR"); - break; - case modem::STATE_P25: - m_modeStr.setText("P25"); - break; - case modem::STATE_NXDN: - m_modeStr.setText("NXDN"); - break; - default: - m_modeStr.setText(""); - break; - } - - if (rsp["peerId"].is()) { - m_peerId = rsp["peerId"].get(); - - // pad peer IDs properly - std::ostringstream peerOss; - peerOss << std::setw(9) << std::setfill('0') << m_peerId; - m_peerIdStr.setText(peerOss.str()); - } - - // get remote node state - if (rsp["dmrTSCCEnable"].is() && rsp["p25CtrlEnable"].is() && - rsp["nxdnCtrlEnable"].is()) { - bool dmrTSCCEnable = rsp["dmrTSCCEnable"].get(); - bool dmrCC = rsp["dmrCC"].get(); - bool p25CtrlEnable = rsp["p25CtrlEnable"].get(); - bool p25CC = rsp["p25CC"].get(); - bool nxdnCtrlEnable = rsp["nxdnCtrlEnable"].get(); - bool nxdnCC = rsp["nxdnCC"].get(); - - // are we a dedicated control channel? - if (dmrCC || p25CC || nxdnCC) { - m_control = true; - m_tbText = std::string("CONTROL"); - } - - // if we aren't a dedicated control channel; set our - // title bar appropriately and set Tx state - if (!m_control) { - if (dmrTSCCEnable || p25CtrlEnable || nxdnCtrlEnable) { - m_tbText = std::string("ENH. VOICE/CONV"); - } - else { - m_tbText = std::string("VOICE/CONV"); - } - - // are we transmitting? - if (rsp["tx"].is()) { - m_tx = rsp["tx"].get(); - } - else { - ::LogWarning(LOG_HOST, "%s:%u, does not report Tx status"); - m_tx = false; - } - } - } - - // get the remote node channel information - if (rsp["channelId"].is() && rsp["channelNo"].is()) { - uint8_t channelId = rsp["channelId"].get(); - uint32_t channelNo = rsp["channelNo"].get(); - - if (m_channelId != channelId && m_channelNo != channelNo) { - m_channelId = channelId; - m_channelNo = channelNo; - - calculateRxTx(); - } - } - else { - ::LogWarning(LOG_HOST, "%s:%u, does not report channel information"); - } - - // report last known transmitted destination ID - if (rsp["lastDstId"].is()) { - uint32_t lastDstId = rsp["lastDstId"].get(); - - // pad TGs properly - std::ostringstream tgidOss; - tgidOss << std::setw(5) << std::setfill('0') << lastDstId; - - m_lastDst.setText(tgidOss.str()); - } - else { - ::LogWarning(LOG_HOST, "%s:%u, does not report last TG information"); - } - - // report last known transmitted source ID - if (rsp["lastSrcId"].is()) { - uint32_t lastSrcId = rsp["lastSrcId"].get(); - m_lastSrc.setText(__INT_STR(lastSrcId)); - } - else { - ::LogWarning(LOG_HOST, "%s:%u, does not report last source information"); - } - } - catch (std::exception& e) { - ::LogWarning(LOG_HOST, "%s:%u, failed to properly handle status, %s", m_chData.address().c_str(), m_chData.port(), e.what()); - } - } - } - - redraw(); - } - - // reconnect timer - if (timer->getTimerId() == m_reconnectTimerId) { - if (m_failed) { - ::LogInfoEx(LOG_HOST, "attempting to reconnect to %s:%u, chNo = %u", m_chData.address().c_str(), m_chData.port(), m_channelNo); - // callback REST API to get status of the channel we represent - json::object req = json::object(); - int ret = RESTClient::send(m_chData.address(), m_chData.port(), m_chData.password(), - HTTP_GET, GET_STATUS, req, m_chData.ssl(), g_debug); - if (ret == restapi::http::HTTPPayload::StatusType::OK) { - m_failed = false; - m_failCnt = 0U; - m_tbText = std::string("UNKNOWN"); - } - } - - redraw(); - } - } - } -}; - -#endif // __NODE_STATUS_WND_H__ \ No newline at end of file diff --git a/src/monitor/PageSubscriberWnd.h b/src/monitor/PageSubscriberWnd.h deleted file mode 100644 index 39ca03e1..00000000 --- a/src/monitor/PageSubscriberWnd.h +++ /dev/null @@ -1,146 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Digital Voice Modem - Host Monitor Software - * GPLv2 Open Source. Use is subject to license terms. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright (C) 2023 Bryan Biedenkapp, N2PLL - * - */ -/** - * @file PageSubscriberWnd.h - * @ingroup monitor - */ -#if !defined(__PAGE_SUBSCRIBER_WND_H__) -#define __PAGE_SUBSCRIBER_WND_H__ - -#include "TransmitWndBase.h" - -#include -using namespace finalcut; - -// --------------------------------------------------------------------------- -// Class Declaration -// --------------------------------------------------------------------------- - -/** - * @brief This class implements the page subscriber window. - * @ingroup monitor - */ -class HOST_SW_API PageSubscriberWnd final : public TransmitWndBase { -public: - /** - * @brief Initializes a new instance of the PageSubscriberWnd class. - * @param channel Channel data. - * @param widget - */ - explicit PageSubscriberWnd(lookups::VoiceChData channel, FWidget* widget = nullptr) : TransmitWndBase{channel, widget} - { - /* stub */ - } - -private: - FLabel m_dialogLabel{"Page Subscriber", this}; - - FLabel m_subscriberLabel{"Subscriber ID: ", this}; - FSpinBox m_subscriber{this}; - - /** - * @brief Initializes the window layout. - */ - void initLayout() override - { - FDialog::setText("Page Subscriber"); - FDialog::setSize(FSize{60, 16}); - - TransmitWndBase::initLayout(); - } - - /** - * @brief Initializes window controls. - */ - void initControls() override - { - TransmitWndBase::initControls(); - - if (m_hideModeSelect) { - FDialog::setSize(FSize{60, 12}); - resizeControls(); - } - - // subscriber entry - { - if (!m_hideModeSelect) { - m_dialogLabel.setGeometry(FPoint(6, 6), FSize(20, 2)); - } - else { - m_dialogLabel.setGeometry(FPoint(6, 2), FSize(20, 2)); - } - m_dialogLabel.setEmphasis(); - m_dialogLabel.setAlignment(Align::Center); - - if (!m_hideModeSelect) { - m_subscriberLabel.setGeometry(FPoint(2, 8), FSize(25, 1)); - m_subscriber.setGeometry(FPoint(28, 8), FSize(20, 1)); - } - else { - m_subscriberLabel.setGeometry(FPoint(2, 4), FSize(25, 1)); - m_subscriber.setGeometry(FPoint(28, 4), FSize(20, 1)); - } - m_subscriber.setRange(0, 16777211); - m_subscriber.setValue(1); - m_subscriber.setShadow(false); - m_subscriber.addCallback("changed", [&]() { - if (m_subscriber.getValue() >= 1 && m_subscriber.getValue() <= 16777211) { - m_txButton.setEnable(true); - } - else { - m_txButton.setEnable(false); - } - - redraw(); - }); - } - - m_dialogLabel.redraw(); - m_subscriberLabel.redraw(); - redraw(); - } - - /** - * @brief Helper to transmit. - */ - void setTransmit() override - { - std::string method = PUT_DMR_RID; - json::object req = json::object(); - req["command"].set(RID_CMD_PAGE); - uint32_t dstId = m_subscriber.getValue(); - req["dstId"].set(dstId); - - switch (m_mode) { - case modem::STATE_DMR: - { - uint8_t slot = m_dmrSlot.getValue(); - req["slot"].set(slot); - } - break; - case modem::STATE_P25: - { - method = PUT_P25_RID; - } - break; - case modem::STATE_NXDN: - return; - } - - // callback REST API - int ret = RESTClient::send(m_selectedCh.address(), m_selectedCh.port(), m_selectedCh.password(), - HTTP_PUT, method, req, m_selectedCh.ssl(), g_debug); - if (ret != restapi::http::HTTPPayload::StatusType::OK) { - ::LogError(LOG_HOST, "failed to send request %s to %s:%u", method.c_str(), m_selectedCh.address().c_str(), m_selectedCh.port()); - } - } -}; - -#endif // __PAGE_SUBSCRIBER_WND_H__ \ No newline at end of file diff --git a/src/monitor/RadioCheckSubscriberWnd.h b/src/monitor/RadioCheckSubscriberWnd.h deleted file mode 100644 index 8114d06d..00000000 --- a/src/monitor/RadioCheckSubscriberWnd.h +++ /dev/null @@ -1,146 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Digital Voice Modem - Host Monitor Software - * GPLv2 Open Source. Use is subject to license terms. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright (C) 2023 Bryan Biedenkapp, N2PLL - * - */ -/** - * @file RadioCheckSubscriberWnd.h - * @ingroup monitor - */ -#if !defined(__RADIO_CHECK_SUBSCRIBER_WND_H__) -#define __RADIO_CHECK_SUBSCRIBER_WND_H__ - -#include "TransmitWndBase.h" - -#include -using namespace finalcut; - -// --------------------------------------------------------------------------- -// Class Declaration -// --------------------------------------------------------------------------- - -/** - * @brief This class implements the radio check subscriber window. - * @ingroup monitor - */ -class HOST_SW_API RadioCheckSubscriberWnd final : public TransmitWndBase { -public: - /** - * @brief Initializes a new instance of the RadioCheckSubscriberWnd class. - * @param channel Channel data. - * @param widget - */ - explicit RadioCheckSubscriberWnd(lookups::VoiceChData channel, FWidget* widget = nullptr) : TransmitWndBase{channel, widget} - { - /* stub */ - } - -private: - FLabel m_dialogLabel{"Radio Check Subscriber", this}; - - FLabel m_subscriberLabel{"Subscriber ID: ", this}; - FSpinBox m_subscriber{this}; - - /** - * @brief Initializes the window layout. - */ - void initLayout() override - { - FDialog::setText("Radio Check Subscriber"); - FDialog::setSize(FSize{60, 16}); - - TransmitWndBase::initLayout(); - } - - /** - * @brief Initializes window controls. - */ - void initControls() override - { - TransmitWndBase::initControls(); - - if (m_hideModeSelect) { - FDialog::setSize(FSize{60, 12}); - resizeControls(); - } - - // subscriber entry - { - if (!m_hideModeSelect) { - m_dialogLabel.setGeometry(FPoint(6, 6), FSize(25, 2)); - } - else { - m_dialogLabel.setGeometry(FPoint(6, 2), FSize(25, 2)); - } - m_dialogLabel.setEmphasis(); - m_dialogLabel.setAlignment(Align::Center); - - if (!m_hideModeSelect) { - m_subscriberLabel.setGeometry(FPoint(2, 8), FSize(25, 1)); - m_subscriber.setGeometry(FPoint(28, 8), FSize(20, 1)); - } - else { - m_subscriberLabel.setGeometry(FPoint(2, 4), FSize(25, 1)); - m_subscriber.setGeometry(FPoint(28, 4), FSize(20, 1)); - } - m_subscriber.setRange(0, 16777211); - m_subscriber.setValue(1); - m_subscriber.setShadow(false); - m_subscriber.addCallback("changed", [&]() { - if (m_subscriber.getValue() >= 1 && m_subscriber.getValue() <= 16777211) { - m_txButton.setEnable(true); - } - else { - m_txButton.setEnable(false); - } - - redraw(); - }); - } - - m_dialogLabel.redraw(); - m_subscriberLabel.redraw(); - redraw(); - } - - /** - * @brief Helper to transmit. - */ - void setTransmit() override - { - std::string method = PUT_DMR_RID; - json::object req = json::object(); - req["command"].set(RID_CMD_CHECK); - uint32_t dstId = m_subscriber.getValue(); - req["dstId"].set(dstId); - - switch (m_mode) { - case modem::STATE_DMR: - { - uint8_t slot = m_dmrSlot.getValue(); - req["slot"].set(slot); - } - break; - case modem::STATE_P25: - { - method = PUT_P25_RID; - } - break; - case modem::STATE_NXDN: - return; - } - - // callback REST API - int ret = RESTClient::send(m_selectedCh.address(), m_selectedCh.port(), m_selectedCh.password(), - HTTP_PUT, method, req, m_selectedCh.ssl(), g_debug); - if (ret != restapi::http::HTTPPayload::StatusType::OK) { - ::LogError(LOG_HOST, "failed to send request %s to %s:%u", method.c_str(), m_selectedCh.address().c_str(), m_selectedCh.port()); - } - } -}; - -#endif // __RADIO_CHECK_SUBSCRIBER_WND_H__ \ No newline at end of file diff --git a/src/monitor/SelectedNodeWnd.h b/src/monitor/SelectedNodeWnd.h deleted file mode 100644 index 02d50c8e..00000000 --- a/src/monitor/SelectedNodeWnd.h +++ /dev/null @@ -1,134 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Digital Voice Modem - Host Monitor Software - * GPLv2 Open Source. Use is subject to license terms. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright (C) 2023 Bryan Biedenkapp, N2PLL - * - */ -/** - * @file SelectedNodeWnd.h - * @ingroup monitor - */ -#if !defined(__SELECTED_NODE_WND_H__) -#define __SELECTED_NODE_WND_H__ - -#include "MonitorMainWnd.h" - -#include -using namespace finalcut; - -// --------------------------------------------------------------------------- -// Class Declaration -// --------------------------------------------------------------------------- - -/** - * @brief This class implements the selected node display window. - * @ingroup monitor - */ -class HOST_SW_API SelectedNodeWnd final : public finalcut::FDialog { -public: - /** - * @brief Initializes a new instance of the SelectedNodeWnd class. - * @param widget - */ - explicit SelectedNodeWnd(FWidget* widget = nullptr) : FDialog{widget} - { - /* stub */ - } - /** - * @brief Copy constructor. - */ - SelectedNodeWnd(const SelectedNodeWnd&) = delete; - /** - * @brief Move constructor. - */ - SelectedNodeWnd(SelectedNodeWnd&&) noexcept = delete; - /** - * @brief Finalizes an instance of the SelectedNodeWnd class. - */ - ~SelectedNodeWnd() noexcept override = default; - - /** - * @brief Disable copy assignment operator (=). - */ - auto operator= (const SelectedNodeWnd&) -> SelectedNodeWnd& = delete; - /** - * @brief Disable move assignment operator (=). - */ - auto operator= (SelectedNodeWnd&&) noexcept -> SelectedNodeWnd& = delete; - - /** - * @brief Disable set X coordinate. - */ - void setX(int, bool = true) override { } - /** - * @brief Disable set Y coordinate. - */ - void setY(int, bool = true) override { } - /** - * @brief Disable set position. - */ - void setPos(const FPoint&, bool = true) override { } - - /** - * @brief Helper to set the selected host text. - * @param str Text. - */ - void setSelectedText(std::string str) - { - m_selectedHost.setText(str); - redraw(); - } - -private: - FLabel m_selectedHostLabel{"Selected Host: ", this}; - FLabel m_selectedHost{this}; - - /** - * @brief Initializes the window layout. - */ - void initLayout() override - { - std::size_t maxWidth; - const auto& rootWidget = getRootWidget(); - - if (rootWidget) { - maxWidth = rootWidget->getClientWidth() - 3; - } - else { - // fallback to xterm default size - maxWidth = 77; - } - - FDialog::setGeometry(FPoint{2, 2}, FSize{maxWidth, 2}); - FDialog::setMinimumSize(FSize{80, 5}); - FDialog::setResizeable(false); - FDialog::setMinimizable(false); - FDialog::setTitlebarButtonVisibility(false); - FDialog::setShadow(false); - - m_selectedHostLabel.setGeometry(FPoint(2, 1), FSize(18, 1)); - m_selectedHost.setGeometry(FPoint(20, 1), FSize(60, 1)); - m_selectedHost.setText("None"); - - FDialog::initLayout(); - } - - /** - * @brief Draws the window. - */ - void draw() override - { - setColor(); - clearArea(); - - const auto& wc = getColorTheme(); - setColor(wc->dialog_resize_fg, getBackgroundColor()); - - finalcut::drawBorder(this, FRect(FPoint{1, 1}, FPoint{(int)getWidth(), (int)getHeight()})); - } -}; - -#endif // __SELECTED_NODE_WND_H__ \ No newline at end of file diff --git a/src/monitor/TransmitWndBase.h b/src/monitor/TransmitWndBase.h deleted file mode 100644 index 4aeca58b..00000000 --- a/src/monitor/TransmitWndBase.h +++ /dev/null @@ -1,278 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Digital Voice Modem - Host Monitor Software - * GPLv2 Open Source. Use is subject to license terms. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright (C) 2023 Bryan Biedenkapp, N2PLL - * - */ -/** - * @file TransmitWndBase.h - * @ingroup monitor - */ -#if !defined(__TRANSMIT_WND_BASE_H__) -#define __TRANSMIT_WND_BASE_H__ - -#include "common/lookups/AffiliationLookup.h" -#include "host/restapi/RESTDefines.h" -#include "host/modem/Modem.h" -#include "remote/RESTClient.h" -#include "MonitorMain.h" - -#include "FDblDialog.h" - -#include -using namespace finalcut; - -// --------------------------------------------------------------------------- -// Class Declaration -// --------------------------------------------------------------------------- - -/** - * @brief This class implements the base class for transmit windows. - * @ingroup monitor - */ -class HOST_SW_API TransmitWndBase : public FDblDialog { -public: - /** - * @brief Initializes a new instance of the TransmitWndBase class. - * @param channel Channel data. - * @param widget - */ - explicit TransmitWndBase(lookups::VoiceChData channel, FWidget* widget = nullptr) : FDblDialog{widget}, - m_selectedCh(channel) - { - /* stub */ - } - -protected: - bool m_hideModeSelect = false; - lookups::VoiceChData m_selectedCh; - - uint8_t m_mode = modem::STATE_DMR; - - /** - * @brief Initializes the window layout. - */ - void initLayout() override - { - FDialog::setMinimizable(true); - FDialog::setShadow(); - - std::size_t maxWidth, maxHeight; - const auto& rootWidget = getRootWidget(); - - if (rootWidget) { - maxWidth = rootWidget->getClientWidth(); - maxHeight = rootWidget->getClientHeight(); - } - else { - // fallback to xterm default size - maxWidth = 80; - maxHeight = 24; - } - - const int x = 1 + int((maxWidth - getWidth()) / 2); - const int y = 1 + int((maxHeight - getHeight()) / 3); - FWindow::setPos(FPoint{x, y}, false); - FDialog::adjustSize(); - - FDialog::setModal(); - - initControls(); - - FDialog::initLayout(); - - rootWidget->redraw(); // bryanb: wtf? - redraw(); - } - - /** - * @brief Initializes window controls. - */ - virtual void initControls() - { - resizeControls(); - - m_dmrSlotLabel.setGeometry(FPoint(2, 4), FSize(10, 1)); - m_dmrSlot.setGeometry(FPoint(18, 4), FSize(5, 1)); - m_dmrSlot.setRange(1, 2); - m_dmrSlot.setValue(1); - m_dmrSlot.setShadow(false); - - // callback REST API to get status of the channel - json::object req = json::object(); - json::object rsp = json::object(); - - int ret = RESTClient::send(m_selectedCh.address(), m_selectedCh.port(), m_selectedCh.password(), - HTTP_GET, GET_STATUS, req, rsp, m_selectedCh.ssl(), g_debug); - if (ret != restapi::http::HTTPPayload::StatusType::OK) { - ::LogError(LOG_HOST, "failed to get status for %s:%u", m_selectedCh.address().c_str(), m_selectedCh.port()); - } - - try { - if (rsp["fixedMode"].get()) { - m_hideModeSelect = true; - } - - m_mode = rsp["state"].get(); - - bool dmrCC = rsp["dmrCC"].get(); - bool p25CC = rsp["p25CC"].get(); - bool nxdnCC = rsp["nxdnCC"].get(); - - // are we a dedicated control channel? - if (dmrCC || p25CC || nxdnCC) { - m_hideModeSelect = true; - if (dmrCC) { - m_mode = modem::STATE_DMR; - } - - if (p25CC) { - m_mode = modem::STATE_P25; - m_dmrSlot.setEnable(false); - redraw(); - } - - if (nxdnCC) { - m_mode = modem::STATE_NXDN; - m_dmrSlot.setEnable(false); - redraw(); - } - } - - // are we hiding the mode select? - if (!m_hideModeSelect) { - bool dmrEnabled = rsp["dmrEnabled"].get(); - bool p25Enabled = rsp["p25Enabled"].get(); - bool nxdnEnabled = rsp["nxdnEnabled"].get(); - - m_digModeGroup.setGeometry(FPoint(2, 1), FSize(56, 2)); - if (dmrEnabled) { - m_modeDMR.setPos(FPoint(1, 1)); - m_modeDMR.addCallback("toggled", [&]() { - if (m_modeDMR.isChecked()) { - m_mode = modem::STATE_DMR; - m_dmrSlot.setEnable(true); - redraw(); - } - }); - } - else { - m_modeDMR.setVisible(false); - } - - if (p25Enabled) { - m_modeP25.setPos(FPoint(13, 1)); - m_modeP25.addCallback("toggled", [&]() { - if (m_modeP25.isChecked()) { - m_mode = modem::STATE_P25; - m_dmrSlot.setEnable(false); - redraw(); - } - }); - } - else { - m_modeP25.setVisible(false); - } - - if (nxdnEnabled) { - m_modeNXDN.setPos(FPoint(22, 1)); - m_modeNXDN.addCallback("toggled", [&]() { - if (m_modeNXDN.isChecked()) { - m_mode = modem::STATE_NXDN; - m_dmrSlot.setEnable(false); - redraw(); - } - }); - } - else { - m_modeNXDN.setVisible(false); - } - } - else { - m_digModeGroup.setVisible(false); - m_modeDMR.setVisible(false); - m_modeP25.setVisible(false); - m_modeNXDN.setVisible(false); - m_dmrSlotLabel.setVisible(false); - m_dmrSlot.setVisible(false); - redraw(); - } - } - catch (std::exception&) { - /* stub */ - } - - focusFirstChild(); - } - - /** - * @brief - */ - void resizeControls() - { - // transmit button and close button logic - m_txButton.setGeometry(FPoint(3, int(getHeight()) - 6), FSize(10, 3)); - m_txButton.addCallback("clicked", [&]() { setTransmit(); }); - - m_closeButton.setGeometry(FPoint(17, int(getHeight()) - 6), FSize(9, 3)); - m_closeButton.addCallback("clicked", [&]() { hide(); }); - } - - /** - * @brief Adjusts window size. - */ - void adjustSize() override - { - FDialog::adjustSize(); - } - - /* - ** Event Handlers - */ - - /** - * @brief Event that occurs on keyboard key press. - * @param e Keyboard Event. - */ - void onKeyPress(finalcut::FKeyEvent* e) override - { - const auto key = e->key(); - if (key == FKey::F12) { - setTransmit(); - } - } - - /** - * @brief Event that occurs when the window is closed. - * @param e Close Event - */ - void onClose(FCloseEvent* e) override - { - hide(); - } - -protected: - /** - * @brief Helper to transmit. - */ - virtual void setTransmit() - { - /* stub */ - } - - FButton m_txButton{"Transmit", this}; - FButton m_closeButton{"Close", this}; - - FButtonGroup m_digModeGroup{"Digital Mode", this}; - FRadioButton m_modeDMR{"DMR", &m_digModeGroup}; - FRadioButton m_modeP25{"P25", &m_digModeGroup}; - FRadioButton m_modeNXDN{"NXDN", &m_digModeGroup}; - - FLabel m_dmrSlotLabel{"DMR Slot: ", this}; - FSpinBox m_dmrSlot{this}; -}; - -#endif // __TRANSMIT_WND_BASE_H__ \ No newline at end of file diff --git a/src/monitor/UninhibitSubscriberWnd.h b/src/monitor/UninhibitSubscriberWnd.h deleted file mode 100644 index ea485137..00000000 --- a/src/monitor/UninhibitSubscriberWnd.h +++ /dev/null @@ -1,146 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Digital Voice Modem - Host Monitor Software - * GPLv2 Open Source. Use is subject to license terms. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright (C) 2023 Bryan Biedenkapp, N2PLL - * - */ -/** - * @file RadioCheckSubscriberWnd.h - * @ingroup monitor - */ -#if !defined(__UNINHIBIT_SUBSCRIBER_WND_H__) -#define __UNINHIBIT_SUBSCRIBER_WND_H__ - -#include "TransmitWndBase.h" - -#include -using namespace finalcut; - -// --------------------------------------------------------------------------- -// Class Declaration -// --------------------------------------------------------------------------- - -/** - * @brief This class implements the uninhibit subscriber window. - * @ingroup monitor - */ -class HOST_SW_API UninhibitSubscriberWnd final : public TransmitWndBase { -public: - /** - * @brief Initializes a new instance of the UninhibitSubscriberWnd class. - * @param channel Channel data. - * @param widget - */ - explicit UninhibitSubscriberWnd(lookups::VoiceChData channel, FWidget* widget = nullptr) : TransmitWndBase{channel, widget} - { - /* stub */ - } - -private: - FLabel m_dialogLabel{"Uninhibit Subscriber", this}; - - FLabel m_subscriberLabel{"Subscriber ID: ", this}; - FSpinBox m_subscriber{this}; - - /** - * @brief Initializes the window layout. - */ - void initLayout() override - { - FDialog::setText("Uninhibit Subscriber"); - FDialog::setSize(FSize{60, 16}); - - TransmitWndBase::initLayout(); - } - - /** - * @brief Initializes window controls. - */ - void initControls() override - { - TransmitWndBase::initControls(); - - if (m_hideModeSelect) { - FDialog::setSize(FSize{60, 12}); - resizeControls(); - } - - // subscriber entry - { - if (!m_hideModeSelect) { - m_dialogLabel.setGeometry(FPoint(6, 6), FSize(20, 2)); - } - else { - m_dialogLabel.setGeometry(FPoint(6, 2), FSize(20, 2)); - } - m_dialogLabel.setEmphasis(); - m_dialogLabel.setAlignment(Align::Center); - - if (!m_hideModeSelect) { - m_subscriberLabel.setGeometry(FPoint(2, 8), FSize(25, 1)); - m_subscriber.setGeometry(FPoint(28, 8), FSize(20, 1)); - } - else { - m_subscriberLabel.setGeometry(FPoint(2, 4), FSize(25, 1)); - m_subscriber.setGeometry(FPoint(28, 4), FSize(20, 1)); - } - m_subscriber.setRange(0, 16777211); - m_subscriber.setValue(1); - m_subscriber.setShadow(false); - m_subscriber.addCallback("changed", [&]() { - if (m_subscriber.getValue() >= 1 && m_subscriber.getValue() <= 16777211) { - m_txButton.setEnable(true); - } - else { - m_txButton.setEnable(false); - } - - redraw(); - }); - } - - m_dialogLabel.redraw(); - m_subscriberLabel.redraw(); - redraw(); - } - - /** - * @brief Helper to transmit. - */ - void setTransmit() override - { - std::string method = PUT_DMR_RID; - json::object req = json::object(); - req["command"].set(RID_CMD_UNINHIBIT); - uint32_t dstId = m_subscriber.getValue(); - req["dstId"].set(dstId); - - switch (m_mode) { - case modem::STATE_DMR: - { - uint8_t slot = m_dmrSlot.getValue(); - req["slot"].set(slot); - } - break; - case modem::STATE_P25: - { - method = PUT_P25_RID; - } - break; - case modem::STATE_NXDN: - return; - } - - // callback REST API - int ret = RESTClient::send(m_selectedCh.address(), m_selectedCh.port(), m_selectedCh.password(), - HTTP_PUT, method, req, m_selectedCh.ssl(), g_debug); - if (ret != restapi::http::HTTPPayload::StatusType::OK) { - ::LogError(LOG_HOST, "failed to send request %s to %s:%u", method.c_str(), m_selectedCh.address().c_str(), m_selectedCh.port()); - } - } -}; - -#endif // __UNINHIBIT_SUBSCRIBER_WND_H__ \ No newline at end of file