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::rc::Rc; use std::sync::{Arc, Mutex, MutexGuard}; use super::prelude::*; pub struct Song { pub name: String, } pub struct MediaData { playlist: Mutex>>, current_song: Mutex>>, song_name: Mutex>, pub next_callback: RefCell ()>>>, } 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 name = self.name_mut(); *name.borrow_mut() = String::new(); } { *self.next_callback.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(); } manager.remove(guild_id); } Ok(()) } pub fn song_mut(&self) -> MutexGuard>> { self.current_song.lock().unwrap() } pub fn playlist_mut(&self) -> MutexGuard>> { self.playlist.lock().unwrap() } pub fn name_mut(&self) -> MutexGuard> { self.song_name.lock().unwrap() } pub fn start_playing( mediadata: &Arc, callback: Rc ()>, channel_id: ChannelId, manager_lock: &Arc< serenity::prelude::Mutex, >, ) { // check if there is already playing let already_started = { let song_lock = mediadata.song_mut(); let song = song_lock.borrow(); song.is_some() }; // if there isnt already a song playing, start a new one if !already_started { *mediadata.next_callback.borrow_mut() = Some(callback.clone()); Self::next_song(mediadata, channel_id, manager_lock, callback); } } pub fn next_song( mediadata: &Arc, channel_id: ChannelId, manager_lock: &Arc< serenity::prelude::Mutex, >, callback: Rc ()>, ) { let mut manager = manager_lock.lock(); let guild_id = match guild_id(channel_id) { Some(id) => id, None => { println!("error getting guild_id"); return; } }; let mut need_to_leave = false; { let handler = { match handler(guild_id, &mut manager) { Some(handler) => handler, None => { println!("error getting handler"); return; } } }; let playlist_lock = mediadata.playlist_mut(); let mut playlist = playlist_lock.borrow_mut(); let song_name_lock = mediadata.name_mut(); let mut name = song_name_lock.borrow_mut(); let song_lock = mediadata.song_mut(); let mut song = song_lock.borrow_mut(); if playlist.is_empty() { need_to_leave = true; handler.stop(); *song = None; *name = String::new(); *mediadata.next_callback.borrow_mut() = None; } else { handler.stop(); let first = playlist.remove(0); let source = match ffmpeg(first.name.clone()) { Ok(mpeg) => mpeg, Err(_) => { playlist.clear(); return; } }; *song = Some(handler.play_returning_and_callback(source, callback)); *name = first.name.clone(); print_error!(channel_id.say(format!("Playing song: {}", first.name))); } } if need_to_leave { manager.remove(guild_id); } } } impl Default for MediaData { fn default() -> MediaData { MediaData { playlist: Mutex::new(RefCell::new(Vec::new())), current_song: Mutex::new(RefCell::new(None)), song_name: Mutex::new(RefCell::new(String::new())), next_callback: RefCell::new(None), } } } unsafe impl Send for MediaData {} unsafe impl Sync for MediaData {}