Preserve desktop catalogue watches across chat selection

This commit is contained in:
evgeny committed 2026-10-20 16:27:17 +02:00
1 parent 4fa9d474ab
commit 94697c1af0
2 files changed
+23 -14

No files matched your search

+21 -13
View File
@@ -1,5 +1,7 @@
#include "stream_bridge.h"
#include <mutex>
#include <map>
#include <set>
extern "C" {
#include "../../../lib/debug_config.h"
@@ -15,17 +17,22 @@ struct Bridge {
std::mutex lock; // Ограничивает lifetime managers для callers GUI/workers.
UTUN_INSTANCE* inst = nullptr;
posted_task* pending = nullptr;
uint64_t watch = 0;
bool watchPending = false;
std::map<uint64_t, uint64_t> watches;
std::set<uint64_t> watchChanges;
stream_viewers* viewers = nullptr;
stream_publisher* publisher = nullptr;
} bridge;
void watch(void*) {
std::lock_guard<std::mutex> guard(bridge.lock);
bridge.pending = nullptr; bridge.watchPending = false;
if (stream_watch_sources(bridge.inst, bridge.watch) != STREAM_OK)
DEBUG_ERROR(DEBUG_CATEGORY_STREAM, "desktop source watch failed group=%llx", (unsigned long long)bridge.watch);
bridge.pending = nullptr;
for (auto owner : bridge.watchChanges) {
uint64_t group = bridge.watches.at(owner);
if (stream_watch_sources(bridge.inst, group, owner) != STREAM_OK)
DEBUG_ERROR(DEBUG_CATEGORY_STREAM, "desktop source watch failed group=%llx", (unsigned long long)group);
if (!group) bridge.watches.erase(owner);
}
bridge.watchChanges.clear();
}
}
@@ -39,11 +46,11 @@ bool gui_stream_attach(UTUN_INSTANCE* inst) {
stream_publisher_destroy(bridge.publisher); bridge.publisher = nullptr; return false;
}
bridge.inst = inst;
if (bridge.watchPending) {
bridge.watchPending = false;
if (stream_watch_sources(inst, bridge.watch) != STREAM_OK)
DEBUG_ERROR(DEBUG_CATEGORY_STREAM, "desktop initial source watch failed group=%llx", (unsigned long long)bridge.watch);
for (const auto& [owner, group] : bridge.watches) {
if (stream_watch_sources(inst, group, owner) != STREAM_OK)
DEBUG_ERROR(DEBUG_CATEGORY_STREAM, "desktop initial source watch failed group=%llx", (unsigned long long)group);
}
bridge.watchChanges.clear();
DEBUG_INFO(DEBUG_CATEGORY_STREAM, "desktop stream bridge attached"); return true;
}
@@ -51,14 +58,15 @@ void gui_stream_detach(UTUN_INSTANCE* inst) {
std::lock_guard<std::mutex> guard(bridge.lock);
if (!inst || bridge.inst != inst) return;
if (bridge.pending) uasync_cancel_post(inst->ua, bridge.pending);
stream_watch_sources(inst, 0); bridge.pending = nullptr;
for (const auto& [owner, group] : bridge.watches) stream_watch_sources(inst, 0, owner);
bridge.pending = nullptr;
stream_viewers_destroy(bridge.viewers); bridge.viewers = nullptr;
stream_publisher_destroy(bridge.publisher); bridge.publisher = nullptr;
bridge.inst = nullptr; bridge.watchPending = bridge.watch != 0;
bridge.inst = nullptr; bridge.watchChanges.clear();
DEBUG_INFO(DEBUG_CATEGORY_STREAM, "desktop stream bridge detached");
}
bool gui_stream_watch(uint64_t group) {
bool gui_stream_watch(uint64_t group, uint64_t owner) {
std::lock_guard<std::mutex> guard(bridge.lock);
if (bridge.inst && !bridge.pending) {
auto* task = static_cast<posted_task*>(u_calloc(1, sizeof(posted_task)));
@@ -66,7 +74,7 @@ bool gui_stream_watch(uint64_t group) {
task->callback = watch; bridge.pending = task;
uasync_post_reserved(bridge.inst->ua, task);
}
bridge.watch = group; bridge.watchPending = true; return true;
bridge.watches[owner] = group; bridge.watchChanges.insert(owner); return true;
}
bool gui_stream_open(uint64_t id, uint64_t group, uint64_t source, uint64_t epoch) {
+2 -1
View File
@@ -23,7 +23,8 @@ struct StreamRecord {
bool gui_stream_attach(UTUN_INSTANCE* inst);
void gui_stream_detach(UTUN_INSTANCE* inst);
bool gui_stream_watch(uint64_t group);
/* owner=0 — выбранный чат; окно многопросмотра держит свой ненулевой owner. group=0 снимает только его. */
bool gui_stream_watch(uint64_t group, uint64_t owner = 0);
bool gui_stream_open(uint64_t id, uint64_t group, uint64_t source, uint64_t epoch);
void gui_stream_stop(uint64_t id);
bool gui_stream_pull(uint64_t id, StreamRecord& record, int64_t position = -1,