summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrabite <rabite@posteo.de>2019-07-02 13:41:34 +0200
committerrabite <rabite@posteo.de>2019-07-08 12:54:48 +0200
commitc8faea0343f6cb5cec6545b884fc3b927fffcd57 (patch)
treec405d368fc9af3356fe54df8cc902694106745f5
parentf5429221768cac7eb2bdc32e1d195720eb9489c3 (diff)
remove preview-gen.rs
-rw-r--r--src/preview-gen.rs524
1 files changed, 0 insertions, 524 deletions
diff --git a/src/preview-gen.rs b/src/preview-gen.rs
deleted file mode 100644
index 6f71674..0000000
--- a/src/preview-gen.rs
+++ /dev/null
@@ -1,524 +0,0 @@
-// Based on https://github.com/jD91mZM2/termplay
-// MIT License
-
-use image::{Pixel, FilterType, DynamicImage, GenericImageView};
-
-use termion::color::{Bg, Fg, Rgb};
-#[cfg(feature = "video")]
-use termion::input::TermRead;
-
-
-#[cfg(feature = "video")]
-use gstreamer::{self, prelude::*};
-#[cfg(feature = "video")]
-use gstreamer_app;
-
-use failure::Error;
-#[cfg(feature = "video")]
-use failure::format_err;
-
-use rayon::prelude::*;
-
-use std::io::Write;
-#[cfg(feature = "video")]
-use std::sync::{Arc, RwLock};
-
-pub type MResult<T> = Result<T, Error>;
-
-fn main() -> MResult<()> {
- let args = std::env::args().collect::<Vec<String>>();
- let xsize: usize = args.get(1)
- .expect("Provide xsize")
- .parse::<usize>()
- .unwrap();
- let ysize = args.get(2)
- .expect("provide ysize")
- .parse()
- .unwrap();
- #[cfg(feature = "video")]
- let preview_type = args.get(3)
- .expect("Provide preview type")
- .parse::<String>()
- .unwrap();
- #[cfg(feature = "video")]
- let autoplay = args.get(4)
- .expect("Autoplay?")
- .parse::<bool>()
- .unwrap();
- #[cfg(feature = "video")]
- let mute = args.get(5)
- .expect("Muted?")
- .parse::<bool>()
- .unwrap();
- let path = args.get(6).expect("Provide path");
-
- #[cfg(feature = "video")]
- let result =
- match preview_type.as_ref() {
- "video" => video_preview(path, xsize, ysize, autoplay, mute),
- "image" => image_preview(path, xsize, ysize),
- "audio" => audio_preview(path, autoplay, mute),
- _ => { panic!("Available types: video/image/audio") }
- };
-
-
-
- #[cfg(not(feature = "video"))]
- let result = image_preview(path, xsize, ysize);
-
- if result.is_err() {
- println!("{:?}", &result);
- result
- } else {
- Ok(())
- }
-}
-
-fn image_preview(path: &str,
- xsize: usize,
- ysize: usize) -> MResult<()> {
- let img = image::open(&path)?;
-
- let renderer = Renderer::new(xsize, ysize);
-
- renderer.send_image(&img)?;
- Ok(())
-}
-
-#[cfg(feature = "video")]
-fn video_preview(path: &String,
- xsize: usize,
- ysize: usize,
- autoplay: bool,
- mute: bool)
- -> MResult<()> {
-
- let (player, appsink) = make_gstreamer()?;
-
- let uri = format!("file://{}", &path);
-
- player.set_property("uri", &uri)?;
-
-
- let renderer = Renderer::new(xsize, ysize);
- let renderer = Arc::new(RwLock::new(renderer));
- let crenderer = renderer.clone();
-
-
-
-
- let p = player.clone();
-
- appsink.set_callbacks(
- gstreamer_app::AppSinkCallbacks::new()
- .new_sample({
- move |sink| {
- let sample = match sink.pull_sample() {
- Some(sample) => sample,
- None => return gstreamer::FlowReturn::Eos,
- };
-
- let position = p.query_position::<gstreamer::ClockTime>()
- .map(|p| p.seconds().unwrap_or(0))
- .unwrap_or(0);
-
- let duration = p.query_duration::<gstreamer::ClockTime>()
- .map(|d| d.seconds().unwrap_or(0))
- .unwrap_or(0);
-
- if let Ok(mut renderer) = crenderer.write() {
- match renderer.send_frame(&*sample,
- position,
- duration) {
- Ok(()) => {
- if autoplay == false {
- // Just render first frame to get a static image
- match p.set_state(gstreamer::State::Paused)
- .into_result() {
- Ok(_) => gstreamer::FlowReturn::Eos,
- Err(_) => gstreamer::FlowReturn::Error
- }
- } else {
- gstreamer::FlowReturn::Ok
- }
- }
- Err(err) => {
- println!("{:?}", err);
- gstreamer::FlowReturn::Error
- }
- }
- } else { gstreamer::FlowReturn::Error }
-
- }
- })
- .eos({
- move |_| {
- std::process::exit(0);
- }
- })
- .build()
- );
-
- if mute == true || autoplay == false {
- player.set_property("volume", &0.0)?;
- }
- player.set_state(gstreamer::State::Playing).into_result()?;
-
-
-
-
-
- read_keys(player, Some(renderer))?;
-
- Ok(())
-}
-
-#[cfg(feature = "video")]
-fn read_keys(player: gstreamer::Element,
- renderer: Option<Arc<RwLock<Renderer>>>) -> MResult<()> {
- let seek_time = gstreamer::ClockTime::from_seconds(5);
-
- let stdin = std::io::stdin();
- let mut stdin = stdin.lock();
-
- loop {
- let input = stdin
- .read_line()?
- .unwrap_or_else(|| String::from("q"));
-
-
- match input.as_str() {
- "q" => std::process::exit(0),
- ">" => {
- if let Some(mut time) = player
- .query_position::<gstreamer::ClockTime>() {
- time += seek_time;
-
- player.seek_simple(
- gstreamer::SeekFlags::FLUSH,
- gstreamer::format::GenericFormattedValue::from_time(time)
- )?;
- }
- },
- "<" => {
- if let Some(mut time) = player
- .query_position::<gstreamer::ClockTime>() {
- if time >= seek_time {
- time -= seek_time;
- } else {
- time = gstreamer::ClockTime(Some(0));
- }
-
- player.seek_simple(
- gstreamer::SeekFlags::FLUSH,
- gstreamer::format::GenericFormattedValue::from_time(time)
- )?;
- }
- }
- "p" => {
- player.set_state(gstreamer::State::Playing).into_result()?;
-
- // To actually start playing again
- if let Some(time) = player
- .query_position::<gstreamer::ClockTime>() {
- player.seek_simple(
- gstreamer::SeekFlags::FLUSH,
- gstreamer::format::GenericFormattedValue::from_time(time)
- )?;
- }
- }
- "a" => {
- player.set_state(gstreamer::State::Paused).into_result()?;
- }
- "m" => {
- player.set_property("volume", &0.0)?;
- }
- "u" => {
- player.set_property("volume", &1.0)?;
- }
- "xy" => {
- if let Some(ref renderer) = renderer {
- let xsize = stdin.read_line()?;
- let ysize = stdin.read_line()?;
-
- let xsize = xsize.unwrap_or(String::from("0")).parse::<usize>()?;
- let ysize = ysize.unwrap_or(String::from("0")).parse::<usize>()?;
-
- let mut renderer = renderer
- .write()
- .map_err(|_| format_err!("Renderer RwLock failed!"))?;
-
- renderer.set_size(xsize, ysize)?;
- }
- }
- _ => {}
- }
- }
-}
-
-#[cfg(feature = "video")]
-pub fn audio_preview(path: &String,
- autoplay: bool,
- mute: bool)
- -> MResult<()> {
- let (player, _) = make_gstreamer()?;
-
- let uri = format!("file://{}", &path);
-
- player.set_property("uri", &uri)?;
- let p = player.clone();
-
- // Since events don't work with audio files...
- std::thread::spawn(move || -> MResult<()> {
- let mut last_pos = None;
- let sleep_duration = std::time::Duration::from_millis(50);
- let mut stdout = std::io::stdout();
- loop {
- std::thread::sleep(sleep_duration);
-
- let position = p.query_position::<gstreamer::ClockTime>()
- .map(|p| p.seconds().unwrap_or(0))
- .unwrap_or(0);
-
- let duration = p.query_duration::<gstreamer::ClockTime>()
- .map(|d| d.seconds().unwrap_or(0))
- .unwrap_or(0);
-
- // Just redo loop until position changes
- if last_pos == Some(position) {
- continue
- }
-
- last_pos = Some(position);
-
- // MediaView needs empty line as separator
- writeln!(stdout, "")?;
- // Send position and duration
- writeln!(stdout, "{}", position)?;
- writeln!(stdout, "{}", duration)?;
- stdout.flush()?;
- }
-
- });
-
- if mute == true || autoplay == false{
- player.set_property("volume", &0.0)?;
- } else {
- player.set_state(gstreamer::State::Playing).into_result()?;
- }
-
- read_keys(player, None)?;
-
- Ok(())
-}
-
-#[cfg(feature = "video")]
-pub fn make_gstreamer() -> MResult<(gstreamer::Element,
- gstreamer_app::AppSink)> {
- gstreamer::init()?;
-
- let player = gstreamer::ElementFactory::make("playbin", None)
- .ok_or(format_err!("Can't create playbin"))?;
-
- let videorate = gstreamer::ElementFactory::make("videorate", None)
- .ok_or(format_err!("Can't create videorate element"))?;
-
- let pnmenc = gstreamer::ElementFactory::make("pnmenc", None)
- .ok_or(format_err!("Can't create PNM-encoder"))?;
-
- let sink = gstreamer::ElementFactory::make("appsink", None)
- .ok_or(format_err!("Can't create appsink"))?;
-
- let appsink = sink.clone()
- .downcast::<gstreamer_app::AppSink>()
- .unwrap();
-
-
- videorate.set_property("max-rate", &60)?;
-
- let elems = &[&videorate, &pnmenc, &sink];
-
- let bin = gstreamer::Bin::new(None);
- bin.add_many(elems)?;
- gstreamer::Element::link_many(elems)?;
-
- // make input for bin point to first element
- let sink = elems[0].get_static_pad("sink").unwrap();
- let ghost = gstreamer::GhostPad::new("sink", &sink)
- .ok_or(format_err!("Can't create GhostPad"))?;
-
- ghost.set_active(true)?;
- bin.add_pad(&ghost)?;
-
- player.set_property("video-sink", &bin.upcast::<gstreamer::Element>())?;
-
- Ok((player, appsink))
-}
-
-
-struct Renderer {
- xsize: usize,
- ysize: usize,
- #[cfg(feature = "video")]
- last_frame: Option<DynamicImage>,
- #[cfg(feature = "video")]
- position: Option<usize>,
- #[cfg(feature = "video")]
- duration: Option<usize>
-}
-
-impl Renderer {
- fn new(xsize: usize, ysize: usize) -> Renderer {
- Renderer {
- xsize,
- ysize,
- #[cfg(feature = "video")]
- last_frame: None,
- #[cfg(feature = "video")]
- position: None,
- #[cfg(feature = "video")]
- duration: None
- }
- }
-
-
- #[cfg(feature = "video")]
- fn set_size(&mut self, xsize: usize, ysize: usize) -> MResult<()> {
- self.xsize = xsize;
- self.ysize = ysize;
-
- if let Some(ref frame) = self.last_frame {
- let pos = self.position.unwrap_or(0);
- let dur = self.duration.unwrap_or(0);
-
- // Use send_image, because send_frame takes SampleRef
- self.send_image(frame)?;
-
- let stdout = std::io::stdout();
- let mut stdout = stdout.lock();
-
- writeln!(stdout, "")?;
- writeln!(stdout, "{}", pos)?;
- writeln!(stdout, "{}", dur)?;
- }
- Ok(())
- }
-
- fn send_image(&self, image: &DynamicImage) -> MResult<()> {
- let rendered_img = self.render_image(image);
- let stdout = std::io::stdout();
- let mut stdout = stdout.lock();
-
- for line in rendered_img {
- writeln!(stdout, "{}", line)?;
- }
-
- Ok(())
- }
-
- #[cfg(feature = "video")]
- fn send_frame(&mut self,
- frame: &gstreamer::sample::SampleRef,
- position: u64,
- duration: u64)
- -> MResult<()> {
- let buffer = frame.get_buffer()
- .ok_or(format_err!("Couldn't get buffer from frame!"))?;
- let map = buffer.map_readable()
- .ok_or(format_err!("Couldn't get buffer from frame!"))?;
-
- let img = image::load_from_memory_with_format(&map,
- image::ImageFormat::PNM)?;
-
- let rendered_img = self.render_image(&img);
-
- self.last_frame = Some(img);
- self.position = Some(position as usize);
- self.duration = Some(duration as usize);
-
- let stdout = std::io::stdout();
- let mut stdout = stdout.lock();
-
- for line in rendered_img {
- writeln!(stdout, "{}", line)?;
- }
-
- // Empty line means end of frame
- writeln!(stdout, "")?;
-
- // Send position and duration
- writeln!(stdout, "{}", position)?;
- writeln!(stdout, "{}", duration)?;
-
- Ok(())
- }
-
- pub fn render_image(&self, image: &DynamicImage) -> Vec<String> {
- let (xsize, ysize) = self.max_size(&image);
-
- let img = image.resize_exact(xsize as u32,
- ysize as u32,
- FilterType::Nearest).to_rgba();
-
-
- let rows = img.pixels()
- .collect::<Vec<_>>()
- .chunks(xsize as usize)
- .map(|line| line.to_vec())
- .collect::<Vec<Vec<_>>>();
-
- rows.par_chunks(2)
- .map(|rows| {
- rows[0]
- .par_iter()
- .zip(rows[1].par_iter())
- .map(|(upper, lower)| {
- let upper_color = upper.to_rgb();
- let lower_color = lower.to_rgb();
-
- format!("{}{}▀{}",
- Fg(Rgb(upper_color[0], upper_color[1], upper_color[2])),
- Bg(Rgb(lower_color[0], lower_color[1], lower_color[2])),
- termion::style::Reset
- )
- }).collect()
- }).collect()
- }
-
- pub fn max_size(&self, image: &DynamicImage) -> (usize, usize)
- {
- let xsize = self.xsize;
- let ysize = self.ysize;
- let img_xsize = image.width();
- let img_ysize = image.height();
- let img_ratio = img_xsize as f32 / img_ysize as f32;
-
- let mut new_x = xsize;
- let mut new_y;
-
- new_y = if img_ratio < 1 as f32 {
- (xsize as f32 * img_ratio) as usize
- } else {
- (xsize as f32 / img_ratio) as usize
- };
-
- // Multiply by two because of half-block
- if new_y > ysize*2 {
- new_y = self.ysize * 2;
-
- new_x = if img_ratio < 1 as f32 {
- (ysize as f32 / img_ratio) as usize * 2
- } else {
- (ysize as f32 * img_ratio) as usize * 2
- };
- }
-
- // To make half-block encoding easier, y should be divisible by 2
- if new_y as u32 % 2 == 1 {
- new_y += 1;
- }
-
-
- (new_x as usize, new_y as usize)
- }
-}