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