1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
use crate::config::Xywh;
use anyhow::{bail, Result};
use std::io::Write;
use std::process::Child;
use std::process::Stdio;
use std::sync::RwLock;

pub struct UeInstance {
    ueberzug: RwLock<Option<Child>>,
}

impl Default for UeInstance {
    fn default() -> Self {
        Self {
            ueberzug: RwLock::new(None),
        }
    }
}

impl UeInstance {
    pub fn draw_cover_ueberzug(&self, url: &str, draw_xywh: &Xywh, use_sixel: bool) -> Result<()> {
        if draw_xywh.width <= 1 || draw_xywh.height <= 1 {
            return Ok(());
        }

        // Ueberzug takes an area given in chars and fits the image to
        // that area (from the top left).
        //   draw_offset.y += (draw_size.y - size.y) - (draw_size.y - size.y) / 2;
        let cmd = format!("{{\"action\":\"add\",\"scaler\":\"forced_cover\",\"identifier\":\"cover\",\"x\":{},\"y\":{},\"width\":{},\"height\":{},\"path\":\"{}\"}}\n",
        // let cmd = format!("{{\"action\":\"add\",\"scaler\":\"fit_contain\",\"identifier\":\"cover\",\"x\":{},\"y\":{},\"width\":{},\"height\":{},\"path\":\"{}\"}}\n",
        // TODO: right now the y position of ueberzug is not consistent, and could be a 0.5 difference
                // draw_xywh.x, draw_xywh.y-1,
                draw_xywh.x, draw_xywh.y,//-1 + (draw_xywh.width-draw_xywh.height) % 2,
                draw_xywh.width,draw_xywh.height/2,//+ (draw_xywh.width-draw_xywh.height)%2,
                url,
            );

        // println!(
        //     "draw_xywh.x = {}, draw_xywh.y = {}, draw_wyxh.width = {}, draw_wyxh.height = {}",
        //     draw_xywh.x, draw_xywh.y, draw_xywh.width, draw_xywh.height,
        // );
        if use_sixel {
            if let Err(e) = self.run_ueberzug_cmd_sixel(&cmd) {
                bail!("Failed to run Ueberzug: {}", e)
                // Ok(())
            }
            return Ok(());
        }

        if let Err(e) = self.run_ueberzug_cmd(&cmd) {
            bail!("Failed to run Ueberzug: {}", e)
            // Ok(())
        }
        Ok(())
    }

    pub fn clear_cover_ueberzug(&self) -> Result<()> {
        let cmd = "{\"action\": \"remove\", \"identifier\": \"cover\"}\n";
        if let Err(e) = self.run_ueberzug_cmd(cmd) {
            bail!("Failed to run Ueberzug: {}", e)
            // Ok(())
        }
        Ok(())
    }

    fn run_ueberzug_cmd(&self, cmd: &str) -> Result<()> {
        let mut ueberzug = self.ueberzug.write().unwrap();

        // eprintln!("using x11 output for ueberzugpp");

        if ueberzug.is_none() {
            *ueberzug = Some(
                std::process::Command::new("ueberzug")
                    .args(["layer", "--silent"])
                    .stdin(Stdio::piped())
                    .stdout(Stdio::piped())
                    .spawn()?,
            );
        }

        let stdin = (*ueberzug).as_mut().unwrap().stdin.as_mut().unwrap();
        stdin.write_all(cmd.as_bytes())?;

        Ok(())
    }

    fn run_ueberzug_cmd_sixel(&self, cmd: &str) -> Result<()> {
        let mut ueberzug = self.ueberzug.write().unwrap();

        // eprintln!("using sixel output for ueberzugpp");

        if ueberzug.is_none() {
            *ueberzug = Some(
                std::process::Command::new("ueberzug")
                    .args(["layer", "--silent"])
                    // .args(["layer", "--silent", "--no-cache", "--output", "sixel"])
                    // .args(["layer", "--sixel"])
                    // .args(["--sixel"])
                    .stdin(Stdio::piped())
                    .stdout(Stdio::piped())
                    .spawn()?,
            );
        }

        let stdin = (*ueberzug).as_mut().unwrap().stdin.as_mut().unwrap();
        stdin.write_all(cmd.as_bytes())?;

        Ok(())
    }
}