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 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 Eou {
109 track_id: String,
110 timestamp: u64,
111 completed: bool,
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 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>, position: Option<u32>, total_duration: u32, current: u32, },
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}