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 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 text: Option<String>,
113 },
114 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>, position: Option<u32>, total_duration: u32, current: u32, },
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}