Voice: Updated README
This commit is contained in:
parent
ccf4c69801
commit
f2d93fe2ba
|
@ -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).
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue