Browse Source
- New chat_setting.c/h: unified chat settings API (int/str getters) - Config parser supports [chat] section, calls chat_setting_set per key - chat_core exposes chat_core_set_setting / trampoline for GUI bridge - chatgui: AudioDevice + Storage pages persist to [chat] config + live apply - chatgui-android: ConfigProvider, NativeLib, headless handle chat settings - MessageList: 200 msg limit, fixed saveChannelState via trampoline - test_media_delivery_full: fix segfault at shutdown (mon() timer vs freed conns)topo_upd
22 changed files with 420 additions and 43 deletions
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* 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_DB_SYNC |
||||
#define CS_ID DEBUG_CATEGORY_DB_SYNC |
||||
#else |
||||
#define CS_ID DEBUG_CATEGORY_GENERAL |
||||
#endif |
||||
|
||||
#include <string.h> |
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
|
||||
/* ─── типы настроек ─── */ |
||||
|
||||
#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}, |
||||
{"storage_autoload_maxsize_mb", CHAT_SETTING_INT, 10, 1, 500}, |
||||
{"storage_maxsize_gb", CHAT_SETTING_INT, 1, 1, 100}, |
||||
{"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}, |
||||
}; |
||||
|
||||
#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; |
||||
} |
||||
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* chat_setting.h — chat-related settings (key-value API) |
||||
* |
||||
* Один API для всех потребителей: парсер конфига (headless) и GUI (через bridge). |
||||
* chat_setting_set(name, value) — валидация + хранение + apply к модулям. |
||||
* Возвращает 0=OK, -1=неизвестная настройка, -2=невалидное значение. |
||||
*/ |
||||
|
||||
#ifndef CHAT_SETTING_H |
||||
#define CHAT_SETTING_H |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
/* Установить настройку. Применяет на лету если модуль уже инициализирован. */ |
||||
int chat_setting_set(const char* name, const char* value); |
||||
|
||||
/* Прочитать сохранённое значение. NULL если такой настройки нет. */ |
||||
const char* chat_setting_get(const char* name); |
||||
|
||||
/* Прочитать как int. Возвращает def если настройка не найдена. */ |
||||
int chat_setting_get_int(const char* name, int def); |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
#endif /* CHAT_SETTING_H */ |
||||
Loading…
Reference in new issue