Centralize owned settings and name requests in the GUI bridge
This commit is contained in:
1 parent
05b0ef50e4
commit
f1f5d33788
3 files changed
+74
-1
No files matched your search
@@ -143,7 +143,7 @@ class SettingsSaveTest : public QObject {
|
||||
QCOMPARE(VoiceEncoder::preset(), 2);
|
||||
}
|
||||
if (kind == Dialog) {
|
||||
QCOMPARE(QString::fromUtf8(core.inst->config->global.my_node_name), QString("After"));
|
||||
QCOMPARE(QString::fromUtf8(core.inst->name), QString("After"));
|
||||
QCOMPARE(chat_setting_get_int(core.inst, "stream_subblocks", -1), 12);
|
||||
QCOMPARE(chat_setting_get_int(core.inst, "stream_rs_redundant", -1), 3);
|
||||
QCOMPARE(core.db.getUiStateInt("join_policy", -1), 1);
|
||||
|
||||
@@ -92,6 +92,18 @@ void gui_bridge_post_uasync_fn(void (*fn)(void*), void* arg);
|
||||
/* Передать отдельный u_malloc/u_calloc-блок arg: 0 — мост принял владение, callback обязан освободить arg;
|
||||
* отмена до callback освобождает его мостом. -1 — arg остаётся вызывающему. Вложенные ресурсы не освобождаются. */
|
||||
int gui_bridge_post_uasync_owned_fn(void (*fn)(void*), void* arg);
|
||||
|
||||
/* Назначение пары key/value: локальный ui_state SQLite либо live chat_setting ядра. */
|
||||
enum gui_setting_target { GUI_SETTING_UI_STATE, GUI_SETTING_CHAT };
|
||||
/* Скопировать NUL-строки key/value в собственный запрос и поставить его текущему ядру под mutex моста.
|
||||
* key непустой; key+NUL+value+NUL должны помещаться в data соответствующего запроса ядра.
|
||||
* 0 — принято (не подтверждение записи/валидации ядром), -1 — отказ с логом, память за вызывающим не остаётся.
|
||||
* При отмене запрос освобождает мост, после исполнения — trampoline. INI-файл эта функция не меняет. */
|
||||
int gui_bridge_post_setting(enum gui_setting_target target, const char* key, const char* value);
|
||||
/* Скопировать name (включая пустое, в пределах update_my_name_arg::name) и поставить обновление текущему ядру.
|
||||
* Владение и результат — как у post_setting; строка/форма вызывающего после возврата больше не нужны. */
|
||||
int gui_bridge_update_name(const char* name);
|
||||
|
||||
/* Composer-запрос: 0 — владение req передано, callback/отмена освободят блок; -1 — req остаётся вызывающему. */
|
||||
struct chat_msg_submit;
|
||||
int gui_bridge_submit_message(struct chat_msg_submit* req);
|
||||
|
||||
@@ -625,6 +625,67 @@ int gui_bridge_post_uasync_owned_fn(void (*fn)(void*), void* arg) {
|
||||
return post_command(fn, arg, true);
|
||||
}
|
||||
|
||||
/* Сериализация и публикация образуют одну границу владения с detach ядра. */
|
||||
int gui_bridge_post_setting(enum gui_setting_target target, const char* key, const char* value) {
|
||||
if ((target != GUI_SETTING_UI_STATE && target != GUI_SETTING_CHAT) || !key || !key[0] || !value) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "GUI setting rejected: target=%d missing/invalid key or value", target); return -1;
|
||||
}
|
||||
const size_t capacity = target == GUI_SETTING_UI_STATE ? sizeof(save_ui_state_arg::data) : sizeof(chat_setting_arg::data);
|
||||
size_t keyLength = 0, valueLength = 0;
|
||||
while (keyLength < capacity && key[keyLength]) ++keyLength;
|
||||
while (valueLength < capacity && value[valueLength]) ++valueLength;
|
||||
if (keyLength + valueLength + 2 > capacity) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "GUI setting rejected: target=%d key_bytes=%zu value_bytes=%zu capacity=%zu",
|
||||
target, keyLength, valueLength, capacity);
|
||||
return -1;
|
||||
}
|
||||
std::lock_guard<std::mutex> guard(bridge_mutex);
|
||||
if (!g_inst || !g_ua) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_CONFIG, "GUI setting rejected: target=%d key=%s core unavailable", target, key); return -1;
|
||||
}
|
||||
const size_t bytes = target == GUI_SETTING_UI_STATE ? sizeof(save_ui_state_arg) : sizeof(chat_setting_arg);
|
||||
void* request = u_malloc(bytes);
|
||||
if (!request) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "GUI setting allocation failed: target=%d key=%s bytes=%zu", target, key, bytes); return -1;
|
||||
}
|
||||
char* data;
|
||||
void (*callback)(void*);
|
||||
if (target == GUI_SETTING_UI_STATE) {
|
||||
auto* arg = static_cast<save_ui_state_arg*>(request);
|
||||
arg->inst = g_inst; data = arg->data; callback = chat_core_save_ui_state_trampoline;
|
||||
} else {
|
||||
auto* arg = static_cast<chat_setting_arg*>(request);
|
||||
arg->inst = g_inst; data = arg->data; callback = chat_core_set_setting_trampoline;
|
||||
}
|
||||
memcpy(data, key, keyLength + 1); memcpy(data + keyLength + 1, value, valueLength + 1);
|
||||
if (post_command(callback, request, true) < 0) {
|
||||
u_free(request);
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "GUI setting queue rejected: target=%d key=%s", target, key); return -1;
|
||||
}
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_CONFIG, "GUI setting queued: target=%d key=%s value_bytes=%zu", target, key, valueLength);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Смена имени использует тот же owned lifecycle без передачи instance из GUI. */
|
||||
int gui_bridge_update_name(const char* name) {
|
||||
if (!name) { DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "GUI name rejected: missing name"); return -1; }
|
||||
size_t length = 0;
|
||||
while (length < sizeof(update_my_name_arg::name) && name[length]) ++length;
|
||||
if (length == sizeof(update_my_name_arg::name)) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "GUI name rejected: name exceeds request capacity"); return -1;
|
||||
}
|
||||
std::lock_guard<std::mutex> guard(bridge_mutex);
|
||||
if (!g_inst || !g_ua) { DEBUG_WARN(DEBUG_CATEGORY_CONFIG, "GUI name rejected: core unavailable"); return -1; }
|
||||
auto* request = static_cast<update_my_name_arg*>(u_malloc(sizeof(update_my_name_arg)));
|
||||
if (!request) { DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "GUI name allocation failed"); return -1; }
|
||||
request->inst = g_inst; memcpy(request->name, name, length + 1);
|
||||
if (post_command(chat_core_update_my_name_trampoline, request, true) < 0) {
|
||||
u_free(request); DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "GUI name queue rejected"); return -1;
|
||||
}
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_CONFIG, "GUI name queued: bytes=%zu", length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gui_bridge_submit_message(struct chat_msg_submit* req) {
|
||||
std::lock_guard<std::mutex> guard(bridge_mutex);
|
||||
if (!req || !g_inst || !g_ua || !uasync_is_running(g_ua)) {
|
||||
|
||||
Reference in new issue
Block a user