Skip to main content

freeswitch_types/commands/
conference.rs

1//! Builders for `conference` API sub-commands (mute, hold, DTMF).
2
3use std::fmt;
4
5/// Conference member mute/unmute action.
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7#[non_exhaustive]
8pub enum MuteAction {
9    /// Mute the member's audio.
10    Mute,
11    /// Unmute the member's audio.
12    Unmute,
13}
14
15impl fmt::Display for MuteAction {
16    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
17        match self {
18            Self::Mute => f.write_str("mute"),
19            Self::Unmute => f.write_str("unmute"),
20        }
21    }
22}
23
24/// Mute or unmute a conference member: `conference <name> mute|unmute <member>`.
25#[derive(Debug, Clone, PartialEq, Eq)]
26#[non_exhaustive]
27pub struct ConferenceMute {
28    /// Conference room name.
29    pub name: String,
30    /// Mute or unmute.
31    pub action: MuteAction,
32    /// Member ID, or `"all"` for all members.
33    pub member: String,
34}
35
36impl ConferenceMute {
37    /// Create a new conference mute/unmute command.
38    pub fn new(name: impl Into<String>, action: MuteAction, member: impl Into<String>) -> Self {
39        Self {
40            name: name.into(),
41            action,
42            member: member.into(),
43        }
44    }
45}
46
47impl fmt::Display for ConferenceMute {
48    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49        write!(
50            f,
51            "conference {} {} {}",
52            self.name, self.action, self.member
53        )
54    }
55}
56
57/// Conference member hold/unhold action.
58#[derive(Debug, Clone, Copy, PartialEq, Eq)]
59#[non_exhaustive]
60pub enum HoldAction {
61    /// Place the member on hold with music-on-hold.
62    Hold,
63    /// Return the member to the conference.
64    Unhold,
65}
66
67impl fmt::Display for HoldAction {
68    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
69        match self {
70            Self::Hold => f.write_str("hold"),
71            Self::Unhold => f.write_str("unhold"),
72        }
73    }
74}
75
76/// Hold or unhold a conference member: `conference <name> hold|unhold <member> [stream]`.
77///
78/// `Hold` plays music-on-hold to the member; `Unhold` returns them to the conference.
79#[derive(Debug, Clone, PartialEq, Eq)]
80#[non_exhaustive]
81pub struct ConferenceHold {
82    /// Conference room name.
83    pub name: String,
84    /// Hold or unhold.
85    pub action: HoldAction,
86    /// Member ID, or `"all"` for all members.
87    pub member: String,
88    /// MOH stream URI (e.g. `local_stream://moh`). Only meaningful with `HoldAction::Hold`.
89    pub stream: Option<String>,
90}
91
92impl ConferenceHold {
93    /// Create a new conference hold/unhold command.
94    pub fn new(name: impl Into<String>, action: HoldAction, member: impl Into<String>) -> Self {
95        Self {
96            name: name.into(),
97            action,
98            member: member.into(),
99            stream: None,
100        }
101    }
102
103    /// Set the MOH stream URI for hold.
104    pub fn with_stream(mut self, stream: impl Into<String>) -> Self {
105        self.stream = Some(stream.into());
106        self
107    }
108}
109
110impl fmt::Display for ConferenceHold {
111    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
112        write!(
113            f,
114            "conference {} {} {}",
115            self.name, self.action, self.member
116        )?;
117        if let Some(ref stream) = self.stream {
118            write!(f, " {}", stream)?;
119        }
120        Ok(())
121    }
122}
123
124/// Send DTMF to conference members: `conference <name> dtmf <member> <digits>`.
125#[derive(Debug, Clone, PartialEq, Eq)]
126#[non_exhaustive]
127pub struct ConferenceDtmf {
128    /// Conference room name.
129    pub name: String,
130    /// Member ID, or `"all"`.
131    pub member: String,
132    /// DTMF digit string (e.g. `"1234#"`).
133    pub dtmf: String,
134}
135
136impl ConferenceDtmf {
137    /// Create a new conference DTMF command.
138    pub fn new(
139        name: impl Into<String>,
140        member: impl Into<String>,
141        dtmf: impl Into<String>,
142    ) -> Self {
143        Self {
144            name: name.into(),
145            member: member.into(),
146            dtmf: dtmf.into(),
147        }
148    }
149}
150
151impl fmt::Display for ConferenceDtmf {
152    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
153        write!(
154            f,
155            "conference {} dtmf {} {}",
156            self.name, self.member, self.dtmf
157        )
158    }
159}
160
161#[cfg(test)]
162mod tests {
163    use super::*;
164
165    #[test]
166    fn conference_mute() {
167        let cmd = ConferenceMute {
168            name: "conf1".into(),
169            action: MuteAction::Mute,
170            member: "5".into(),
171        };
172        assert_eq!(cmd.to_string(), "conference conf1 mute 5");
173    }
174
175    #[test]
176    fn conference_unmute() {
177        let cmd = ConferenceMute {
178            name: "conf1".into(),
179            action: MuteAction::Unmute,
180            member: "5".into(),
181        };
182        assert_eq!(cmd.to_string(), "conference conf1 unmute 5");
183    }
184
185    #[test]
186    fn conference_hold_all() {
187        let cmd = ConferenceHold {
188            name: "conf1".into(),
189            action: HoldAction::Hold,
190            member: "all".into(),
191            stream: None,
192        };
193        assert_eq!(cmd.to_string(), "conference conf1 hold all");
194    }
195
196    #[test]
197    fn conference_hold_with_stream() {
198        let cmd = ConferenceHold {
199            name: "conf1".into(),
200            action: HoldAction::Hold,
201            member: "all".into(),
202            stream: Some("local_stream://moh".into()),
203        };
204        assert_eq!(
205            cmd.to_string(),
206            "conference conf1 hold all local_stream://moh"
207        );
208    }
209
210    #[test]
211    fn conference_unhold() {
212        let cmd = ConferenceHold {
213            name: "conf1".into(),
214            action: HoldAction::Unhold,
215            member: "all".into(),
216            stream: None,
217        };
218        assert_eq!(cmd.to_string(), "conference conf1 unhold all");
219    }
220
221    #[test]
222    fn conference_dtmf() {
223        let cmd = ConferenceDtmf {
224            name: "conf1".into(),
225            member: "all".into(),
226            dtmf: "1234".into(),
227        };
228        assert_eq!(cmd.to_string(), "conference conf1 dtmf all 1234");
229    }
230}