/* * session/session.h โ€” client-side mirror of the server's channel/user state. * * Populated from ServerStateSnapshot (full snapshot) and incremental UserEvent / * ChannelEvent messages. Not thread-safe โ€” always called from io_thread_. */ #ifndef VOICECAT_SESSION_SESSION_H #define VOICECAT_SESSION_SESSION_H #include #include #include #include #ifdef VOICECAT_HAS_NET #include "proto/voicecat.pb.h" #endif namespace voicecat::session { struct Channel { uint32_t id{0}; uint32_t parent_id{0}; std::string name; std::string topic; bool password_protected{false}; uint32_t max_users{0}; }; struct Stream { uint32_t stream_id{0}; uint32_t ssrc{0}; int kind{0}; std::string label; // Full effective AudioConfig (docs/protocol.md ยง5), as broadcast by the server in // StreamInfo.audio โ€” mirrors voicecat::v1::AudioConfig field-for-field so M3 per-channel // tuning (mono/stereo, bitrate, FEC/DTX, application) is observable client-side, not just // sample_rate/frame_ms. uint32_t sample_rate{48000}; uint32_t frame_ms{20}; uint32_t mode{0}; // 0 = mono, 1 = stereo (ChannelMode) uint32_t bitrate_bps{0}; uint32_t application{0}; // 0=VOIP, 1=AUDIO, 2=LOWDELAY (OpusApplication) bool fec{false}; uint32_t expected_packet_loss{0}; bool dtx{false}; uint32_t complexity{0}; bool dred{false}; }; struct User { uint32_t id{0}; std::string nickname; bool is_guest{true}; uint32_t channel_id{0}; bool self_mic_muted{false}; bool self_deafened{false}; bool server_muted{false}; bool server_deafened{false}; std::vector streams; }; class SessionModel { public: const std::vector& channels() const { return channels_; } const std::vector& users() const { return users_; } const Channel* find_channel(uint32_t id) const; const User* find_user(uint32_t id) const; // Find the user that owns a given media ssrc, and the matching Stream entry. // Returns {nullptr, nullptr} if not found. std::pair find_user_by_ssrc(uint32_t ssrc) const; #ifdef VOICECAT_HAS_NET void apply_snapshot(const voicecat::v1::ServerStateSnapshot& snap); void apply_user_event(const voicecat::v1::UserEvent& ev); void apply_channel_event(const voicecat::v1::ChannelEvent& ev); #endif private: std::vector channels_; std::vector users_; }; } // namespace voicecat::session #endif // VOICECAT_SESSION_SESSION_H