Make sure to add track event handler

This commit is contained in:
Alex Page 2023-03-08 18:57:03 -05:00
parent 2fd2079330
commit 825e15202e

View file

@ -1,6 +1,6 @@
//! Implements a queue for the bot to play songs in order //! Implements a queue for the bot to play songs in order
use std::sync::Arc; use std::{collections::VecDeque, sync::Arc};
use anyhow::Result; use anyhow::Result;
use parking_lot::Mutex; use parking_lot::Mutex;
@ -8,7 +8,7 @@ use poise::async_trait;
use songbird::{ use songbird::{
events::EventData, events::EventData,
input::Input, input::Input,
tracks::{self, TrackHandle}, tracks::{self, Track, TrackHandle},
Driver, Event, EventContext, EventHandler, TrackEvent, Driver, Event, EventContext, EventHandler, TrackEvent,
}; };
use thiserror::Error; use thiserror::Error;
@ -19,11 +19,31 @@ pub enum QueueError {
EmptyQueue, EmptyQueue,
} }
/// Inner queue data behind a Mutex to allow the event handler to access it
struct QueueCore {
tracks: VecDeque<TrackHandle>,
}
/// Event handler for the queue /// Event handler for the queue
struct QueueHandler { struct QueueHandler {
remote_lock: Arc<Mutex<QueueCore>>, remote_lock: Arc<Mutex<QueueCore>>,
} }
impl QueueHandler {
/// Event to remove the track from the queue when it ends
pub fn register_track_end_event(track: &mut Track, remote_lock: Arc<Mutex<QueueCore>>) {
let position = track.position();
track
.events
.as_mut()
.expect("Why is this even an Option?")
.add_event(
EventData::new(Event::Track(TrackEvent::End), QueueHandler { remote_lock }),
position,
);
}
}
#[async_trait] #[async_trait]
impl EventHandler for QueueHandler { impl EventHandler for QueueHandler {
async fn act(&self, ctx: &EventContext<'_>) -> Option<Event> { async fn act(&self, ctx: &EventContext<'_>) -> Option<Event> {
@ -37,20 +57,20 @@ impl EventHandler for QueueHandler {
// This slice should have exactly one entry. // This slice should have exactly one entry.
// If the ended track has same id as the queue head, then // If the ended track has same id as the queue head, then
// we can progress the queue. // we can progress the queue.
if inner.tracks.first()?.uuid() != ts.first()?.1.uuid() { if inner.tracks.front()?.uuid() != ts.first()?.1.uuid() {
return None; return None;
} }
} }
_ => return None, _ => return None,
} }
let _old = inner.tracks.remove(0); let _old = inner.tracks.pop_front();
// Keep going until we find one track which works, or we run out. // Keep going until we find one track which works, or we run out.
while let Some(new) = inner.tracks.first() { while let Some(new) = inner.tracks.front() {
if new.play().is_err() { if new.play().is_err() {
// Discard files which cannot be used for whatever reason. // Discard files which cannot be used for whatever reason.
inner.tracks.remove(0); inner.tracks.pop_front();
} else { } else {
break; break;
} }
@ -60,11 +80,6 @@ impl EventHandler for QueueHandler {
} }
} }
/// Inner queue data behind a Mutex to allow the event handler to access it
struct QueueCore {
tracks: Vec<TrackHandle>,
}
/// A queue of tracks to play /// A queue of tracks to play
pub struct Queue { pub struct Queue {
inner: Arc<Mutex<QueueCore>>, inner: Arc<Mutex<QueueCore>>,
@ -74,14 +89,16 @@ impl Queue {
#[must_use] #[must_use]
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
inner: Arc::new(Mutex::new(QueueCore { tracks: Vec::new() })), inner: Arc::new(Mutex::new(QueueCore {
tracks: VecDeque::new(),
})),
} }
} }
/// Resumes the current track /// Resumes the current track
pub fn resume(&mut self) -> Result<()> { pub fn resume(&mut self) -> Result<()> {
let inner = self.inner.lock(); let inner = self.inner.lock();
let Some(track) = inner.tracks.first() else { let Some(track) = inner.tracks.front() else {
return Err(QueueError::EmptyQueue.into()); return Err(QueueError::EmptyQueue.into());
}; };
track.play()?; track.play()?;
@ -91,18 +108,18 @@ impl Queue {
/// Stops the current track and removes it from the queue /// Stops the current track and removes it from the queue
pub fn stop(&mut self) -> Result<()> { pub fn stop(&mut self) -> Result<()> {
let mut inner = self.inner.lock(); let mut inner = self.inner.lock();
let Some(track) = inner.tracks.first() else { let Some(track) = inner.tracks.front() else {
return Err(QueueError::EmptyQueue.into()); return Err(QueueError::EmptyQueue.into());
}; };
track.stop()?; track.stop()?;
inner.tracks.remove(0); inner.tracks.pop_front();
Ok(()) Ok(())
} }
/// Pauses the current track /// Pauses the current track
pub fn pause(&mut self) -> Result<()> { pub fn pause(&mut self) -> Result<()> {
let inner = self.inner.lock(); let inner = self.inner.lock();
let Some(track) = inner.tracks.first() else { let Some(track) = inner.tracks.front() else {
return Err(QueueError::EmptyQueue.into()); return Err(QueueError::EmptyQueue.into());
}; };
track.pause()?; track.pause()?;
@ -114,22 +131,8 @@ impl Queue {
let mut inner = self.inner.lock(); let mut inner = self.inner.lock();
let (mut track, handle) = tracks::create_player(source); let (mut track, handle) = tracks::create_player(source);
track.pause(); track.pause();
let position = track.position(); QueueHandler::register_track_end_event(&mut track, self.inner.clone());
// Event to remove the track from the queue when it ends inner.tracks.push_back(handle.clone());
track
.events
.as_mut()
.expect("Why is this even an Option?")
.add_event(
EventData::new(
Event::Track(TrackEvent::End),
QueueHandler {
remote_lock: self.inner.clone(),
},
),
position,
);
inner.tracks.push(handle.clone());
handler.play(track); handler.play(track);
handle handle
} }
@ -152,8 +155,9 @@ impl Queue {
let mut inner = self.inner.lock(); let mut inner = self.inner.lock();
let (mut track, handle) = tracks::create_player(source); let (mut track, handle) = tracks::create_player(source);
track.pause(); track.pause();
QueueHandler::register_track_end_event(&mut track, self.inner.clone());
if inner.tracks.is_empty() { if inner.tracks.is_empty() {
inner.tracks.push(handle.clone()); inner.tracks.push_back(handle.clone());
} else { } else {
inner.tracks.insert(1, handle.clone()); inner.tracks.insert(1, handle.clone());
} }