Make sure to add track event handler
This commit is contained in:
parent
2fd2079330
commit
825e15202e
1 changed files with 37 additions and 33 deletions
70
src/queue.rs
70
src/queue.rs
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue