use crate::{model::*, node::Node};
use dashmap::{
mapref::one::{Ref, RefMut},
DashMap,
};
use futures_channel::mpsc::TrySendError;
use std::{
fmt::Debug,
sync::{
atomic::{AtomicBool, Ordering},
Arc,
},
};
use twilight_model::id::{ChannelId, GuildId};
#[derive(Clone, Debug, Default)]
pub struct PlayerManager {
pub(crate) players: Arc<DashMap<GuildId, Player>>,
}
impl PlayerManager {
pub(crate) fn new() -> Self {
Self::default()
}
pub fn get(&self, guild_id: &GuildId) -> Option<Ref<'_, GuildId, Player>> {
self.players.get(guild_id)
}
pub(crate) fn get_mut(&self, guild_id: &GuildId) -> Option<RefMut<'_, GuildId, Player>> {
self.players.get_mut(guild_id)
}
pub fn get_or_insert(&self, guild_id: GuildId, node: Node) -> RefMut<'_, GuildId, Player> {
self.players
.entry(guild_id)
.or_insert_with(|| Player::new(guild_id, node))
}
}
#[derive(Debug)]
pub struct Player {
channel_id: Option<ChannelId>,
guild_id: GuildId,
node: Node,
paused: AtomicBool,
playing: Option<()>,
position: i64,
time: i64,
volume: u16,
}
impl Player {
pub(crate) fn new(guild_id: GuildId, node: Node) -> Self {
Self {
channel_id: None,
guild_id,
node,
paused: AtomicBool::new(false),
playing: None,
position: 0,
time: 0,
volume: 0,
}
}
pub fn send(&self, event: impl Into<OutgoingEvent>) -> Result<(), TrySendError<OutgoingEvent>> {
self._send(event.into())
}
fn _send(&self, event: OutgoingEvent) -> Result<(), TrySendError<OutgoingEvent>> {
tracing::debug!(
"sending event on guild player {}: {:?}",
self.guild_id,
event
);
if let OutgoingEvent::Pause(ref event) = event {
self.paused.store(event.pause, Ordering::Release);
}
self.node.send(event)
}
pub fn node(&self) -> &Node {
&self.node
}
pub fn channel_id(&self) -> Option<ChannelId> {
self.channel_id.as_ref().copied()
}
pub fn guild_id(&self) -> GuildId {
self.guild_id
}
pub fn paused(&self) -> bool {
self.paused.load(Ordering::Acquire)
}
pub fn position(&self) -> i64 {
self.position
}
pub(crate) fn position_mut(&mut self) -> &mut i64 {
&mut self.position
}
pub fn time_ref(&mut self) -> i64 {
self.time
}
pub(crate) fn time_mut(&mut self) -> &mut i64 {
&mut self.time
}
pub fn volume_ref(&self) -> u16 {
self.volume
}
}
#[cfg(test)]
mod tests {
use super::{Player, PlayerManager};
use static_assertions::assert_impl_all;
use std::fmt::Debug;
assert_impl_all!(PlayerManager: Clone, Debug, Default, Send, Sync);
assert_impl_all!(Player: Debug, Send, Sync);
}