Tracks: Add TypeMap to Handles.

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.
This commit is contained in:
Kyle Simpson
2021-01-02 23:43:28 +00:00
parent 873458d288
commit d42e09f72b
4 changed files with 47 additions and 9 deletions

View File

@@ -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"
@@ -140,6 +144,7 @@ driver = [
"tokio/rt-core",
"tokio/sync",
"tokio/time",
"typemap_rev",
"url",
"uuid",
"xsalsa20poly1305",

View File

@@ -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;

View File

@@ -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 {
@@ -42,8 +58,9 @@ impl TrackHandle {
let inner = Arc::new(InnerHandle {
command_channel,
seekable,
metadata,
uuid,
metadata,
typemap: RwLock::new(TypeMap::new()),
});
Self { inner }
@@ -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.
///

View File

@@ -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();