mirror of
https://github.com/bobwen-dev/hunter
synced 2025-04-12 00:55:41 +02:00
initial support for SIXEL/kitty graphics
This commit is contained in:
parent
9b6bb7fea0
commit
072b39b3cf
123
Cargo.lock
generated
123
Cargo.lock
generated
@ -5,6 +5,14 @@ name = "adler32"
|
||||
version = "1.0.3"
|
||||
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"
|
||||
@ -89,6 +97,14 @@ dependencies = [
|
||||
"libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[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"
|
||||
@ -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)",
|
||||
@ -586,6 +604,19 @@ name = "lzw"
|
||||
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"
|
||||
@ -1086,6 +1117,18 @@ dependencies = [
|
||||
"redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[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"
|
||||
@ -1098,6 +1141,11 @@ dependencies = [
|
||||
"utf8-ranges 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[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"
|
||||
@ -1145,6 +1193,15 @@ dependencies = [
|
||||
"semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[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"
|
||||
@ -1164,6 +1221,24 @@ name = "siphasher"
|
||||
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"
|
||||
@ -1219,6 +1294,17 @@ dependencies = [
|
||||
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[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"
|
||||
@ -1238,6 +1324,23 @@ dependencies = [
|
||||
"unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[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"
|
||||
@ -1318,6 +1421,11 @@ dependencies = [
|
||||
"libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[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"
|
||||
@ -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"
|
||||
|
@ -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]
|
||||
|
@ -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
|
||||
|
18
src/hbox.rs
18
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)),
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
} else { 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::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() * 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;
|
||||
let mut new_y;
|
||||
|
||||
if img_ratio < 1 as f32 {
|
||||
new_x = (ysize as f32 * img_ratio) as usize;
|
||||
new_y = ysize;
|
||||
} else {
|
||||
new_x = xsize;
|
||||
new_y = (xsize as f32 / img_ratio) as usize;
|
||||
}
|
||||
|
||||
// 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 = xsize;
|
||||
let mut new_x;
|
||||
let mut new_y;
|
||||
|
||||
new_y = if img_ratio < 1 as f32 {
|
||||
(xsize as f32 * img_ratio) as usize
|
||||
// tall / slim
|
||||
if img_ratio < 1 as f32 {
|
||||
new_x = (ysize as f32 * img_ratio) as usize;
|
||||
new_y = ysize;
|
||||
// short / wide
|
||||
} 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
|
||||
};
|
||||
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 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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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\\");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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")
|
||||
|
@ -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: {:?}",
|
||||
@ -185,6 +196,12 @@ impl MediaView {
|
||||
|
||||
// Newline means frame is complete
|
||||
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();
|
||||
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user