1use crate::media::PcmBuf;
2use serde::{Deserialize, Serialize};
3use serde_with::skip_serializing_none;
4use std::collections::HashMap;
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 Speaking {
83 track_id: String,
84 timestamp: u64,
85 start_time: u64,
86 },
87 Silence {
88 track_id: String,
89 timestamp: u64,
90 start_time: u64,
91 duration: u64,
92 #[serde(skip)]
93 samples: Option<PcmBuf>,
94 },
95 Eou {
97 track_id: String,
98 timestamp: u64,
99 completed: bool,
100 },
101 Inactivity { track_id: String, timestamp: u64 },
103 Dtmf {
104 track_id: String,
105 timestamp: u64,
106 digit: String,
107 },
108 TrackStart {
109 track_id: String,
110 timestamp: u64,
111 play_id: Option<String>,
112 },
113 TrackEnd {
114 track_id: String,
115 timestamp: u64,
116 duration: u64,
117 ssrc: u32,
118 play_id: Option<String>,
119 },
120 Interruption {
121 track_id: String,
122 timestamp: u64,
123 play_id: Option<String>,
124 subtitle: Option<String>, position: Option<u32>, total_duration: u32, current: u32, },
129 AsrFinal {
130 track_id: String,
131 timestamp: u64,
132 index: u32,
133 start_time: Option<u64>,
134 end_time: Option<u64>,
135 text: String,
136 },
137 AsrDelta {
138 track_id: String,
139 index: u32,
140 timestamp: u64,
141 start_time: Option<u64>,
142 end_time: Option<u64>,
143 text: String,
144 },
145 Metrics {
146 timestamp: u64,
147 key: String,
148 duration: u32,
149 data: serde_json::Value,
150 },
151 Error {
152 track_id: String,
153 timestamp: u64,
154 sender: String,
155 error: String,
156 code: Option<u32>,
157 },
158 AddHistory {
159 sender: Option<String>,
160 timestamp: u64,
161 speaker: String,
162 text: String,
163 },
164 Other {
165 track_id: String,
166 timestamp: u64,
167 sender: String,
168 extra: Option<HashMap<String, String>>,
169 },
170 Binary {
171 track_id: String,
172 timestamp: u64,
173 data: Vec<u8>,
174 },
175 Ping {
176 timestamp: u64,
177 payload: Option<String>,
178 },
179}
180
181pub type EventSender = tokio::sync::broadcast::Sender<SessionEvent>;
182pub type EventReceiver = tokio::sync::broadcast::Receiver<SessionEvent>;
183
184pub fn create_event_sender() -> EventSender {
185 EventSender::new(128)
186}