Files
utun2/tools/chatgui/src/stream_sources.h
T

38 lines
2.2 KiB
C++

/* Снимок каталога CHAT_EVT_STREAM_SOURCES для шапки чата и отдельного окна просмотра.
* parse применяет данные целиком; valid=false означает недоступность, а не пустой каталог. */
#pragma once
#include <QJsonDocument>
#include <QJsonArray>
#include <QJsonObject>
#include <QSet>
#include <QtEndian>
#include "../../../lib/debug_config.h"
struct LiveStreamSource { quint64 id, epoch; QString name; bool self = false; };
struct StreamSourceSnapshot { quint64 group = 0; bool valid = false; QList<LiveStreamSource> sources; };
inline bool parseStreamSources(const uint8_t* data, int length, StreamSourceSnapshot& out) {
if (!data || length < 11 || data[8] > 1) {
DEBUG_ERROR(DEBUG_CATEGORY_STREAM, "desktop source event invalid bytes=%d", length); return false;
}
StreamSourceSnapshot next; next.group = qFromBigEndian<quint64>(data); next.valid = data[8];
QJsonParseError error;
auto document = QJsonDocument::fromJson(QByteArray(reinterpret_cast<const char*>(data + 9), length - 9), &error);
if (!next.group || error.error != QJsonParseError::NoError || !document.isArray()) {
DEBUG_ERROR(DEBUG_CATEGORY_STREAM, "desktop source JSON invalid group=%llx error=%s",
(unsigned long long)next.group, qPrintable(error.errorString())); return false;
}
QSet<quint64> seen;
for (const auto& value : document.array()) {
auto member = value.toObject(); bool idOk = false, epochOk = false;
quint64 id = member.value("id").toString().toULongLong(&idOk);
quint64 epoch = member.value("epoch").toString().toULongLong(&epochOk, 16);
if (!idOk || !epochOk || !id || !epoch || seen.contains(id) || !member.value("name").isString()) {
DEBUG_ERROR(DEBUG_CATEGORY_STREAM, "desktop source identity invalid group=%llx", (unsigned long long)next.group); return false;
}
QString name = member.value("name").toString(); if (name.isEmpty()) name = QString::number(id);
next.sources.append({id, epoch, name, member.value("self").toInt() != 0}); seen.insert(id);
}
out = std::move(next); return true;
}