use serenity; use serenity::model::id::ChannelId; use serenity::voice::ffmpeg; use serenity::voice::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 name: String, } pub struct MediaData { playlist: Mutex>>, current_song: Mutex>>, watcher_thread: Mutex>>>, } 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::().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>> { self.current_song.lock().unwrap() } pub fn playlist_mut(&self) -> MutexGuard>> { 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, channel_id: ChannelId, manager_lock: &Arc< serenity::prelude::Mutex, >, ) { 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 there is currently something playing 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; } // nothing is playing { 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); let source = match ffmpeg(first.name.clone()) { Ok(mpeg) => mpeg, Err(_) => { playlist.clear(); *borrow = None; handler.stop(); media_clone.reset_thread(); return; } }; *borrow = Some(handler.play_returning(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, channel_id: ChannelId, manager_lock: &Arc< serenity::prelude::Mutex, >, ) -> 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(); let source = match ffmpeg(first.name.clone()) { Ok(mpeg) => mpeg, Err(_) => { playlist.clear(); return false; } }; *song = handler.play_returning(source); print_error!(channel_id.say(format!("Playing song: {}", first.name))); return true; } } return false; } fn set_song() {} } 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 {}