RMusicBot/src/player/mediadata.rs

209 lines
6.1 KiB
Rust
Raw Normal View History

2018-11-14 14:29:58 +00:00
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 {}