diff options
Diffstat (limited to 'src/playback.rs')
| -rw-r--r-- | src/playback.rs | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/src/playback.rs b/src/playback.rs new file mode 100644 index 0000000..05196dd --- /dev/null +++ b/src/playback.rs @@ -0,0 +1,183 @@ +use crate::errors::*; +use crate::structs::*; +use crate::utils::*; + +use std::fs::{DirBuilder, File}; +use std::io::{self, BufReader, Read, Write}; +use std::process::Command; + +use regex::Regex; +use rss::Channel; +use std::path::PathBuf; + +fn launch_player(url: &str) -> Result<()> { + if launch_mpv(url).is_err() { + return launch_vlc(url); + } + Ok(()) +} + +fn launch_mpv(url: &str) -> Result<()> { + if let Err(err) = Command::new("mpv") + .args(&["--audio-display=no", "--ytdl=no", url]) + .status() + { + let stderr = io::stderr(); + let mut handle = stderr.lock(); + match err.kind() { + io::ErrorKind::NotFound => { + writeln!(&mut handle, "Couldn't open mpv\nTrying vlc...").ok() + } + _ => writeln!(&mut handle, "Error: {}", err).ok(), + }; + } + Ok(()) +} + +fn launch_vlc(url: &str) -> Result<()> { + if let Err(err) = Command::new("vlc").args(&["-I ncurses", url]).status() { + let stderr = io::stderr(); + let mut handle = stderr.lock(); + match err.kind() { + io::ErrorKind::NotFound => writeln!(&mut handle, "Couldn't open vlc...aborting").ok(), + _ => writeln!(&mut handle, "Error: {}", err).ok(), + }; + } + Ok(()) +} + +pub fn play_latest(state: &State, p_search: &str) -> Result<()> { + let re_pod: Regex = Regex::new(&format!("(?i){}", &p_search))?; + let mut path: PathBuf = get_xml_dir()?; + DirBuilder::new().recursive(true).create(&path)?; + for subscription in &state.subscriptions { + if re_pod.is_match(&subscription.title) { + let mut filename: String = subscription.title.clone(); + filename.push_str(".xml"); + path.push(filename); + + let file: File = File::open(&path)?; + let podcast: Podcast = Podcast::from(Channel::read_from(BufReader::new(file))?); + let episodes = podcast.episodes(); + let episode = episodes[0].clone(); + + filename = episode.title().unwrap(); + filename.push_str(&episode.extension().unwrap()); + path = get_podcast_dir()?; + path.push(podcast.title()); + path.push(filename); + if path.exists() { + launch_player(path.to_str().unwrap())?; + } else { + launch_player(episode.url().unwrap())?; + } + return Ok(()); + } + } + Ok(()) +} + +pub fn play_episode_by_num(state: &State, p_search: &str, ep_num_string: &str) -> Result<()> { + let re_pod: Regex = Regex::new(&format!("(?i){}", &p_search))?; + if let Ok(ep_num) = ep_num_string.parse::<usize>() { + let mut path: PathBuf = get_xml_dir()?; + let stderr = io::stderr(); + let mut handle = stderr.lock(); + if let Err(err) = DirBuilder::new().recursive(true).create(&path) { + writeln!( + &mut handle, + "Couldn't create directory: {}\nReason: {}", + path.to_str().unwrap(), + err + ) + .ok(); + return Ok(()); + } + for subscription in &state.subscriptions { + if re_pod.is_match(&subscription.title) { + let mut filename: String = subscription.title.clone(); + filename.push_str(".xml"); + path.push(filename); + + let file: File = File::open(&path).unwrap(); + let podcast = Podcast::from(Channel::read_from(BufReader::new(file)).unwrap()); + let episodes = podcast.episodes(); + let episode = episodes[episodes.len() - ep_num].clone(); + + filename = episode.title().unwrap(); + filename.push_str(&episode.extension().unwrap()); + path = get_podcast_dir()?; + path.push(podcast.title()); + path.push(filename); + if path.exists() { + launch_player(path.to_str().unwrap())?; + } else { + launch_player(episode.url().unwrap())?; + } + return Ok(()); + } + } + } else { + { + let stdout = io::stdout(); + let mut handle = stdout.lock(); + writeln!(&mut handle, "Failed to parse episode index number...").ok(); + writeln!(&mut handle, "Attempting to find episode by name...").ok(); + } + play_episode_by_name(state, p_search, ep_num_string)?; + } + Ok(()) +} + +pub fn play_episode_by_name(state: &State, p_search: &str, ep_string: &str) -> Result<()> { + let re_pod: Regex = Regex::new(&format!("(?i){}", &p_search))?; + let mut path: PathBuf = get_xml_dir()?; + if let Err(err) = DirBuilder::new().recursive(true).create(&path) { + let stderr = io::stderr(); + let mut handle = stderr.lock(); + writeln!( + &mut handle, + "Couldn't create directory: {:?}\nReason: {}", + path, err + ) + .ok(); + return Ok(()); + } + for subscription in &state.subscriptions { + if re_pod.is_match(&subscription.title) { + let mut filename: String = subscription.title.clone(); + filename.push_str(".xml"); + path.push(filename); + + let mut file: File = File::open(&path).unwrap(); + let mut content: Vec<u8> = Vec::new(); + file.read_to_end(&mut content).unwrap(); + + let podcast = Podcast::from(Channel::read_from(content.as_slice()).unwrap()); + let episodes = podcast.episodes(); + let filtered_episodes: Vec<&Episode> = episodes + .iter() + .filter(|ep| { + ep.title() + .unwrap_or_else(|| "".to_string()) + .to_lowercase() + .contains(&ep_string.to_lowercase()) + }) + .collect(); + if let Some(episode) = filtered_episodes.first() { + filename = episode.title().unwrap(); + filename.push_str(&episode.extension().unwrap()); + path = get_podcast_dir()?; + path.push(podcast.title()); + path.push(filename); + if path.exists() { + launch_player(path.to_str().unwrap())?; + } else { + launch_player(episode.url().unwrap())?; + } + } + return Ok(()); + } + } + Ok(()) +} |
