diff options
Diffstat (limited to 'src/commands/playback/types.rs')
| -rw-r--r-- | src/commands/playback/types.rs | 271 |
1 files changed, 0 insertions, 271 deletions
diff --git a/src/commands/playback/types.rs b/src/commands/playback/types.rs deleted file mode 100644 index e4bbd26..0000000 --- a/src/commands/playback/types.rs +++ /dev/null @@ -1,271 +0,0 @@ -use std::{ - collections::VecDeque, - sync::{Arc, RwLock}, - thread, - time::Duration, - io::{ - Read, - Result as IoResult, - }, - process::{ - Command, - Stdio, - Child, - } -}; - -use chrono::Duration as CDuration; -use either::{Either, Left, Right}; -use serenity::{ - client::bridge::voice::ClientVoiceManager, - model::id::ChannelId, - prelude::*, - voice::{ - LockedAudio, - AudioSource, - pcm, - }, -}; -use typemap::Key; -use serde_json::Value; - -use crate::{ - commands::{ - send, - sound::DEFAULT_VOLUME - }, - must_env_lookup, - TARGET_GUILD_ID, - Result, -}; - -pub struct VoiceManager; - -impl Key for VoiceManager { - type Value = Arc<Mutex<ClientVoiceManager>>; -} - -impl VoiceManager { - pub fn register(c: &mut Client) { - let mut data = c.data.lock(); - data.insert::<VoiceManager>(Arc::clone(&c.voice_manager)); - } -} - -#[derive(Clone, Debug)] -pub struct PlayArgs { - pub data: Either<String, Vec<u8>>, - pub initiator: String, - pub sender_channel: ChannelId, - pub start: Option<CDuration>, - pub end: Option<CDuration>, -} - -#[derive(Clone)] -pub struct CurrentItem { - pub init_args: PlayArgs, - pub audio: LockedAudio, -} - -#[derive(Clone)] -pub struct PlayQueue { - pub queue: VecDeque<PlayArgs>, - pub playing: Option<CurrentItem>, - pub volume: f32, -} - -impl Key for PlayQueue { - type Value = Arc<RwLock<PlayQueue>>; -} - -impl PlayQueue { - pub fn new() -> Self { - PlayQueue { - queue: VecDeque::new(), - playing: None, - volume: DEFAULT_VOLUME, - } - } - - pub fn register(c: &mut Client) { - let voice_manager = Arc::clone(&c.voice_manager); - - let mut data = c.data.lock(); - let queue = Arc::new(RwLock::new(PlayQueue::new())); - - data.insert::<PlayQueue>(Arc::clone(&queue)); - - thread::spawn(move || { - let queue_lck = Arc::clone(&queue); - let voice_manager = voice_manager; - - loop { - thread::sleep(Duration::from_millis(250)); - let (queue_is_empty, queue_has_playing) = { - let queue = queue_lck.read().unwrap(); - - let allow_continue = queue.playing.clone().map_or(false, |x| !x.audio.lock().finished); - - if allow_continue { - continue; - } - - (queue.queue.is_empty(), queue.playing.is_some()) - }; - - if queue_is_empty { - if queue_has_playing { - let mut queue = queue_lck.write().unwrap(); - - assert!({ - let audio_lck = queue.playing.clone().unwrap().audio; - let audio = audio_lck.lock(); - audio.finished - }); - - queue.playing = None; - - let mut manager = voice_manager.lock(); - manager.leave(*TARGET_GUILD_ID); - debug!("disconnected because playback finished"); - } - continue; - } - - let mut queue = queue_lck.write().unwrap(); - let item = queue.queue.pop_front().unwrap(); - - let src = match item.data { - Left(ref url) => { - match ytdl(url, item.start, item.end) { - Ok(src) => src, - Err(e) => { - error!("bad link: {}; {:?}", url, e); - let _ = send(item.sender_channel, "what the fuck", false); - continue; - } - } - }, - Right(ref vec) => { - ::serenity::voice::opus(true, ::std::io::Cursor::new(vec.clone())) - } - }; - - - let mut manager = voice_manager.lock(); - let handler = manager.join(*TARGET_GUILD_ID, must_env_lookup::<u64>("VOICE_CHANNEL")); - - match handler { - Some(handler) => { - let audio = handler.play_only(src); - { - audio.lock().volume(queue.volume); - } - - queue.playing = Some(CurrentItem { - init_args: item, - audio, - }); - - debug!("playing new song"); - }, - None => { - error!("couldn't join channel"); - let _ = send(item.sender_channel, "something happened somewhere somehow.", false); - } - } - } - }); - } -} - -// Copied from serenity -struct ChildContainer(Child); - -impl Read for ChildContainer { - fn read(&mut self, buffer: &mut [u8]) -> IoResult<usize> { - self.0.stdout.as_mut().unwrap().read(buffer) - } -} - -impl Drop for ChildContainer { - fn drop (&mut self) { - if let Err(e) = self.0.kill() { - debug!("[Voice] Error awaiting child process: {:?}", e); - } - } -} - -pub fn ytdl(uri: &str, start: Option<CDuration>, end: Option<CDuration>) -> Result<Box<AudioSource>> { - let args = [ - "-f", - "webm[abr>0]/bestaudio/best", - "--no-playlist", - "--print-json", - "--skip-download", - uri, - ]; - - let out = Command::new("youtube-dl") - .args(&args) - .stdin(Stdio::null()) - .output()?; - - if !out.status.success() { - return Err(VoiceError::YouTubeDLRun(out).into()); - } - - let value = serde_json::from_reader(&out.stdout[..])?; - let mut obj = match value { - Value::Object(obj) => obj, - other => return Err(VoiceError::YouTubeDLProcessing(other).into()), - }; - - let uri = match obj.remove("url") { - Some(v) => match v { - Value::String(uri) => uri, - other => return Err(VoiceError::YouTubeDLUrl(other).into()), - }, - None => return Err(VoiceError::YouTubeDLUrl(Value::Object(obj)).into()), - }; - - let start = start.unwrap_or(CDuration::zero()); - let start_str = format!("{:02}:{:02}:{:02}", start.num_hours(), start.num_minutes() % 60, start.num_seconds() % 60); - - let mut opts = vec! [ - "-f", - "s16le", - "-ac", - "2", // force stereo -- this may cause issues - "-ar", - "48000", - "-acodec", - "pcm_s16le", - "-ss", - &start_str, - ] - .into_iter() - .map(|s| s.to_owned()) - .collect::<Vec<_>>(); - - match end { - Some(e) => { - opts.push("-to".to_owned()); - opts.push(format!("{:02}:{:02}:{:02}", e.num_hours(), e.num_minutes() % 60, e.num_seconds() % 60)); - }, - _ => {}, - } - - opts.push("-".to_owned()); - - let command = Command::new("ffmpeg") - .arg("-i") - .arg(uri) - .args(opts) - .stderr(Stdio::null()) - .stdin(Stdio::null()) - .stdout(Stdio::piped()) - .spawn()?; - - Ok(pcm(true, ChildContainer(command))) -} |
