voice_engine/
event.rs

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        // Answer machine detection
72        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    ///End of Utterance
92    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>, // current tts text
119        position: Option<u32>,    // word index in subtitle
120        total_duration: u32,      // whole tts duration
121        current: u32,             // elapsed time since start of tts
122    },
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}