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