diff --git a/src/types/events/voice_gateway/mod.rs b/src/types/events/voice_gateway/mod.rs index 3cd13eb..39e0342 100644 --- a/src/types/events/voice_gateway/mod.rs +++ b/src/types/events/voice_gateway/mod.rs @@ -12,6 +12,7 @@ pub use select_protocol::*; pub use session_description::*; pub use speaking::*; pub use voice_backend_version::*; +pub use ssrc_definition::*; mod client_connect; mod client_disconnect; @@ -23,6 +24,7 @@ mod select_protocol; mod session_description; mod speaking; mod voice_backend_version; +mod ssrc_definition; #[derive(Debug, Default, Serialize, Clone)] /// The payload used for sending events to the webrtc gateway. @@ -102,8 +104,7 @@ pub const VOICE_HEARTBEAT_ACK: u8 = 6; pub const VOICE_RESUME: u8 = 7; pub const VOICE_HELLO: u8 = 8; pub const VOICE_RESUMED: u8 = 9; -/// See -pub const VOICE_VIDEO: u8 = 12; +pub const VOICE_SSRC_DEFINITION: u8 = 12; pub const VOICE_CLIENT_DISCONNECT: u8 = 13; pub const VOICE_SESSION_UPDATE: u8 = 14; diff --git a/src/types/events/voice_gateway/ssrc_definition.rs b/src/types/events/voice_gateway/ssrc_definition.rs new file mode 100644 index 0000000..08192fb --- /dev/null +++ b/src/types/events/voice_gateway/ssrc_definition.rs @@ -0,0 +1,39 @@ +use crate::types::{Snowflake, WebSocketEvent}; +use serde::{Serialize, Deserialize}; + +/// Defines an event which provides ssrcs for voice and video for a user id. +/// +/// This event is sent via opcode 12. +/// +/// Examples of the event: +/// +/// When receiving: +/// ``` +/// {"op":12,"d":{"video_ssrc":0,"user_id":"463640391196082177","streams":[{"ssrc":26595,"rtx_ssrc":26596,"rid":"100","quality":100,"max_resolution":{"width":1280,"type":"fixed","height":720},"max_framerate":30,"active":false}],"audio_ssrc":26597}}{"op":12,"d":{"video_ssrc":0,"user_id":"463640391196082177","streams":[{"ssrc":26595,"rtx_ssrc":26596,"rid":"100","quality":100,"max_resolution":{"width":1280,"type":"fixed","height":720},"max_framerate":30,"active":false}],"audio_ssrc":26597}} +/// ``` +/// +/// When sending: +/// ``` +/// {"op":12,"d":{"audio_ssrc":2307250864,"video_ssrc":0,"rtx_ssrc":0,"streams":[{"type":"video","rid":"100","ssrc":26595,"active":false,"quality":100,"rtx_ssrc":26596,"max_bitrate":2500000,"max_framerate":30,"max_resolution":{"type":"fixed","width":1280,"height":720}}]}} +/// ``` +#[derive(Debug, Deserialize, Serialize, Default, Clone, PartialEq, Eq)] +pub struct SsrcDefinition { + /// The ssrc used for video communications. + /// + /// Is always sent and received, though is 0 if describing only the audio ssrc. + #[serde(default)] + pub video_ssrc: usize, + /// The ssrc used for audio communications. + /// + /// Is always sent and received, though is 0 if describing only the video ssrc. + #[serde(default)] + pub audio_ssrc: usize, + /// The user id these ssrcs apply to. + /// + /// Is never sent by the user and is filled in by the server + #[serde(skip_serializing)] + pub user_id: Option, + // TODO: Add video streams +} + +impl WebSocketEvent for SsrcDefinition {} diff --git a/src/voice/gateway.rs b/src/voice/gateway.rs index 8880f3c..c8f374a 100644 --- a/src/voice/gateway.rs +++ b/src/voice/gateway.rs @@ -17,11 +17,12 @@ use tokio_tungstenite::{connect_async_tls_with_config, Connector, WebSocketStrea use crate::errors::VoiceGatewayError; use crate::gateway::{heartbeat::HEARTBEAT_ACK_TIMEOUT, GatewayEvent}; use crate::types::{ - self, SelectProtocol, Speaking, VoiceGatewayReceivePayload, VoiceGatewaySendPayload, - VoiceIdentify, WebSocketEvent, VOICE_BACKEND_VERSION, VOICE_CLIENT_CONNECT_FLAGS, - VOICE_CLIENT_CONNECT_PLATFORM, VOICE_CLIENT_DISCONNECT, VOICE_HEARTBEAT, VOICE_HEARTBEAT_ACK, - VOICE_HELLO, VOICE_IDENTIFY, VOICE_MEDIA_SINK_WANTS, VOICE_READY, VOICE_RESUME, - VOICE_SELECT_PROTOCOL, VOICE_SESSION_DESCRIPTION, VOICE_SESSION_UPDATE, VOICE_SPEAKING, + self, SelectProtocol, Speaking, SsrcDefinition, VoiceGatewayReceivePayload, + VoiceGatewaySendPayload, VoiceIdentify, WebSocketEvent, VOICE_BACKEND_VERSION, + VOICE_CLIENT_CONNECT_FLAGS, VOICE_CLIENT_CONNECT_PLATFORM, VOICE_CLIENT_DISCONNECT, + VOICE_HEARTBEAT, VOICE_HEARTBEAT_ACK, VOICE_HELLO, VOICE_IDENTIFY, VOICE_MEDIA_SINK_WANTS, + VOICE_READY, VOICE_RESUME, VOICE_SELECT_PROTOCOL, VOICE_SESSION_DESCRIPTION, + VOICE_SESSION_UPDATE, VOICE_SPEAKING, VOICE_SSRC_DEFINITION, }; use self::voice_events::VoiceEvents; @@ -159,6 +160,15 @@ impl VoiceGatewayHandle { self.send_json(VOICE_SPEAKING, to_send_value).await; } + /// Sends an ssrc definition event + pub async fn send_ssrc_definition(&self, to_send: SsrcDefinition) { + let to_send_value = serde_json::to_value(&to_send).unwrap(); + + trace!("VGW: Sending SsrcDefinition"); + + self.send_json(VOICE_SSRC_DEFINITION, to_send_value).await; + } + /// Sends a voice backend version request to the gateway pub async fn send_voice_backend_version_request(&self) { let data_empty_object = json!("{}"); @@ -408,6 +418,18 @@ impl VoiceGateway { warn!("Failed to parse VOICE_SPEAKING ({})", result.err().unwrap()); } } + VOICE_SSRC_DEFINITION => { + trace!("VGW: Received Ssrc Definition"); + + let event = &mut self.events.lock().await.ssrc_definition; + let result = VoiceGateway::handle_event(gateway_payload.data.get(), event).await; + if result.is_err() { + warn!( + "Failed to parse VOICE_SSRC_DEFINITION ({})", + result.err().unwrap() + ); + } + } VOICE_CLIENT_DISCONNECT => { trace!("VGW: Received Client Disconnect"); @@ -663,6 +685,7 @@ pub mod voice_events { pub session_description: GatewayEvent, pub session_update: GatewayEvent, pub speaking: GatewayEvent, + pub ssrc_definition: GatewayEvent, pub client_disconnect: GatewayEvent, pub client_connect_flags: GatewayEvent, pub client_connect_platform: GatewayEvent,