//! Voice transmit mode (SDD-095). //! //! Selects how `transmit_active` is driven from the user's input //! signals. Persisted per-identity in //! [`chanora_storage::IdentityFileStore`] under the `transmit_mode` //! metadata key (default [`TransmitMode::Ptt`]). //! //! `VoiceActivity` is reserved per DEC-030 — for v1 the //! [`crate::transmit_selector::TransmitModeSelector`] treats it //! exactly like [`TransmitMode::Continuous`] until a real VAD //! implementation lands. /// User-visible voice transmit mode. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[repr(u8)] pub enum TransmitMode { /// Push-to-talk: transmit only while the bound key is held /// (with release-tail per SDD-096). Ptt = 0, /// Continuous: transmit whenever the user is in a voice /// channel and not hard-muted. Continuous = 1, /// Voice activity detection. Reserved per DEC-030; v1 behaves /// as [`TransmitMode::Continuous`] until a VAD implementation /// is allocated. VoiceActivity = 2, } impl Default for TransmitMode { fn default() -> Self { Self::Ptt } } impl TransmitMode { /// Encode as the persisted single-byte value. pub fn as_u8(self) -> u8 { self as u8 } /// Decode from the persisted single-byte value. Returns /// `None` for unknown encodings (the storage layer should /// fall back to [`TransmitMode::default`] in that case). pub fn from_u8(v: u8) -> Option { match v { 0 => Some(Self::Ptt), 1 => Some(Self::Continuous), 2 => Some(Self::VoiceActivity), _ => None, } } /// Stable diagnostic identifier (never localised). pub fn as_str(self) -> &'static str { match self { Self::Ptt => "ptt", Self::Continuous => "continuous", Self::VoiceActivity => "voice-activity", } } } #[cfg(test)] mod tests { use super::*; #[test] fn default_is_ptt() { assert_eq!(TransmitMode::default(), TransmitMode::Ptt); } #[test] fn round_trip_u8() { for m in [ TransmitMode::Ptt, TransmitMode::Continuous, TransmitMode::VoiceActivity, ] { assert_eq!(TransmitMode::from_u8(m.as_u8()), Some(m)); } assert_eq!(TransmitMode::from_u8(99), None); } #[test] fn as_str_is_stable() { assert_eq!(TransmitMode::Ptt.as_str(), "ptt"); assert_eq!(TransmitMode::Continuous.as_str(), "continuous"); assert_eq!(TransmitMode::VoiceActivity.as_str(), "voice-activity"); } }