209 lines
6.1 KiB
Rust
209 lines
6.1 KiB
Rust
|
use serenity;
|
||
|
use serenity::model::id::ChannelId;
|
||
|
use serenity::voice::{AudioSource, LockedAudio};
|
||
|
|
||
|
use std::cell::RefCell;
|
||
|
use std::ops::DerefMut;
|
||
|
use std::sync::{Arc, Mutex, MutexGuard};
|
||
|
use std::thread;
|
||
|
use std::thread::JoinHandle;
|
||
|
use std::time;
|
||
|
|
||
|
use super::prelude::*;
|
||
|
|
||
|
pub struct Song {
|
||
|
pub source: Box<AudioSource>,
|
||
|
pub name: String,
|
||
|
}
|
||
|
|
||
|
pub struct MediaData {
|
||
|
playlist: Mutex<RefCell<Vec<Song>>>,
|
||
|
current_song: Mutex<RefCell<Option<LockedAudio>>>,
|
||
|
watcher_thread: Mutex<RefCell<Option<JoinHandle<()>>>>,
|
||
|
}
|
||
|
|
||
|
impl MediaData {
|
||
|
pub fn reset(
|
||
|
&self,
|
||
|
ctx: &mut serenity::client::Context,
|
||
|
msg: &serenity::model::channel::Message,
|
||
|
) -> Result<(), String> {
|
||
|
{
|
||
|
let playlist = self.playlist_mut();
|
||
|
playlist.borrow_mut().clear();
|
||
|
}
|
||
|
|
||
|
{
|
||
|
let song = self.song_mut();
|
||
|
*song.borrow_mut() = None;
|
||
|
}
|
||
|
|
||
|
{
|
||
|
let manager_lock = ctx.data.lock().get::<VoiceManager>().cloned().unwrap();
|
||
|
|
||
|
let mut manager = manager_lock.lock();
|
||
|
let guild_id = match guild_id(msg.channel_id) {
|
||
|
Some(guild_id) => guild_id,
|
||
|
None => return Ok(()),
|
||
|
};
|
||
|
|
||
|
let handler = match handler(guild_id, &mut manager) {
|
||
|
Some(handler) => handler,
|
||
|
None => return Ok(()),
|
||
|
};
|
||
|
|
||
|
println!("stopped handler");
|
||
|
|
||
|
handler.stop();
|
||
|
}
|
||
|
|
||
|
Ok(())
|
||
|
}
|
||
|
|
||
|
pub fn song_mut(&self) -> MutexGuard<RefCell<Option<LockedAudio>>> {
|
||
|
self.current_song.lock().unwrap()
|
||
|
}
|
||
|
|
||
|
pub fn playlist_mut(&self) -> MutexGuard<RefCell<Vec<Song>>> {
|
||
|
self.playlist.lock().unwrap()
|
||
|
}
|
||
|
|
||
|
pub fn reset_thread(&self) {
|
||
|
let thread_mutex = self.watcher_thread.lock().unwrap();
|
||
|
*thread_mutex.borrow_mut() = None;
|
||
|
}
|
||
|
|
||
|
pub fn start_thread(
|
||
|
media: &Arc<MediaData>,
|
||
|
channel_id: ChannelId,
|
||
|
manager_lock: &Arc<
|
||
|
serenity::prelude::Mutex<serenity::client::bridge::voice::ClientVoiceManager>,
|
||
|
>,
|
||
|
) {
|
||
|
let media_clone = media.clone();
|
||
|
let manager_clone = manager_lock.clone();
|
||
|
|
||
|
let thread_mutex = media.watcher_thread.lock().unwrap();
|
||
|
let mut watcher_mut = thread_mutex.borrow_mut();
|
||
|
|
||
|
if watcher_mut.is_none() {
|
||
|
*watcher_mut = Some(thread::spawn(move || loop {
|
||
|
{
|
||
|
let song_lock = media_clone.song_mut();
|
||
|
let mut borrow = song_lock.borrow_mut();
|
||
|
|
||
|
if let Some(ref mut song) = borrow.deref_mut() {
|
||
|
let song_lock = song.clone();
|
||
|
let audio = song_lock.lock();
|
||
|
|
||
|
if audio.finished {
|
||
|
let playlist = media_clone.playlist_mut();
|
||
|
|
||
|
if !Self::next_song(
|
||
|
song,
|
||
|
playlist.borrow_mut().deref_mut(),
|
||
|
channel_id,
|
||
|
&manager_clone,
|
||
|
) {
|
||
|
manager_clone
|
||
|
.lock()
|
||
|
.remove(check_option!(guild_id(channel_id)));
|
||
|
|
||
|
media_clone.reset_thread();
|
||
|
|
||
|
println!("left channel");
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
{
|
||
|
let playlist_mutex = media_clone.playlist_mut();
|
||
|
let mut playlist = playlist_mutex.borrow_mut();
|
||
|
|
||
|
if !playlist.is_empty() {
|
||
|
let mut manager = manager_clone.lock();
|
||
|
|
||
|
if let Some(handler) =
|
||
|
handler(check_option!(guild_id(channel_id)), &mut manager)
|
||
|
{
|
||
|
let first = playlist.remove(0);
|
||
|
|
||
|
*borrow = Some(handler.play_returning(first.source));
|
||
|
|
||
|
print_error!(
|
||
|
channel_id.say(format!("Playing song: {}", first.name))
|
||
|
);
|
||
|
} else {
|
||
|
return;
|
||
|
}
|
||
|
} else {
|
||
|
manager_clone
|
||
|
.lock()
|
||
|
.remove(check_option!(guild_id(channel_id)));
|
||
|
|
||
|
media_clone.reset_thread();
|
||
|
|
||
|
println!("left channel");
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
let two_sec = time::Duration::from_secs(2);
|
||
|
thread::sleep(two_sec);
|
||
|
}));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fn next_song(
|
||
|
song: &mut LockedAudio,
|
||
|
playlist: &mut Vec<Song>,
|
||
|
channel_id: ChannelId,
|
||
|
manager_lock: &Arc<
|
||
|
serenity::prelude::Mutex<serenity::client::bridge::voice::ClientVoiceManager>,
|
||
|
>,
|
||
|
) -> bool {
|
||
|
let mut manager = manager_lock.lock();
|
||
|
|
||
|
let guild_id = match guild_id(channel_id) {
|
||
|
Some(id) => id,
|
||
|
None => return false,
|
||
|
};
|
||
|
|
||
|
if let Some(handler) = handler(guild_id, &mut manager) {
|
||
|
if playlist.is_empty() {
|
||
|
return false;
|
||
|
} else {
|
||
|
let first = playlist.remove(0);
|
||
|
|
||
|
handler.stop();
|
||
|
*song = handler.play_returning(first.source);
|
||
|
|
||
|
print_error!(channel_id.say(format!("Playing song: {}", first.name)));
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl Default for MediaData {
|
||
|
fn default() -> MediaData {
|
||
|
MediaData {
|
||
|
playlist: Mutex::new(RefCell::new(Vec::new())),
|
||
|
current_song: Mutex::new(RefCell::new(None)),
|
||
|
watcher_thread: Mutex::new(RefCell::new(None)),
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
unsafe impl Send for MediaData {}
|
||
|
unsafe impl Sync for MediaData {}
|