Files
ink-board/main/ui/apps/discord_app.h

124 lines
3.3 KiB
C++

#pragma once
#include "ui/ui_app.h"
#include "ui/page_stack.h"
#include "ui/app_registry.h"
#include "network/udp_client.h"
#include "io/nvs_handler.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include <string>
/**
* @brief Discord voice control app
*
* Allows control of Discord voice settings (mute/unmute) via UDP communication
* with the IotDis Node.js bridge. Features:
* - Main page: Status icon + mute button
* - Settings page: IP/port configuration with connection test
* - Periodic status polling with automatic retry
* - Error notification when remote is unreachable
*/
class DiscordApp : public UIApp {
public:
DiscordApp();
~DiscordApp() override;
// UIApp interface
esp_err_t init(lv_obj_t* container) override;
esp_err_t deinit() override;
std::string get_name() const override { return "Discord"; }
void handle_event(uint32_t event_type, void* event_data = nullptr) override;
bool on_back_button_pressed() override;
private:
// Voice state enum
enum class VoiceState {
UNKNOWN,
MUTED,
UNMUTED,
ERROR
};
// Page management
PageStack* page_stack_;
void build_main_page(lv_obj_t* page);
void build_settings_page(lv_obj_t* page);
void show_settings_page();
// Main page widgets
lv_obj_t* status_icon_label_;
lv_obj_t* status_text_label_;
lv_obj_t* mute_button_;
lv_obj_t* error_notification_;
// Settings page widgets
lv_obj_t* ip_textarea_;
lv_obj_t* port_textarea_;
lv_obj_t* test_result_label_;
// UDP client and configuration
UDPClient udp_client_;
std::string remote_ip_;
uint16_t remote_port_;
bool settings_configured_;
// Voice state
VoiceState current_state_;
SemaphoreHandle_t state_mutex_;
// Polling task
TaskHandle_t poll_task_handle_;
bool stop_polling_;
int consecutive_failures_;
static constexpr int MAX_FAILURES_BEFORE_ERROR = 3;
static constexpr int POLL_INTERVAL_MS = 5000;
static constexpr int ERROR_POLL_INTERVAL_MS = 15000;
static constexpr int RESPONSE_TIMEOUT_MS = 2000;
// NVS storage
NVSStorageHandler* storage_;
static constexpr const char* NVS_NAMESPACE = "discord";
static constexpr const char* NVS_KEY_IP = "remote_ip";
static constexpr const char* NVS_KEY_PORT = "remote_port";
// Event callbacks
static void on_mute_button_clicked(lv_event_t* e);
static void on_settings_button_clicked(lv_event_t* e);
static void on_save_settings_clicked(lv_event_t* e);
static void on_test_connection_clicked(lv_event_t* e);
// UDP communication
void send_mute_command();
bool test_connection();
void update_status_display();
void show_error_notification(bool show);
// Settings management
void load_settings();
void save_settings();
// Polling task
static void poll_task(void* param);
void start_polling_task();
void stop_polling_task();
void poll_status();
};
/**
* @brief Discord app descriptor for registration
*/
class DiscordAppDescriptor : public AppDescriptor {
public:
static DiscordAppDescriptor& instance() {
static DiscordAppDescriptor instance;
return instance;
}
void draw_icon(lv_obj_t* parent) override;
private:
DiscordAppDescriptor();
};