Docs: Move to new intra-doc links, make events non-exhaustive. (#19)

Far cleaner and more reliable than the old doc-link pattern. Also allowed me to spot some event types and sources which should have been made non_exhaustive.
This commit is contained in:
Kyle Simpson
2020-11-24 19:52:23 +00:00
committed by GitHub
parent 1ada46d24b
commit 94157b12bc
32 changed files with 169 additions and 166 deletions

View File

@@ -12,7 +12,7 @@ pub struct Config {
/// driver is actively connected, but will apply to subsequent
/// sessions.
///
/// [`CryptoMode::Normal`]: enum.CryptoMode.html#variant.Normal
/// [`CryptoMode::Normal`]: CryptoMode::Normal
pub crypto_mode: CryptoMode,
/// Configures whether decoding and decryption occur for all received packets.
///
@@ -24,10 +24,10 @@ pub struct Config {
/// Defaults to [`DecodeMode::Decrypt`]. This is due to per-packet decoding costs,
/// which most users will not want to pay, but allowing speaking events which are commonly used.
///
/// [`DecodeMode::Decode`]: enum.DecodeMode.html#variant.Decode
/// [`DecodeMode::Decrypt`]: enum.DecodeMode.html#variant.Decrypt
/// [`DecodeMode::Pass`]: enum.DecodeMode.html#variant.Pass
/// [user speaking events]: ../events/enum.CoreEvent.html#variant.SpeakingUpdate
/// [`DecodeMode::Decode`]: DecodeMode::Decode
/// [`DecodeMode::Decrypt`]: DecodeMode::Decrypt
/// [`DecodeMode::Pass`]: DecodeMode::Pass
/// [user speaking events]: crate::events::CoreEvent::SpeakingUpdate
pub decode_mode: DecodeMode,
/// Number of concurrently active tracks to allocate memory for.
///

View File

@@ -12,7 +12,7 @@ pub enum DecodeMode {
/// are not present, as they are encrypted.
/// This event requires such functionality.*
///
/// [user speaking events]: ../events/enum.CoreEvent.html#variant.SpeakingUpdate
/// [user speaking events]: crate::events::CoreEvent::SpeakingUpdate
Pass,
/// Decrypts the body of each received packet.
///

View File

@@ -125,8 +125,8 @@ impl Driver {
///
/// This can be a source created via [`ffmpeg`] or [`ytdl`].
///
/// [`ffmpeg`]: ../input/fn.ffmpeg.html
/// [`ytdl`]: ../input/fn.ytdl.html
/// [`ffmpeg`]: crate::input::ffmpeg
/// [`ytdl`]: crate::input::ytdl
#[instrument(skip(self))]
pub fn play_source(&mut self, source: Input) -> TrackHandle {
let (player, handle) = super::create_player(source);
@@ -140,7 +140,7 @@ impl Driver {
/// Unlike [`play_source`], this stops all other sources attached
/// to the channel.
///
/// [`play_source`]: #method.play_source
/// [`play_source`]: Driver::play_source
#[instrument(skip(self))]
pub fn play_only_source(&mut self, source: Input) -> TrackHandle {
let (player, handle) = super::create_player(source);
@@ -156,9 +156,9 @@ impl Driver {
/// that this allows for direct manipulation of the [`Track`] object
/// before it is passed over to the voice and mixing contexts.
///
/// [`create_player`]: ../tracks/fn.create_player.html
/// [`Track`]: ../tracks/struct.Track.html
/// [`play_source`]: #method.play_source
/// [`create_player`]: crate::tracks::create_player
/// [`create_player`]: crate::tracks::Track
/// [`play_source`]: Driver::play_source
#[instrument(skip(self))]
pub fn play(&mut self, track: Track) {
self.send(CoreMessage::AddTrack(track));
@@ -171,10 +171,10 @@ impl Driver {
/// channel. Like [`play`], however, this allows for direct manipulation of the
/// [`Track`] object before it is passed over to the voice and mixing contexts.
///
/// [`create_player`]: ../tracks/fn.create_player.html
/// [`Track`]: ../tracks/struct.Track.html
/// [`play_only_source`]: #method.play_only_source
/// [`play`]: #method.play
/// [`create_player`]: crate::tracks::create_player
/// [`Track`]: crate::tracks::Track
/// [`play_only_source`]: Driver::play_only_source
/// [`play`]: Driver::play
#[instrument(skip(self))]
pub fn play_only(&mut self, track: Track) {
self.send(CoreMessage::SetTrack(Some(track)));
@@ -216,9 +216,9 @@ impl Driver {
/// within the supplied function or closure. *Taking excess time could prevent
/// timely sending of packets, causing audio glitches and delays*.
///
/// [`Track`]: ../tracks/struct.Track.html
/// [`TrackEvent`]: ../events/enum.TrackEvent.html
/// [`EventContext`]: ../events/enum.EventContext.html
/// [`Track`]: crate::tracks::Track
/// [`TrackEvent`]: crate::events::TrackEvent
/// [`EventContext`]: crate::events::EventContext
#[instrument(skip(self, action))]
pub fn add_global_event<F: EventHandler + 'static>(&mut self, event: Event, action: F) {
self.send(CoreMessage::AddEvent(EventData::new(event, action)));
@@ -243,8 +243,8 @@ impl Driver {
/// Queue additions should be made via [`enqueue`] and
/// [`enqueue_source`].
///
/// [`enqueue`]: #method.enqueue
/// [`enqueue_source`]: #method.enqueue_source
/// [`enqueue`]: Driver::enqueue
/// [`enqueue_source`]: Driver::enqueue_source
pub fn queue(&self) -> &TrackQueue {
&self.queue
}
@@ -253,7 +253,7 @@ impl Driver {
///
/// Requires the `"builtin-queue"` feature.
///
/// [`Input`]: ../input/struct.input.html
/// [`Input`]: crate::input::Input
pub fn enqueue_source(&mut self, source: Input) {
let (mut track, _) = tracks::create_player(source);
self.queue.add_raw(&mut track);
@@ -264,7 +264,7 @@ impl Driver {
///
/// Requires the `"builtin-queue"` feature.
///
/// [`Track`]: ../tracks/struct.track.html
/// [`Track`]: crate::tracks::Track
pub fn enqueue(&mut self, mut track: Track) {
self.queue.add_raw(&mut track);
self.play(track);

View File

@@ -19,7 +19,7 @@ pub enum JoinError {
NoSender,
/// Tried to leave a [`Call`] which was not found.
///
/// [`Call`]: ../struct.Call.html
/// [`Call`]: crate::Call
NoCall,
#[cfg(feature = "serenity")]
/// Serenity-specific WebSocket send error.

View File

@@ -8,17 +8,18 @@ use discortp::{rtcp::Rtcp, rtp::Rtp};
/// Information about which tracks or data fired an event.
///
/// [`Track`] events may be local or global, and have no tracks
/// if fired on the global context via [`Handler::add_global_event`].
/// if fired on the global context via [`Driver::add_global_event`].
///
/// [`Track`]: ../tracks/struct.Track.html
/// [`Handler::add_global_event`]: ../struct.Handler.html#method.add_global_event
/// [`Track`]: crate::tracks::Track
/// [`Driver::add_global_event`]: crate::driver::Driver::add_global_event
#[derive(Clone, Debug)]
#[non_exhaustive]
pub enum EventContext<'a> {
/// Track event context, passed to events created via [`TrackHandle::add_event`],
/// [`EventStore::add_event`], or relevant global events.
///
/// [`EventStore::add_event`]: struct.EventStore.html#method.add_event
/// [`TrackHandle::add_event`]: ../tracks/struct.TrackHandle.html#method.add_event
/// [`EventStore::add_event`]: EventStore::add_event
/// [`TrackHandle::add_event`]: TrackHandle::add_event
Track(&'a [(&'a TrackState, &'a TrackHandle)]),
/// Speaking state update, typically describing how another voice
/// user is transmitting audio data. Clients must send at least one such

View File

@@ -1,11 +1,12 @@
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
/// Voice core events occur on receipt of
/// voice packets and telemetry.
///
/// Core events persist while the `action` in [`EventData`]
/// returns `None`.
///
/// [`EventData`]: struct.EventData.html
/// [`EventData`]: super::EventData
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[non_exhaustive]
pub enum CoreEvent {
/// Fired on receipt of a speaking state update from another host.
///

View File

@@ -17,10 +17,10 @@ impl EventData {
/// Event handlers will be re-added with their new trigger condition,
/// or removed if [`Cancel`]led
///
/// [`EventContext`]: enum.EventContext.html
/// [`Event`]: enum.Event.html
/// [`Delayed`]: enum.Event.html#variant.Delayed
/// [`Cancel`]: enum.Event.html#variant.Cancel
/// [`EventContext`]: EventContext
/// [`Event`]: Event
/// [`Delayed`]: Event::Delayed
/// [`Cancel`]: Event::Cancel
pub fn new<F: EventHandler + 'static>(event: Event, action: F) -> Self {
Self {
event,

View File

@@ -12,16 +12,15 @@ pub use self::{context::*, core::*, data::*, store::*, track::*, untimed::*};
use async_trait::async_trait;
use std::time::Duration;
#[async_trait]
/// Trait to handle an event which can be fired per-track, or globally.
///
/// These may be feasibly reused between several event sources.
#[async_trait]
pub trait EventHandler: Send + Sync {
/// Respond to one received event.
async fn act(&self, ctx: &EventContext<'_>) -> Option<Event>;
}
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
/// Classes of event which may occur, triggering a handler
/// at the local (track-specific) or global level.
///
@@ -32,7 +31,9 @@ pub trait EventHandler: Send + Sync {
///
/// Event handlers themselves are described in [`EventData::action`].
///
/// [`EventData::action`]: struct.EventData.html#method.action
/// [`EventData::action`]: EventData::action
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[non_exhaustive]
pub enum Event {
/// Periodic events rely upon two parameters: a *period*
/// and an optional *phase*.
@@ -41,7 +42,7 @@ pub enum Event {
/// in one *period*. Periodic events repeat automatically
/// so long as the `action` in [`EventData`] returns `None`.
///
/// [`EventData`]: struct.EventData.html
/// [`EventData`]: EventData
Periodic(Duration, Option<Duration>),
/// Delayed events rely upon a *delay* parameter, and
/// fire one *delay* after the audio context processes them.
@@ -49,7 +50,7 @@ pub enum Event {
/// Delayed events are automatically removed once fired,
/// so long as the `action` in [`EventData`] returns `None`.
///
/// [`EventData`]: struct.EventData.html
/// [`EventData`]: EventData
Delayed(Duration),
/// Track events correspond to certain actions or changes
/// of state, such as a track finishing, looping, or being
@@ -58,7 +59,7 @@ pub enum Event {
/// Track events persist while the `action` in [`EventData`]
/// returns `None`.
///
/// [`EventData`]: struct.EventData.html
/// [`EventData`]: EventData
Track(TrackEvent),
/// Core events
///
@@ -66,7 +67,7 @@ pub enum Event {
/// returns `None`. Core events **must** be applied globally,
/// as attaching them to a track is a no-op.
///
/// [`EventData`]: struct.EventData.html
/// [`EventData`]: EventData
Core(CoreEvent),
/// Cancels the event, if it was intended to persist.
Cancel,

View File

@@ -15,7 +15,7 @@ use tracing::info;
/// Timed events are stored in a binary heap for fast selection, and have custom `Eq`,
/// `Ord`, etc. implementations to support (only) this.
///
/// [`EventData`]: struct.EventData.html
/// [`EventData`]: EventData
pub struct EventStore {
timed: BinaryHeap<EventData>,
untimed: HashMap<UntimedEvent, Vec<EventData>>,
@@ -33,7 +33,7 @@ impl EventStore {
/// This is usually automatically installed by the driver once
/// a track has been registered.
///
/// [`Track`]: ../tracks/struct.Track.html
/// [`Track`]: crate::tracks::Track
pub fn new_local() -> Self {
EventStore {
local_only: true,
@@ -45,7 +45,7 @@ impl EventStore {
///
/// Updates `evt` according to [`EventData::compute_activation`].
///
/// [`EventData::compute_activation`]: struct.EventData.html#method.compute_activation
/// [`EventData::compute_activation`]: EventData::compute_activation
pub fn add_event(&mut self, mut evt: EventData, now: Duration) {
evt.compute_activation(now);

View File

@@ -1,4 +1,3 @@
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
/// Track events correspond to certain actions or changes
/// of state, such as a track finishing, looping, or being
/// manually stopped. Voice core events occur on receipt of
@@ -7,7 +6,9 @@
/// Track events persist while the `action` in [`EventData`]
/// returns `None`.
///
/// [`EventData`]: struct.EventData.html
/// [`EventData`]: super::EventData
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[non_exhaustive]
pub enum TrackEvent {
/// The attached track has ended.
End,

View File

@@ -1,12 +1,13 @@
use super::*;
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
/// Track and voice core events.
///
/// Untimed events persist while the `action` in [`EventData`]
/// returns `None`.
///
/// [`EventData`]: struct.EventData.html
/// [`EventData`]: EventData
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[non_exhaustive]
pub enum UntimedEvent {
/// Untimed events belonging to a track, such as state changes, end, or loops.
Track(TrackEvent),

View File

@@ -29,8 +29,7 @@ enum Return {
/// If the `"driver"` feature is enabled, then a Call exposes all control methods of
/// [`Driver`] via `Deref(Mut)`.
///
/// [`Driver`]: driver/struct.Driver.html
/// [`Shard`]: ../gateway/struct.Shard.html
/// [`Driver`]: struct@Driver
#[derive(Clone, Debug)]
pub struct Call {
connection: Option<(ChannelId, ConnectionProgress, Return)>,
@@ -45,11 +44,14 @@ pub struct Call {
/// Whether the current handler is set to mute voice connections.
self_mute: bool,
user_id: UserId,
/// Will be set when a `Call` is made via the [`new`][`Call::new`]
/// Will be set when a `Call` is made via the [`new`]
/// method.
///
/// When set via [`standalone`][`Call::standalone`], it will not be
/// When set via [`standalone`](`Call::standalone`), it will not be
/// present.
///
/// [`new`]: Call::new
/// [`standalone`]: Call::standalone
ws: Option<Shard>,
}
@@ -153,7 +155,7 @@ impl Call {
/// **Note**: If the `Call` was created via [`standalone`], then this
/// will _only_ update whether the connection is internally deafened.
///
/// [`standalone`]: #method.standalone
/// [`standalone`]: Call::standalone
#[instrument(skip(self))]
pub async fn deafen(&mut self, deaf: bool) -> JoinResult<()> {
self.self_deaf = deaf;
@@ -217,7 +219,7 @@ impl Call {
/// will _only_ update whether the connection is internally connected to a
/// voice channel.
///
/// [`standalone`]: #method.standalone
/// [`standalone`]: Call::standalone
#[instrument(skip(self))]
pub async fn leave(&mut self) -> JoinResult<()> {
// Only send an update if we were in a voice channel.
@@ -237,7 +239,7 @@ impl Call {
/// **Note**: If the `Call` was created via [`standalone`], then this
/// will _only_ update whether the connection is internally muted.
///
/// [`standalone`]: #method.standalone
/// [`standalone`]: Call::standalone
#[instrument(skip(self))]
pub async fn mute(&mut self, mute: bool) -> JoinResult<()> {
self.self_mute = mute;
@@ -259,11 +261,7 @@ impl Call {
/// You should only need to use this if you initialized the `Call` via
/// [`standalone`].
///
/// Refer to the documentation for [`connect`] for when this will
/// automatically connect to a voice channel.
///
/// [`connect`]: #method.connect
/// [`standalone`]: #method.standalone
/// [`standalone`]: Call::standalone
#[instrument(skip(self, token))]
pub fn update_server(&mut self, endpoint: String, token: String) {
let try_conn = if let Some((_, ref mut progress, _)) = self.connection.as_mut() {
@@ -282,11 +280,7 @@ impl Call {
/// You should only need to use this if you initialized the `Call` via
/// [`standalone`].
///
/// refer to the documentation for [`connect`] for when this will
/// automatically connect to a voice channel.
///
/// [`connect`]: #method.connect
/// [`standalone`]: #method.standalone
/// [`standalone`]: Call::standalone
#[instrument(skip(self))]
pub fn update_state(&mut self, session_id: String) {
let try_conn = if let Some((_, ref mut progress, _)) = self.connection.as_mut() {
@@ -304,7 +298,7 @@ impl Call {
///
/// Does nothing if initialized via [`standalone`].
///
/// [`standalone`]: #method.standalone
/// [`standalone`]: Call::standalone
#[instrument(skip(self))]
async fn update(&mut self) -> JoinResult<()> {
if let Some(ws) = self.ws.as_mut() {

View File

@@ -43,9 +43,9 @@ use tracing::{debug, trace};
/// retrieved as **compressed Opus audio**. There is an associated memory cost,
/// but this is far smaller than using a [`Memory`].
///
/// [`Input`]: ../struct.Input.html
/// [`Memory`]: struct.Memory.html
/// [`Restartable`]: ../struct.Restartable.html
/// [`Input`]: Input
/// [`Memory`]: super::Memory
/// [`Restartable`]: crate::input::restartable::Restartable
#[derive(Clone, Debug)]
pub struct Compressed {
/// Inner shared bytestore.
@@ -59,7 +59,7 @@ pub struct Compressed {
impl Compressed {
/// Wrap an existing [`Input`] with an in-memory store, compressed using Opus.
///
/// [`Input`]: ../struct.Input.html
/// [`Input`]: Input
/// [`Metadata.duration`]: ../struct.Metadata.html#structfield.duration
pub fn new(source: Input, bitrate: Bitrate) -> Result<Self> {
Self::with_config(source, bitrate, None)
@@ -69,10 +69,10 @@ impl Compressed {
///
/// `config.length_hint` may be used to control the size of the initial chunk, preventing
/// needless allocations and copies. If this is not present, the value specified in
/// `source`'s [`Metadata.duration`] will be used.
/// `source`'s [`Metadata::duration`] will be used.
///
/// [`Input`]: ../struct.Input.html
/// [`Metadata.duration`]: ../struct.Metadata.html#structfield.duration
/// [`Input`]: Input
/// [`Metadata::duration`]: crate::input::Metadata::duration
pub fn with_config(source: Input, bitrate: Bitrate, config: Option<Config>) -> Result<Self> {
let channels = if source.stereo {
Channels::Stereo
@@ -92,8 +92,8 @@ impl Compressed {
/// `length_hint` functions as in [`new`]. This function's behaviour is undefined if your encoder
/// has a different sample rate than 48kHz, and if the decoder has a different channel count from the source.
///
/// [`Input`]: ../struct.Input.html
/// [`new`]: #method.new
/// [`Input`]: Input
/// [`new`]: Compressed::new
pub fn with_encoder(
mut source: Input,
encoder: OpusEncoder,
@@ -154,7 +154,7 @@ impl From<Compressed> for Input {
///
/// Created and managed by [`Compressed`].
///
/// [`Compressed`]: struct.Compressed.html
/// [`Compressed`]: Compressed
#[derive(Debug)]
pub struct OpusCompressor {
encoder: OpusEncoder,

View File

@@ -25,9 +25,9 @@ use streamcatcher::{Catcher, Config};
/// cost of audio processing. This is a significant *3 Mbps (375 kiB/s)*,
/// or 131 MiB of RAM for a 6 minute song.
///
/// [`Input`]: ../struct.Input.html
/// [`Compressed`]: struct.Compressed.html
/// [`Restartable`]: ../struct.Restartable.html
/// [`Input`]: Input
/// [`Compressed`]: super::Compressed
/// [`Restartable`]: crate::input::restartable::Restartable
#[derive(Clone, Debug)]
pub struct Memory {
/// Inner shared bytestore.
@@ -45,7 +45,7 @@ pub struct Memory {
impl Memory {
/// Wrap an existing [`Input`] with an in-memory store with the same codec and framing.
///
/// [`Input`]: ../struct.Input.html
/// [`Input`]: Input
pub fn new(source: Input) -> Result<Self> {
Self::with_config(source, None)
}
@@ -54,10 +54,10 @@ impl Memory {
///
/// `length_hint` may be used to control the size of the initial chunk, preventing
/// needless allocations and copies. If this is not present, the value specified in
/// `source`'s [`Metadata.duration`] will be used, assuming that the source is uncompressed.
/// `source`'s [`Metadata::duration`] will be used, assuming that the source is uncompressed.
///
/// [`Input`]: ../struct.Input.html
/// [`Metadata.duration`]: ../struct.Metadata.html#structfield.duration
/// [`Input`]: Input
/// [`Metadata::duration`]: crate::input::Metadata::duration
pub fn with_config(mut source: Input, config: Option<Config>) -> Result<Self> {
let stereo = source.stereo;
let kind = (&source.kind).into();

View File

@@ -9,7 +9,7 @@ use std::{fmt::Debug, mem};
/// State used to decode input bytes of an [`Input`].
///
/// [`Input`]: ../struct.Input.html
/// [`Input`]: Input
#[non_exhaustive]
#[derive(Clone, Debug)]
pub enum Codec {
@@ -18,19 +18,19 @@ pub enum Codec {
///
/// Must be combined with a non-[`Raw`] container.
///
/// [`Raw`]: ../enum.Container.html#variant.Raw
/// [`Raw`]: Container::Raw
Opus(OpusDecoderState),
/// The inner bytestream is encoded using raw `i16` samples.
///
/// Must be combined with a [`Raw`] container.
///
/// [`Raw`]: ../enum.Container.html#variant.Raw
/// [`Raw`]: Container::Raw
Pcm,
/// The inner bytestream is encoded using raw `f32` samples.
///
/// Must be combined with a [`Raw`] container.
///
/// [`Raw`]: ../enum.Container.html#variant.Raw
/// [`Raw`]: Container::Raw
FloatPcm,
}
@@ -48,7 +48,7 @@ impl From<&Codec> for CodecType {
/// Type of data being passed into an [`Input`].
///
/// [`Input`]: ../struct.Input.html
/// [`Input`]: Input
#[non_exhaustive]
#[derive(Copy, Clone, Debug)]
pub enum CodecType {
@@ -56,19 +56,19 @@ pub enum CodecType {
///
/// Must be combined with a non-[`Raw`] container.
///
/// [`Raw`]: ../enum.Container.html#variant.Raw
/// [`Raw`]: Container::Raw
Opus,
/// The inner bytestream is encoded using raw `i16` samples.
///
/// Must be combined with a [`Raw`] container.
///
/// [`Raw`]: ../enum.Container.html#variant.Raw
/// [`Raw`]: Container::Raw
Pcm,
/// The inner bytestream is encoded using raw `f32` samples.
///
/// Must be combined with a [`Raw`] container.
///
/// [`Raw`]: ../enum.Container.html#variant.Raw
/// [`Raw`]: Container::Raw
FloatPcm,
}

View File

@@ -4,7 +4,7 @@ use parking_lot::Mutex;
use std::sync::Arc;
#[derive(Clone, Debug)]
/// Inner state
/// Inner state used to decode Opus input sources.
pub struct OpusDecoderState {
/// Inner decoder used to convert opus frames into a stream of samples.
pub decoder: Arc<Mutex<OpusDecoder>>,

View File

@@ -7,7 +7,7 @@ use streamcatcher::CatcherError;
/// An error returned when creating a new [`Input`].
///
/// [`Input`]: ../struct.Input.html
/// [`Input`]: crate::input::Input
#[derive(Debug)]
#[non_exhaustive]
pub enum Error {
@@ -71,7 +71,7 @@ impl From<OpusError> for Error {
/// An error returned from the [`dca`] method.
///
/// [`dca`]: ../fn.dca.html
/// [`dca`]: crate::input::dca
#[derive(Debug)]
#[non_exhaustive]
pub enum DcaError {
@@ -89,5 +89,5 @@ pub enum DcaError {
/// Convenience type for fallible return of [`Input`]s.
///
/// [`Input`]: ../struct.Input.html
/// [`Input`]: crate::input::Input
pub type Result<T> = std::result::Result<T, Error>;

View File

@@ -72,6 +72,8 @@ pub(crate) async fn _ffmpeg(path: &OsStr) -> Result<Input> {
/// "-",
/// ]));
/// ```
///
/// [`ffmpeg`]: ffmpeg
pub async fn ffmpeg_optioned<P: AsRef<OsStr>>(
path: P,
pre_input_args: &[&str],

View File

@@ -4,7 +4,7 @@ use std::time::Duration;
/// Information about an [`Input`] source.
///
/// [`Input`]: struct.Input.html
/// [`Input`]: crate::input::Input
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct Metadata {
/// The title of this stream.
@@ -95,7 +95,7 @@ impl Metadata {
}
}
/// Use `youtube-dl` to extract metadata for an online resource.
/// Use `youtube-dl`'s JSON output for metadata for an online resource.
pub fn from_ytdl_output(value: Value) -> Self {
let obj = value.as_object();

View File

@@ -20,13 +20,13 @@
//! * its [`Input`] [meets the promises described herein](codec/struct.OpusDecoderState.html#structfield.allow_passthrough),
//! * and that track's volume is set to `1.0`.
//!
//! [`Input`]: struct.Input.html
//! [`Reader`]: reader/enum.Reader.html
//! [`Container`]: enum.Container.html
//! [`Codec`]: codec/enum.Codec.html
//! [`Input`]: Input
//! [`Reader`]: reader::Reader
//! [`Container`]: Container
//! [`Codec`]: Codec
//! [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html
//! [`Compressed`]: cached/struct.Compressed.html
//! [`dca`]: fn.dca.html
//! [`Compressed`]: cached::Compressed
//! [`dca`]: dca()
pub mod cached;
mod child;
@@ -80,8 +80,8 @@ use tracing::{debug, error};
///
/// See the [module root] for more information.
///
/// [`Reader`]: enum.Reader.html
/// [module root]: index.html
/// [`Reader`]: Reader
/// [module root]: super
#[derive(Debug)]
pub struct Input {
/// Information about the played source.
@@ -130,7 +130,7 @@ impl Input {
/// Returns whether the inner [`Reader`] implements [`Seek`].
///
/// [`Reader`]: reader/enum.Reader.html
/// [`Reader`]: reader::Reader
/// [`Seek`]: https://doc.rust-lang.org/std/io/trait.Seek.html
pub fn is_seekable(&self) -> bool {
self.reader.is_seekable()
@@ -143,7 +143,7 @@ impl Input {
/// Returns the type of the inner [`Codec`].
///
/// [`Codec`]: codec/enum.Codec.html
/// [`Codec`]: Codec
pub fn get_type(&self) -> CodecType {
(&self.kind).into()
}

View File

@@ -23,14 +23,14 @@ use streamcatcher::{Catcher, TxCatcher};
/// Users may define their own data sources using [`Extension`]
/// and [`ExtensionSeek`].
///
/// [`Extension`]: #variant.Extension
/// [`ExtensionSeek`]: #variant.ExtensionSeek
/// [`Extension`]: Reader::Extension
/// [`ExtensionSeek`]: Reader::ExtensionSeek
pub enum Reader {
/// Piped output of another program (i.e., [`ffmpeg`]).
///
/// Does not support seeking.
///
/// [`ffmpeg`]: ../fn.ffmpeg.html
/// [`ffmpeg`]: super::ffmpeg
Pipe(BufReader<ChildContainer>),
/// A cached, raw in-memory store, provided by Songbird.
///

View File

@@ -37,9 +37,9 @@ type RecreateChannel = Receiver<Result<(Box<Input>, Recreator)>>;
/// cannot be spared. Forward seeks will drain the track until reaching
/// the desired timestamp.
///
/// [`Input`]: struct.Input.html
/// [`Memory`]: cached/struct.Memory.html
/// [`Compressed`]: cached/struct.Compressed.html
/// [`Input`]: Input
/// [`Memory`]: cached::Memory
/// [`Compressed`]: cached::Compressed
pub struct Restartable {
async_handle: Option<Handle>,
awaiting_source: Option<RecreateChannel>,
@@ -89,7 +89,7 @@ impl Restartable {
/// Trait used to create an instance of a [`Reader`] at instantiation and when
/// a backwards seek is needed.
///
/// [`Reader`]: ../reader/enum.Reader.html
/// [`Reader`]: reader::Reader
#[async_trait]
pub trait Restart {
/// Tries to create a replacement source.

View File

@@ -3,6 +3,7 @@
html_favicon_url = "https://raw.githubusercontent.com/serenity-rs/songbird/current/songbird-ico.png"
)]
#![deny(missing_docs)]
#![deny(broken_intra_doc_links)]
//! ![project logo][logo]
//!
//! Songbird is an async, cross-library compatible voice system for Discord, written in Rust.
@@ -33,7 +34,7 @@
//! [twilight]: https://github.com/twilight-rs/twilight
//! [this crate's examples directory]: https://github.com/serenity-rs/songbird/tree/current/examples
//! ["Black-Capped Chickadee"]: https://www.oldbookillustrations.com/illustrations/black-capped-chickadee/
//! [`ConnectionInfo`]: struct.ConnectionInfo.html
//! [`ConnectionInfo`]: struct@ConnectionInfo
//! [lavalink]: https://github.com/Frederikam/Lavalink
pub mod constants;

View File

@@ -41,7 +41,7 @@ struct ClientData {
/// This manager transparently maps guild state and a source of shard information
/// into individual calls, and forwards state updates which affect call state.
///
/// [`Call`]: struct.Call.html
/// [`Call`]: Call
#[derive(Debug)]
pub struct Songbird {
client_data: PRwLock<ClientData>,
@@ -58,7 +58,7 @@ impl Songbird {
///
/// This must be [registered] after creation.
///
/// [registered]: serenity/fn.register_with.html
/// [registered]: crate::serenity::register_with
pub fn serenity() -> Arc<Self> {
Arc::new(Self {
client_data: Default::default(),
@@ -77,7 +77,7 @@ impl Songbird {
/// users are responsible for passing in any events using
/// [`process`].
///
/// [`process`]: #method.process
/// [`process`]: Songbird::process
pub fn twilight<U>(cluster: Cluster, shard_count: u64, user_id: U) -> Arc<Self>
where
U: Into<UserId>,
@@ -101,7 +101,7 @@ impl Songbird {
/// If this struct is already initialised (e.g., from [`::twilight`]),
/// or a previous call, then this function is a no-op.
///
/// [`::twilight`]: #method.twilight
/// [`::twilight`]: Songbird::twilight
pub fn initialise_client_data<U: Into<UserId>>(&self, shard_count: u64, user_id: U) {
let mut client_data = self.client_data.write();
@@ -116,7 +116,7 @@ impl Songbird {
/// Retreives a [`Call`] for the given guild, if one already exists.
///
/// [`Call`]: struct.Call.html
/// [`Call`]: Call
pub fn get<G: Into<GuildId>>(&self, guild_id: G) -> Option<Arc<Mutex<Call>>> {
let map_read = self.calls.read();
map_read.get(&guild_id.into()).cloned()
@@ -127,7 +127,7 @@ impl Songbird {
///
/// This will not join any calls, or cause connection state to change.
///
/// [`Call`]: struct.Call.html
/// [`Call`]: Call
pub fn get_or_insert(&self, guild_id: GuildId) -> Arc<Mutex<Call>> {
self.get(guild_id).unwrap_or_else(|| {
let mut map_read = self.calls.write();
@@ -183,8 +183,8 @@ impl Songbird {
/// If you _only_ need to retrieve the handler for a target, then use
/// [`get`].
///
/// [`Call`]: struct.Call.html
/// [`get`]: #method.get
/// [`Call`]: Call
/// [`get`]: Songbird::get
#[inline]
pub async fn join<C, G>(
&self,
@@ -220,7 +220,7 @@ impl Songbird {
/// This method returns the handle and the connection info needed for other libraries
/// or drivers, such as lavalink, and does not actually start or run a voice call.
///
/// [`Call`]: struct.Call.html
/// [`Call`]: Call
#[inline]
pub async fn join_gateway<C, G>(
&self,
@@ -257,9 +257,9 @@ impl Songbird {
/// This is a wrapper around [getting][`get`] a handler and calling
/// [`leave`] on it.
///
/// [`Call`]: struct.Call.html
/// [`get`]: #method.get
/// [`leave`]: struct.Call.html#method.leave
/// [`Call`]: Call
/// [`get`]: Songbird::get
/// [`leave`]: Call::leave
#[inline]
pub async fn leave<G: Into<GuildId>>(&self, guild_id: G) -> JoinResult<()> {
self._leave(guild_id.into()).await
@@ -282,7 +282,7 @@ impl Songbird {
/// An Err(...) value implies that the gateway could not be contacted,
/// and that leaving should be attempted again later (i.e., after reconnect).
///
/// [`Call`]: struct.Call.html
/// [`Call`]: Call
#[inline]
pub async fn remove<G: Into<GuildId>>(&self, guild_id: G) -> JoinResult<()> {
self._remove(guild_id.into()).await

View File

@@ -13,7 +13,7 @@ use std::sync::Arc;
/// Zero-size type used to retrieve the registered [`Songbird`] instance
/// from serenity's inner TypeMap.
///
/// [`Songbird`]: ../struct.Songbird.html
/// [`Songbird`]: Songbird
pub struct SongbirdKey;
impl TypeMapKey for SongbirdKey {
@@ -54,7 +54,7 @@ pub trait SerenityInit {
/// Registers a new Songbird voice system with serenity, storing it for easy
/// access via [`get`].
///
/// [`get`]: fn.get.html
/// [`get`]: get
fn register_songbird(self) -> Self;
/// Registers a given Songbird voice system with serenity, as above.
fn register_songbird_with(self, voice: Arc<Songbird>) -> Self;

View File

@@ -6,8 +6,9 @@ use tokio::sync::oneshot::Sender as OneshotSender;
/// A request from external code using a [`TrackHandle`] to modify
/// or act upon an [`Track`] object.
///
/// [`Track`]: struct.Track.html
/// [`TrackHandle`]: struct.TrackHandle.html
/// [`Track`]: Track
/// [`TrackHandle`]: TrackHandle
#[non_exhaustive]
pub enum TrackCommand {
/// Set the track's play_mode to play/resume.
Play,

View File

@@ -15,7 +15,7 @@ use uuid::Uuid;
/// the underlying [`Track`] object has been discarded. Those which aren't refer
/// to immutable properties of the underlying stream.
///
/// [`Track`]: struct.Track.html
/// [`Track`]: Track
pub struct TrackHandle {
command_channel: UnboundedSender<TrackCommand>,
seekable: bool,
@@ -26,7 +26,7 @@ impl TrackHandle {
/// Creates a new handle, using the given command sink and hint as to whether
/// the underlying [`Input`] supports seek operations.
///
/// [`Input`]: ../input/struct.Input.html
/// [`Input`]: crate::input::Input
pub fn new(command_channel: UnboundedSender<TrackCommand>, seekable: bool, uuid: Uuid) -> Self {
Self {
command_channel,
@@ -50,7 +50,7 @@ impl TrackHandle {
/// This is *final*, and will cause the audio context to fire
/// a [`TrackEvent::End`] event.
///
/// [`TrackEvent::End`]: ../events/enum.TrackEvent.html#variant.End
/// [`TrackEvent::End`]: crate::events::TrackEvent::End
pub fn stop(&self) -> TrackResult {
self.send(TrackCommand::Stop)
}
@@ -62,11 +62,11 @@ impl TrackHandle {
/// Denotes whether the underlying [`Input`] stream is compatible with arbitrary seeking.
///
/// If this returns `false`, all calls to [`seek`] will fail, and the track is
/// If this returns `false`, all calls to [`seek_time`] will fail, and the track is
/// incapable of looping.
///
/// [`seek`]: #method.seek
/// [`Input`]: ../input/struct.Input.html
/// [`seek_time`]: TrackHandle::seek_time
/// [`Input`]: crate::input::Input
pub fn is_seekable(&self) -> bool {
self.seekable
}
@@ -76,7 +76,7 @@ impl TrackHandle {
/// If the underlying [`Input`] does not support this behaviour,
/// then all calls will fail.
///
/// [`Input`]: ../input/struct.Input.html
/// [`Input`]: crate::input::Input
pub fn seek_time(&self, position: Duration) -> TrackResult {
if self.seekable {
self.send(TrackCommand::Seek(position))
@@ -91,8 +91,8 @@ impl TrackHandle {
/// within the supplied function or closure. *Taking excess time could prevent
/// timely sending of packets, causing audio glitches and delays*.
///
/// [`Track`]: struct.Track.html
/// [`EventContext::Track`]: ../events/enum.EventContext.html#variant.Track
/// [`Track`]: Track
/// [`EventContext::Track`]: crate::events::EventContext::Track
pub fn add_event<F: EventHandler + 'static>(&self, event: Event, action: F) -> TrackResult {
let cmd = TrackCommand::AddEvent(EventData::new(event, action));
if event.is_global_only() {
@@ -108,7 +108,7 @@ impl TrackHandle {
/// within the supplied function or closure. *Taking excess time could prevent
/// timely sending of packets, causing audio glitches and delays*.
///
/// [`Track`]: struct.Track.html
/// [`Track`]: Track
pub fn action<F>(&self, action: F) -> TrackResult
where
F: FnOnce(&mut Track) + Send + Sync + 'static,
@@ -160,7 +160,7 @@ impl TrackHandle {
#[inline]
/// Send a raw command to the [`Track`] object.
///
/// [`Track`]: struct.Track.html
/// [`Track`]: Track
pub fn send(&self, cmd: TrackCommand) -> TrackResult {
self.command_channel.send(cmd)
}

View File

@@ -1,7 +1,7 @@
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
/// Looping behaviour for a [`Track`].
///
/// [`Track`]: struct.Track.html
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum LoopState {
/// Track will loop endlessly until loop state is changed or
/// manually stopped.
@@ -11,7 +11,7 @@ pub enum LoopState {
///
/// `Finite(0)` is the `Default`, stopping the track once its [`Input`] ends.
///
/// [`Input`]: ../input/struct.Input.html
/// [`Input`]: crate::input::Input
Finite(usize),
}

View File

@@ -361,8 +361,8 @@ impl Track {
/// Typically, this would be used if you wished to directly work on or configure
/// the [`Track`] object before it is passed over to the driver.
///
/// [`Track`]: struct.Track.html
/// [`TrackHandle`]: struct.TrackHandle.html
/// [`Track`]: Track
/// [`TrackHandle`]: TrackHandle
pub fn create_player(source: Input) -> (Track, TrackHandle) {
let (tx, rx) = mpsc::unbounded_channel();
let can_seek = source.is_seekable();
@@ -378,7 +378,7 @@ pub fn create_player(source: Input) -> (Track, TrackHandle) {
/// Failure indicates that the accessed audio object has been
/// removed or deleted by the audio context.
///
/// [`TrackHandle`]: struct.TrackHandle.html
/// [`TrackHandle`]: TrackHandle
pub type TrackResult = Result<(), SendError<TrackCommand>>;
/// Alias for return value from calls to [`TrackHandle::get_info`].
@@ -389,5 +389,5 @@ pub type TrackResult = Result<(), SendError<TrackCommand>>;
/// Failure indicates that the accessed audio object has been
/// removed or deleted by the audio context.
///
/// [`TrackHandle::get_info`]: struct.TrackHandle.html#method.get_info
/// [`TrackHandle::get_info`]: TrackHandle::get_info
pub type TrackQueryResult = Result<OneshotReceiver<Box<TrackState>>, SendError<TrackCommand>>;

View File

@@ -1,5 +1,6 @@
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
/// Playback status of a track.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum PlayMode {
/// The track is currently playing.
Play,

View File

@@ -53,8 +53,8 @@ use tracing::{info, warn};
/// # };
/// ```
///
/// [`TrackEvent`]: ../events/enum.TrackEvent.html
/// [`Driver::queue`]: ../driver/struct.Driver.html#method.queue
/// [`TrackEvent`]: crate::events::TrackEvent
/// [`Driver::queue`]: crate::driver::Driver::queue
#[derive(Clone, Debug, Default)]
pub struct TrackQueue {
// NOTE: the choice of a parking lot mutex is quite deliberate
@@ -88,7 +88,7 @@ impl Queued {
/// This abstracts away thread-safety from the user,
/// and offers a convenient location to store further state if required.
///
/// [`TrackQueue`]: struct.TrackQueue.html
/// [`TrackQueue`]: TrackQueue
struct TrackQueueCore {
tracks: VecDeque<Queued>,
}
@@ -163,11 +163,11 @@ impl TrackQueue {
/// Adds a [`Track`] object to the queue, to be played in the channel managed by `handler`.
///
/// This is used with [`voice::create_player`] if additional configuration or event handlers
/// This is used with [`create_player`] if additional configuration or event handlers
/// are required before enqueueing the audio track.
///
/// [`Track`]: struct.Track.html
/// [`voice::create_player`]: fn.create_player.html
/// [`Track`]: Track
/// [`create_player`]: super::create_player
pub fn add(&self, mut track: Track, handler: &mut Driver) {
self.add_raw(&mut track);
handler.play(track);
@@ -208,7 +208,7 @@ impl TrackQueue {
///
/// The returned entry can be readded to *this* queue via [`modify_queue`].
///
/// [`modify_queue`]: #method.modify_queue
/// [`modify_queue`]: TrackQueue::modify_queue
pub fn dequeue(&self, index: usize) -> Option<Queued> {
self.modify_queue(|vq| vq.remove(index))
}
@@ -285,7 +285,7 @@ impl TrackQueue {
///
/// Use [`modify_queue`] for direct modification of the queue.
///
/// [`modify_queue`]: #method.modify_queue
/// [`modify_queue`]: TrackQueue::modify_queue
pub fn current_queue(&self) -> Vec<TrackHandle> {
let inner = self.inner.lock();

View File

@@ -1,12 +1,10 @@
use super::*;
/// State of an [`Track`] object, designed to be passed to event handlers
/// and retrieved remotely via [`TrackHandle::get_info`] or
/// [`TrackHandle::get_info_blocking`].
/// and retrieved remotely via [`TrackHandle::get_info`].
///
/// [`Track`]: struct.Track.html
/// [`TrackHandle::get_info`]: struct.TrackHandle.html#method.get_info
/// [`TrackHandle::get_info_blocking`]: struct.TrackHandle.html#method.get_info_blocking
/// [`Track`]: Track
/// [`TrackHandle::get_info`]: TrackHandle::get_info
#[derive(Copy, Clone, Debug, Default, PartialEq)]
pub struct TrackState {
/// Play status (e.g., active, paused, stopped) of this track.
@@ -15,7 +13,8 @@ pub struct TrackState {
pub volume: f32,
/// Current playback position in the source.
///
/// This is altered by loops and seeks
/// This is altered by loops and seeks, and represents this track's
/// position in its underlying input stream.
pub position: Duration,
/// Total playback time, increasing monotonically.
pub play_time: Duration,