aboutsummaryrefslogtreecommitdiff
path: root/src/audio/play_queue.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/audio/play_queue.rs')
-rw-r--r--src/audio/play_queue.rs260
1 files changed, 0 insertions, 260 deletions
diff --git a/src/audio/play_queue.rs b/src/audio/play_queue.rs
deleted file mode 100644
index 34fc113..0000000
--- a/src/audio/play_queue.rs
+++ /dev/null
@@ -1,260 +0,0 @@
-use std::{
- collections::VecDeque,
- io::{self, BufRead, BufReader, Cursor, Read},
- process,
- sync::{Arc, RwLock},
- thread,
- time::Duration,
-};
-
-use either::{Left, Right};
-use log::{
- debug,
- error,
- trace,
-};
-use serenity::{
- CacheAndHttp,
- client::bridge::voice::ClientVoiceManager,
- prelude::*,
- voice,
-};
-use typemap::Key;
-
-use crate::{
- audio::{
- CurrentItem,
- PlayArgs,
- ytdl_url,
- },
- commands::{
- sound_levels::DEFAULT_VOLUME,
- },
- Result,
- CONFIG, FFMPEG_COMMAND,
-};
-
-const SECONDS_LEAD_TIME: f32 = 0.75;
-const SECONDS_TRAIL_TIME: f32 = 0.1;
-const SAMPLE_RATE: usize = 48000;
-const CHANNELS: usize = 2;
-const BYTES_PER_SAMPLE: usize = 2;
-const PRE_SILENCE_BYTES: usize = (SECONDS_LEAD_TIME * (SAMPLE_RATE * CHANNELS * BYTES_PER_SAMPLE) as f32) as usize;
-const POST_SILENCE_BYTES: usize = (SECONDS_TRAIL_TIME * (SAMPLE_RATE * CHANNELS * BYTES_PER_SAMPLE) as f32) as usize;
-
-#[derive(Clone)]
-pub struct PlayQueue {
- pub general_queue: VecDeque<PlayArgs>,
- pub meme_queue: VecDeque<PlayArgs>,
- pub playing: Option<CurrentItem>,
- pub volume: f32,
-}
-
-impl Key for PlayQueue {
- type Value = Arc<RwLock<PlayQueue>>;
-}
-
-impl serenity::prelude::TypeMapKey for PlayQueue {
- type Value = Arc<RwLock<PlayQueue>>;
-}
-
-impl PlayQueue {
- pub fn new() -> Self {
- PlayQueue {
- general_queue: VecDeque::new(),
- meme_queue: VecDeque::new(),
- playing: None,
- volume: DEFAULT_VOLUME,
- }
- }
-
- pub fn register(c: &mut Client) {
- let voice_manager = Arc::clone(&c.voice_manager);
-
- let queue = Arc::new(RwLock::new(PlayQueue::new()));
-
- {
- let mut data = c.data.write();
- data.insert::<PlayQueue>(Arc::clone(&queue));
- }
-
-
- let cache_http = c.cache_and_http.clone();
- thread::spawn(move || {
- loop {
- if let Err(e) = Self::update(&cache_http, &queue, &voice_manager) {
- error!("updating playqueue: {}", e);
- }
-
- thread::sleep(Duration::from_millis(250));
- }
- });
-
- }
-
- fn update(cache_http: &CacheAndHttp, queue_lck: &Arc<RwLock<Self>>, voice_manager: &Arc<Mutex<ClientVoiceManager>>) -> Result<()> {
- 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 {
- return Ok(());
- }
-
- (queue.general_queue.is_empty() && queue.meme_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(CONFIG.discord.guild());
- debug!("disconnected because playback finished");
- }
-
- return Ok(());
- }
-
- let mut queue = queue_lck.write().unwrap();
-
- let mut item = if !queue.meme_queue.is_empty() {
- queue.meme_queue.pop_front().unwrap()
- } else {
- queue.general_queue.pop_front().unwrap()
- };
-
- let src = match &mut item.data {
- Left(ref url) => {
- let youtube_url = ytdl_url(url.as_str())?;
-
- let duration_opts = if let Some(e) = item.end {
- vec! [
- "-ss".to_owned(), item.start.map_or_else(
- || "00:00:00".to_owned(),
- |s| format!("{:02}:{:02}:{:02}", s.num_hours(), s.num_minutes() % 60, s.num_seconds() % 60)
- ),
-
- "-to".to_owned(), format!("{:02}:{:02}:{:02}", e.num_hours(), e.num_minutes() % 60, e.num_seconds() % 60),
- ]
- } else {
- vec! []
- };
-
- let ffmpeg_command = process::Command::new(&*FFMPEG_COMMAND)
- .arg("-i")
- .arg(youtube_url)
- .args(duration_opts)
- .args(&[
- "-ac", "2",
- "-ar", "48000",
- "-f", "s16le",
- "-acodec", "pcm_s16le",
- "-",
- ])
- .stdout(process::Stdio::piped())
- .stderr(process::Stdio::null())
- .stdin(process::Stdio::null())
- .spawn()?;
-
- let audio_reader = ffmpeg_command.stdout.unwrap();
-
- let pre_silence = vec![0u8; PRE_SILENCE_BYTES];
- let post_silence = vec![0u8; POST_SILENCE_BYTES];
-
- let reader = Cursor::new(pre_silence).chain(audio_reader).chain(Cursor::new(post_silence));
-
- voice::pcm(true, reader)
- },
- Right(ref vec) => {
- let transcoder = process::Command::new(&*FFMPEG_COMMAND)
- .args(&[
- "-format", "opus",
- "-i", "pipe:0",
- "-acodec", "pcm_s16le",
- "-f", "s16le",
- "-"
- ])
- .stdin(process::Stdio::piped())
- .stdout(process::Stdio::piped())
- .stderr(process::Stdio::piped())
- .spawn()
- .expect("unable to call ffmpeg");
-
- let process::Child {
- stdin,
- stderr,
- stdout,
- ..
- } = transcoder;
-
- thread::spawn(move || {
- let stderr = BufReader::new(stderr.unwrap());
-
- for line in stderr.lines() {
- let line = line.unwrap();
-
- trace!("{}", line);
- }
- });
-
- let v = vec.clone();
- thread::spawn(move || {
- if let Err(e) = io::copy(&mut Cursor::new(v), &mut stdin.unwrap()) {
- use std::io::ErrorKind;
- if e.kind() == ErrorKind::BrokenPipe {
- debug!("ffmpeg closed unexpectedly");
- } else {
- error!("copying audio to ffmpeg {}", e);
- }
- }
- });
-
- let pre_silence = vec![0u8; PRE_SILENCE_BYTES];
- let post_silence = vec![0u8; POST_SILENCE_BYTES];
-
- let reader = Cursor::new(pre_silence)
- .chain(stdout.unwrap())
- .chain(Cursor::new(post_silence));
-
- voice::pcm(true, reader)
- }
- };
-
- let mut manager = voice_manager.lock();
- let handler = manager.join(CONFIG.discord.guild(), CONFIG.discord.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");
- item.sender_channel.say(&cache_http.http, "something happened somewhere somehow.")?;
- }
- }
-
- Ok(())
- }
-
-}
-