use serenity; use serenity::model::id::ChannelId; use serenity::voice::ffmpeg; use serenity::voice::LockedAudio; use std::cell::RefCell; use std::sync::{Arc, Mutex, MutexGuard}; use super::prelude::*; use rusqlite::{params, Connection}; pub struct Song { pub name: String, } pub struct MediaData { playlist: Mutex>>, current_song: Mutex>>, song_name: Mutex>, pub next_callback: RefCell ()>>>, sql_data_base: Mutex, } impl MediaData { pub fn new(file: &str) -> Result { let connection = match Connection::open(file) { Ok(file) => file, Err(_) => return Err(format!("can't open {}", file)), }; match connection.execute( "CREATE TABLE IF NOT EXISTS Vulva3 ( name TEXT PRIMARY KEY, link TEXT NOT NULL )", params![], ) { Ok(_) => (), Err(err) => { println!("{}", err); return Err(format!("can't create table")); } }; Ok(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), sql_data_base: Mutex::new(connection), }) } 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; } if let Some(manager_lock) = ctx.data.lock().get::().cloned() { 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 lock_db(&self) -> Result, String> { match self.sql_data_base.lock() { Ok(sql) => Ok(sql), Err(_) => Err("failed locking db".to_string()), } } pub fn song_mut(&self) -> Result>>, String> { match self.current_song.lock() { Ok(sql) => Ok(sql), Err(_) => Err("failed locking current song".to_string()), } } pub fn playlist_mut(&self) -> Result>>, String> { match self.playlist.lock() { Ok(sql) => Ok(sql), Err(_) => Err("failed locking playlist".to_string()), } } pub fn name_mut(&self) -> Result>, String> { match self.song_name.lock() { Ok(sql) => Ok(sql), Err(_) => Err("failed locking current song name".to_string()), } } pub fn start_playing( mediadata: &Arc, callback: Arc ()>, channel_id: ChannelId, manager_lock: &Arc< serenity::prelude::Mutex, >, ) { // check if there is already playing let already_started = { let song_lock = match mediadata.song_mut() { Ok(song) => song, Err(msg) => { println!("{}", msg); return; } }; 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: Arc ()>, ) { 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 = match mediadata.playlist_mut() { Ok(playlist) => playlist, Err(msg) => { println!("{}", msg); return; } }; let mut playlist = playlist_lock.borrow_mut(); let song_name_lock = match mediadata.name_mut() { Ok(name) => name, Err(msg) => { println!("{}", msg); return; } }; let mut name = song_name_lock.borrow_mut(); let song_lock = match mediadata.song_mut() { Ok(song) => song, Err(msg) => { println!("{}", msg); return; } }; let mut song = song_lock.borrow_mut(); if playlist.is_empty() { need_to_leave = true; handler.stop(); *song = None; *name = String::new(); } 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); } } } unsafe impl Send for MediaData {} unsafe impl Sync for MediaData {}