summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/config.rs19
-rw-r--r--src/hbox.rs18
-rw-r--r--src/hunter-media.rs365
-rw-r--r--src/imgview.rs25
-rw-r--r--src/main.rs6
-rw-r--r--src/mediaview.rs41
6 files changed, 313 insertions, 161 deletions
diff --git a/src/config.rs b/src/config.rs
index 5e24123..21d8404 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -13,7 +13,8 @@ use crate::fail::{HError, HResult, ErrorLog};
struct ArgvConfig {
animation: Option<bool>,
show_hidden: Option<bool>,
- icons: Option<bool>
+ icons: Option<bool>,
+ sixel: Option<bool>,
}
impl ArgvConfig {
@@ -21,7 +22,8 @@ impl ArgvConfig {
ArgvConfig {
animation: None,
show_hidden: None,
- icons: None
+ icons: None,
+ sixel: None
}
}
}
@@ -35,6 +37,7 @@ pub fn set_argv_config(args: clap::ArgMatches) -> HResult<()> {
let animation = args.is_present("animation-off");
let show_hidden = args.is_present("show-hidden");
let icons = args.is_present("icons");
+ let sixel = args.is_present("sixel");
let mut config = ArgvConfig::new();
@@ -50,6 +53,10 @@ pub fn set_argv_config(args: clap::ArgMatches) -> HResult<()> {
config.icons = Some(true)
}
+ if sixel == true {
+ config.sixel = Some(true)
+ }
+
*ARGV_CONFIG.write()? = config;
Ok(())
}
@@ -64,6 +71,7 @@ fn infuse_argv_config(mut config: Config) -> Config {
argv_config.animation.map(|val| config.animation = val);
argv_config.show_hidden.map(|val| config.show_hidden = val);
argv_config.icons.map(|val| config.icons = val);
+ argv_config.sixel.map(|val| config.sixel = val);
config
}
@@ -78,7 +86,8 @@ pub struct Config {
pub media_autoplay: bool,
pub media_mute: bool,
pub media_previewer: String,
- pub ratios: Vec::<usize>
+ pub ratios: Vec::<usize>,
+ pub sixel: bool,
}
@@ -99,7 +108,8 @@ impl Config {
media_autoplay: false,
media_mute: false,
media_previewer: "hunter-media".to_string(),
- ratios: vec![20,30,49]
+ ratios: vec![20,30,49],
+ sixel: false
}
}
@@ -149,6 +159,7 @@ impl Config {
}
}
}
+ Ok(("sixel", "off")) => { config.sixel = true; }
_ => { HError::config_error::<Config>(line.to_string()).log(); }
}
config
diff --git a/src/hbox.rs b/src/hbox.rs
index 8ad23c6..e370fde 100644
--- a/src/hbox.rs
+++ b/src/hbox.rs
@@ -123,17 +123,23 @@ impl<T> HBox<T> where T: Widget + PartialEq {
let len = coords.len();
let gap = if len == ratios.len() { 0 } else { 1 };
- let widget_xsize = *ratio as u16;
+ let prev_coords = coords.last();
+ let prev_xsize = prev_coords.map(|c| c.xsize());
+ let prev_xpos = prev_coords.map(|c| c.xpos());
+
+ let widget_xsize = box_xsize * *ratio as u16 / 100;
+
let widget_xpos = if len == 0 {
box_coords.top().x()
} else {
- let prev_coords = coords.last().unwrap();
- let prev_xsize = prev_coords.xsize();
- let prev_xpos = prev_coords.position().x();
-
- prev_xsize + prev_xpos + gap
+ prev_xsize.unwrap() + prev_xpos.unwrap() + gap
};
+ // Ensure that last widget isn't under/over sized due to gap/rounding
+ let widget_xsize = if len+1 == ratios.len() && len != 0 {
+ box_xsize - (prev_xpos.unwrap() + prev_xsize.unwrap())
+ } else { widget_xsize };
+
coords.push(Coordinates {
size: Size((widget_xsize,
box_ysize)),
diff --git a/src/hunter-media.rs b/src/hunter-media.rs
index 193dc06..cc1de41 100644
--- a/src/hunter-media.rs
+++ b/src/hunter-media.rs
@@ -1,7 +1,9 @@
// Based on https://github.com/jD91mZM2/termplay
// MIT License
-use image::{Pixel, FilterType, DynamicImage, GenericImageView};
+use image::{FilterType, DynamicImage, GenericImageView};
+use sixel::encoder::Encoder;
+use base64;
use termion::color::{Bg, Fg, Rgb};
#[cfg(feature = "video")]
@@ -34,48 +36,61 @@ fn main() -> MResult<()> {
.expect("provide ysize")
.parse()
.unwrap();
- #[cfg(feature = "video")]
- let xpos = args.get(3)
- .expect("provide xpos")
+ let xpix = args.get(3)
+ .expect("provide xsize in pixels")
.parse::<usize>()
.unwrap();
- #[cfg(feature = "video")]
- let ypos = args.get(4)
- .expect("provide ypos")
+ let ypix = args.get(4)
+ .expect("provide ysize in pixels")
.parse::<usize>()
.unwrap();
let preview_type = args.get(5)
.expect("Provide preview type")
.parse::<String>()
.unwrap();
- #[cfg(feature = "video")]
+ // #[cfg(feature = "video")]
let autoplay = args.get(6)
.expect("Autoplay?")
.parse::<bool>()
.unwrap();
- #[cfg(feature = "video")]
+ // #[cfg(feature = "video")]
let mute = args.get(7)
.expect("Muted?")
.parse::<bool>()
.unwrap();
- let path = args.get(8).expect("Provide path");
+ let sixel = args.get(8)
+ .expect("Use SIXEL?")
+ .parse::<bool>()
+ .unwrap();
+ let path = args.get(9).expect("Provide path");
+ let target = if sixel {
+ if std::env::var("TERM") == Ok(String::from("xterm-kitty")) {
+ RenderTarget::Kitty
+ } else {
+ RenderTarget::Sixel
+ }
+ } else {
+ RenderTarget::Unicode
+ };
+
+
+ let renderer = Renderer::new(target,
+ xsize,
+ ysize,
+ xpix,
+ ypix);
let result =
match preview_type.as_ref() {
#[cfg(feature = "video")]
"video" => video_preview(path,
- xsize,
- ysize,
- 0,
- 0,
+ renderer,
autoplay,
- mute,
- false),
+ mute),
"image" => image_preview(path,
- xsize,
- ysize),
+ renderer),
#[cfg(feature = "video")]
"audio" => audio_preview(path,
@@ -83,16 +98,7 @@ fn main() -> MResult<()> {
mute),
#[cfg(feature = "video")]
- "video-raw" => video_preview(path,
- xsize,
- ysize,
- xpos,
- ypos,
- autoplay,
- mute,
- true),
- #[cfg(feature = "video")]
- _ => { panic!("Available types: video(-raw)/image/audio") }
+ _ => { panic!("Available types: video/image/audio") }
#[cfg(not(feature = "video"))]
_ => { panic!("Available type: image") }
@@ -107,15 +113,9 @@ fn main() -> MResult<()> {
}
fn image_preview(path: &str,
- xsize: usize,
- ysize: usize) -> MResult<()> {
+ renderer: Renderer) -> MResult<()> {
let img = image::open(&path)?;
- let renderer = Renderer::new(xsize,
- ysize,
- 0,
- 0);
-
renderer.send_image(&img)?;
Ok(())
@@ -123,23 +123,19 @@ fn image_preview(path: &str,
#[cfg(feature = "video")]
fn video_preview(path: &String,
- xsize: usize,
- ysize: usize,
- xpos: usize,
- ypos: usize,
+ renderer: Renderer,
autoplay: bool,
- mute: bool,
- raw: bool)
+ mute: bool)
-> MResult<()> {
+ let low_fps = renderer.target == RenderTarget::Sixel;
- let (player, appsink) = make_gstreamer()?;
+ let (player, appsink) = make_gstreamer(low_fps)?;
let uri = format!("file://{}", &path);
player.set_property("uri", &uri)?;
- let renderer = Renderer::new(xsize, ysize, xpos, ypos);
let renderer = Arc::new(RwLock::new(renderer));
let crenderer = renderer.clone();
@@ -165,30 +161,24 @@ fn video_preview(path: &String,
.map(|d| d.seconds().unwrap_or(0))
.unwrap_or(0);
- if let Ok(mut renderer) = crenderer.write() {
- match renderer.send_frame(&*sample,
- position,
- duration,
- raw) {
- 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
+ let renderer = crenderer.clone();
+ std::thread::spawn(move || {
+ renderer.write()
+ .map(|mut r| r.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::Error }
-
+ } else {
+ gstreamer::FlowReturn::Ok
+ }
}
})
.eos({
@@ -276,6 +266,7 @@ fn read_keys(player: gstreamer::Element,
"u" => {
player.set_property("volume", &1.0)?;
}
+ // TODO add pixel size
"xy" => {
if let Some(ref renderer) = renderer {
let xsize = stdin.read_line()?;
@@ -301,7 +292,7 @@ pub fn audio_preview(path: &String,
autoplay: bool,
mute: bool)
-> MResult<()> {
- let (player, _) = make_gstreamer()?;
+ let (player, _) = make_gstreamer(false)?;
let uri = format!("file://{}", &path);
@@ -333,7 +324,8 @@ pub fn audio_preview(path: &String,
// MediaView needs empty line as separator
writeln!(stdout, "")?;
- // Send position and duration
+ // Send height, position and duration
+ writeln!(stdout, "0")?;
writeln!(stdout, "{}", position)?;
writeln!(stdout, "{}", duration)?;
stdout.flush()?;
@@ -353,8 +345,8 @@ pub fn audio_preview(path: &String,
}
#[cfg(feature = "video")]
-pub fn make_gstreamer() -> MResult<(gstreamer::Element,
- gstreamer_app::AppSink)> {
+pub fn make_gstreamer(low_fps: bool) -> MResult<(gstreamer::Element,
+ gstreamer_app::AppSink)> {
gstreamer::init()?;
let player = gstreamer::ElementFactory::make("playbin", None)
@@ -374,7 +366,11 @@ pub fn make_gstreamer() -> MResult<(gstreamer::Element,
.unwrap();
- videorate.set_property("max-rate", &30)?;
+ if low_fps {
+ videorate.set_property("max-rate", &10)?;
+ } else {
+ videorate.set_property("max-rate", &30)?;
+ }
let elems = &[&videorate, &pnmenc, &sink];
@@ -395,14 +391,20 @@ pub fn make_gstreamer() -> MResult<(gstreamer::Element,
Ok((player, appsink))
}
+#[derive(PartialEq)]
+enum RenderTarget {
+ Unicode,
+ Sixel,
+ Kitty
+}
struct Renderer {
+ // encoder: RwLock<Encoder>,
+ target: RenderTarget,
xsize: usize,
ysize: usize,
- #[cfg(feature = "video")]
- xpos: usize,
- #[cfg(feature = "video")]
- ypos: usize,
+ xsize_pix: usize,
+ ysize_pix: usize,
#[cfg(feature = "video")]
last_frame: Option<DynamicImage>,
#[cfg(feature = "video")]
@@ -412,17 +414,26 @@ struct Renderer {
}
impl Renderer {
- fn new(xsize: usize,
+ fn new(target: RenderTarget,
+ xsize: usize,
ysize: usize,
- xpos: usize,
- ypos: usize) -> Renderer {
+ mut xsize_pix: usize,
+ mut ysize_pix: usize) -> Renderer {
+
+ if std::env::var("TERM") == Ok(String::from("xterm"))
+ && target == RenderTarget::Sixel {
+ // xterm has a hard limit on graphics size
+ // maybe splitting the image into parts would work?
+ if xsize_pix > 1000 { xsize_pix = 1000 };
+ if ysize_pix > 1000 { ysize_pix = 1000 };
+ }
+
Renderer {
+ target,
xsize,
ysize,
- #[cfg(feature = "video")]
- xpos,
- #[cfg(feature = "video")]
- ypos,
+ xsize_pix,
+ ysize_pix,
#[cfg(feature = "video")]
last_frame: None,
#[cfg(feature = "video")]
@@ -432,7 +443,7 @@ impl Renderer {
}
}
-
+ // TODO: Add pixel size
#[cfg(feature = "video")]
fn set_size(&mut self, xsize: usize, ysize: usize) -> MResult<()> {
self.xsize = xsize;
@@ -456,12 +467,10 @@ impl Renderer {
}
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)?;
+ match self.target {
+ RenderTarget::Sixel => self.print_sixel(image)?,
+ RenderTarget::Unicode => self.print_unicode(image)?,
+ RenderTarget::Kitty => self.print_kitty(image)?
}
Ok(())
@@ -471,8 +480,7 @@ impl Renderer {
fn send_frame(&mut self,
frame: &gstreamer::sample::SampleRef,
position: u64,
- duration: u64,
- raw: bool)
+ duration: u64)
-> MResult<()> {
let buffer = frame.get_buffer()
.ok_or(format_err!("Couldn't get buffer from frame!"))?;
@@ -482,50 +490,38 @@ impl Renderer {
let stdout = std::io::stdout();
let mut stdout = stdout.lock();
+ let img = image::load_from_memory_with_format(&map,
+ image::ImageFormat::PNM)?;
+ let (_, height) = self.max_size(&img);
- if !raw {
- 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);
-
- for line in rendered_img {
- writeln!(stdout, "{}", line)?;
- }
- } else {
- stdout.write_all(map.as_slice())?;
-
- // Add newline after frame data
- write!(stdout, "\n")?;
+ match self.target {
+ RenderTarget::Sixel => self.print_sixel(&img)?,
+ RenderTarget::Unicode => self.print_unicode(&img)?,
+ RenderTarget::Kitty => self.print_kitty(&img)?
}
+ self.last_frame = Some(img);
+ self.position = Some(position as usize);
+ self.duration = Some(duration as usize);
+
// Empty line means end of frame
writeln!(stdout, "")?;
- // Send position and duration
+ // Send size (in rows), position and duration
+ writeln!(stdout, "{}", height)?;
writeln!(stdout, "{}", position)?;
writeln!(stdout, "{}", duration)?;
- #[cfg(feature = "video")]
- match raw {
- true => {
- writeln!(stdout, "{}", self.xpos)?;
- writeln!(stdout, "{}", self.ypos)?;
- }
- _ => {}
- }
-
Ok(())
}
pub fn render_image(&self, image: &DynamicImage) -> Vec<String> {
+ use image::Pixel;
let (xsize, ysize) = self.max_size(&image);
+ // double height, because of half-height unicode
let img = image.resize_exact(xsize as u32,
- ysize as u32,
+ ysize as u32 * 2,
FilterType::Nearest).to_rgba();
@@ -553,37 +549,134 @@ impl Renderer {
}).collect()
}
+ fn print_unicode(&self, img: &DynamicImage) -> MResult<()> {
+ let rendered_img = self.render_image(img);
+ let stdout = std::io::stdout();
+ let mut stdout = stdout.lock();
+
+ for line in rendered_img {
+ writeln!(stdout, "{}", line)?;
+ }
+
+ Ok(())
+ }
+
+ fn print_kitty(&self, img: &DynamicImage) -> MResult<()> {
+ let w = img.width();
+ let h = img.height();
+
+ let (max_x, max_y) = self.max_size(img);
+
+ let img = img.to_rgb().into_vec();
+
+ let mut file = std::fs::File::create("/tmp/img.raw").unwrap();
+ file.write_all(&img)?;
+ // Necessary?
+ file.flush()?;
+ std::mem::drop(file);
+
+ let path = base64::encode("/tmp/img.raw");
+
+ println!("\x1b_Gf=24,s={},v={},c={},r={},a=T,t=t;{}\x1b\\",
+ w,
+ h,
+ max_x,
+ max_y,
+ path);
+
+ Ok(())
+ }
+
+ fn print_sixel(&self, img: &DynamicImage) -> MResult<()> {
+ use sixel::optflags::*;
+
+ // Currently faster than covnerting/resizing using image...
+ img.save("/tmp/img.bmp")?;
+
+ let encoder = Encoder::new().unwrap();
+
+ let (xpix, ypix) = self.max_size_pix(img);
+
+ encoder.set_quality(Quality::Low).ok();
+ encoder.set_encode_policy(EncodePolicy::Fast).ok();
+ encoder.set_color_option(ColorOption::Builtin("xterm256")).ok();
+ encoder.set_width(SizeSpecification::Pixel(xpix as u64)).ok();
+ encoder.set_height(SizeSpecification::Pixel(ypix as u64)).ok();
+ encoder.encode_file(&std::path::PathBuf::from("/tmp/img.bmp")).ok();
+
+ // End line printed by encoder
+ println!("");
+
+ Ok(())
+ }
+
pub fn max_size(&self, image: &DynamicImage) -> (usize, usize)
{
+ // TODO: cell_ratio = xpix / ypix!
let xsize = self.xsize;
let ysize = self.ysize;
- let img_xsize = image.width();
+ let img_xsize = image.width() * 2; // Cells are roughly 2:1
let img_ysize = image.height();
let img_ratio = img_xsize as f32 / img_ysize as f32;
- let mut new_x = xsize;
+ let mut new_x;
let mut new_y;
- new_y = if img_ratio < 1 as f32 {
- (xsize as f32 * img_ratio) as usize
+ if img_ratio < 1 as f32 {
+ new_x = (ysize as f32 * img_ratio) as usize;
+ new_y = ysize;
} else {
- (xsize as f32 / img_ratio) as usize
- };
+ new_x = xsize;
+ new_y = (xsize as f32 / img_ratio) as usize;
+ }
- // Multiply by two because of half-block
- if new_y > ysize*2 {
- new_y = self.ysize * 2;
+ // ensure it fits within xsize
+ if new_x > xsize {
+ new_x = xsize;
+ new_y = (xsize as f32 / img_ratio) as usize;
+ }
+
+ // ensure it fits within ysize
+ if new_y > ysize {
+ new_y = ysize;
+ new_x = (ysize as f32 * img_ratio) as usize;
+ }
+
+
+ (new_x as usize, new_y as usize)
+ }
+
+ pub fn max_size_pix(&self, image: &DynamicImage) -> (usize, usize)
+ {
+ let xsize = self.xsize_pix;
+ let ysize = self.ysize_pix;
+ 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;
+ let mut new_y;
+
+ // tall / slim
+ if img_ratio < 1 as f32 {
+ new_x = (ysize as f32 * img_ratio) as usize;
+ new_y = ysize;
+ // short / wide
+ } else {
+ new_x = xsize;
+ new_y = (xsize as f32 / img_ratio) as usize;
+ }
- 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
- };
+ // ensure it fits within xsize
+ if new_x > xsize {
+ new_x = xsize;
+ new_y = (xsize as f32 / img_ratio) as usize;
}
- // To make half-block encoding easier, y should be divisible by 2
- if new_y as u32 % 2 == 1 {
- new_y += 1;
+ // ensure it fits within ysize
+ if new_y > ysize {
+ new_y = ysize;
+ new_x = (ysize as f32 * img_ratio) as usize;
}
diff --git a/src/imgview.rs b/src/imgview.rs
index 93e1832..7534a7b 100644
--- a/src/imgview.rs
+++ b/src/imgview.rs
@@ -33,18 +33,25 @@ impl ImgView {
pub fn encode_file(&mut self) -> HResult<()> {
let (xsize, ysize) = self.core.coordinates.size_u();
- let (xpos, ypos) = self.core.coordinates.position_u();
+ let (cols, rows) = termion::terminal_size()?;
+ let (xpix, ypix) = termion::terminal_size_pixels()?;
+ let (xpix, ypix) = (xpix/cols, ypix/rows);
+ let (xpix, ypix) = (xpix * (xsize as u16 + 1),
+ ypix * (ysize as u16 + 1));
+
let file = &self.file;
let media_previewer = self.core.config().media_previewer;
+ let sixel = self.core.config().sixel;
let output = std::process::Command::new(&media_previewer)
- .arg(format!("{}", (xsize)))
+ .arg(format!("{}", (xsize+1)))
.arg(format!("{}", (ysize+1)))
- .arg(format!("{}", xpos))
- .arg(format!("{}", ypos))
+ .arg(format!("{}", xpix))
+ .arg(format!("{}", ypix))
.arg("image")
.arg(format!("true"))
.arg(format!("true"))
+ .arg(format!("{}", sixel))
.arg(file.to_string_lossy().to_string())
.output()
.map_err(|e| {
@@ -111,7 +118,7 @@ impl Widget for ImgView {
.iter()
.enumerate()
.fold(String::new(), |mut draw, (pos, line)| {
- draw += &format!("{}", crate::term::goto_xy_u(xpos+1,
+ draw += &format!("{}", crate::term::goto_xy_u(xpos,
ypos + pos));
draw += line;
draw
@@ -122,3 +129,11 @@ impl Widget for ImgView {
Ok(draw)
}
}
+
+impl Drop for ImgView {
+ fn drop(&mut self) {
+ if self.core.config().sixel {
+ print!("\x1b_Ga=d\x1b\\");
+ }
+ }
+}
diff --git a/src/main.rs b/src/main.rs
index 7efbad7..959e5a2 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -151,6 +151,12 @@ fn parse_args() -> HResult<()> {
.long("icons")
.help("Show icons for different file types")
.takes_value(false))
+ .arg(
+ Arg::with_name("sixel")
+ .short("s")
+ .long("sixel")
+ .help("Show HQ graphics using sixel")
+ .takes_value(false))
// For "Add Action" action
.arg(
Arg::with_name("mime")
diff --git a/src/mediaview.rs b/src/mediaview.rs
index 2f9153c..6d3b1cc 100644
--- a/src/mediaview.rs
+++ b/src/mediaview.rs
@@ -45,6 +45,7 @@ pub struct MediaView {
controller: Sender<String>,
paused: bool,
media_type: MediaType,
+ height: Arc<Mutex<usize>>,
position: Arc<Mutex<usize>>,
duration: Arc<Mutex<usize>>,
stale: Stale,
@@ -52,6 +53,7 @@ pub struct MediaView {
preview_runner: Option<Box<dyn FnOnce(bool,
bool,
Arc<Mutex<usize>>,
+ Arc<Mutex<usize>>,
Arc<Mutex<usize>>)
-> HResult<()> + Send + 'static>>
}
@@ -90,7 +92,12 @@ impl MediaView {
}
let (xsize, ysize) = core.coordinates.size_u();
- let (xpos, ypos) = core.coordinates.position_u();
+ let (cols, rows) = termion::terminal_size()?;
+ let (xpix, ypix) = termion::terminal_size_pixels()?;
+ let (xpix, ypix) = (xpix/cols, ypix/rows);
+ let (xpix, ypix) = (xpix * (xsize as u16 + 1),
+ ypix * (ysize as u16 - 1));
+
let (tx_cmd, rx_cmd) = channel();
let imgview = ImgView {
@@ -113,9 +120,11 @@ impl MediaView {
let ctype = media_type.clone();
let ccore = core.clone();
let media_previewer = core.config().media_previewer;
+ let sixel = core.config().sixel;
let run_preview = Box::new(move | auto,
mute,
+ height: Arc<Mutex<usize>>,
position: Arc<Mutex<usize>>,
duration: Arc<Mutex<usize>>| -> HResult<()> {
loop {
@@ -125,18 +134,20 @@ impl MediaView {
let mut previewer = std::process::Command::new(&media_previewer)
- .arg(format!("{}", (xsize)))
+ .arg(format!("{}", (xsize+1)))
// Leave space for position/seek bar
.arg(format!("{}", (ysize-1)))
- .arg(format!("{}", xpos))
- .arg(format!("{}", ypos))
+ .arg(format!("{}", xpix))
+ .arg(format!("{}", ypix))
.arg(format!("{}", ctype.to_str()))
.arg(format!("{}", auto))
.arg(format!("{}", mute))
+ .arg(format!("{}", sixel))
.arg(&path)
.stdin(std::process::Stdio::piped())
.stdout(std::process::Stdio::piped())
- .stderr(std::process::Stdio::piped())
+ .stderr(std::process::Stdio::inherit())
+ // .stderr(std::process::Stdio::piped())
.spawn()
.map_err(|e| {
let msg = format!("Couldn't run {}{}{}! Error: {:?}",
@@ -187,6 +198,12 @@ impl MediaView {
if line_buf == newline {
line_buf.clear();
stdout.read_line(&mut line_buf)?;
+ let h = &line_buf.trim();
+ *height.lock().unwrap() = h
+ .parse::<usize>()?;
+
+ line_buf.clear();
+ stdout.read_line(&mut line_buf)?;
let pos = &line_buf.trim();
*position.lock().unwrap() = pos
.parse::<usize>()?;
@@ -225,6 +242,7 @@ impl MediaView {
media_type: media_type,
controller: tx_cmd,
paused: false,
+ height: Arc::new(Mutex::new(0)),
position: Arc::new(Mutex::new(0)),
duration: Arc::new(Mutex::new(0)),
stale: stale,
@@ -240,6 +258,7 @@ impl MediaView {
let stale = self.stale.clone();
let autoplay = self.autoplay();
let mute = self.mute();
+ let height = self.height.clone();
let position = self.position.clone();
let duration = self.duration.clone();
let clear = self.get_core()?.get_clearlist()?;
@@ -254,6 +273,7 @@ impl MediaView {
runner.map(|runner| runner(autoplay,
mute,
+ height,
position,
duration));
}
@@ -470,19 +490,20 @@ impl Widget for MediaView {
fn get_drawlist(&self) -> HResult<String> {
let (xpos, ypos) = self.core.coordinates.position_u();
+ let height = *self.height.lock()?;
let progress_str = self.progress_string()?;
let progress_bar = self.progress_bar()?;
- let (frame, lines) = self.imgview
+ let frame= self.imgview
.lock()
- .map(|img| (img.get_drawlist(), img.lines()))?;
+ .map(|img| img.get_drawlist())?;
let mut frame = frame?;
- frame += &crate::term::goto_xy_u(xpos+1, ypos+lines);
+ frame += &crate::term::goto_xy_u(xpos, ypos+height);
frame += &progress_str;
- frame += &self.get_icons(lines)?;
- frame += &crate::term::goto_xy_u(xpos+1, ypos+lines+1);
+ frame += &self.get_icons(height)?;
+ frame += &crate::term::goto_xy_u(xpos, ypos+height+1);
frame += &progress_bar;
Ok(frame)