From f2d93fe2bade5672656802519e11b31a1ffbd5ad Mon Sep 17 00:00:00 2001 From: "diamondburned (Forefront)" Date: Fri, 24 Apr 2020 20:14:06 -0700 Subject: [PATCH] Voice: Updated README --- voice/README.md | 49 ++++++++++++++++++++++++------------------------ voice/packet.go | 11 ----------- voice/udp/udp.go | 13 +++++++------ 3 files changed, 32 insertions(+), 41 deletions(-) delete mode 100644 voice/packet.go diff --git a/voice/README.md b/voice/README.md index d0fd38c..bbdec8c 100644 --- a/voice/README.md +++ b/voice/README.md @@ -16,47 +16,48 @@ the stored `*Voice` instance --- * The **library** sends a [Voice State Update](https://discordapp.com/developers/docs/topics/voice-connections#retrieving-voice-server-information-gateway-voice-state-update-example) -to the **Discord Gateway** +to the **Discord Gateway**. * The **library** waits until it receives a [Voice Server Update](https://discordapp.com/developers/docs/topics/voice-connections#retrieving-voice-server-information-example-voice-server-update-payload) -from the **Discord Gateway** -* Once a *Voice Server Update* event is received, a new connection is opened to the **Discord Voice Gateway** +from the **Discord Gateway**. +* Once a *Voice Server Update* event is received, a new connection is opened to the **Discord Voice Gateway**. --- -* When the connection is opened an [Identify Event](https://discordapp.com/developers/docs/topics/voice-connections#establishing-a-voice-websocket-connection-example-voice-identify-payload) -or [Resume Event](https://discordapp.com/developers/docs/topics/voice-connections#resuming-voice-connection-example-resume-connection-payload) -is sent to the **Discord Voice Gateway** depending on if the **library** is reconnecting -* The **Discord Voice Gateway** should respond with a [Hello Event](https://discordapp.com/developers/docs/topics/voice-connections#heartbeating-example-hello-payload-since-v3) -which will be used to create a new `*gateway.Pacemaker` and start sending heartbeats to the **Discord Voice Gateway** +* The **Discord Voice Gateway** will first send a [Hello Event](https://discordapp.com/developers/docs/topics/voice-connections#heartbeating-example-hello-payload-since-v3) +which will be used to create a new `*heart.PacemakerLoop` and start sending heartbeats to the **Discord Voice Gateway**. +* Afterwards, an [Identify Command](https://discordapp.com/developers/docs/topics/voice-connections#establishing-a-voice-websocket-connection-example-voice-identify-payload) +or [Resume Command](https://discordapp.com/developers/docs/topics/voice-connections#resuming-voice-connection-example-resume-connection-payload) +is sent to the **Discord Voice Gateway** depending on whether or not the **library** is reconnecting. --- -* The **Discord Voice Gateway** should also respond with a [Ready Event](https://discordapp.com/developers/docs/topics/voice-connections#establishing-a-voice-websocket-connection-example-voice-ready-payload) -once the connection is opened, providing the required information to connect to a **Voice Server** +* The **Discord Voice Gateway** should then respond with a [Ready Event](https://discordapp.com/developers/docs/topics/voice-connections#establishing-a-voice-websocket-connection-example-voice-ready-payload) +once the connection is opened, providing the required information to connect to a **Voice Server**. * Using the information provided in the *Ready Event*, a new UDP connection is opened to the **Voice Server** -and [IP Discovery](https://discordapp.com/developers/docs/topics/voice-connections#ip-discovery) occurs +and [IP Discovery](https://discordapp.com/developers/docs/topics/voice-connections#ip-discovery) occurs. * After *IP Discovery* returns the **Application**'s external ip and port it connected to the **Voice Server** with, the **library** sends a [Select Protocol Event](https://discordapp.com/developers/docs/topics/voice-connections#establishing-a-voice-udp-connection-example-select-protocol-payload) -to the **Discord Voice Gateway** +to the **Discord Voice Gateway**. * The **library** waits until it receives a [Session Description Event](https://discordapp.com/developers/docs/topics/voice-connections#establishing-a-voice-udp-connection-example-session-description-payload) -from the **Discord Voice Gateway** +from the **Discord Voice Gateway**. * Once the *Session Description Event* is received, [Speaking Events](https://discordapp.com/developers/docs/topics/voice-connections#speaking-example-speaking-payload) -and **Voice Packets** can begin to be sent to the **Discord Voice Gateway** and **Voice Server** respectively +and **Voice Packets** can begin to be sent to the **Discord Voice Gateway** and **Voice Server** respectively. ## Usage * The **application** would get a new `*Voice` instance by calling `NewVoice()` and keep it -stored for when it needs to open voice connections +stored for when it needs to open voice connections. * When the **application** wants to connect to a voice channel they would call `JoinChannel()` on -the stored `*Voice` instance +the stored `*Voice` instance. * `JoinChannel()` will block as it follows the [Connection Flow](#connection-flow), returning an -`error` if one occurs and a `*Connection` if it was successful -* The **application** should now call `*Connection#Speaking()` with the wanted [voice flag](https://discordapp.com/developers/docs/topics/voice-connections#speaking) -(`Microphone`, `Soundshare`, `Priority`) -* The **application** can now send **Voice Packets** to the `*Connection#OpusSend` channel -which will be sent to the **Voice Server** +`error` if one occurs and a `*voice.Session` if it was successful. +* The **application** should now call `(*voice.Session).Speaking()` with the wanted [voice flag](https://discordapp.com/developers/docs/topics/voice-connections#speaking) +(`voicegateway.Microphone`, `voicegateway.Soundshare`, or `voicegateway.Priority`). +* The **application** can now send **Voice Packets** using the `(*voice.Session).Write()` method +which will be sent to the **Voice Server**. `(*voice.Session)` also implements `io.Writer`. * When the **application** wants to stop sending **Voice Packets** they should call -`*Connection#StopSpeaking()`, any required voice cleanup (closing streams, etc), then -`*Connection#Disconnect()` +`(*voice.Session).StopSpeaking()`, then any required voice cleanup (closing streams, etc.), then +`(*voice.Session).Disconnect()` ## Examples -###### Coming SoonTM + +Check the integration tests at [voice/integration_test.go](https://github.com/diamondburned/arikawa/blob/master/voice/integration_test.go). diff --git a/voice/packet.go b/voice/packet.go deleted file mode 100644 index e3ff58a..0000000 --- a/voice/packet.go +++ /dev/null @@ -1,11 +0,0 @@ -package voice - -// https://discordapp.com/developers/docs/topics/voice-connections#encrypting-and-sending-voice -type Packet struct { - Version byte // Single byte value of 0x80 - 1 byte - Type byte // Single byte value of 0x78 - 1 byte - Sequence uint16 // Unsigned short (big endian) - 4 bytes - Timestamp uint32 // Unsigned integer (big endian) - 4 bytes - SSRC uint32 // Unsigned integer (big endian) - 4 bytes - Opus []byte // Binary data -} diff --git a/voice/udp/udp.go b/voice/udp/udp.go index c8a9116..6ba50a7 100644 --- a/voice/udp/udp.go +++ b/voice/udp/udp.go @@ -86,7 +86,8 @@ func DialConnection(addr string, ssrc uint32) (*Connection, error) { } func (c *Connection) Start(secret *[32]byte) { - header := [12]byte{ + // https://discordapp.com/developers/docs/topics/voice-connections#encrypting-and-sending-voice + packet := [12]byte{ 0: 0x80, // Version + Flags 1: 0x78, // Payload Type // [2:4] // Sequence @@ -94,7 +95,7 @@ func (c *Connection) Start(secret *[32]byte) { } // Write SSRC to the header. - binary.BigEndian.PutUint32(header[8:12], c.ssrc) // SSRC + binary.BigEndian.PutUint32(packet[8:12], c.ssrc) // SSRC // 50 sends per second, 960 samples each at 48kHz frequency := time.NewTicker(time.Millisecond * 20) @@ -120,15 +121,15 @@ func (c *Connection) Start(secret *[32]byte) { } // Write a new sequence. - binary.BigEndian.PutUint16(header[2:4], c.sequence) + binary.BigEndian.PutUint16(packet[2:4], c.sequence) c.sequence++ - binary.BigEndian.PutUint32(header[4:8], c.timestamp) + binary.BigEndian.PutUint32(packet[4:8], c.timestamp) c.timestamp += 960 // Samples - copy(c.nonce[:], header[:]) + copy(c.nonce[:], packet[:]) - toSend := secretbox.Seal(header[:], b, &c.nonce, secret) + toSend := secretbox.Seal(packet[:], b, &c.nonce, secret) select { case <-frequency.C: