Ctrl K
ComunidadGuías…

room_status.h

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
#pragma once
#include <atomic>
#include "volume_control.h"
#include "queue_uri_log.h"
#include "podcast_settings.h"
#include <mutex>
#include <sstream>
#include <string>
#include <vector>
namespace bridge {
struct ModeStatus {
    std::string requested = "stream", active = "stream", state = "active", reason = "default-stream";
    std::string path;
    bool owned = false;
    uint64_t occurrence = 0;
    uint32_t renderedRate = 0;
    std::vector<std::string> ownedUris;
    std::string currentUri, lastFault, title;
};
// Passive snapshot registry, never a mode controller. A single room worker
// publishes queue observations and the complete diagnostic file synchronously.
class RoomStatus {
    mutable std::mutex mutex;
    ModeStatus value;

public:
    ModeStatus status() const {
        std::lock_guard<std::mutex> lock(mutex);
        return value;
    }
    void publish(ModeStatus v) {
        std::lock_guard<std::mutex> lock(mutex);
        value = std::move(v);
    }
    static std::string quote(const std::string &t) {
        std::string out = "\"";
        for (unsigned char c : t) {
            if (c == '\n') out += "\\n";
            else if (c == '\r') out += "\\r";
            else if (c == '\t') out += "\\t";
            else {
                if (c == '"' || c == '\\') out += '\\';
                out += c >= 32 ? char(c) : '?';
            }
        }
        return out + '"';
    }
    static std::string json(const ModeStatus &v) {
        auto q = [](const std::string &t) {
            std::string out = "\"";
            for (unsigned char c : t) {
                if (c == '"' || c == '\\') out += '\\';
                out += c >= 32 ? char(c) : '?';
            }
            return out + '"';
        };
        std::ostringstream out;
        out << "{\"requested\":" << q(v.requested) << ",\"active\":" << q(v.active)
            << ",\"state\":" << q(v.state) << ",\"reason\":" << q(v.reason);
        const auto &volume = roomVolumeSettings();
        out << ",\"lms_volume\":" << q(volume.speaker ? "speaker" : "off")
            << ",\"lms_volume_source\":" << q(volume.source) << ",\"volume_max\":" << volume.maximum;
        for (const auto &setting : roomPodcastSettings())
            out << "," << q(setting.key) << ":" << q(setting.enabled ? "yes" : "no")
                << "," << q(std::string(setting.key)+"_source") << ":" << q(setting.source);
        if (!v.path.empty())
            out << ",\"path\":" << q(v.path);
        if (v.active == "queue") {
            out << ",\"occurrence\":" << v.occurrence << ",\"owned\":" << (v.owned ? "true" : "false")
                << ",\"rendered_rate\":" << v.renderedRate << ",\"current_owned_item\":" << q(queueUriLog(v.currentUri))
                << ",\"last_fault\":" << q(queueUriLog(v.lastFault)) << ",\"owned_item_uris\":[";
            for (size_t i = 0; i < v.ownedUris.size(); ++i) {
                if (i)
                    out << ',';
                out << q(queueUriLog(v.ownedUris[i]));
            }
            out << "]";
            if (v.path == "relay") out << ",\"title\":" << quote(v.title);
            out << '}';
        } else {
            // Preserve the stream diagnostic's established representation.
            out << ",\"occurrence\":0,\"epoch\":0,\"generation\":1,\"owned\":false,\"mirrored_ahead\":0,"
                   "\"last_fallback\":\"\",\"handoff_gap_ms\":-1,\"latched\":false";
            if (v.requested == "queue")
                out << ",\"lms_cli_slow_replies\":0,\"lms_cli_failed_replies\":0";
            out << '}';
        }
        return out.str();
    }
};
inline std::atomic<RoomStatus *> &statusRegistry() {
    static auto *registry = new std::atomic<RoomStatus *>(nullptr);
    return *registry;
}
inline RoomStatus *roomMode() { return statusRegistry().load(); }
inline void setRoomStatus(RoomStatus *value) { statusRegistry() = value; }
} // namespace bridge