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 = 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    TrackStart {
130        track_id: String,
131        timestamp: u64,
132        play_id: Option<String>,
133    },
134    TrackEnd {
135        track_id: String,
136        timestamp: u64,
137        duration: u64,
138        ssrc: u32,
139        play_id: Option<String>,
140    },
141    Interruption {
142        track_id: String,
143        timestamp: u64,
144        play_id: Option<String>,
145        subtitle: Option<String>, // current tts text
146        position: Option<u32>,    // word index in subtitle
147        total_duration: u32,      // whole tts duration
148        current: u32,             // elapsed time since start of tts
149    },
150    AsrFinal {
151        track_id: String,
152        timestamp: u64,
153        index: u32,
154        start_time: Option<u64>,
155        end_time: Option<u64>,
156        text: String,
157        is_filler: Option<bool>,
158        confidence: Option<f32>,
159        task_id: Option<String>,
160    },
161    AsrDelta {
162        track_id: String,
163        index: u32,
164        timestamp: u64,
165        start_time: Option<u64>,
166        end_time: Option<u64>,
167        text: String,
168        is_filler: Option<bool>,
169        confidence: Option<f32>,
170        task_id: Option<String>,
171    },
172    Metrics {
173        timestamp: u64,
174        key: String,
175        duration: u32,
176        data: serde_json::Value,
177    },
178    Error {
179        track_id: String,
180        timestamp: u64,
181        sender: String,
182        error: String,
183        code: Option<u32>,
184    },
185    AddHistory {
186        sender: Option<String>,
187        timestamp: u64,
188        speaker: String,
189        text: String,
190    },
191    Other {
192        track_id: String,
193        timestamp: u64,
194        sender: String,
195        extra: Option<HashMap<String, String>>,
196    },
197    Binary {
198        track_id: String,
199        timestamp: u64,
200        data: Vec<u8>,
201    },
202    Ping {
203        timestamp: u64,
204        payload: Option<String>,
205    },
206}
207
208impl Display for SessionEvent {
209    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
210        match self {
211            SessionEvent::Silence {
212                track_id, duration, ..
213            } => {
214                write!(f, "Silence(track_id={}, duration={})", track_id, duration)
215            }
216            SessionEvent::Binary { track_id, data, .. } => {
217                write!(f, "Silence(track_id={}, data_len={})", track_id, data.len())
218            }
219            _ => {
220                write!(f, "{:?}", self)
221            }
222        }
223    }
224}
225
226pub type EventSender = tokio::sync::broadcast::Sender<SessionEvent>;
227pub type EventReceiver = tokio::sync::broadcast::Receiver<SessionEvent>;
228
229pub fn create_event_sender() -> EventSender {
230    EventSender::new(128)
231}