| D++ (DPP) C++ Discord API Bot Library

Search
Loading...
Searching...
No Matches
dpp::discord_voice_client Class Reference

Implements a discord voice connection. Each discord_voice_client connects to one voice channel and derives from a websocket client. More...

`#include <discordvoiceclient.h>`

Inheritance diagram for dpp::discord_voice_client:
[legend]
Collaboration diagram for dpp::discord_voice_client:
[legend]

## Public Types

enum | send_audio_type_t { satype_recorded_audio , satype_live_audio , satype_overlap_audio }
| The audio type to be sent. More...

## Public Member Functions

| discord_voice_client (dpp::cluster *_cluster, full_reconnection_callback_t _reconnection_callback, snowflake _channel_id, snowflake _server_id, const std::string &_token, const std::string &_session_id, const std::string &_host, bool enable_dave=true)
virtual | ~discord_voice_client () override
| Destroy the discord voice client object.
virtual void | close () override
| Close websocket.
void | complete_handshake (const struct socket_events *ev)
| Called while SSL handshake is in progress. If the handshake completes, the state of the socket is progressed to an established state.
std::string | discover_ip ()
| Discord external IP detection.
void | enable_raw_tracing ()
| For low-level debugging, calling this function will enable low level I/O logging for this connection to the logger. This can be very loud, and output a lot of data, so only enable it selectively where you need it.
virtual void | error (uint32_t errorcode) override
| Handle a websocket error.
bool | execute_pending_upgrade_downgrade ()
| Execute pending protocol upgrade/downgrade to/from dave.
uint64_t | get_bytes_in ()
| Get total bytes received.
uint64_t | get_bytes_out ()
| Get total bytes sent.
std::string | get_cipher ()
| Get SSL cipher name.
uint16_t | get_iteration_interval ()
| Get the iteration interval time (in milliseconds).
const std::vector< std::string > | get_marker_metadata ()
| Get the metadata string associated with each inserted marker.
std::string | get_privacy_code () const
| Returns the privacy code for the end to end encryption scheme ("DAVE"). if end-to-end encryption is not active, or is not yet established, this will return an empty string.
dpp::utility::uptime | get_remaining ()
| Get the time remaining to send the audio output buffer in hours:minutes:seconds.
float | get_secs_remaining ()
| Get the number of seconds remaining of the audio output buffer.
uint64_t | get_timescale ()
| Get the current timescale, this will default to 1000000 which means 1 millisecond.
uint32_t | get_tracks_remaining ()
| Get the number of tracks remaining in the output buffer. This is calculated by the number of track markers plus one.
uint64_t | get_unique_id () const
| Every request made has a unique ID. This increments for every request, starting at 1. You can use this for statistics, or to associate requests and replies in external event loops.
dpp::utility::uptime | get_uptime ()
| Returns the connection time of the voice client.
void | get_user_privacy_code (const dpp::snowflake user, privacy_code_callback_t callback) const
| Returns the privacy code for a given user by id, if they are in the voice call, and enc-to-end encryption is enabled.
virtual bool | handle_buffer (std::string &buffer) override
| Processes incoming frames from the SSL socket input buffer.
virtual bool | handle_frame (const std::string &buffer, ws_opcode opcode) override
| Handle JSON from the websocket.
discord_voice_client & | insert_marker (const std::string &metadata="")

Insert a track marker into the audio output buffer. A track marker is an arbitrary flag in the buffer contents that indicates the end of some block of audio of significance to the sender. This may be a song from a streaming site, or some voice audio/speech, a sound effect, or whatever you choose. You can later skip to the next marker using the dpp::discord_voice_client::skip_to_next_marker function.

bool | is_connected ()
| Returns true if the voice client is connected to the websocket.
bool | is_end_to_end_encrypted () const
| Returns true if end-to-end encryption is enabled for the active voice call (Discord Audio Visual Encryption, a.k.a. DAVE).
bool | is_paused ()
| Returns true if the audio is paused. You can unpause with dpp::discord_voice_client::pause_audio.
bool | is_playing ()
| Returns true if we are playing audio.
bool | is_ready ()
| voice client is ready to stream audio. The voice client is considered ready if it has a secret key.
virtual void | log (dpp::loglevel severity, const std::string &msg) const override
| Log a message to whatever log the user is using. The logged message is passed up the chain to the on_log event in user code which can then do whatever it wants to do with it.
void | on_disconnect () override
| Called on websocket disconnection.
void | on_error (dpp::socket fd, const struct dpp::socket_events &, int error_code)
| Called when there is an error on the TCP socket.
void | on_read (dpp::socket fd, const struct dpp::socket_events &ev)
| Called when the TCP socket has data to read.
void | on_write (dpp::socket fd, const struct dpp::socket_events &e)
| Called when the TCP socket can be written to without blocking.
virtual void | one_second_timer () override
| Fires every second from the underlying socket I/O loop, used for sending heartbeats.
discord_voice_client & | pause_audio (bool pause)
| Pause sending of audio.
void | process_mls_group_rosters (const std::map< uint64_t, std::vector< uint8_t > > &rmap)
| Process roster map from commit/welcome.
void | read_loop ()
| Set up non blocking I/O and configure on_read, on_write and on_error.
void | ready_for_transition (const std::string &data)
| Notify gateway ready for a DAVE transition.
void | recover_from_invalid_commit_welcome ()
| Reset dave session, send voice_client_dave_mls_invalid_commit_welcome payload with current transition Id and our new key package to gateway.
void | reinit_dave_mls_group ()
| Reset dave session and prepare initial session group.
void | run ()
| Start and monitor websocket I/O.
discord_voice_client & | send_audio_opus (const uint8_t *opus_packet, const size_t length)
| Send opus packets to the voice channel.
discord_voice_client & | send_audio_opus (const uint8_t *opus_packet, const size_t length, uint64_t duration, bool send_now=false)
| Send opus packets to the voice channel.
discord_voice_client & | send_audio_raw (uint16_t *audio_data, const size_t length)
| Send raw audio to the voice channel.
void | send_close_packet ()
| Send OP_CLOSE error code 1000 to the other side of the connection. This indicates graceful close.
discord_voice_client & | send_silence (const uint64_t duration)
| Send silence to the voice channel.
discord_voice_client & | send_stop_frames (bool send_now=false)
| Send stop frames to the voice channel.
discord_voice_client & | set_iteration_interval (uint16_t interval)
| Change the iteration interval time.
discord_voice_client & | set_send_audio_type (send_audio_type_t type)
| Sets the audio type that will be sent with send_audio_* methods.
discord_voice_client & | set_timescale (uint64_t new_timescale)
| Set the timescale in nanoseconds.
void | set_user_gain (snowflake user_id, float factor)
| Sets the gain for the specified user.
discord_voice_client & | skip_to_next_marker ()
| Skip tp the next track marker, previously inserted by using the dpp::discord_voice_client::insert_marker function. If there are no markers in the output buffer, then this skips to the end of the buffer and is equivalent to the dpp::discord_voice_client::stop_audio function.
void | socket_write (const std::string_view data)
| Write to the output buffer.
discord_voice_client & | speak ()
| Mark the voice connection as 'speaking'. This sends a JSON message to the voice websocket which tells discord that the user is speaking. The library automatically calls this for you whenever you send audio.
discord_voice_client & | stop_audio ()
| Immediately stop all audio. Clears the packet queue.
virtual void | write (const std::string_view data, ws_opcode _opcode=OP_AUTO)
| Write to websocket. Encapsulates data in frames if the status is CONNECTED.

## Public Attributes

snowflake | channel_id
| Channel ID.
class dpp::cluster * | creator {}
| Owning cluster.
float | current_gain {}
| The gain value for the current voice iteration.
float | end_gain {}
| The gain value for the end of the current voice iteration.
uint32_t | heartbeat_interval {}
| Heartbeat interval for sending heartbeat keepalive.
float | increment {}
| The amount to increment each successive sample for, for the current voice iteration.
uint16_t | iteration_interval {500}
| The time (in milliseconds) between each interval when parsing audio.
bool | keepalive
| True if we are keeping the connection alive after it has finished.
time_t | last_heartbeat {}
| Last voice channel websocket heartbeat.
moving_averager | moving_average
| Moving averager.
class cluster * | owner
| Owning cluster.
std::string | private_key_file
| Private key PEM file path for inbound SSL connections.
std::string | public_key_file
| Public key PEM file path for inbound SSL connections.
full_reconnection_callback_t | reconnection_callback
enum dpp::discord_voice_client::send_audio_type_t | send_audio_type
snowflake | server_id
| Server ID.
std::string | sessionid
| Discord voice session id.
bool | terminating {}
| True when the thread is shutting down.
std::string | token
| Discord voice session token.

## Protected Member Functions

virtual void | connect () override
| Connect to websocket server.
void | do_raw_trace (const std::string &message) const
| If raw_trace is set to true, log a debug message for this connection.
ws_state | get_state () const
| Get websocket state.
virtual void | on_buffer_drained ()
int | start_connecting (dpp::socket sockfd, const struct sockaddr *addr, socklen_t addrlen)
| Start connecting to a TCP socket. This simply calls connect() and checks for error return, as the timeout is now handled in the main IO events for the ssl_connection class.

## Protected Attributes

std::string | buffer
| Input buffer received from socket.
uint64_t | bytes_in
| Bytes in.
uint64_t | bytes_out
| Bytes out.
std::string | cipher
| SSL cipher in use.
uint8_t | connect_retries {0}
| How many times we retried connect().
bool | connected {false}
| True if connection is completed.
std::string | hostname
| Hostname connected to.
time_t | last_tick
| For timers.
std::string | obuffer
| Output buffer for sending to socket.
bool | plaintext
| True for a plain text connection.
bool | raw_trace {false}
| Set this to true to log all IO to debug for this connection. This is an internal developer facility. Do not enable it unless you need to, as it will be very noisy.
dpp::socket | sfd
| Raw file descriptor of connection.
openssl_connection * | ssl
| Openssl opaque contexts.
std::mutex | ssl_close_mutex
| Protects openssl opaque contexts when closing.
time_t | start
| Start time of connection.
bool | tcp_connect_done {false}
| True if tcp connect() succeeded.
bool | timed_out
| If true the connection timed out while waiting, when waiting for SSL negotiation, TCP connect(), or HTTP.
time_t | timeout
| Time at which the connection should be abandoned, if we are still connecting or negotiating with a HTTP server.
timer | timer_handle
| Timer handle for one second timer.
uint64_t | unique_id
| Unique ID of socket used as a nonce You can use this to identify requests vs reply if you want. D++ itself only sets this, and does not use it in any logic. It starts at 1 and increments for each request made.

## Detailed Description

Implements a discord voice connection. Each discord_voice_client connects to one voice channel and derives from a websocket client.

## Member Enumeration Documentation

## ◆ send_audio_type_t

enum dpp::discord_voice_client::send_audio_type_t

The audio type to be sent.

Note
  On Windows, the default type is overlap audio. On all other platforms, it is recorded audio.

If the audio is recorded, the sending of audio packets is throttled. Otherwise, if the audio is live, the sending is not throttled.

Discord voice engine is expecting audio data as if they were from some audio device, e.g. microphone, where the data become available as they get captured from the audio device.

In case of recorded audio, unlike from a device, the audio data are usually instantly available in large chunks. Throttling is needed to simulate audio data coming from an audio device. In case of live audio, the throttling is by nature, so no extra throttling is needed.

Using live audio mode for recorded audio can cause Discord to skip audio data because Discord does not expect to receive, say, 3 minutes' worth of audio data in 1 second.

There are some inaccuracies in the throttling method used by the recorded audio mode on some systems (mainly Windows) which causes gaps and stutters in the resulting audio stream. The overlap audio mode provides a different implementation that fixes the issue. This method is slightly more CPU intensive, and should only be used if you encounter issues with recorded audio on your system.

Use discord_voice_client::set_send_audio_type to change this value as it ensures thread safety.

Enumerator
satype_recorded_audio |
satype_live_audio |
satype_overlap_audio |

## Constructor & Destructor Documentation

## ◆ discord_voice_client()

dpp::discord_voice_client::discord_voice_client | ( | dpp::cluster * | _cluster,
|  | full_reconnection_callback_t | _reconnection_callback,
|  | snowflake | _channel_id,
|  | snowflake | _server_id,
|  | const std::string & | _token,
|  | const std::string & | _session_id,
|  | const std::string & | _host,
|  | bool | enable_dave = true )

Constructor takes shard id, max shards and token.

Parameters

  _cluster | The cluster which owns this voice connection, for related logging, REST requests etc
  _reconnection_callback | The callback this voice client calls if the voice connection was closed due to error
  _channel_id | The channel id to identify the voice connection as
  _server_id | The server id (guild id) to identify the voice connection as
  _token | The voice session token to use for identifying to the websocket
  _session_id | The voice session id to identify with
  _host | The voice server hostname to connect to (hostname:port format)
  enable_dave | Enable DAVE E2EE

Exceptions

  dpp::voice_exception | Opus failed to initialise, or D++ is not compiled with voice support

## ◆ ~discord_voice_client()

virtual dpp::discord_voice_client::~discord_voice_client | ( |  | ) |

override virtual

Destroy the discord voice client object.

## Member Function Documentation

## ◆ close()

virtual void dpp::websocket_client::close | ( |  | ) |

override virtual inherited

Close websocket.

Reimplemented from dpp::ssl_connection.

## ◆ complete_handshake()

void dpp::ssl_connection::complete_handshake | ( | const struct socket_events * | ev | ) |

inherited

Called while SSL handshake is in progress. If the handshake completes, the state of the socket is progressed to an established state.

Parameters

  ev | Socket events for the socket

## ◆ connect()

virtual void dpp::websocket_client::connect | ( |  | ) |

override protected virtual inherited

Connect to websocket server.

Reimplemented from dpp::ssl_connection.

## ◆ discover_ip()

std::string dpp::discord_voice_client::discover_ip | ( |  | ) |

Discord external IP detection.

Returns
  std::string Your external IP address

Note
  This is a blocking operation that waits for a single packet from Discord's voice servers.

## ◆ do_raw_trace()

void dpp::ssl_connection::do_raw_trace | ( | const std::string & | message | ) | const

protected inherited

If raw_trace is set to true, log a debug message for this connection.

Parameters

  message | debug message

## ◆ enable_raw_tracing()

void dpp::ssl_connection::enable_raw_tracing | ( |  | ) |

inherited

For low-level debugging, calling this function will enable low level I/O logging for this connection to the logger. This can be very loud, and output a lot of data, so only enable it selectively where you need it.

Generally, you won't need this, it is a library development utility.

## ◆ error()

virtual void dpp::discord_voice_client::error | ( | uint32_t | errorcode | ) |

override virtual

Handle a websocket error.

Parameters

  errorcode | The error returned from the websocket

Reimplemented from dpp::websocket_client.

## ◆ execute_pending_upgrade_downgrade()

bool dpp::discord_voice_client::execute_pending_upgrade_downgrade | ( |  | ) |

Execute pending protocol upgrade/downgrade to/from dave.

Returns
  true if did an upgrade/downgrade

## ◆ get_bytes_in()

uint64_t dpp::ssl_connection::get_bytes_in | ( |  | ) |

inherited

Get total bytes received.

Returns
  uint64_t bytes received

## ◆ get_bytes_out()

uint64_t dpp::ssl_connection::get_bytes_out | ( |  | ) |

inherited

Get total bytes sent.

Returns
  uint64_t bytes sent

## ◆ get_cipher()

std::string dpp::ssl_connection::get_cipher | ( |  | ) |

inherited

Get SSL cipher name.

Returns
  std::string ssl cipher name

## ◆ get_iteration_interval()

uint16_t dpp::discord_voice_client::get_iteration_interval | ( |  | ) |

Get the iteration interval time (in milliseconds).

Returns
  iteration_interval

## ◆ get_marker_metadata()

const std::vector< std::string > dpp::discord_voice_client::get_marker_metadata | ( |  | ) |

Get the metadata string associated with each inserted marker.

Returns
  const std::vector<std::string>& list of metadata strings

## ◆ get_privacy_code()

std::string dpp::discord_voice_client::get_privacy_code | ( |  | ) | const

Returns the privacy code for the end to end encryption scheme ("DAVE"). if end-to-end encryption is not active, or is not yet established, this will return an empty string.

Returns
  A sequence of six five-digit integers which can be matched against the Discord client, in the privacy tab for the properties of the voice call.

## ◆ get_remaining()

dpp::utility::uptime dpp::discord_voice_client::get_remaining | ( |  | ) |

Get the time remaining to send the audio output buffer in hours:minutes:seconds.

Returns
  dpp::utility::uptime length of buffer

## ◆ get_secs_remaining()

float dpp::discord_voice_client::get_secs_remaining | ( |  | ) |

Get the number of seconds remaining of the audio output buffer.

Returns
  float number of seconds remaining

## ◆ get_state()

ws_state dpp::websocket_client::get_state | ( |  | ) | const

nodiscard protected inherited

Get websocket state.

Returns
  websocket state

## ◆ get_timescale()

uint64_t dpp::discord_voice_client::get_timescale | ( |  | ) |

Get the current timescale, this will default to 1000000 which means 1 millisecond.

Returns
  uint64_t timescale in nanoseconds

## ◆ get_tracks_remaining()

uint32_t dpp::discord_voice_client::get_tracks_remaining | ( |  | ) |

Get the number of tracks remaining in the output buffer. This is calculated by the number of track markers plus one.

Returns
  uint32_t Number of tracks in the buffer

## ◆ get_unique_id()

uint64_t dpp::ssl_connection::get_unique_id | ( |  | ) | const

inherited

Every request made has a unique ID. This increments for every request, starting at 1. You can use this for statistics, or to associate requests and replies in external event loops.

Returns
  Unique ID

## ◆ get_uptime()

dpp::utility::uptime dpp::discord_voice_client::get_uptime | ( |  | ) |

Returns the connection time of the voice client.

Returns
  dpp::utility::uptime Detail of how long the voice client has been connected for

## ◆ get_user_privacy_code()

void dpp::discord_voice_client::get_user_privacy_code | ( | const dpp::snowflake | user,
|  | privacy_code_callback_t | callback ) const

Returns the privacy code for a given user by id, if they are in the voice call, and enc-to-end encryption is enabled.

Parameters

  user | User ID to fetch the privacy code for
  callback | Callback to call with the privacy code when the creation of the code is complete.

Warning
  This call spawns a thread, as getting a user's privacy code is a CPU-intensive and memory-intensive operation which internally uses scrypt.

## ◆ handle_buffer()

virtual bool dpp::websocket_client::handle_buffer | ( | std::string & | buffer | ) |

override virtual inherited

Processes incoming frames from the SSL socket input buffer.

Parameters

  buffer | The buffer contents. Can modify this value removing the head elements when processed.

Reimplemented from dpp::ssl_connection.

## ◆ handle_frame()

virtual bool dpp::discord_voice_client::handle_frame | ( | const std::string & | buffer,
|  | ws_opcode | opcode )

override virtual

Handle JSON from the websocket.

Parameters

  buffer | The entire buffer content from the websocket client
  opcode | Frame type, e.g. OP_TEXT, OP_BINARY

Returns
  bool True if a frame has been handled

Exceptions

  dpp::exception | If there was an error processing the frame, or connection to UDP socket failed

Reimplemented from dpp::websocket_client.

## ◆ insert_marker()

discord_voice_client & dpp::discord_voice_client::insert_marker | ( | const std::string & | metadata = "" | ) |

Insert a track marker into the audio output buffer. A track marker is an arbitrary flag in the buffer contents that indicates the end of some block of audio of significance to the sender. This may be a song from a streaming site, or some voice audio/speech, a sound effect, or whatever you choose. You can later skip to the next marker using the dpp::discord_voice_client::skip_to_next_marker function.

Parameters

  metadata | Arbitrary information related to this track

Returns
  reference to self

## ◆ is_connected()

bool dpp::discord_voice_client::is_connected | ( |  | ) |

Returns true if the voice client is connected to the websocket.

Returns
  True if connected

## ◆ is_end_to_end_encrypted()

bool dpp::discord_voice_client::is_end_to_end_encrypted | ( |  | ) | const

Returns true if end-to-end encryption is enabled for the active voice call (Discord Audio Visual Encryption, a.k.a. DAVE).

Returns
  True if end-to-end encrypted

## ◆ is_paused()

bool dpp::discord_voice_client::is_paused | ( |  | ) |

Returns true if the audio is paused. You can unpause with dpp::discord_voice_client::pause_audio.

Returns
  true if paused

## ◆ is_playing()

bool dpp::discord_voice_client::is_playing | ( |  | ) |

Returns true if we are playing audio.

Returns
  true if audio is playing

## ◆ is_ready()

bool dpp::discord_voice_client::is_ready | ( |  | ) |

voice client is ready to stream audio. The voice client is considered ready if it has a secret key.

Returns
  true if ready to stream audio

## ◆ log()

virtual void dpp::discord_voice_client::log | ( | dpp::loglevel | severity,
|  | const std::string & | msg ) const

override virtual

Log a message to whatever log the user is using. The logged message is passed up the chain to the on_log event in user code which can then do whatever it wants to do with it.

Parameters

  severity | The log level from dpp::loglevel
  msg | The log message to output

Reimplemented from dpp::ssl_connection.

## ◆ on_buffer_drained()

virtual void dpp::ssl_connection::on_buffer_drained | ( |  | ) |

protected virtual inherited

Reimplemented in dpp::http_server_request.

## ◆ on_disconnect()

void dpp::discord_voice_client::on_disconnect | ( |  | ) |

override virtual

Called on websocket disconnection.

Reimplemented from dpp::websocket_client.

## ◆ on_error()

void dpp::ssl_connection::on_error | ( | dpp::socket | fd,
|  | const struct dpp::socket_events & | ,
|  | int | error_code )

inherited

Called when there is an error on the TCP socket.

Parameters

  fd | File descriptor
  error_code | Error code

## ◆ on_read()

void dpp::ssl_connection::on_read | ( | dpp::socket | fd,
|  | const struct dpp::socket_events & | ev )

inherited

Called when the TCP socket has data to read.

Parameters

  fd | File descriptor
  ev | Socket events

## ◆ on_write()

void dpp::ssl_connection::on_write | ( | dpp::socket | fd,
|  | const struct dpp::socket_events & | e )

inherited

Called when the TCP socket can be written to without blocking.

Parameters

  fd | File descriptor
  e | Socket events

## ◆ one_second_timer()

virtual void dpp::discord_voice_client::one_second_timer | ( |  | ) |

override virtual

Fires every second from the underlying socket I/O loop, used for sending heartbeats.

Exceptions

  dpp::exception | if the socket needs to disconnect

Reimplemented from dpp::websocket_client.

## ◆ pause_audio()

discord_voice_client & dpp::discord_voice_client::pause_audio | ( | bool | pause | ) |

Pause sending of audio.

Parameters

  pause | True to pause, false to resume

Returns
  reference to self

## ◆ process_mls_group_rosters()

void dpp::discord_voice_client::process_mls_group_rosters | ( | const std::map< uint64_t, std::vector< uint8_t > > & | rmap | ) |

Process roster map from commit/welcome.

Parameters

  rmap | Roster map

## ◆ read_loop()

void dpp::ssl_connection::read_loop | ( |  | ) |

inherited

Set up non blocking I/O and configure on_read, on_write and on_error.

Exceptions

  std::exception | Any std::exception (or derivative) thrown from read_loop() indicates setup failed

## ◆ ready_for_transition()

void dpp::discord_voice_client::ready_for_transition | ( | const std::string & | data | ) |

Notify gateway ready for a DAVE transition.

Fires Voice Ready event when appropriate.

https://daveprotocol.com/#commit-handling

Parameters

  data | Websocket frame data

## ◆ recover_from_invalid_commit_welcome()

void dpp::discord_voice_client::recover_from_invalid_commit_welcome | ( |  | ) |

Reset dave session, send voice_client_dave_mls_invalid_commit_welcome payload with current transition Id and our new key package to gateway.

https://daveprotocol.com/#recovery-from-invalid-commit-or-welcome

## ◆ reinit_dave_mls_group()

void dpp::discord_voice_client::reinit_dave_mls_group | ( |  | ) |

Reset dave session and prepare initial session group.

## ◆ run()

void dpp::discord_voice_client::run | ( |  | ) |

Start and monitor websocket I/O.

## ◆ send_audio_opus() [1/2]

discord_voice_client & dpp::discord_voice_client::send_audio_opus | ( | const uint8_t * | opus_packet,
|  | const size_t | length )

Send opus packets to the voice channel.

Some containers such as .ogg may contain OPUS encoded data already. In this case, we don't need to encode the frames using opus here. We can bypass the codec, only applying opens to the stream.

Duration is calculated internally

Parameters

  opus_packet | Opus packets. Discord expects opus frames to be encoded at 48000Hz
  length | The length of the audio data.

Returns
  discord_voice_client& Reference to self

Note
  It is your responsibility to ensure that packets of data sent to send_audio are correctly repacketized for streaming, e.g. that audio frames are not too large or contain an incorrect format. Discord will still expect the same frequency and bit width of audio and the same signedness.

Exceptions

  dpp::voice_exception | If data length is invalid or voice support not compiled into D++

## ◆ send_audio_opus() [2/2]

discord_voice_client & dpp::discord_voice_client::send_audio_opus | ( | const uint8_t * | opus_packet,
|  | const size_t | length,
|  | uint64_t | duration,
|  | bool | send_now = false )

Send opus packets to the voice channel.

Some containers such as .ogg may contain OPUS encoded data already. In this case, we don't need to encode the frames using opus here. We can bypass the codec, only applying openssl to the stream.

Parameters

  opus_packet | Opus packets. Discord expects opus frames to be encoded at 48000Hz
  length | The length of the audio data.
  duration | Generally duration is 2.5, 5, 10, 20, 40 or 60 if the timescale is 1000000 (1ms)
  send_now | Send this packet right away without buffering, this will skip duration calculation for the packet being sent and only safe to be set to true in write_ready.

Returns
  discord_voice_client& Reference to self

Note
  It is your responsibility to ensure that packets of data sent to send_audio are correctly repacketized for streaming, e.g. that audio frames are not too large or contain an incorrect format. Discord will still expect the same frequency and bit width of audio and the same signedness.

Exceptions

  dpp::voice_exception | If data length is invalid or voice support not compiled into D++

## ◆ send_audio_raw()

discord_voice_client & dpp::discord_voice_client::send_audio_raw | ( | uint16_t * | audio_data,
|  | const size_t | length )

Send raw audio to the voice channel.

You should send an audio packet of send_audio_raw_max_length (11520) bytes. Note that this function can be costly as it has to opus encode the PCM audio on the fly, and also encrypt it with openssl.

Note
  Because this function encrypts and encodes packets before pushing them onto the output queue, if you have a complete stream ready to send and know its length it is advisable to call this method multiple times to enqueue the entire stream audio so that it is all encoded at once (unless you have set use_opus to false). Constantly calling this from dpp::cluster::on_voice_buffer_send can, and will, eat a TON of cpu!

Parameters

  audio_data | Raw PCM audio data. Channels are interleaved, with each channel's amplitude being a 16 bit value.

Warning
  The audio data needs to be 48000Hz signed 16 bit audio, otherwise, the audio will come through incorrectly!

Parameters

  length | The length of the audio data. The length should be a multiple of 4 (2x 16 bit stereo channels) with a maximum length of send_audio_raw_max_length, which is a complete opus frame at highest quality.

Generally when you're streaming and you know there will be more packet to come you should always provide packet data with length of send_audio_raw_max_length. Silence packet will be appended if length is less than send_audio_raw_max_length as discord expects to receive such specific packet size. This can cause gaps in your stream resulting in distorted audio if you have more packet to send later on.

Returns
  discord_voice_client& Reference to self

Exceptions

  dpp::voice_exception | If data length is invalid or voice support not compiled into D++

## ◆ send_close_packet()

void dpp::websocket_client::send_close_packet | ( |  | ) |

inherited

Send OP_CLOSE error code 1000 to the other side of the connection. This indicates graceful close.

Note
  This informs Discord to invalidate the session, you cannot resume if you send this

## ◆ send_silence()

discord_voice_client & dpp::discord_voice_client::send_silence | ( | const uint64_t | duration | ) |

Send silence to the voice channel.

Parameters

  duration | How long to send silence for. With the standard timescale this is in milliseconds. Allowed values are 2.5, 5, 10, 20, 40 or 60 milliseconds.

Returns
  discord_voice_client& Reference to self

Exceptions

  dpp::voice_exception | if voice support is not compiled into D++

## ◆ send_stop_frames()

discord_voice_client & dpp::discord_voice_client::send_stop_frames | ( | bool | send_now = false | ) |

Send stop frames to the voice channel.

Parameters

  send_now | send this packet right away without buffering. Do NOT set send_now to true outside write_ready. Also make sure you're not locking stream_mutex if you don't set send_now to true.

Returns
  discord_voice_client& Reference to self

Exceptions

  dpp::voice_exception | if voice support is not compiled into D++

## ◆ set_iteration_interval()

discord_voice_client & dpp::discord_voice_client::set_iteration_interval | ( | uint16_t | interval | ) |

Change the iteration interval time.

Parameters

  interval | The time (in milliseconds) between each interval when parsing audio.

Returns
  Reference to self.

## ◆ set_send_audio_type()

discord_voice_client & dpp::discord_voice_client::set_send_audio_type | ( | send_audio_type_t | type | ) |

Sets the audio type that will be sent with send_audio_* methods.

See also
  send_audio_type_t

## ◆ set_timescale()

discord_voice_client & dpp::discord_voice_client::set_timescale | ( | uint64_t | new_timescale | ) |

Set the timescale in nanoseconds.

Parameters

  new_timescale | Timescale to set. This defaults to 1000000, which means 1 millisecond.

Returns
  discord_voice_client& Reference to self

Exceptions

  dpp::voice_exception | If data length is invalid or voice support not compiled into D++

## ◆ set_user_gain()

void dpp::discord_voice_client::set_user_gain | ( | snowflake | user_id,
|  | float | factor )

Sets the gain for the specified user.

Similar to the User Volume slider, controls the listening volume per user. Uses native Opus gain control, so clients don't have to perform extra audio processing.

The gain setting will affect the both individual and combined voice audio.

The gain value can also be set even before the user connects to the voice channel.

Parameters

  user_id | The ID of the user where the gain is to be controlled.
  factor | Nonnegative factor to scale the amplitude by, where 1.f reverts to the default volume.

## ◆ skip_to_next_marker()

discord_voice_client & dpp::discord_voice_client::skip_to_next_marker | ( |  | ) |

Skip tp the next track marker, previously inserted by using the dpp::discord_voice_client::insert_marker function. If there are no markers in the output buffer, then this skips to the end of the buffer and is equivalent to the dpp::discord_voice_client::stop_audio function.

Note
  It is possible to use this function while the output stream is paused.

Returns
  reference to self

## ◆ socket_write()

void dpp::ssl_connection::socket_write | ( | const std::string_view | data | ) |

inherited

Write to the output buffer.

Parameters

  data | Data to be written to the buffer.

Note
  The data may not be written immediately and may be written at a later time to the socket.

## ◆ speak()

discord_voice_client & dpp::discord_voice_client::speak | ( |  | ) |

Mark the voice connection as 'speaking'. This sends a JSON message to the voice websocket which tells discord that the user is speaking. The library automatically calls this for you whenever you send audio.

Returns
  discord_voice_client& Reference to self

## ◆ start_connecting()

int dpp::ssl_connection::start_connecting | ( | dpp::socket | sockfd,
|  | const struct sockaddr * | addr,
|  | socklen_t | addrlen )

protected inherited

Start connecting to a TCP socket. This simply calls connect() and checks for error return, as the timeout is now handled in the main IO events for the ssl_connection class.

Parameters

  sockfd | socket descriptor
  addr | address to connect to
  addrlen | address length
  timeout_ms | timeout in milliseconds

Returns
  int -1 on error, 0 on success just like POSIX connect()

Exceptions

  dpp::connection_exception | on failure

## ◆ stop_audio()

discord_voice_client & dpp::discord_voice_client::stop_audio | ( |  | ) |

Immediately stop all audio. Clears the packet queue.

Returns
  reference to self

## ◆ write()

virtual void dpp::websocket_client::write | ( | const std::string_view | data,
|  | ws_opcode | _opcode = OP_AUTO )

virtual inherited

Write to websocket. Encapsulates data in frames if the status is CONNECTED.

Parameters

  data | The data to send.
  _opcode | The opcode of the data to send, either binary or text. The default is to use the socket's opcode as set in the constructor.

## Member Data Documentation

## ◆ buffer

std::string dpp::ssl_connection::buffer

protected inherited

Input buffer received from socket.

## ◆ bytes_in

uint64_t dpp::ssl_connection::bytes_in

protected inherited

Bytes in.

## ◆ bytes_out

uint64_t dpp::ssl_connection::bytes_out

protected inherited

Bytes out.

## ◆ channel_id

snowflake dpp::discord_voice_client::channel_id

Channel ID.

## ◆ cipher

std::string dpp::ssl_connection::cipher

protected inherited

SSL cipher in use.

## ◆ connect_retries

uint8_t dpp::ssl_connection::connect_retries {0}

protected inherited

How many times we retried connect().

## ◆ connected

bool dpp::ssl_connection::connected {false}

protected inherited

True if connection is completed.

## ◆ creator

class dpp::cluster* dpp::discord_voice_client::creator {}

Owning cluster.

## ◆ current_gain

float dpp::discord_voice_client::current_gain {}

The gain value for the current voice iteration.

## ◆ end_gain

float dpp::discord_voice_client::end_gain {}

The gain value for the end of the current voice iteration.

## ◆ heartbeat_interval

uint32_t dpp::discord_voice_client::heartbeat_interval {}

Heartbeat interval for sending heartbeat keepalive.

## ◆ hostname

std::string dpp::ssl_connection::hostname

protected inherited

Hostname connected to.

## ◆ increment

float dpp::discord_voice_client::increment {}

The amount to increment each successive sample for, for the current voice iteration.

## ◆ iteration_interval

uint16_t dpp::discord_voice_client::iteration_interval {500}

The time (in milliseconds) between each interval when parsing audio.

Warning
  You should only change this if you know what you're doing. It is set to 500ms by default.

## ◆ keepalive

bool dpp::ssl_connection::keepalive

inherited

True if we are keeping the connection alive after it has finished.

## ◆ last_heartbeat

time_t dpp::discord_voice_client::last_heartbeat {}

Last voice channel websocket heartbeat.

## ◆ last_tick

time_t dpp::ssl_connection::last_tick

protected inherited

For timers.

## ◆ moving_average

moving_averager dpp::discord_voice_client::moving_average

Moving averager.

## ◆ obuffer

std::string dpp::ssl_connection::obuffer

protected inherited

Output buffer for sending to socket.

## ◆ owner

class cluster* dpp::ssl_connection::owner

inherited

Owning cluster.

## ◆ plaintext

bool dpp::ssl_connection::plaintext

protected inherited

True for a plain text connection.

## ◆ private_key_file

std::string dpp::ssl_connection::private_key_file

inherited

Private key PEM file path for inbound SSL connections.

## ◆ public_key_file

std::string dpp::ssl_connection::public_key_file

inherited

Public key PEM file path for inbound SSL connections.

## ◆ raw_trace

bool dpp::ssl_connection::raw_trace {false}

protected inherited

Set this to true to log all IO to debug for this connection. This is an internal developer facility. Do not enable it unless you need to, as it will be very noisy.

## ◆ reconnection_callback

full_reconnection_callback_t dpp::discord_voice_client::reconnection_callback

## ◆ send_audio_type

enum dpp::discord_voice_client::send_audio_type_t dpp::discord_voice_client::send_audio_type

Initial value:
=
satype_recorded_audio
dpp::discord_voice_client::satype_recorded_audio
@ satype_recorded_audio
Definition discordvoiceclient.h:814

## ◆ server_id

snowflake dpp::discord_voice_client::server_id

Server ID.

## ◆ sessionid

std::string dpp::discord_voice_client::sessionid

Discord voice session id.

## ◆ sfd

dpp::socket dpp::ssl_connection::sfd

protected inherited

Raw file descriptor of connection.

## ◆ ssl

openssl_connection* dpp::ssl_connection::ssl

protected inherited

Openssl opaque contexts.

## ◆ ssl_close_mutex

std::mutex dpp::ssl_connection::ssl_close_mutex

protected inherited

Protects openssl opaque contexts when closing.

There's data races when reconnecting severed connection. This makes sure we don't double free our contexts.

## ◆ start

time_t dpp::ssl_connection::start

protected inherited

Start time of connection.

## ◆ tcp_connect_done

bool dpp::ssl_connection::tcp_connect_done {false}

protected inherited

True if tcp connect() succeeded.

## ◆ terminating

bool dpp::discord_voice_client::terminating {}

True when the thread is shutting down.

## ◆ timed_out

bool dpp::websocket_client::timed_out

protected inherited

If true the connection timed out while waiting, when waiting for SSL negotiation, TCP connect(), or HTTP.

## ◆ timeout

time_t dpp::websocket_client::timeout

protected inherited

Time at which the connection should be abandoned, if we are still connecting or negotiating with a HTTP server.

## ◆ timer_handle

timer dpp::ssl_connection::timer_handle

protected inherited

Timer handle for one second timer.

## ◆ token

std::string dpp::discord_voice_client::token

Discord voice session token.

## ◆ unique_id

uint64_t dpp::ssl_connection::unique_id

protected inherited

Unique ID of socket used as a nonce You can use this to identify requests vs reply if you want. D++ itself only sets this, and does not use it in any logic. It starts at 1 and increments for each request made.

D++ Library version 9.0.13 D++ Library version 9.0.12 D++ Library version 9.0.11 D++ Library version 9.0.10 D++ Library version 9.0.9 D++ Library version 9.0.8 D++ Library version 9.0.7 D++ Library version 9.0.6 D++ Library version 9.0.5 D++ Library version 9.0.4 D++ Library version 9.0.3 D++ Library version 9.0.2 D++ Library version 9.0.1 D++ Library version 9.0.0 D++ Library version 1.0.2 D++ Library version 1.0.1 D++ Library version 1.0.0