voice

package
v2.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 8, 2021 License: ISC Imports: 14 Imported by: 4

README

Voice

Terminology

  • Discord Gateway - The standard Discord Gateway users connect to and receive update events from
  • Discord Voice Gateway - The Discord Voice gateway that allows voice connections to be configured
  • Voice Server - What the Discord Voice Gateway allows connection to for sending of Opus voice packets over UDP
  • Voice Packet - Opus encoded UDP packet that contains audio
  • Application - Could be a custom Discord Client or Bot (nothing that is within this package)
  • Library - Code within this package

Connection Flow

  • The application would get a new *Voice instance by calling NewVoice()
  • When the application wants to connect to a voice channel they would call JoinChannel() on the stored *Voice instance

  • The library sends a Voice State Update to the Discord Gateway.
  • The library waits until it receives a Voice Server Update from the Discord Gateway.
  • Once a Voice Server Update event is received, a new connection is opened to the Discord Voice Gateway.

  • The Discord Voice Gateway will first send a Hello Event which will be used to create a new *heart.PacemakerLoop and start sending heartbeats to the Discord Voice Gateway.
  • Afterwards, an Identify Command or Resume Command is sent to the Discord Voice Gateway depending on whether the library is reconnecting.

  • The Discord Voice Gateway should then respond with a Ready Event 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 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 to the Discord Voice Gateway.
  • The library waits until it receives a Session Description Event from the Discord Voice Gateway.
  • Once the Session Description Event is received, Speaking Events 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.
  • When the application wants to connect to a voice channel they would call JoinChannel() on the stored *Voice instance.
  • JoinChannel() will block as it follows the Connection Flow, returning an 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 (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 (*voice.Session).StopSpeaking(), then any required voice cleanup (closing streams, etc.), then (*voice.Session).Disconnect()

Examples

Check the integration tests at voice/integration_test.go.

Documentation

Overview

Package voice handles the Discord voice gateway and UDP connections. It does not handle book-keeping of those sessions.

This package abstracts the subpackage voice/voicesession and voice/udp.

Index

Examples

Constants

View Source
const Protocol = "xsalsa20_poly1305"

Protocol is the encryption protocol that this library uses.

Variables

View Source
var ErrAlreadyConnecting = errors.New("already connecting")

ErrAlreadyConnecting is returned when the session is already connecting.

View Source
var ErrCannotSend = errors.New("cannot send audio to closed channel")

ErrCannotSend is an error when audio is sent to a closed channel.

View Source
var WSTimeout = 10 * time.Second

WSTimeout is the duration to wait for a gateway operation including Session to complete before erroring out. This only applies to functions that don't take in a context already.

Functions

func AddIntents

func AddIntents(gw *gateway.Gateway)

AddIntents adds the needed voice intents into gw. Bots should always call this before Open if voice is required.

Types

type Session

type Session struct {
	*handler.Handler
	ErrorLog func(err error)
	// contains filtered or unexported fields
}

Session is a single voice session that wraps around the voice gateway and UDP connection.

Example
package main

import (
	"io"
	"log"

	"github.com/diamondburned/arikawa/v2/discord"
	"github.com/diamondburned/arikawa/v2/state"
	"github.com/diamondburned/arikawa/v2/voice"
)

var (
	token     string
	channelID discord.ChannelID
)

// pseudo function for example
func writeOpusInto(w io.Writer) {}

func main() {
	s, err := state.New("Bot " + token)
	if err != nil {
		log.Fatalln("failed to make state:", err)
	}

	// This is required for bots.
	voice.AddIntents(s.Gateway)

	if err := s.Open(); err != nil {
		log.Fatalln("failed to open gateway:", err)
	}
	defer s.Close()

	c, err := s.Channel(channelID)
	if err != nil {
		log.Fatalln("failed to get channel:", err)
	}

	v, err := voice.NewSession(s)
	if err != nil {
		log.Fatalln("failed to create voice session:", err)
	}

	if err := v.JoinChannel(c.GuildID, c.ID, false, false); err != nil {
		log.Fatalln("failed to join voice channel:", err)
	}
	defer v.Leave()

	// Start writing Opus frames.
	for {
		writeOpusInto(v)
	}
}
Output:

func NewSession

func NewSession(state *state.State) (*Session, error)

NewSession creates a new voice session for the current user.

func NewSessionCustom

func NewSessionCustom(ses *session.Session, userID discord.UserID) *Session

NewSessionCustom creates a new voice session from the given session and user ID.

func (*Session) JoinChannel

func (s *Session) JoinChannel(gID discord.GuildID, cID discord.ChannelID, mute, deaf bool) error

func (*Session) JoinChannelCtx

func (s *Session) JoinChannelCtx(
	ctx context.Context, gID discord.GuildID, cID discord.ChannelID, mute, deaf bool) error

JoinChannelCtx joins a voice channel. Callers shouldn't use this method directly, but rather Voice's. This method shouldn't ever be called concurrently.

func (*Session) Leave

func (s *Session) Leave() error

Leave disconnects the current voice session from the currently connected channel.

func (*Session) LeaveCtx

func (s *Session) LeaveCtx(ctx context.Context) error

LeaveCtx disconencts with a context. Refer to Leave for more information.

func (*Session) ReadPacket

func (s *Session) ReadPacket() (*udp.Packet, error)

ReadPacket reads a single packet from the UDP connection. This is NOT at all thread safe, and must be used very carefully. The backing buffer is always reused.

func (*Session) Speaking

func (s *Session) Speaking(flag voicegateway.SpeakingFlag) error

Speaking tells Discord we're speaking. This method should not be called concurrently.

func (*Session) UseContext

func (s *Session) UseContext(ctx context.Context) error

UseContext tells the UDP voice connection to write with the given context.

func (*Session) VoiceUDPConn

func (s *Session) VoiceUDPConn() *udp.Connection

VoiceUDPConn gets a voice UDP connection. The caller could use this method to circumvent the rapid mutex-read-lock acquire inside Write.

func (*Session) Write

func (s *Session) Write(b []byte) (int, error)

Write writes into the UDP voice connection WITHOUT a timeout. Refer to WriteCtx for more information.

func (*Session) WriteCtx

func (s *Session) WriteCtx(ctx context.Context, b []byte) (int, error)

WriteCtx writes into the UDP voice connection with a context for timeout. This method is thread safe as far as calling other methods of Session goes; HOWEVER it is not thread safe to call Write itself concurrently.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL