summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrabite <rabite@posteo.de>2019-07-08 12:53:44 +0200
committerrabite <rabite@posteo.de>2019-07-08 13:00:32 +0200
commit072b39b3cfeac109f8bb0fff747c6dc50d747942 (patch)
treeb96cbdc6e8cdcfcc214cbfcf92145cd19b00e3fc
parent9b6bb7fea092b621337e797b8fd3628ff7ad8218 (diff)
initial support for SIXEL/kitty graphics
-rw-r--r--Cargo.lock123
-rw-r--r--Cargo.toml9
-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
8 files changed, 442 insertions, 164 deletions
diff --git a/Cargo.lock b/Cargo.lock
index b7e04c8..ab33336 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -7,6 +7,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "aho-corasick"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "aho-corasick"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
@@ -90,6 +98,14 @@ dependencies = [
]
[[package]]
+name = "base64"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "bitflags"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -448,6 +464,7 @@ version = "1.3.4"
dependencies = [
"alphanumeric-sort 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
"async_value 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
"chrono 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
"dirs-2 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -468,8 +485,9 @@ dependencies = [
"rayon 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"signal-notify 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "sixel 0.3.0 (git+https://github.com/rabite0/sixel-rs?tag=v0.3.0)",
"systemstat 0.1.4 (git+https://github.com/myfreeweb/systemstat?tag=v0.1.4)",
- "termion 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "termion 1.5.3 (git+https://github.com/redox-os/termion)",
"tree_magic 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"users 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -587,6 +605,19 @@ version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
+name = "make-cmd"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "memchr"
+version = "0.1.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "memchr"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1088,6 +1119,18 @@ dependencies = [
[[package]]
name = "regex"
+version = "0.1.80"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "regex"
version = "1.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
@@ -1100,6 +1143,11 @@ dependencies = [
[[package]]
name = "regex-syntax"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "regex-syntax"
version = "0.6.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
@@ -1147,6 +1195,15 @@ dependencies = [
[[package]]
name = "semver-parser"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "semver-parser"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1165,6 +1222,24 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
+name = "sixel"
+version = "0.3.0"
+source = "git+https://github.com/rabite0/sixel-rs?tag=v0.3.0#9018082b3b5d094e7a634292d7c3ae09f4fd2cd1"
+dependencies = [
+ "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "semver-parser 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "sixel-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "sixel-sys"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "make-cmd 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "slab"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1222,6 +1297,17 @@ dependencies = [
[[package]]
name = "termion"
version = "1.5.3"
+source = "git+https://github.com/redox-os/termion#11fbe7155681c3c87495a2fa8ee9f822b18e2b2a"
+dependencies = [
+ "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
+ "numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "termion"
+version = "1.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1239,6 +1325,23 @@ dependencies = [
]
[[package]]
+name = "thread-id"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "thread_local"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "thread_local"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1320,6 +1423,11 @@ dependencies = [
[[package]]
name = "utf8-ranges"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "utf8-ranges"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1391,6 +1499,7 @@ dependencies = [
[metadata]
"checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c"
+"checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66"
"checksum aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e6f484ae0c99fec2e858eb6134949117399f222608d84cadb3f58c1f97c2364c"
"checksum alphanumeric-sort 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7cd2580c95c654d681db0194a310af67a293f5e1c8bafa5b35b63269c4665a39"
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
@@ -1401,6 +1510,7 @@ dependencies = [
"checksum autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0e49efa51329a5fd37e7c79db4621af617cd4e3e5bc224939808d076077077bf"
"checksum backtrace 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)" = "18b50f5258d1a9ad8396d2d345827875de4261b158124d4c819d9b351454fae5"
"checksum backtrace-sys 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)" = "5b3a000b9c543553af61bc01cbfc403b04b5caa9e421033866f2e98061eb3e61"
+"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e"
"checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd"
"checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400"
"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
@@ -1454,6 +1564,8 @@ dependencies = [
"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6"
"checksum lscolors 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e9938fd8c379393454f73ec4c9c5b40f3d8332d80b25a29da05e41ee0ecbb559"
"checksum lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d947cbb889ed21c2a84be6ffbaebf5b4e0f4340638cba0444907e38b56be084"
+"checksum make-cmd 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8ca8afbe8af1785e09636acb5a41e08a765f5f0340568716c18a8700ba3c0d3"
+"checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20"
"checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a"
"checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39"
"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3"
@@ -1510,7 +1622,9 @@ dependencies = [
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
"checksum redox_users 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "214a97e49be64fd2c86f568dd0cb2c757d2cc53de95b273b6ad0a1c908482f26"
"checksum redox_users 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe5204c3a17e97dde73f285d49be585df59ed84b50a872baf416e73b62c3828"
+"checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f"
"checksum regex 1.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0b2f0808e7d7e4fb1cb07feb6ff2f4bc827938f24f8c2e6a3beb7370af544bdd"
+"checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957"
"checksum regex-syntax 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d76410686f9e3a17f06128962e0ecc5755870bb890c34820c7af7f1db2e1d48"
"checksum rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f4dccf6f4891ebcc0c39f9b6eb1a83b9bf5d747cb439ec6fba4f3b977038af"
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
@@ -1518,9 +1632,12 @@ dependencies = [
"checksum scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8"
"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
+"checksum semver-parser 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d8fff3c9c5a54636ab95acd8c1349926e04cb1eb8cd70b5adced8a1d1f703a67"
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
"checksum signal-notify 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "847fbedad7c2e6fbb6077befa1fa61a6336658eaae2d9fe66cb94a0024742f4e"
"checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac"
+"checksum sixel 0.3.0 (git+https://github.com/rabite0/sixel-rs?tag=v0.3.0)" = "<none>"
+"checksum sixel-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fb46e0cd5569bf910390844174a5a99d52dd40681fff92228d221d9f8bf87dea"
"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
"checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7"
"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8"
@@ -1528,8 +1645,11 @@ dependencies = [
"checksum syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d960b829a55e56db167e861ddb43602c003c7be0bee1d345021703fac2fb7c"
"checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f"
"checksum systemstat 0.1.4 (git+https://github.com/myfreeweb/systemstat?tag=v0.1.4)" = "<none>"
+"checksum termion 1.5.3 (git+https://github.com/redox-os/termion)" = "<none>"
"checksum termion 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6a8fb22f7cde82c8220e5aeacb3258ed7ce996142c77cba193f203515e26c330"
"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
+"checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03"
+"checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5"
"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
"checksum tiff 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1e4834f28a0330cb9f3f2c87d2649dca723cb33802e2bdcf18da32759fbec7ce"
"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
@@ -1540,6 +1660,7 @@ dependencies = [
"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526"
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
"checksum users 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7fed7d0912567d35f88010c23dbaf865e9da8b5227295e8dc0f2fdd109155ab7"
+"checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f"
"checksum utf8-ranges 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9d50aa7650df78abf942826607c62468ce18d9019673d4a2ebe1865dbb96ffde"
"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
diff --git a/Cargo.toml b/Cargo.toml
index 05d3740..407a351 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -16,7 +16,8 @@ default-run = "hunter"
[dependencies]
-termion = "1.5.1"
+# Added terminal_size_pixels recently
+termion = { git = "https://github.com/redox-os/termion" }
unicode-width = "0.1.5"
lazy_static = "0.2.11"
alphanumeric-sort = "1.0.6"
@@ -39,13 +40,17 @@ osstrtools = "0.1.9"
pathbuftools = "0.1"
clap = "2.33"
mime = "0.3.13"
+# Updated to work with recent sixel-sys
+sixel = { git = "https://github.com/rabite0/sixel-rs", tag="v0.3.0" }
+base64 = { version = "0.10.1" }
image = { version = "0.21.1", optional = true }
gstreamer = { version = "0.11.2", optional = true }
gstreamer-app = { version = "0.11.2", optional = true }
[build-dependencies]
-termion = "1.5.1"
+# Added terminal_size_pixels recently
+termion = { git = "https://github.com/redox-os/termion" }
rustc_version = "0.2.3"
[features]
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 si