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