Skip to main content

active_call/
event.rs

1use crate::media::PcmBuf;
2use serde::{Deserialize, Serialize};
3use serde_with::skip_serializing_none;
4use std::{collections::HashMap, fmt::Display};
5
6#[derive(Debug, Clone, Serialize, Deserialize)]
7#[serde(rename_all = "camelCase")]
8pub struct Attendee {
9    pub username: String,
10    pub realm: String,
11    pub source: String,
12}
13
14impl From<&String> for Attendee {
15    fn from(source: &String) -> Self {
16        let uri = rsipstack::rsip::Uri::try_from(source.as_str()).unwrap_or_default();
17        Self {
18            username: uri.user().unwrap_or_default().to_string(),
19            realm: uri.host().to_string(),
20            source: source.to_string(),
21        }
22    }
23}
24
25#[skip_serializing_none]
26#[derive(Debug, Clone, Serialize, Deserialize)]
27#[serde(
28    tag = "event",
29    rename_all = "camelCase",
30    rename_all_fields = "camelCase"
31)]
32pub enum SessionEvent {
33    Incoming {
34        track_id: String,
35        timestamp: u64,
36        caller: String,
37        callee: String,
38        sdp: String,
39    },
40    Answer {
41        track_id: String,
42        timestamp: u64,
43        sdp: String,
44        refer: Option<bool>,
45    },
46    Reject {
47        track_id: String,
48        timestamp: u64,
49        reason: String,
50        refer: Option<bool>,
51        code: Option<u32>,
52    },
53    Ringing {
54        track_id: String,
55        timestamp: u64,
56        early_media: bool,
57        refer: Option<bool>,
58    },
59    Hangup {
60        track_id: String,
61        timestamp: u64,
62        reason: Option<String>,
63        initiator: Option<String>,
64        start_time: String,
65        hangup_time: String,
66        answer_time: Option<String>,
67        ringing_time: Option<String>,
68        from: Option<Attendee>,
69        to: Option<Attendee>,
70        extra: Option<HashMap<String, serde_json::Value>>,
71        refer: Option<bool>,
72    },
73    AnswerMachineDetection {
74        // Answer machine detection
75        track_id: String,
76        timestamp: u64,
77        start_time: u64,
78        end_time: u64,
79        text: String,
80    },
81    Interrupt {
82        receiver: Option<String>,
83    },
84    FunctionCall {
85        track_id: String,
86        call_id: String,
87        name: String,
88        arguments: String,
89        timestamp: u64,
90    },
91    Speaking {
92        track_id: String,
93        timestamp: u64,
94        start_time: u64,
95        is_filler: Option<bool>,
96        confidence: Option<f32>,
97    },
98    Silence {
99        track_id: String,
100        timestamp: u64,
101        start_time: u64,
102        duration: u64,
103        #[serde(skip)]
104        samples: Option<PcmBuf>,
105    },
106    ///End of Utterance
107    Eou {
108        track_id: String,
109        timestamp: u64,
110        completed: bool,
111        interrupt_point: Option<String>,
112        text: Option<String>,
113    },
114    ///Inactivity timeout
115    Inactivity {
116        track_id: String,
117        timestamp: u64,
118    },
119    Dtmf {
120        track_id: String,
121        timestamp: u64,
122        digit: String,
123    },
124    Hold {
125        track_id: String,
126        timestamp: u64,
127        on_hold: bool,
128    },
129    TransferRequest {
130        track_id: String,
131        timestamp: u64,
132        refer_to: String,
133        referred_by: Option<String>,
134        refer: Option<bool>,
135    },
136    TrackStart {
137        track_id: String,
138        timestamp: u64,
139        play_id: Option<String>,
140    },
141    TrackEnd {
142        track_id: String,
143        timestamp: u64,
144        duration: u64,
145        ssrc: u32,
146        play_id: Option<String>,
147    },
148    Interruption {
149        track_id: String,
150        timestamp: u64,
151        play_id: Option<String>,
152        subtitle: Option<String>, // current tts text
153        position: Option<u32>,    // word index in subtitle
154        total_duration: u32,      // whole tts duration
155        current: u32,             // elapsed time since start of tts
156    },
157    AsrFinal {
158        track_id: String,
159        timestamp: u64,
160        index: u32,
161        start_time: Option<u64>,
162        end_time: Option<u64>,
163        text: String,
164        is_filler: Option<bool>,
165        confidence: Option<f32>,
166        task_id: Option<String>,
167    },
168    AsrDelta {
169        track_id: String,
170        index: u32,
171        timestamp: u64,
172        start_time: Option<u64>,
173        end_time: Option<u64>,
174        text: String,
175        is_filler: Option<bool>,
176        confidence: Option<f32>,
177        task_id: Option<String>,
178    },
179    Metrics {
180        timestamp: u64,
181        key: String,
182        duration: u32,
183        data: serde_json::Value,
184    },
185    Error {
186        track_id: String,
187        timestamp: u64,
188        sender: String,
189        error: String,
190        code: Option<u32>,
191    },
192    AddHistory {
193        sender: Option<String>,
194        timestamp: u64,
195        speaker: String,
196        text: String,
197    },
198    Other {
199        track_id: String,
200        timestamp: u64,
201        sender: String,
202        extra: Option<HashMap<String, String>>,
203    },
204    Binary {
205        track_id: String,
206        timestamp: u64,
207        data: Vec<u8>,
208    },
209    Ping {
210        timestamp: u64,
211        payload: Option<String>,
212    },
213    Custom {
214        timestamp: u64,
215        sender: Option<String>,
216        data: serde_json::Value,
217    },
218}
219
220impl Display for SessionEvent {
221    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
222        match self {
223            SessionEvent::Silence {
224                track_id, duration, ..
225            } => {
226                write!(f, "Silence(track_id={}, duration={})", track_id, duration)
227            }
228            SessionEvent::Binary { track_id, data, .. } => {
229                write!(f, "Silence(track_id={}, data_len={})", track_id, data.len())
230            }
231            _ => {
232                write!(f, "{:?}", self)
233            }
234        }
235    }
236}
237
238pub type EventSender = tokio::sync::broadcast::Sender<SessionEvent>;
239pub type EventReceiver = tokio::sync::broadcast::Receiver<SessionEvent>;
240
241pub fn create_event_sender() -> EventSender {
242    EventSender::new(128)
243}