From c3af98298317266b2224495320efc23377dc63fc Mon Sep 17 00:00:00 2001 From: hodasemi Date: Sun, 15 Dec 2019 15:25:48 +0100 Subject: [PATCH] Start implementing controller thread for playlist --- src/main.rs | 37 ++++++++++++++++++++++++++++++----- src/player/commands/list.rs | 4 +++- src/player/commands/pause.rs | 4 +++- src/player/commands/play.rs | 10 ++++++---- src/player/commands/remove.rs | 6 ++++-- src/player/commands/skip.rs | 31 +++++++++-------------------- src/player/commands/stop.rs | 4 +++- src/player/mediadata.rs | 7 ++----- src/player/player.rs | 3 ++- 9 files changed, 64 insertions(+), 42 deletions(-) diff --git a/src/main.rs b/src/main.rs index 1e4a4c1..87a26bf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -26,7 +26,9 @@ use serenity::{ // This imports `typemap`'s `Key` as `TypeMapKey`. use serenity::prelude::*; -use std::sync::Arc; +use std::sync::{Arc, Mutex}; +use std::thread; +use std::time::Duration; use player::prelude::*; use std::collections::HashSet; @@ -103,15 +105,17 @@ fn main() -> VerboseResult<()> { let mut client = Client::new(&config.token, Handler).expect("Err creating client"); + let media_data = Arc::new(Mutex::new( + MediaData::new("Penis1", Arc::clone(&client.voice_manager), config.volume) + .expect("failed to create media data handle"), + )); + // Obtain a lock to the data owned by the client, and insert the client's // voice manager into it. This allows the voice manager to be accessible by // event handlers and framework commands. { let mut data = client.data.write(); - data.insert::( - MediaData::new("Penis1", Arc::clone(&client.voice_manager), config.volume) - .expect("failed to create media data handle"), - ); + data.insert::(media_data.clone()); } // We will fetch your bot's owners and id @@ -143,6 +147,29 @@ fn main() -> VerboseResult<()> { .help(&MY_HELP), ); + thread::spawn(move || loop { + { + let mut media_lock = media_data.lock().unwrap(); + + // check if there is a song currently being played + let mut is_playing = false; + + if let Some(song) = media_lock.song() { + let song_lock = song.lock(); + + if !song_lock.finished { + is_playing = true; + } + } + + if !is_playing { + MediaData::next_song(&mut media_lock).unwrap(); + } + } + + thread::sleep(Duration::from_millis(1500)); + }); + let _ = client .start() .map_err(|why| println!("Client ended: {:?}", why)); diff --git a/src/player/commands/list.rs b/src/player/commands/list.rs index 8a9e216..e8d355c 100644 --- a/src/player/commands/list.rs +++ b/src/player/commands/list.rs @@ -24,7 +24,9 @@ fn list(ctx: &mut Context, msg: &Message, _: Args) -> CommandResult { } }; - let playlist = media.playlist(); + let media_lock = media.lock().unwrap(); + + let playlist = media_lock.playlist(); output += &format!( "{} {} queued\n", diff --git a/src/player/commands/pause.rs b/src/player/commands/pause.rs index 2441f99..aff1044 100644 --- a/src/player/commands/pause.rs +++ b/src/player/commands/pause.rs @@ -24,7 +24,9 @@ fn pause(ctx: &mut Context, msg: &Message, _: Args) -> CommandResult { } }; - if let Some(song) = media.song() { + let media_lock = media.lock().unwrap(); + + if let Some(song) = media_lock.song() { let mut lock = song.lock(); lock.pause(); } diff --git a/src/player/commands/play.rs b/src/player/commands/play.rs index c1d0133..a9530c0 100644 --- a/src/player/commands/play.rs +++ b/src/player/commands/play.rs @@ -29,8 +29,10 @@ fn play(ctx: &mut Context, msg: &Message, mut args: Args) -> CommandResult { } }; + let mut media_lock = media.lock().unwrap(); + if args.len() == 0 { - if !check_for_continue(media.song_mut()) { + if !check_for_continue(media_lock.song_mut()) { msg.channel_id .say(&ctx.http, "Must provide a URL to a video or audio")?; } @@ -38,9 +40,9 @@ fn play(ctx: &mut Context, msg: &Message, mut args: Args) -> CommandResult { let first_arg = args.current().unwrap(); if first_arg == "--local" { - handle_local_request(media, ctx, msg)?; + handle_local_request(&mut media_lock, ctx, msg)?; } else if first_arg.starts_with("http") { - handle_http_request(media, ctx, msg, first_arg)?; + handle_http_request(&mut media_lock, ctx, msg, first_arg)?; } else { let mut arg_list = args.single::()?; @@ -48,7 +50,7 @@ fn play(ctx: &mut Context, msg: &Message, mut args: Args) -> CommandResult { arg_list += &format!(" {}", arg?.trim()); } - handle_song_request(media, ctx, msg, &arg_list)? + handle_song_request(&mut media_lock, ctx, msg, &arg_list)? } } diff --git a/src/player/commands/remove.rs b/src/player/commands/remove.rs index 5658532..43372db 100644 --- a/src/player/commands/remove.rs +++ b/src/player/commands/remove.rs @@ -23,8 +23,10 @@ fn remove(ctx: &mut Context, msg: &Message, _: Args) -> CommandResult { } }; - let song_name = media.song_name(); - let sql = media.db(); + let media_lock = media.lock().unwrap(); + + let song_name = media_lock.song_name(); + let sql = media_lock.db(); if let Err(_) = sql.execute("DELETE FROM Vulva3 WHERE name = ?", params![song_name]) { return Err(serenity::framework::standard::CommandError( diff --git a/src/player/commands/skip.rs b/src/player/commands/skip.rs index de5769d..ae12cdf 100644 --- a/src/player/commands/skip.rs +++ b/src/player/commands/skip.rs @@ -19,21 +19,23 @@ fn skip(ctx: &mut Context, msg: &Message, _: Args) -> CommandResult { let mut data = ctx.data.write(); if let Some(media) = data.get_mut::() { - let voice_manager = media.voice_manager.clone(); + let mut media_lock = media.lock().unwrap(); + + let voice_manager = media_lock.voice_manager.clone(); let mut manager = voice_manager.lock(); let guild_id = guild_id(ctx, msg)?; if let Some(handler) = handler(guild_id, &mut manager) { // if current song is the last song in this playlist, just return - if media.playlist().is_empty() { + if media_lock.playlist().is_empty() { msg.channel_id .say(&ctx.http, "playlist is empty, no next song available")?; return Ok(()); } else { // remove the current song from the playlist - let first = media.playlist_mut().remove(0); + let first = media_lock.playlist_mut().remove(0); // stop the current song from playing handler.stop(); @@ -42,30 +44,15 @@ fn skip(ctx: &mut Context, msg: &Message, _: Args) -> CommandResult { let source = match ffmpeg(first.name.clone()) { Ok(mpeg) => mpeg, Err(_) => { - media.playlist_mut().clear(); - *media.song_mut() = None; + media_lock.playlist_mut().clear(); + *media_lock.song_mut() = None; return Ok(()); } }; - // start the next song if possible - /* - match self.media.next_callback.borrow().as_ref() { - Some(callback) => { - *song = Some(handler.play_returning_and_callback(source, callback.clone())); - let song_name = self.media.name_mut()?; - *song_name.borrow_mut() = first.name.clone(); - - print_error!(msg - .channel_id - .say(format!("Skipped current song, now playing: {}", first.name))); - } - None => println!("error getting callback from media"), - } - */ - *media.song_mut() = Some(handler.play_returning(source)); - *media.song_name_mut() = first.name.clone(); + *media_lock.song_mut() = Some(handler.play_returning(source)); + *media_lock.song_name_mut() = first.name.clone(); msg.channel_id.say( &ctx.http, diff --git a/src/player/commands/stop.rs b/src/player/commands/stop.rs index 9ecb3ae..95d6914 100644 --- a/src/player/commands/stop.rs +++ b/src/player/commands/stop.rs @@ -22,7 +22,9 @@ fn stop(ctx: &mut Context, msg: &Message, _: Args) -> CommandResult { } }; - media.reset(ctx, msg)?; + let mut media_lock = media.lock().unwrap(); + + media_lock.reset(ctx, msg)?; Ok(()) } diff --git a/src/player/mediadata.rs b/src/player/mediadata.rs index 19790c8..92195ac 100644 --- a/src/player/mediadata.rs +++ b/src/player/mediadata.rs @@ -7,7 +7,7 @@ use serenity::voice::LockedAudio; use parking_lot::lock_api::{MutexGuard, RawMutex}; use serenity::client::bridge::voice::ClientVoiceManager; use serenity::prelude::Mutex; -use std::sync::Arc; +use std::sync::{Arc, Mutex as StdMutex}; use super::prelude::*; @@ -27,7 +27,6 @@ pub struct MediaData { playlist: Vec, current_song: Option, song_name: String, - pub next_callback: Option ()>>, sql_data_base: Connection, @@ -64,7 +63,6 @@ impl MediaData { playlist: Vec::new(), current_song: None, song_name: String::new(), - next_callback: None, sql_data_base: connection, @@ -80,7 +78,6 @@ impl MediaData { self.playlist.clear(); self.current_song = None; self.song_name = String::new(); - self.next_callback = None; let mut manager = self.voice_manager.lock(); @@ -293,5 +290,5 @@ unsafe impl Sync for MediaData {} pub struct Media; impl TypeMapKey for Media { - type Value = MediaData; + type Value = Arc>; } diff --git a/src/player/player.rs b/src/player/player.rs index f79172f..5ca0e72 100644 --- a/src/player/player.rs +++ b/src/player/player.rs @@ -62,7 +62,8 @@ pub fn channel_contains_author( }; if let Some(media) = ctx.data.read().get::() { - let manager = media.voice_manager.lock(); + let media_lock = media.lock().unwrap(); + let manager = media_lock.voice_manager.lock(); if let Some(handler) = manager.get(guild_id) { // check if the bot is in a channel