Make use of callback serenity

This commit is contained in:
hodasemi 2018-11-23 22:06:35 +01:00
parent de1beb11e7
commit 1fcd593f4d
3 changed files with 95 additions and 128 deletions

View file

@ -5,7 +5,8 @@ use serenity::voice::LockedAudio;
use std::cell::RefCell; use std::cell::RefCell;
use std::fs; use std::fs;
use std::ops::DerefMut; use std::ops::{Deref, DerefMut};
use std::rc::Rc;
use std::sync::{Arc, MutexGuard}; use std::sync::{Arc, MutexGuard};
use rand::{seq::SliceRandom, thread_rng}; use rand::{seq::SliceRandom, thread_rng};
@ -84,7 +85,27 @@ impl Play {
Self::check_join_channel(&manager_lock, msg); Self::check_join_channel(&manager_lock, msg);
MediaData::start_thread(&self.media, msg.channel_id, &manager_lock); let check_finished = {
let media_clone = self.media.clone();
let channel_id = msg.channel_id;
let manager_lock_clone = manager_lock.clone();
Rc::new(move || {
let callback = match media_clone.next_callback.borrow().deref() {
Some(callback) => callback.clone(),
None => {
println!("next_callback not set!");
return;
}
};
MediaData::next_song(&media_clone, channel_id, &manager_lock_clone, callback);
})
};
MediaData::start_playing(&self.media, check_finished, msg.channel_id, &manager_lock);
//MediaData::start_thread(&self.media, msg.channel_id, &manager_lock);
} }
fn handle_http_request( fn handle_http_request(

View file

@ -5,10 +5,8 @@ use serenity::voice::LockedAudio;
use std::cell::RefCell; use std::cell::RefCell;
use std::ops::DerefMut; use std::ops::DerefMut;
use std::rc::Rc;
use std::sync::{Arc, Mutex, MutexGuard}; use std::sync::{Arc, Mutex, MutexGuard};
use std::thread;
use std::thread::JoinHandle;
use std::time;
use super::prelude::*; use super::prelude::*;
@ -20,7 +18,7 @@ pub struct MediaData {
playlist: Mutex<RefCell<Vec<Song>>>, playlist: Mutex<RefCell<Vec<Song>>>,
current_song: Mutex<RefCell<Option<LockedAudio>>>, current_song: Mutex<RefCell<Option<LockedAudio>>>,
song_name: Mutex<RefCell<String>>, song_name: Mutex<RefCell<String>>,
watcher_thread: Mutex<RefCell<Option<JoinHandle<()>>>>, pub next_callback: RefCell<Option<Rc<Fn() -> ()>>>,
} }
impl MediaData { impl MediaData {
@ -45,22 +43,30 @@ impl MediaData {
} }
{ {
let manager_lock = ctx.data.lock().get::<VoiceManager>().cloned().unwrap(); *self.next_callback.borrow_mut() = None;
}
{
let manager_lock = ctx.data.lock().get::<VoiceManager>().cloned().unwrap();
let mut manager = manager_lock.lock(); let mut manager = manager_lock.lock();
let guild_id = match guild_id(msg.channel_id) { let guild_id = match guild_id(msg.channel_id) {
Some(guild_id) => guild_id, Some(guild_id) => guild_id,
None => return Ok(()), None => return Ok(()),
}; };
let handler = match handler(guild_id, &mut manager) { {
Some(handler) => handler, let handler = match handler(guild_id, &mut manager) {
None => return Ok(()), Some(handler) => handler,
}; None => return Ok(()),
};
println!("stopped handler"); println!("stopped handler");
handler.stop(); handler.stop();
}
manager.remove(guild_id);
} }
Ok(()) Ok(())
@ -78,135 +84,75 @@ impl MediaData {
self.song_name.lock().unwrap() self.song_name.lock().unwrap()
} }
pub fn reset_thread(&self) { pub fn start_playing(
let thread_mutex = self.watcher_thread.lock().unwrap(); mediadata: &Arc<MediaData>,
*thread_mutex.borrow_mut() = None; callback: Rc<Fn() -> ()>,
}
pub fn start_thread(
media: &Arc<MediaData>,
channel_id: ChannelId, channel_id: ChannelId,
manager_lock: &Arc< manager_lock: &Arc<
serenity::prelude::Mutex<serenity::client::bridge::voice::ClientVoiceManager>, serenity::prelude::Mutex<serenity::client::bridge::voice::ClientVoiceManager>,
>, >,
) { ) {
let media_clone = media.clone(); // check if there is already playing
let manager_clone = manager_lock.clone(); let already_started = {
let song_lock = mediadata.song_mut();
let song = song_lock.borrow();
song.is_some()
};
let thread_mutex = media.watcher_thread.lock().unwrap(); // if there isnt already a song playing, start a new one
let mut watcher_mut = thread_mutex.borrow_mut(); if !already_started {
*mediadata.next_callback.borrow_mut() = Some(callback.clone());
if watcher_mut.is_none() { Self::next_song(mediadata, channel_id, manager_lock, callback);
*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();
let song_name = media_clone.name_mut();
if !Self::next_song(
song,
song_name.borrow_mut().deref_mut(),
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));
let song_name = media_clone.name_mut();
*song_name.borrow_mut() = first.name.clone();
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( pub fn next_song(
song: &mut LockedAudio, mediadata: &Arc<MediaData>,
name: &mut String,
playlist: &mut Vec<Song>,
channel_id: ChannelId, channel_id: ChannelId,
manager_lock: &Arc< manager_lock: &Arc<
serenity::prelude::Mutex<serenity::client::bridge::voice::ClientVoiceManager>, serenity::prelude::Mutex<serenity::client::bridge::voice::ClientVoiceManager>,
>, >,
) -> bool { callback: Rc<Fn() -> ()>,
) {
let mut manager = manager_lock.lock(); let mut manager = manager_lock.lock();
let guild_id = match guild_id(channel_id) { let guild_id = match guild_id(channel_id) {
Some(id) => id, Some(id) => id,
None => return false, None => {
println!("error getting guild_id");
return;
}
}; };
if let Some(handler) = handler(guild_id, &mut manager) { 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() { if playlist.is_empty() {
return false; need_to_leave = true;
handler.stop();
*song = None;
*name = String::new();
*mediadata.next_callback.borrow_mut() = None;
} else { } else {
handler.stop(); handler.stop();
@ -217,20 +163,20 @@ impl MediaData {
Err(_) => { Err(_) => {
playlist.clear(); playlist.clear();
return false; return;
} }
}; };
*song = handler.play_returning(source); *song = Some(handler.play_returning_and_callback(source, callback));
*name = first.name.clone(); *name = first.name.clone();
print_error!(channel_id.say(format!("Playing song: {}", first.name))); print_error!(channel_id.say(format!("Playing song: {}", first.name)));
return true;
} }
} }
return false; if need_to_leave {
manager.remove(guild_id);
}
} }
} }
@ -240,7 +186,7 @@ impl Default for MediaData {
playlist: Mutex::new(RefCell::new(Vec::new())), playlist: Mutex::new(RefCell::new(Vec::new())),
current_song: Mutex::new(RefCell::new(None)), current_song: Mutex::new(RefCell::new(None)),
song_name: Mutex::new(RefCell::new(String::new())), song_name: Mutex::new(RefCell::new(String::new())),
watcher_thread: Mutex::new(RefCell::new(None)), next_callback: RefCell::new(None),
} }
} }
} }

View file

@ -57,7 +57,7 @@ pub fn channel_contains_author(
Some(id) => id, Some(id) => id,
None => { None => {
println!("error getting channel_id for bot"); println!("error getting channel_id for bot");
return false; return true;
} }
}, },
) )