2018-11-14 14:29:58 +00:00
|
|
|
use serenity;
|
|
|
|
use serenity::model::id::ChannelId;
|
2018-11-14 15:43:53 +00:00
|
|
|
use serenity::voice::ffmpeg;
|
2018-11-14 14:29:58 +00:00
|
|
|
use serenity::voice::{AudioSource, 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<RefCell<Vec<Song>>>,
|
|
|
|
current_song: Mutex<RefCell<Option<LockedAudio>>>,
|
|
|
|
watcher_thread: Mutex<RefCell<Option<JoinHandle<()>>>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
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::<VoiceManager>().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<RefCell<Option<LockedAudio>>> {
|
|
|
|
self.current_song.lock().unwrap()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn playlist_mut(&self) -> MutexGuard<RefCell<Vec<Song>>> {
|
|
|
|
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<MediaData>,
|
|
|
|
channel_id: ChannelId,
|
|
|
|
manager_lock: &Arc<
|
|
|
|
serenity::prelude::Mutex<serenity::client::bridge::voice::ClientVoiceManager>,
|
|
|
|
>,
|
|
|
|
) {
|
|
|
|
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();
|
|
|
|
|
2018-11-14 15:43:53 +00:00
|
|
|
// if there is currently something playing
|
2018-11-14 14:29:58 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2018-11-14 15:43:53 +00:00
|
|
|
// nothing is playing
|
2018-11-14 14:29:58 +00:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
|
2018-11-14 15:43:53 +00:00
|
|
|
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));
|
2018-11-14 14:29:58 +00:00
|
|
|
|
|
|
|
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<Song>,
|
|
|
|
channel_id: ChannelId,
|
|
|
|
manager_lock: &Arc<
|
|
|
|
serenity::prelude::Mutex<serenity::client::bridge::voice::ClientVoiceManager>,
|
|
|
|
>,
|
|
|
|
) -> 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();
|
2018-11-14 15:43:53 +00:00
|
|
|
|
|
|
|
let source = match ffmpeg(first.name.clone()) {
|
|
|
|
Ok(mpeg) => mpeg,
|
|
|
|
Err(_) => {
|
|
|
|
playlist.clear();
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
*song = handler.play_returning(source);
|
2018-11-14 14:29:58 +00:00
|
|
|
|
|
|
|
print_error!(channel_id.say(format!("Playing song: {}", first.name)));
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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 {}
|