/* * chat_setting.c — chat-related settings: validation, storage, on-the-fly apply * * Используется и из парсера конфига (headless), и из GUI (через bridge). * Никаких зависимостей от g_cc или instance — работает автономно. */ #include "chat_setting.h" #include "../../lib/debug_config.h" #ifdef DEBUG_CATEGORY_CHAT_SYNC #define CS_ID DEBUG_CATEGORY_CHAT_SYNC #else #define CS_ID DEBUG_CATEGORY_GENERAL #endif #include #include #include /* ─── типы настроек ─── */ #define CHAT_SETTING_INT 0 #define CHAT_SETTING_BOOL 1 struct chat_setting_def { const char* name; int type; int default_val; int min_val; int max_val; }; /* ─── реестр всех известных настроек ─── */ static const struct chat_setting_def g_setting_defs[] = { {"storage_autoload", CHAT_SETTING_BOOL, 1, 0, 1}, {"opus_codec_preset", CHAT_SETTING_INT, 1, 0, 4}, {"compressor_enabled", CHAT_SETTING_BOOL, 0, 0, 1}, {"compressor_max_gain_db", CHAT_SETTING_INT, 25, 1, 100}, {"compressor_rise_rate", CHAT_SETTING_INT, 10, 1, 100}, {"media_download_max_peers", CHAT_SETTING_INT, 3, 1, 16}, {"join_policy", CHAT_SETTING_INT, 1, 0, 2}, /* 0=autojoin, 1=ask, 2=deny */ }; #define CHAT_SETTING_COUNT (sizeof(g_setting_defs) / sizeof(g_setting_defs[0])) /* ─── состояние (текущие значения) ─── */ static int g_chat_values[CHAT_SETTING_COUNT]; static int g_chat_initialized = 0; static void chat_setting_reset_defaults(void) { for (size_t i = 0; i < CHAT_SETTING_COUNT; i++) g_chat_values[i] = g_setting_defs[i].default_val; g_chat_initialized = 1; } /* ─── поиск ─── */ static int chat_setting_find(const char* name) { for (size_t i = 0; i < CHAT_SETTING_COUNT; i++) if (strcmp(g_setting_defs[i].name, name) == 0) return (int)i; return -1; } /* ─── apply: вызов специфичного для настройки кода ─── */ static void chat_setting_apply(void) { /* будет заполняться по мере появления runtime-setter'ов в модулях: if (idx == ...) some_module_set_xxx(value); */ } /* ─── public API ─── */ int chat_setting_set(const char* name, const char* value) { if (!name || !value || !*name || !*value) return -2; if (!g_chat_initialized) chat_setting_reset_defaults(); int idx = chat_setting_find(name); if (idx < 0) { DEBUG_ERROR(CS_ID, "chat_setting: unknown setting '%s'", name); return -1; } const struct chat_setting_def* def = &g_setting_defs[idx]; int v; if (def->type == CHAT_SETTING_BOOL) { if (strcmp(value, "0") == 0 || strcmp(value, "no") == 0 || strcmp(value, "false") == 0) v = 0; else if (strcmp(value, "1") == 0 || strcmp(value, "yes") == 0 || strcmp(value, "true") == 0) v = 1; else { DEBUG_ERROR(CS_ID, "chat_setting: '%s' invalid bool '%s' (expect 0/1)", name, value); return -2; } } else { char* end = NULL; long lv = strtol(value, &end, 10); if (!end || *end != '\0' || lv < def->min_val || lv > def->max_val) { DEBUG_ERROR(CS_ID, "chat_setting: '%s' invalid int '%s' (range %d..%d)", name, value, def->min_val, def->max_val); return -2; } v = (int)lv; } if (g_chat_values[idx] == v) return 0; g_chat_values[idx] = v; DEBUG_INFO(CS_ID, "chat_setting: %s = %s", name, value); chat_setting_apply(); return 0; } const char* chat_setting_get(const char* name) { if (!g_chat_initialized) chat_setting_reset_defaults(); int idx = chat_setting_find(name); if (idx < 0) return NULL; static char buf[16]; snprintf(buf, sizeof(buf), "%d", g_chat_values[idx]); return buf; } int chat_setting_get_int(const char* name, int def) { if (!g_chat_initialized) chat_setting_reset_defaults(); int idx = chat_setting_find(name); return idx >= 0 ? g_chat_values[idx] : def; }