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 },
46 Reject {
47 track_id: String,
48 timestamp: u64,
49 reason: String,
50 code: Option<u32>,
51 },
52 Ringing {
53 track_id: String,
54 timestamp: u64,
55 early_media: bool,
56 },
57 Hangup {
58 track_id: String,
59 timestamp: u64,
60 reason: Option<String>,
61 initiator: Option<String>,
62 start_time: String,
63 hangup_time: String,
64 answer_time: Option<String>,
65 ringing_time: Option<String>,
66 from: Option<Attendee>,
67 to: Option<Attendee>,
68 extra: Option<HashMap<String, serde_json::Value>>,
69 },
70 AnswerMachineDetection {
71 track_id: String,
73 timestamp: u64,
74 start_time: u64,
75 end_time: u64,
76 text: String,
77 },
78 Speaking {
79 track_id: String,
80 timestamp: u64,
81 start_time: u64,
82 },
83 Silence {
84 track_id: String,
85 timestamp: u64,
86 start_time: u64,
87 duration: u64,
88 #[serde(skip)]
89 samples: Option<PcmBuf>,
90 },
91 Eou {
93 track_id: String,
94 timestamp: u64,
95 completed: bool,
96 },
97 Dtmf {
98 track_id: String,
99 timestamp: u64,
100 digit: String,
101 },
102 TrackStart {
103 track_id: String,
104 timestamp: u64,
105 play_id: Option<String>,
106 },
107 TrackEnd {
108 track_id: String,
109 timestamp: u64,
110 duration: u64,
111 ssrc: u32,
112 play_id: Option<String>,
113 },
114 Interruption {
115 track_id: String,
116 timestamp: u64,
117 play_id: Option<String>,
118 subtitle: Option<String>, position: Option<u32>, total_duration: u32, current: u32, },
123 AsrFinal {
124 track_id: String,
125 timestamp: u64,
126 index: u32,
127 start_time: Option<u64>,
128 end_time: Option<u64>,
129 text: String,
130 },
131 AsrDelta {
132 track_id: String,
133 index: u32,
134 timestamp: u64,
135 start_time: Option<u64>,
136 end_time: Option<u64>,
137 text: String,
138 },
139 Metrics {
140 timestamp: u64,
141 key: String,
142 duration: u32,
143 data: serde_json::Value,
144 },
145 Error {
146 track_id: String,
147 timestamp: u64,
148 sender: String,
149 error: String,
150 code: Option<u32>,
151 },
152 AddHistory {
153 sender: Option<String>,
154 timestamp: u64,
155 speaker: String,
156 text: String,
157 },
158 Other {
159 track_id: String,
160 timestamp: u64,
161 sender: String,
162 extra: Option<HashMap<String, String>>,
163 },
164 Binary {
165 track_id: String,
166 timestamp: u64,
167 data: Vec<u8>,
168 },
169 Ping {
170 timestamp: u64,
171 payload: Option<String>,
172 },
173}
174
175pub type EventSender = tokio::sync::broadcast::Sender<SessionEvent>;
176pub type EventReceiver = tokio::sync::broadcast::Receiver<SessionEvent>;
177
178pub fn create_event_sender() -> EventSender {
179 EventSender::new(128)
180}