Skip to content

Commit

Permalink
Tracks: Add TypeMap to Handles.
Browse files Browse the repository at this point in the history
Adds a shared TypeMap per TrackHandle. This should greatly simplify the user experience for attaching additional per-track state which the driver does not care for.
  • Loading branch information
FelixMcFelix committed Jan 2, 2021
1 parent 873458d commit d42e09f
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 9 deletions.
5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ optional = true
version = "0.2"
default-features = false

[dependencies.typemap_rev]
optional = true
version = "0.1"

[dependencies.url]
optional = true
version = "2"
Expand Down Expand Up @@ -140,6 +144,7 @@ driver = [
"tokio/rt-core",
"tokio/sync",
"tokio/time",
"typemap_rev",
"url",
"uuid",
"xsalsa20poly1305",
Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ pub use audiopus::{self as opus, Bitrate};
pub use discortp as packet;
#[cfg(feature = "driver")]
pub use serenity_voice_model as model;
#[cfg(feature = "driver")]
pub use typemap_rev as typemap;

#[cfg(test)]
use utils as test_utils;
Expand Down
44 changes: 36 additions & 8 deletions src/tracks/handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,45 @@ use crate::{
events::{Event, EventData, EventHandler},
input::Metadata,
};
use std::{sync::Arc, time::Duration};
use tokio::sync::{mpsc::UnboundedSender, oneshot};
use std::{fmt, sync::Arc, time::Duration};
use tokio::sync::{mpsc::UnboundedSender, oneshot, RwLock};
use typemap_rev::TypeMap;
use uuid::Uuid;

#[derive(Clone, Debug)]
/// Handle for safe control of a [`Track`] track from other threads, outside
/// Handle for safe control of a [`Track`] from other threads, outside
/// of the audio mixing and voice handling context.
///
/// Almost all method calls here are fallible; in most cases, this will be because
/// These are cheap to clone, using `Arc<...>` internally.
///
/// Many method calls here are fallible; in most cases, this will be because
/// the underlying [`Track`] object has been discarded. Those which aren't refer
/// to immutable properties of the underlying stream.
/// to immutable properties of the underlying stream, or shared data not used
/// by the driver.
///
/// [`Track`]: Track
pub struct TrackHandle {
inner: Arc<InnerHandle>,
}

#[derive(Clone, Debug)]
struct InnerHandle {
command_channel: UnboundedSender<TrackCommand>,
seekable: bool,
metadata: Box<Metadata>,
uuid: Uuid,
metadata: Box<Metadata>,
typemap: RwLock<TypeMap>,
}

impl fmt::Debug for InnerHandle {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("InnerHandle")
.field("command_channel", &self.command_channel)
.field("seekable", &self.seekable)
.field("uuid", &self.uuid)
.field("metadata", &self.metadata)
.field("typemap", &"<LOCK>")
.finish()
}
}

impl TrackHandle {
Expand All @@ -42,8 +58,9 @@ impl TrackHandle {
let inner = Arc::new(InnerHandle {
command_channel,
seekable,
metadata,
uuid,
metadata,
typemap: RwLock::new(TypeMap::new()),
});

Self { inner }
Expand Down Expand Up @@ -209,6 +226,17 @@ impl TrackHandle {
&self.inner.metadata
}

/// Allows access to this track's attached TypeMap.
///
/// TypeMaps allow additional, user-defined data shared by all handles
/// to be attached to any track.
///
/// Driver code will never attempt to lock access to this map,
/// preventing deadlock/stalling.
pub fn typemap(&self) -> &RwLock<TypeMap> {
&self.inner.typemap
}

#[inline]
/// Send a raw command to the [`Track`] object.
///
Expand Down
5 changes: 4 additions & 1 deletion src/tracks/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -382,9 +382,12 @@ pub fn create_player(source: Input) -> (Track, TrackHandle) {
create_player_with_uuid(source, Uuid::new_v4())
}

/// Refer to the documentation for [`create_player`] however, allows for a custom uuid to be inserted into the Track and Handle
/// Creates a [`Track`] and [`TrackHandle`] as in [`create_player`], allowing
/// a custom UUID to be set.
///
/// [`create_player`]: create_player
/// [`Track`]: Track
/// [`TrackHandle`]: TrackHandle
pub fn create_player_with_uuid(source: Input, uuid: Uuid) -> (Track, TrackHandle) {
let (tx, rx) = mpsc::unbounded_channel();
let can_seek = source.is_seekable();
Expand Down

0 comments on commit d42e09f

Please sign in to comment.