D++ (DPP)
C++ Discord API Bot Library
|
Implements a discord voice connection. Each discord_voice_client connects to one voice channel and derives from a websocket client. More...
#include <discordvoiceclient.h>
Public Member Functions | |
virtual void | log (dpp::loglevel severity, const std::string &msg) const |
virtual void | one_second_timer () |
Fires every second from the underlying socket I/O loop, used for sending heartbeats. More... | |
bool | is_ready () |
voice client is ready to stream audio. The voice client is considered ready if it has a secret key. More... | |
bool | is_connected () |
Returns true if the voice client is connected to the websocket. More... | |
dpp::utility::uptime | get_uptime () |
Returns the connection time of the voice client. More... | |
discord_voice_client (dpp::cluster *_cluster, snowflake _channel_id, snowflake _server_id, const std::string &_token, const std::string &_session_id, const std::string &_host) | |
virtual | ~discord_voice_client () |
virtual bool | handle_frame (const std::string &buffer) |
virtual void | error (uint32_t errorcode) |
void | run () |
discord_voice_client & | send_audio_raw (uint16_t *audio_data, const size_t length) |
Send raw audio to the voice channel. More... | |
discord_voice_client & | send_audio_opus (uint8_t *opus_packet, const size_t length, uint64_t duration) |
Send opus packets to the voice channel. More... | |
discord_voice_client & | send_audio_opus (uint8_t *opus_packet, const size_t length) |
Send opus packets to the voice channel. More... | |
discord_voice_client & | send_silence (const uint64_t duration) |
Send silence to the voice channel. More... | |
discord_voice_client & | set_timescale (uint64_t new_timescale) |
Set the timescale in nanoseconds. More... | |
uint64_t | get_timescale () |
Get the current timescale, this will default to 1000000 which means 1 millisecond. More... | |
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. More... | |
void | pause_audio (bool pause) |
Pause sending of audio. More... | |
void | stop_audio () |
Immediately stop all audio. Clears the packet queue. More... | |
bool | is_playing () |
Returns true if we are playing audio. More... | |
float | get_secs_remaining () |
Get the number of seconds remaining of the audio output buffer. More... | |
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. More... | |
dpp::utility::uptime | get_remaining () |
Get the time remaining to send the audio output buffer in hours:minutes:seconds. More... | |
void | 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 indictes 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. More... | |
void | 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. More... | |
const std::vector< std::string > | get_marker_metadata () |
Get the metdata string associated with each inserted marker. More... | |
bool | is_paused () |
Returns true if the audio is paused. You can unpause with dpp::discord_voice_client::pause_audio. More... | |
std::string | discover_ip () |
Discord external IP detection. More... | |
virtual void | write (const std::string &data) |
Write to websocket. Encapsulates data in frames if the status is CONNECTED. More... | |
virtual bool | handle_buffer (std::string &buffer) |
Processes incoming frames from the SSL socket input buffer. More... | |
virtual void | close () |
Close websocket. More... | |
uint64_t | get_bytes_out () |
uint64_t | get_bytes_in () |
std::string | get_cipher () |
void | read_loop () |
Nonblocking I/O loop. More... | |
Public Attributes | |
class dpp::cluster * | creator |
bool | terminating |
bool | decode_voice_recv |
uint32_t | heartbeat_interval |
time_t | last_heartbeat |
std::thread::native_handle_type | thread_id |
std::string | token |
std::string | sessionid |
snowflake | server_id |
snowflake | channel_id |
socket_callback_t | custom_readable_fd |
Attaching an additional file descriptor to this function will send notifications when there is data to read. More... | |
socket_callback_t | custom_writeable_fd |
Attaching an additional file descriptor to this function will send notifications when you are able to write to the socket. More... | |
socket_notification_t | custom_readable_ready |
This event will be called when you can read from the custom fd. More... | |
socket_notification_t | custom_writeable_ready |
This event will be called when you can write to a custom fd. More... | |
Static Public Attributes | |
static bool | sodium_initialised |
Protected Member Functions | |
virtual void | connect () |
ws_state | get_state () |
Protected Attributes | |
std::string | buffer |
std::string | obuffer |
bool | nonblocking |
dpp::socket | sfd |
opensslcontext * | ssl |
std::string | cipher |
time_t | last_tick |
std::string | hostname |
uint64_t | bytes_out |
uint64_t | bytes_in |
Implements a discord voice connection. Each discord_voice_client connects to one voice channel and derives from a websocket client.
dpp::discord_voice_client::discord_voice_client | ( | dpp::cluster * | _cluster, |
snowflake | _channel_id, | ||
snowflake | _server_id, | ||
const std::string & | _token, | ||
const std::string & | _session_id, | ||
const std::string & | _host | ||
) |
Constructor takes shard id, max shards and token.
_cluster | The cluster which owns this voice connection, for related logging, REST requests etc |
_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) |
dpp::exception | Sodium or Opus failed to initialise |
|
virtual |
Destructor
|
virtualinherited |
Close websocket.
Reimplemented from dpp::ssl_client.
|
protectedvirtualinherited |
(Re)connect
Reimplemented from dpp::ssl_client.
std::string dpp::discord_voice_client::discover_ip | ( | ) |
Discord external IP detection.
|
virtual |
Handle a websocket error.
errorcode | The error returned from the websocket |
Reimplemented from dpp::websocket_client.
|
inherited |
Get total bytes received
|
inherited |
Get total bytes sent
|
inherited |
Get SSL cipher name
const std::vector< std::string > dpp::discord_voice_client::get_marker_metadata | ( | ) |
Get the metdata string associated with each inserted marker.
dpp::utility::uptime dpp::discord_voice_client::get_remaining | ( | ) |
Get the time remaining to send the audio output buffer in hours:minutes:seconds.
float dpp::discord_voice_client::get_secs_remaining | ( | ) |
Get the number of seconds remaining of the audio output buffer.
|
protectedinherited |
Get websocket state
uint64_t dpp::discord_voice_client::get_timescale | ( | ) |
Get the current timescale, this will default to 1000000 which means 1 millisecond.
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.
dpp::utility::uptime dpp::discord_voice_client::get_uptime | ( | ) |
Returns the connection time of the voice client.
|
virtualinherited |
Processes incoming frames from the SSL socket input buffer.
buffer | The buffer contents. Can modify this value removing the head elements when processed. |
Reimplemented from dpp::ssl_client.
|
virtual |
Handle JSON from the websocket.
buffer | The entire buffer content from the websocket client |
dpp::exception | If there was an error processing the frame, or connection to UDP socket failed |
Reimplemented from dpp::websocket_client.
void 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 indictes 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.
metadata | Arbitrary information related to this track |
bool dpp::discord_voice_client::is_connected | ( | ) |
Returns true if the voice client is connected to the websocket.
bool dpp::discord_voice_client::is_paused | ( | ) |
Returns true if the audio is paused. You can unpause with dpp::discord_voice_client::pause_audio.
bool dpp::discord_voice_client::is_playing | ( | ) |
Returns true if we are playing audio.
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.
|
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.
severity | The log level from dpp::loglevel |
msg | The log message to output |
Reimplemented from dpp::ssl_client.
|
virtual |
Fires every second from the underlying socket I/O loop, used for sending heartbeats.
dpp::exception | if the socket needs to disconnect |
Reimplemented from dpp::websocket_client.
void dpp::discord_voice_client::pause_audio | ( | bool | pause | ) |
Pause sending of audio.
pause | True to pause, false to resume |
|
inherited |
Nonblocking I/O loop.
std::exception | Any std::exception (or derivative) thrown from read_loop() causes reconnection of the shard |
void dpp::discord_voice_client::run | ( | ) |
Start and monitor I/O loop
discord_voice_client & dpp::discord_voice_client::send_audio_opus | ( | 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 libsodium to the stream.
Duration is calculated internally
opus_packet | Opus packets. Discord expects opus frames to be encoded at 48000Hz |
length | The length of the audio data. |
dpp::exception | If data length is invalid |
discord_voice_client & dpp::discord_voice_client::send_audio_opus | ( | uint8_t * | opus_packet, |
const size_t | length, | ||
uint64_t | duration | ||
) |
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 libsodium to the stream.
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) |
dpp::exception | If data length is invalid |
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 n11520 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 libsodium.
audio_data | Raw PCM audio data. Channels are interleaved, with each channel's amplitude being a 16 bit value. |
The audio data should be 48000Hz signed 16 bit audio.
length | The length of the audio data. The length should be a multiple of 4 (2x 16 bit stero channels) with a maximum length of 11520, which is a complete opus frame at highest quality. |
dpp::exception | If data length is invalid |
discord_voice_client & dpp::discord_voice_client::send_silence | ( | const uint64_t | duration | ) |
Send silence to the voice channel.
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. |
discord_voice_client & dpp::discord_voice_client::set_timescale | ( | uint64_t | new_timescale | ) |
Set the timescale in nanoseconds.
new_timescale | Timescale to set. This defaults to 1000000, which means 1 millisecond. |
dpp::exception | If data length is invalid |
void 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.
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.
void dpp::discord_voice_client::stop_audio | ( | ) |
Immediately stop all audio. Clears the packet queue.
|
virtualinherited |
Write to websocket. Encapsulates data in frames if the status is CONNECTED.
data | The data to send. |
Reimplemented from dpp::ssl_client.
|
protectedinherited |
Input buffer received from openssl
|
protectedinherited |
Bytes in
|
protectedinherited |
Bytes out
snowflake dpp::discord_voice_client::channel_id |
Channel ID
|
protectedinherited |
SSL cipher in use
class dpp::cluster* dpp::discord_voice_client::creator |
Owning cluster
|
inherited |
Attaching an additional file descriptor to this function will send notifications when there is data to read.
NOTE: Only hook this if you NEED it as it can increase CPU usage of the thread! Returning -1 means that you don't want to be notified.
|
inherited |
This event will be called when you can read from the custom fd.
|
inherited |
Attaching an additional file descriptor to this function will send notifications when you are able to write to the socket.
NOTE: Only hook this if you NEED it as it can increase CPU usage of the thread! You should toggle this to -1 when you do not have anything to write otherwise it'll keep triggering repeatedly (it is level triggered).
|
inherited |
This event will be called when you can write to a custom fd.
bool dpp::discord_voice_client::decode_voice_recv |
Decode received voice packets to PCM
uint32_t dpp::discord_voice_client::heartbeat_interval |
Heartbeat interval for sending heartbeat keepalive
|
protectedinherited |
Hostname connected to
time_t dpp::discord_voice_client::last_heartbeat |
Last heartbeat
|
protectedinherited |
For timers
|
protectedinherited |
True if in nonblocking mode. The socket switches to nonblocking mode once ReadLoop is called.
|
protectedinherited |
Output buffer for sending to openssl
snowflake dpp::discord_voice_client::server_id |
Server ID
std::string dpp::discord_voice_client::sessionid |
Discord voice session id
|
protectedinherited |
Raw file descriptor of connection
|
static |
|
protectedinherited |
Openssl opaque contexts
bool dpp::discord_voice_client::terminating |
True when the thread is shutting down
std::thread::native_handle_type dpp::discord_voice_client::thread_id |
Thread ID
std::string dpp::discord_voice_client::token |
Discord voice session token