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 Dtmf {
102 track_id: String,
103 timestamp: u64,
104 digit: String,
105 },
106 TrackStart {
107 track_id: String,
108 timestamp: u64,
109 play_id: Option<String>,
110 },
111 TrackEnd {
112 track_id: String,
113 timestamp: u64,
114 duration: u64,
115 ssrc: u32,
116 play_id: Option<String>,
117 },
118 Interruption {
119 track_id: String,
120 timestamp: u64,
121 play_id: Option<String>,
122 subtitle: Option<String>, position: Option<u32>, total_duration: u32, current: u32, },
127 AsrFinal {
128 track_id: String,
129 timestamp: u64,
130 index: u32,
131 start_time: Option<u64>,
132 end_time: Option<u64>,
133 text: String,
134 },
135 AsrDelta {
136 track_id: String,
137 index: u32,
138 timestamp: u64,
139 start_time: Option<u64>,
140 end_time: Option<u64>,
141 text: String,
142 },
143 Metrics {
144 timestamp: u64,
145 key: String,
146 duration: u32,
147 data: serde_json::Value,
148 },
149 Error {
150 track_id: String,
151 timestamp: u64,
152 sender: String,
153 error: String,
154 code: Option<u32>,
155 },
156 AddHistory {
157 sender: Option<String>,
158 timestamp: u64,
159 speaker: String,
160 text: String,
161 },
162 Other {
163 track_id: String,
164 timestamp: u64,
165 sender: String,
166 extra: Option<HashMap<String, String>>,
167 },
168 Binary {
169 track_id: String,
170 timestamp: u64,
171 data: Vec<u8>,
172 },
173 Ping {
174 timestamp: u64,
175 payload: Option<String>,
176 },
177}
178
179pub type EventSender = tokio::sync::broadcast::Sender<SessionEvent>;
180pub type EventReceiver = tokio::sync::broadcast::Receiver<SessionEvent>;
181
182pub fn create_event_sender() -> EventSender {
183 EventSender::new(128)
184}