mirror of https://github.com/bobwen-dev/hunter
merge in media-preview stuff
Squashed commit of the following: commit 4087cee2f2a72bc2d3e44832809cbe99d25a3309 Author: rabite <rabite@posteo.de> Date: Tue May 21 20:40:27 2019 +0200 rename to preview-gen commit 275fd420a01c24393ae9cc07287204fde309130a Author: rabite <rabite@posteo.de> Date: Tue May 21 20:30:50 2019 +0200 update Cargo.toml and README commit bf4c3fec0f8e0ff4628153297ac64fe165b4e443 Author: rabite <rabite@posteo.de> Date: Tue May 21 20:30:33 2019 +0200 add config options for media commit 3bf681cd078177d634507c51d04a45bdae184f1b Author: rabite <rabite@posteo.de> Date: Tue May 21 13:46:00 2019 +0200 always use unicode icons for play/pause/mute commit ed2a0b31d1911e4d42086699ca1db636c327bacf Author: rabite <rabite@posteo.de> Date: Tue May 21 13:04:11 2019 +0200 rename to mediaview and some fixups commit bda3f8f83bec07c3f52d06cf5f8eaad7fdbd85a0 Author: rabite <rabite@posteo.de> Date: Tue May 21 11:44:52 2019 +0200 fix warnings commit 9c917903cfa958b225f268ed4fb9f55f27162be0 Author: rabite <rabite@posteo.de> Date: Tue May 21 01:10:58 2019 +0200 play audio through viedo widget commit 9fe208b213710fae889f7701bdb3bf96d599c9a8 Author: rabite <rabite@posteo.de> Date: Tue May 21 00:15:12 2019 +0200 fixed play when autoplay is off commit d4036d52864d0a4e08f7da2cf6f7419ef070c1a9 Author: rabite <rabite@posteo.de> Date: Mon May 20 13:15:44 2019 +0200 add icons for play/pause/mute commit 29f0d203cfd7501b50d80501de146da9d89388bb Author: rabite <rabite@posteo.de> Date: Mon May 20 12:26:53 2019 +0200 add basic gif support commit 8d28e4c23a91b0ef83739554c3a2f6671a9ff6f5 Author: rabite <rabite@posteo.de> Date: Mon May 20 11:43:57 2019 +0200 fixed play after pause commit 142017df78de77bcfffd8f3dd9612a06927e183b Author: rabite <rabite@posteo.de> Date: Sun May 19 14:22:16 2019 +0200 change to stale on drop commit c0026c7f56f6a841df18e41bd1c9b33543e26cfb Author: rabite <rabite@posteo.de> Date: Sat May 18 23:46:27 2019 +0200 handle errors in gstreamer closure commit ef37f872c54b9d21ed5505c2edb480c793afaef9 Author: rabite <rabite@posteo.de> Date: Sat May 18 23:40:24 2019 +0200 add image-only mode to preview-gen commit 15752464563463c6ecf892c1d8a14651bf32e1e5 Author: rabite <rabite@posteo.de> Date: Sat May 18 23:28:33 2019 +0200 add copyright note commit 4c9f08fc4de5d3bffefd42284b60aa81cfbae9f7 Author: rabite <rabite@posteo.de> Date: Sat May 18 23:27:30 2019 +0200 make image/video previews optional commit 9c2c2db2b20ecd4c30acbb1c77ad18c71f528c4c Author: rabite <rabite@posteo.de> Date: Sat May 18 22:13:25 2019 +0200 remove blank space under video commit f7056d70fbe9147b3b95d7c10950653eadbb4f48 Author: rabite <rabite@posteo.de> Date: Sat May 18 22:06:49 2019 +0200 remove dbg commit cce820657ff1258cdb78d455dd3cf04564450cea Author: rabite <rabite@posteo.de> Date: Sat May 18 21:50:25 2019 +0200 added error handling to preview-gen commit 80bbe15bacb99d1f4f97504a5d10ecf59544993f Author: rabite <rabite@posteo.de> Date: Sat May 18 21:04:31 2019 +0200 add time and visual seek bars to videoview commit 4349945cc5549334f246be64bc7c8e2db43f9150 Author: rabite <rabite@posteo.de> Date: Thu May 16 22:39:19 2019 +0200 fix sneaky process commit 373128b7096d4de29924617e549a613a3aeea5b2 Author: rabite <rabite@posteo.de> Date: Thu May 16 22:07:27 2019 +0200 fix out of controll processes commit e061e065e913ab3923ffac1079a9f0a2be0df532 Author: rabite <rabite@posteo.de> Date: Thu May 16 20:51:56 2019 +0200 add media_preview commit f68c754895a9718d1a962980de9fbf02e5cb48cd Author: rabite <rabite@posteo.de> Date: Thu May 16 19:37:04 2019 +0200 beta image/video previews commit 9a5460e553dd26ebccffaf819c64a8dc6ba74818 Author: rabite <rabite@posteo.de> Date: Tue May 14 20:36:25 2019 +0200 external img preview commit 3c4edfcb7611b36f6e537c73743e0b6bd269037b Author: rabite <rabite@posteo.de> Date: Tue May 14 20:35:12 2019 +0200 video preview
This commit is contained in:
parent
6f8a636603
commit
e8d9c6ad1f
|
@ -1,5 +1,10 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "adler32"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.3"
|
||||
|
@ -40,13 +45,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "async_value"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
version = "0.2.3"
|
||||
dependencies = [
|
||||
"failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"objekt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -91,6 +94,11 @@ dependencies = [
|
|||
"constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "bytesize"
|
||||
version = "0.1.3"
|
||||
|
@ -124,6 +132,11 @@ dependencies = [
|
|||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "color_quant"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "constant_time_eq"
|
||||
version = "0.1.3"
|
||||
|
@ -160,6 +173,15 @@ dependencies = [
|
|||
"cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deflate"
|
||||
version = "0.7.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs"
|
||||
version = "1.0.5"
|
||||
|
@ -261,19 +283,150 @@ name = "fuchsia-zircon-sys"
|
|||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "gif"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"color_quant 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glib"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gobject-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glib-sys"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gobject-sys"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gstreamer"
|
||||
version = "0.11.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gobject-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"muldiv 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-rational 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gstreamer-app"
|
||||
version = "0.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gobject-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer 0.11.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer-app-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer-base 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer-base-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gstreamer-app-sys"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"glib-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer-base-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gstreamer-base"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gobject-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer 0.11.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer-base-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gstreamer-base-sys"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gobject-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gstreamer-sys"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gobject-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hunter"
|
||||
version = "1.1.4"
|
||||
dependencies = [
|
||||
"alphanumeric-sort 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"async_value 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"async_value 0.2.3",
|
||||
"chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dirs-2 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer 0.11.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gstreamer-app 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"image 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lscolors 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"notify 4.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"osstrtools 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parse-ansi 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -287,6 +440,31 @@ dependencies = [
|
|||
"users 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "image"
|
||||
version = "0.21.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gif 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"jpeg-decoder 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-rational 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"png 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tiff 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inflate"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inotify"
|
||||
version = "0.6.1"
|
||||
|
@ -314,6 +492,15 @@ dependencies = [
|
|||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jpeg-decoder"
|
||||
version = "0.1.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kernel32-sys"
|
||||
version = "0.2.2"
|
||||
|
@ -359,6 +546,11 @@ dependencies = [
|
|||
"ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lzw"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "1.0.2"
|
||||
|
@ -377,6 +569,25 @@ name = "memoffset"
|
|||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "mime"
|
||||
version = "0.3.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mime_guess"
|
||||
version = "2.0.0-alpha.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.6.16"
|
||||
|
@ -417,6 +628,11 @@ dependencies = [
|
|||
"ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "muldiv"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "net2"
|
||||
version = "0.2.33"
|
||||
|
@ -463,6 +679,16 @@ dependencies = [
|
|||
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-derive"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.39"
|
||||
|
@ -471,6 +697,33 @@ dependencies = [
|
|||
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-iter"
|
||||
version = "0.1.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-rational"
|
||||
version = "0.1.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-rational"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.6"
|
||||
|
@ -489,11 +742,6 @@ name = "numtoa"
|
|||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "objekt"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "ordermap"
|
||||
version = "0.3.5"
|
||||
|
@ -558,6 +806,57 @@ dependencies = [
|
|||
"ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf"
|
||||
version = "0.7.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_codegen"
|
||||
version = "0.7.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_generator"
|
||||
version = "0.7.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_shared"
|
||||
version = "0.7.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "png"
|
||||
version = "0.14.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"deflate 0.7.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"inflate 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "0.4.30"
|
||||
|
@ -586,6 +885,33 @@ dependencies = [
|
|||
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.3.1"
|
||||
|
@ -599,6 +925,32 @@ name = "rand_core"
|
|||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "rand_hc"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_isaac"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_jitter"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_os"
|
||||
version = "0.1.3"
|
||||
|
@ -612,6 +964,23 @@ dependencies = [
|
|||
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_pcg"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_xorshift"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.0.3"
|
||||
|
@ -728,6 +1097,11 @@ dependencies = [
|
|||
"libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "siphasher"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.2"
|
||||
|
@ -797,6 +1171,17 @@ dependencies = [
|
|||
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tiff"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-derive 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.1.42"
|
||||
|
@ -824,6 +1209,22 @@ name = "ucd-util"
|
|||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "unicase"
|
||||
version = "1.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicase"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.5"
|
||||
|
@ -847,6 +1248,11 @@ name = "utf8-ranges"
|
|||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.2.7"
|
||||
|
@ -904,26 +1310,29 @@ dependencies = [
|
|||
]
|
||||
|
||||
[metadata]
|
||||
"checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c"
|
||||
"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"
|
||||
"checksum argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f67b0b6a86dae6e67ff4ca2b6201396074996379fba2b92ff649126f37cb392"
|
||||
"checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71"
|
||||
"checksum async_value 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1c4cd683ef2421e8767b2a0c02b105707812a98a4e1eb0559f615a15e3a80183"
|
||||
"checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799"
|
||||
"checksum backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "f106c02a3604afcdc0df5d36cc47b44b55917dbaf3d808f71c163a0ddba64637"
|
||||
"checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6"
|
||||
"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
|
||||
"checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400"
|
||||
"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb"
|
||||
"checksum bytesize 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "16d794c5fe594cfa8fbe8ae274de4048176c69f2d9ac5e637166e73b71d460b8"
|
||||
"checksum cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)" = "a0c56216487bb80eec9c4516337b2588a4f2a2290d72a1416d930e4dcdb0c90d"
|
||||
"checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4"
|
||||
"checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878"
|
||||
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
|
||||
"checksum color_quant 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0dbbb57365263e881e805dc77d94697c9118fd94d8da011240555aa7b23445bd"
|
||||
"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e"
|
||||
"checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3"
|
||||
"checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150"
|
||||
"checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9"
|
||||
"checksum deflate 0.7.19 (registry+https://github.com/rust-lang/crates.io-index)" = "8a6abb26e16e8d419b5c78662aa9f82857c2386a073da266840e474d5055ec86"
|
||||
"checksum dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3fd78930633bd1c6e35c4b42b1df7b0cbc6bc191146e512bb3bedf243fcc3901"
|
||||
"checksum dirs-2 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "50b7e2b65c73137ec48935d50a5ae89b03150df566b7e14a1371df044e76765c"
|
||||
"checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b"
|
||||
|
@ -937,9 +1346,22 @@ dependencies = [
|
|||
"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
|
||||
"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
|
||||
"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
|
||||
"checksum gif 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4bca55ac1f213920ce3527ccd62386f1f15fa3f1714aeee1cf93f2c416903f"
|
||||
"checksum glib 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5e0be1b1432e227bcd1a9b28db9dc1474a7e7fd4227e08e16f35304f32d09b61"
|
||||
"checksum glib-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "615bef979b5838526aee99241afc80cfb2e34a8735d4bcb8ec6072598c18a408"
|
||||
"checksum gobject-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "70409d6405db8b1591602fcd0cbe8af52cd9976dd39194442b4c149ba343f86d"
|
||||
"checksum gstreamer 0.11.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6c5a43723784a8b3a308541f3752370ee0ee3b6dc26ed50cdd06e8d9f5399cc"
|
||||
"checksum gstreamer-app 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4e68d96a6a86fe4e4796d7ecb5a3cacd6b4680277da6daea7934612fa8c5c2bf"
|
||||
"checksum gstreamer-app-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a224d33c7780957c30f9280b1256b3882792dda6916f75b54bb30b5b71ed505a"
|
||||
"checksum gstreamer-base 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05ec7a84b4160b61c72ea27ccf3f46eb9c8f996c5991746623e69e3e532e3cb5"
|
||||
"checksum gstreamer-base-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "501a7add44f256aab6cb5b65ef121c449197cf55087d6a7586846c8d1e42e88b"
|
||||
"checksum gstreamer-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b2f51e25a6f97dd4bfd640cba96f192f8759b8766afd66d6d9ea0f82ca14a37"
|
||||
"checksum image 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)" = "293e54ce142a936a39da748ba8178ae6aa1914b82d846a4278f11590c89bf116"
|
||||
"checksum inflate 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1cdb29978cc5797bd8dcc8e5bf7de604891df2a8dc576973d71a281e916db2ff"
|
||||
"checksum inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40b54539f3910d6f84fbf9a643efd6e3aa6e4f001426c0329576128255994718"
|
||||
"checksum inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e74a1aa87c59aeff6ef2cc2fa62d41bc43f54952f55652656b18a02fd5e356c0"
|
||||
"checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08"
|
||||
"checksum jpeg-decoder 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c8b7d43206b34b3f94ea9445174bda196e772049b9bddbc620c9d29b2d20110d"
|
||||
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
||||
"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73"
|
||||
"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14"
|
||||
|
@ -947,22 +1369,29 @@ dependencies = [
|
|||
"checksum libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)" = "c6785aa7dd976f5fbf3b71cfd9cd49d7f783c1ff565a858d71031c6c313aa5c6"
|
||||
"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 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"
|
||||
"checksum mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "3e27ca21f40a310bd06d9031785f4801710d566c184a6e15bad4f1d9b65f9425"
|
||||
"checksum mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30de2e4613efcba1ec63d8133f344076952090c122992a903359be5a4f99c3ed"
|
||||
"checksum mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "71646331f2619b1026cc302f87a2b8b648d5c6dd6937846a16cc8ce0f347f432"
|
||||
"checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40"
|
||||
"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
|
||||
"checksum muldiv 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1cbef5aa2e8cd82a18cc20e26434cc9843e1ef46e55bfabe5bddb022236c5b3e"
|
||||
"checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88"
|
||||
"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945"
|
||||
"checksum nom 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf51a729ecf40266a2368ad335a5fdde43471f545a967109cd62146ecf8b66ff"
|
||||
"checksum nom 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05aec50c70fd288702bcd93284a8444607f3292dbdf2a30de5ea5dcdbe72287b"
|
||||
"checksum notify 4.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "ceb1a496a81dd6125f68ce772b41b83efe89a54d21768ed6d0c33c95832604e6"
|
||||
"checksum num-derive 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "eafd0b45c5537c3ba526f79d3e75120036502bebacbb3f3220914067ce39dbf2"
|
||||
"checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea"
|
||||
"checksum num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "af3fdbbc3291a5464dc57b03860ec37ca6bf915ed6ee385e7c6c052c422b2124"
|
||||
"checksum num-rational 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "ee314c74bd753fc86b4780aa9475da469155f3848473a261d2d18e35245a784e"
|
||||
"checksum num-rational 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4e96f040177bb3da242b5b1ecf3f54b5d5af3efbbfb18608977a5d2767b22f10"
|
||||
"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1"
|
||||
"checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba"
|
||||
"checksum numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef"
|
||||
"checksum objekt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2069a3ae3dad97a4ae47754e8f47e5d2f1fd32ab7ad8a84bb31d051faa59cc3c"
|
||||
"checksum ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063"
|
||||
"checksum osstrtools 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "63557d11f265b66ffcda9cc624d5f92315cfeebb7ee01c76257f890f7d730f5b"
|
||||
"checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37"
|
||||
|
@ -971,12 +1400,25 @@ dependencies = [
|
|||
"checksum parse-ansi 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "50c48b4d524f8a10bf6ab37dc0b7583f17c8ec88b617b364ddfc3baee4dcf878"
|
||||
"checksum pathbuftools 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "908eefc77ffb9f995c7eb707eed61e66ef34fa66a735673517e65a34da3ef7a0"
|
||||
"checksum petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3659d1ee90221741f65dd128d9998311b0e40c5d3c23a62445938214abce4f"
|
||||
"checksum phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b3da44b85f8e8dfaec21adae67f95d93244b2ecf6ad2a692320598dcc8e6dd18"
|
||||
"checksum phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b03e85129e324ad4166b06b2c7491ae27fe3ec353af72e72cd1654c7225d517e"
|
||||
"checksum phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662"
|
||||
"checksum phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0"
|
||||
"checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c"
|
||||
"checksum png 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "63daf481fdd0defa2d1d2be15c674fbfa1b0fd71882c303a91f9a79b3252c359"
|
||||
"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
|
||||
"checksum quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db"
|
||||
"checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"
|
||||
"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
|
||||
"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
|
||||
"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
|
||||
"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0"
|
||||
"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
|
||||
"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
|
||||
"checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b"
|
||||
"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
|
||||
"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
|
||||
"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
|
||||
"checksum rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "373814f27745b2686b350dd261bfd24576a6fb0e2c5919b3a2b6005f820b0473"
|
||||
"checksum rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b055d1e92aba6877574d8fe604a63c8b5df60f60e5982bf7ccbb1338ea527356"
|
||||
"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
|
||||
|
@ -991,6 +1433,7 @@ 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 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 slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
|
||||
"checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be"
|
||||
"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8"
|
||||
|
@ -999,13 +1442,17 @@ dependencies = [
|
|||
"checksum systemstat 0.1.5 (git+https://github.com/myfreeweb/systemstat)" = "<none>"
|
||||
"checksum termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dde0593aeb8d47accea5392b39350015b5eccb12c0d98044d856983d89548dea"
|
||||
"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"
|
||||
"checksum tree_magic 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8ed063ec7b632ba8173200d7e818db4ba01564b6c085c1a7d1041b93b55b0e02"
|
||||
"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86"
|
||||
"checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33"
|
||||
"checksum unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a84e5511b2a947f3ae965dcb29b13b7b1691b6e7332cf5dbc1744138d5acb7f6"
|
||||
"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 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737"
|
||||
"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
|
||||
"checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1"
|
||||
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
|
||||
"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770"
|
||||
|
|
28
Cargo.toml
28
Cargo.toml
|
@ -29,9 +29,35 @@ notify = "4.0.9"
|
|||
parse-ansi = "0.1.6"
|
||||
signal-notify = "0.1.3"
|
||||
systemstat = "0.1.4"
|
||||
mime_guess = "2.0.0-alpha.6"
|
||||
|
||||
osstrtools = "0.1"
|
||||
pathbuftools = "0.1"
|
||||
async_value = "0.2.2"
|
||||
|
||||
|
||||
|
||||
image = { version = "0.21.1", optional = true }
|
||||
gstreamer = { version = "0.11.2", optional = true }
|
||||
gstreamer-app = { version = "0.11.2", optional = true }
|
||||
|
||||
[dependencies.async_value]
|
||||
path = "../async_value/"
|
||||
|
||||
[features]
|
||||
default = ["img", "video"]
|
||||
img = ["image"]
|
||||
video = ["img", "gstreamer", "gstreamer-app"]
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "hunter"
|
||||
path = "src/main.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "preview-gen"
|
||||
path = "src/media_preview.rs"
|
||||
required-features = ["img"]
|
||||
|
||||
|
||||
[patch.crates-io]
|
||||
systemstat = { git = 'https://github.com/myfreeweb/systemstat' }
|
||||
|
|
36
README.md
36
README.md
|
@ -29,6 +29,7 @@ A big thanks to ranger and its developers. Without its inspiration this wouldn't
|
|||
* Exit and cd into last directory and put selected files into shell variables
|
||||
* Slide up animation for previews for a smoother experience (configurable)
|
||||
* Can show icons with the [right fonts](https://github.com/ryanoasis/nerd-fonts)
|
||||
* Optional support for previews of image/video/audio files using Unicode half-block drawing
|
||||
|
||||
|
||||
|
||||
|
@ -45,16 +46,21 @@ If it works on a system not mentioned here, please open an issue. Also feel free
|
|||
* gcc
|
||||
* libmagic-dev
|
||||
* Rust-nighly compiler
|
||||
* GStreamer for video/audio previews
|
||||
|
||||
### Debian/Ubuntu
|
||||
|
||||
* ```apt install gcc libmagic-dev```
|
||||
* ```apt install gcc libmagic-dev gstreamer1.0-devel gst-plugins-base gst-plugins-good```
|
||||
|
||||
## INSTALLATION:
|
||||
|
||||
Compiling hunter currently requires a nightly Rust compiler!
|
||||
The easiest way to get a nightly compiler is with [rustup](https://rustup.rs/). If you have rustup installed it will automatically download and use a version that is known to work when you run cargo.
|
||||
|
||||
By default it will install a full-featured version with support for media-previews. You can control this using the feature flags ```img```, and ```video```. These can be disabled by calling cargo with ```--features ""```, if you want to disable all media previews, or ```--features=img"``` if you only want to disable video/audio previews.
|
||||
|
||||
Note that this only works if hunter can find the "preview-gen" tool somewhere in $PATH!
|
||||
|
||||
### Install rustup
|
||||
|
||||
```
|
||||
|
@ -65,34 +71,26 @@ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
|||
### Build with cargo
|
||||
|
||||
```
|
||||
cargo install hunter
|
||||
cargo install (--features=...) hunter
|
||||
```
|
||||
|
||||
|
||||
### Build from source
|
||||
|
||||
```
|
||||
// Clone the git repo
|
||||
git clone https://github.com/rabite0/hunter.git
|
||||
// Clone the git repo
|
||||
git clone https://github.com/rabite0/hunter.git
|
||||
|
||||
// Go into the repos directory
|
||||
cd {source_dir}/hunter/
|
||||
|
||||
// Note: if you want vim bindings you will have to switch to the evil branch.
|
||||
// git checkout evil
|
||||
// (Optional) Build
|
||||
// cargo build --release (--features=...)
|
||||
|
||||
// Build
|
||||
cargo build --release
|
||||
// Install
|
||||
cargo install (--features=...) --path .
|
||||
```
|
||||
|
||||
###
|
||||
|
||||
This will create a binary in {source_dir}/hunter/target/release/hunter. If you want to call this like any other terminal app you have to put this binary in your path.
|
||||
|
||||
```ln -s {source_dir}/hunter/target/release/hunter /usr/bin/local/hunter```
|
||||
|
||||
This will link the the binary to your local bin file. You can call hunter from anywhere. To update repeat the process, but you will **not** need to redo the binary link.
|
||||
|
||||
## NOTE:
|
||||
hunter uses [ranger's rifle](https://github.com/ranger/ranger/blob/master/ranger/ext/rifle.py) to open files if rifle is in your $PATH. If it can't find rifle it uses xdg-open. It also uses ranger's scope.sh to generate previews for non-text files. A slightly modified version is included in the "extra" directory. Put it in your $PATH somewhere if you want previews for non-text files.
|
||||
|
||||
|
@ -105,6 +103,8 @@ show_hidden=off
|
|||
select_cmd=find -type f | fzf -m
|
||||
cd_cmd=find -type d | fzf
|
||||
icons=off
|
||||
media_autostart=off
|
||||
media_mute=off
|
||||
```
|
||||
|
||||
## Drop into hunter cwd on quit
|
||||
|
@ -160,6 +160,10 @@ By default hunter uses vi-style keybindings. If you use a QWERTY-like keyboard l
|
|||
| z | open subshell in cwd |
|
||||
| c | toggle columns |
|
||||
| F(n) | switch to tab |
|
||||
| Alt(m) | toggle media pause and autoplay |
|
||||
| Alt(M) | toggle media mute |
|
||||
| Alt(>) | seek media +5s |
|
||||
| Alt(<) | seek media -5s |
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -7,7 +7,9 @@ pub struct Config {
|
|||
pub show_hidden: bool,
|
||||
pub select_cmd: String,
|
||||
pub cd_cmd: String,
|
||||
pub icons: bool
|
||||
pub icons: bool,
|
||||
pub media_autoplay: bool,
|
||||
pub media_mute: bool,
|
||||
}
|
||||
|
||||
|
||||
|
@ -18,7 +20,9 @@ impl Config {
|
|||
show_hidden: false,
|
||||
select_cmd: "find -type f | fzf -m".to_string(),
|
||||
cd_cmd: "find -type d | fzf".to_string(),
|
||||
icons: false
|
||||
icons: false,
|
||||
media_autoplay: false,
|
||||
media_mute: false
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -47,6 +51,10 @@ impl Config {
|
|||
let cmd = cmd.to_string();
|
||||
config.cd_cmd = cmd;
|
||||
}
|
||||
Ok(("media_autoplay", "on")) => { config.media_autoplay = true; },
|
||||
Ok(("media_autoplay", "off")) => { config.media_autoplay = false; },
|
||||
Ok(("media_mute", "on")) => { config.media_mute = true; },
|
||||
Ok(("media_mute", "off")) => { config.media_mute = false; },
|
||||
_ => { HError::config_error::<Config>(line.to_string()).log(); }
|
||||
}
|
||||
config
|
||||
|
|
19
src/fail.rs
19
src/fail.rs
|
@ -97,6 +97,10 @@ pub enum HError {
|
|||
ConfigLineError(String),
|
||||
#[fail(display = "New input in Minibuffer")]
|
||||
MiniBufferInputUpdated(String),
|
||||
#[fail(display = "Failed to parse into UTF8")]
|
||||
UTF8ParseError(std::str::Utf8Error),
|
||||
#[fail(display = "Failed to parse integer!")]
|
||||
ParseIntError(std::num::ParseIntError),
|
||||
}
|
||||
|
||||
impl HError {
|
||||
|
@ -308,3 +312,18 @@ impl From<async_value::AError> for HError {
|
|||
err
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::str::Utf8Error> for HError {
|
||||
fn from(error: std::str::Utf8Error) -> Self {
|
||||
let err = HError::UTF8ParseError(error);
|
||||
err
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl From<std::num::ParseIntError> for HError {
|
||||
fn from(error: std::num::ParseIntError) -> Self {
|
||||
let err = HError::ParseIntError(error);
|
||||
err
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1280,7 +1280,12 @@ impl Widget for FileBrowser {
|
|||
Key::Char('g') => self.show_log()?,
|
||||
Key::Char('z') => self.run_subshell()?,
|
||||
Key::Char('c') => self.toggle_colums(),
|
||||
_ => { self.main_widget_mut()?.on_key(key)?; },
|
||||
_ => {
|
||||
let main_widget_result = self.main_widget_mut()?.on_key(key);
|
||||
if let Err(HError::WidgetUndefinedKeyError{..}) = main_widget_result {
|
||||
self.preview_widget_mut()?.on_key(key)?;
|
||||
}
|
||||
},
|
||||
}
|
||||
if !self.columns.zoom_active { self.update_preview().log(); }
|
||||
Ok(())
|
||||
|
|
11
src/files.rs
11
src/files.rs
|
@ -18,6 +18,8 @@ use failure::Error;
|
|||
use notify::DebouncedEvent;
|
||||
use rayon::{ThreadPool, ThreadPoolBuilder};
|
||||
use alphanumeric_sort::compare_str;
|
||||
use mime_guess;
|
||||
|
||||
use pathbuftools::PathBufTools;
|
||||
use async_value::{Async, Stale};
|
||||
|
||||
|
@ -830,9 +832,12 @@ impl File {
|
|||
Ok((size, unit))
|
||||
}
|
||||
|
||||
// pub fn get_mime(&self) -> String {
|
||||
// tree_magic::from_filepath(&self.path)
|
||||
// }
|
||||
pub fn get_mime(&self) -> Option<mime_guess::Mime> {
|
||||
if let Some(ext) = self.path.extension() {
|
||||
let mime = mime_guess::get_mime_type(&ext.to_string_lossy());
|
||||
Some(mime)
|
||||
} else { None }
|
||||
}
|
||||
|
||||
pub fn is_text(&self) -> bool {
|
||||
tree_magic::match_filepath("text/plain", &self.path)
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
use crate::widget::{Widget, WidgetCore};
|
||||
use crate::fail::HResult;
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
impl std::cmp::PartialEq for ImgView {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.core == other.core &&
|
||||
self.buffer == other.buffer
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ImgView {
|
||||
pub core: WidgetCore,
|
||||
pub buffer: Vec<String>,
|
||||
pub file: PathBuf
|
||||
}
|
||||
|
||||
impl ImgView {
|
||||
pub fn new_from_file(core: WidgetCore, file: &Path) -> HResult<ImgView> {
|
||||
let (xsize, ysize) = core.coordinates.size_u();
|
||||
|
||||
let output = std::process::Command::new("preview-gen")
|
||||
.arg(format!("{}", (xsize)))
|
||||
.arg(format!("{}", (ysize+1)))
|
||||
.arg("image")
|
||||
.arg(format!("true"))
|
||||
.arg(format!("true"))
|
||||
.arg(file.to_string_lossy().to_string())
|
||||
.output()?
|
||||
.stdout;
|
||||
|
||||
let output = std::str::from_utf8(&output)?;
|
||||
let output = output.lines()
|
||||
.map(|l| l.to_string())
|
||||
.collect();
|
||||
|
||||
Ok(ImgView {
|
||||
core: core,
|
||||
buffer: output,
|
||||
file: file.to_path_buf()
|
||||
})
|
||||
}
|
||||
|
||||
pub fn set_image_data(&mut self, img_data: Vec<String>) {
|
||||
self.buffer = img_data;
|
||||
}
|
||||
|
||||
pub fn lines(&self) -> usize {
|
||||
self.buffer.len()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl Widget for ImgView {
|
||||
fn get_core(&self) -> HResult<&WidgetCore> {
|
||||
Ok(&self.core)
|
||||
}
|
||||
|
||||
fn get_core_mut(&mut self) -> HResult<&mut WidgetCore> {
|
||||
Ok(&mut self.core)
|
||||
}
|
||||
|
||||
fn refresh(&mut self) -> HResult<()> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_drawlist(&self) -> HResult<String> {
|
||||
let (xpos, ypos) = self.core.coordinates.position_u();
|
||||
|
||||
let mut draw = self.buffer
|
||||
.iter()
|
||||
.enumerate()
|
||||
.fold(String::new(), |mut draw, (pos, line)| {
|
||||
draw += &format!("{}", crate::term::goto_xy_u(xpos+1,
|
||||
ypos + pos));
|
||||
draw += line;
|
||||
draw
|
||||
});
|
||||
|
||||
draw += &format!("{}", termion::style::Reset);
|
||||
|
||||
Ok(draw)
|
||||
}
|
||||
}
|
|
@ -21,6 +21,8 @@ extern crate parse_ansi;
|
|||
extern crate signal_notify;
|
||||
extern crate tree_magic;
|
||||
extern crate systemstat;
|
||||
extern crate mime_guess;
|
||||
|
||||
extern crate osstrtools;
|
||||
extern crate pathbuftools;
|
||||
extern crate async_value;
|
||||
|
@ -52,6 +54,11 @@ mod config;
|
|||
mod stats;
|
||||
mod icon;
|
||||
|
||||
#[cfg(feature = "img")]
|
||||
mod imgview;
|
||||
#[cfg(feature = "video")]
|
||||
mod mediaview;
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,442 @@
|
|||
use lazy_static;
|
||||
use termion::event::{Event, Key};
|
||||
|
||||
use crate::widget::{Widget, WidgetCore};
|
||||
use crate::async_value::Stale;
|
||||
use crate::fail::{HResult, HError, ErrorLog};
|
||||
use crate::imgview::ImgView;
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::{Arc, Mutex, RwLock,
|
||||
mpsc::{channel, Sender}};
|
||||
|
||||
use std::io::{BufRead, BufReader, Write};
|
||||
use std::process::Child;
|
||||
|
||||
impl std::cmp::PartialEq for MediaView {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.core == other.core
|
||||
}
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref MUTE: Arc<RwLock<bool>> = Arc::new(RwLock::new(false));
|
||||
static ref AUTOPLAY: Arc<RwLock<bool>> = Arc::new(RwLock::new(true));
|
||||
}
|
||||
|
||||
pub struct MediaView {
|
||||
core: WidgetCore,
|
||||
imgview: Arc<Mutex<ImgView>>,
|
||||
file: PathBuf,
|
||||
controller: Sender<String>,
|
||||
paused: bool,
|
||||
media_type: MediaType,
|
||||
position: Arc<Mutex<usize>>,
|
||||
duration: Arc<Mutex<usize>>,
|
||||
stale: Stale,
|
||||
process: Arc<Mutex<Option<Child>>>,
|
||||
preview_runner: Option<Box<dyn FnOnce(bool,
|
||||
bool,
|
||||
Arc<Mutex<usize>>,
|
||||
Arc<Mutex<usize>>)
|
||||
-> HResult<()> + Send + 'static>>
|
||||
}
|
||||
|
||||
#[derive(Clone,Debug)]
|
||||
pub enum MediaType {
|
||||
Video,
|
||||
Audio
|
||||
}
|
||||
|
||||
impl MediaType {
|
||||
pub fn to_str(&self) -> &str {
|
||||
match self {
|
||||
MediaType::Video => "video",
|
||||
MediaType::Audio => "audio"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MediaView {
|
||||
pub fn new_from_file(core: WidgetCore,
|
||||
file: &Path,
|
||||
media_type: MediaType) -> MediaView {
|
||||
let (xsize, ysize) = core.coordinates.size_u();
|
||||
let (tx_cmd, rx_cmd) = channel();
|
||||
|
||||
let imgview = ImgView {
|
||||
core: core.clone(),
|
||||
buffer: vec![],
|
||||
file: file.to_path_buf()
|
||||
};
|
||||
|
||||
let imgview = Arc::new(Mutex::new(imgview));
|
||||
let thread_imgview = imgview.clone();
|
||||
|
||||
let path = file.to_string_lossy().to_string();
|
||||
let sender = core.get_sender();
|
||||
let stale = Stale::new();
|
||||
let tstale = stale.clone();
|
||||
let rx_cmd = Arc::new(Mutex::new(rx_cmd));
|
||||
let process = Arc::new(Mutex::new(None));
|
||||
let cprocess = process.clone();
|
||||
let ctype = media_type.clone();
|
||||
|
||||
|
||||
let run_preview = Box::new(move | auto,
|
||||
mute,
|
||||
position: Arc<Mutex<usize>>,
|
||||
duration: Arc<Mutex<usize>>| -> HResult<()> {
|
||||
loop {
|
||||
if tstale.is_stale()? {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut previewer = std::process::Command::new("preview-gen")
|
||||
.arg(format!("{}", (xsize)))
|
||||
// Leave space for position/seek bar
|
||||
.arg(format!("{}", (ysize-3)))
|
||||
.arg(format!("{}", ctype.to_str()))
|
||||
.arg(format!("{}", auto))
|
||||
.arg(format!("{}", mute))
|
||||
.arg(&path)
|
||||
.stdin(std::process::Stdio::piped())
|
||||
.stdout(std::process::Stdio::piped())
|
||||
.stderr(std::process::Stdio::inherit())
|
||||
.spawn()?;
|
||||
|
||||
let mut stdout = BufReader::new(previewer.stdout.take()?);
|
||||
let mut stdin = previewer.stdin.take()?;
|
||||
|
||||
cprocess.lock().map(|mut p| *p = Some(previewer))?;
|
||||
|
||||
let mut frame = vec![];
|
||||
let newline = String::from("\n");
|
||||
let mut line_buf = String::new();
|
||||
let rx_cmd = rx_cmd.clone();
|
||||
|
||||
std::thread::spawn(move || -> HResult<()> {
|
||||
for cmd in rx_cmd.lock()?.iter() {
|
||||
write!(stdin, "{}", cmd)?;
|
||||
write!(stdin, "\n")?;
|
||||
stdin.flush()?;
|
||||
}
|
||||
Ok(())
|
||||
});
|
||||
|
||||
loop {
|
||||
// Check if preview-gen finished and break out of loop to restart
|
||||
if let Ok(Some(code)) = cprocess.lock()?
|
||||
.as_mut()?
|
||||
.try_wait() {
|
||||
if code.success() {
|
||||
break;
|
||||
} else { return Ok(()); }
|
||||
}
|
||||
|
||||
|
||||
stdout.read_line(&mut line_buf)?;
|
||||
|
||||
|
||||
// Newline means frame is complete
|
||||
if line_buf == newline {
|
||||
line_buf.clear();
|
||||
stdout.read_line(&mut line_buf)?;
|
||||
let pos = &line_buf.trim();
|
||||
*position.lock().unwrap() = pos
|
||||
.parse::<usize>()?;
|
||||
|
||||
|
||||
line_buf.clear();
|
||||
stdout.read_line(&mut line_buf)?;
|
||||
let dur = &line_buf.trim();
|
||||
*duration.lock().unwrap() = dur
|
||||
.parse::<usize>()?;
|
||||
|
||||
|
||||
if let Ok(mut imgview) = thread_imgview.lock() {
|
||||
imgview.set_image_data(frame);
|
||||
sender.send(crate::widget::Events::WidgetReady)
|
||||
.map_err(|e| HError::from(e))
|
||||
.log();;
|
||||
}
|
||||
|
||||
line_buf.clear();
|
||||
frame = vec![];
|
||||
continue;
|
||||
} else {
|
||||
frame.push(line_buf);
|
||||
line_buf = String::new();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
MediaView {
|
||||
core: core.clone(),
|
||||
imgview: imgview,
|
||||
file: file.to_path_buf(),
|
||||
media_type: media_type,
|
||||
controller: tx_cmd,
|
||||
paused: false,
|
||||
position: Arc::new(Mutex::new(0)),
|
||||
duration: Arc::new(Mutex::new(0)),
|
||||
stale: stale,
|
||||
process: process,
|
||||
preview_runner: Some(run_preview)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start_video(&mut self) -> HResult<()> {
|
||||
let runner = self.preview_runner.take();
|
||||
let stale = self.stale.clone();
|
||||
let autoplay = self.autoplay();
|
||||
let mute = self.mute();
|
||||
let position = self.position.clone();
|
||||
let duration = self.duration.clone();
|
||||
|
||||
if runner.is_some() {
|
||||
self.clear().log();
|
||||
std::thread::spawn(move || -> HResult<()> {
|
||||
let sleeptime = std::time::Duration::from_millis(50);
|
||||
std::thread::sleep(sleeptime);
|
||||
|
||||
if !stale.is_stale()? {
|
||||
runner.map(|runner| runner(autoplay,
|
||||
mute,
|
||||
position,
|
||||
duration));
|
||||
}
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn play(&self) -> HResult<()> {
|
||||
Ok(self.controller.send(String::from("p"))?)
|
||||
}
|
||||
|
||||
pub fn pause(&self) -> HResult<()> {
|
||||
Ok(self.controller.send(String::from ("a"))?)
|
||||
}
|
||||
|
||||
pub fn progress_bar(&self) -> HResult<String> {
|
||||
let xsize = self.core.coordinates.xsize_u();
|
||||
|
||||
let position = self.position.lock()?.clone();
|
||||
let duration = self.duration.lock()?.clone();
|
||||
|
||||
if duration == 0 || position == 0 {
|
||||
Ok(format!("{:elements$}", "|", elements=xsize))
|
||||
} else {
|
||||
let element_percent = 100 as f32 / xsize as f32;
|
||||
let progress_percent = position as f32 / duration as f32 * 100 as f32;
|
||||
let element_count = progress_percent as f32 / element_percent as f32;
|
||||
|
||||
Ok(format!("{:|>elements$}|{: >empty$}",
|
||||
"",
|
||||
"",
|
||||
empty=xsize - (element_count as usize + 1),
|
||||
elements=element_count as usize))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn progress_string(&self) -> HResult<String> {
|
||||
let position = self.position.lock()?.clone();
|
||||
let duration = self.duration.lock()?.clone();
|
||||
|
||||
let fposition = self.format_secs(position);
|
||||
let fduration = self.format_secs(duration);
|
||||
|
||||
Ok(format!("{} / {}", fposition, fduration))
|
||||
}
|
||||
|
||||
pub fn get_icons(&self, lines: usize) -> HResult<String> {
|
||||
let (xpos, ypos) = self.core.coordinates.position_u();
|
||||
let (xsize, _) = self.core.coordinates.size_u();
|
||||
|
||||
let mute_char = "🔇";
|
||||
let pause_char = "⏸";
|
||||
let play_char = "⏴";
|
||||
|
||||
let mut icons = String::new();
|
||||
|
||||
if *MUTE.read()? == true {
|
||||
icons += &crate::term::goto_xy_u(xpos+xsize-2, ypos+lines);
|
||||
icons += mute_char;
|
||||
} else {
|
||||
// Clear the mute symbol, or it doesn't go away
|
||||
icons += &crate::term::goto_xy_u(xpos+xsize-2, ypos+lines);
|
||||
icons += " ";
|
||||
}
|
||||
|
||||
if *AUTOPLAY.read()? == true {
|
||||
icons += &crate::term::goto_xy_u(xpos+xsize-4, ypos+lines);
|
||||
icons += play_char;
|
||||
} else {
|
||||
icons += &crate::term::goto_xy_u(xpos+xsize-4, ypos+lines);
|
||||
icons += pause_char;
|
||||
}
|
||||
|
||||
Ok(icons)
|
||||
}
|
||||
|
||||
pub fn format_secs(&self, secs: usize) -> String {
|
||||
let hours = if secs >= 60*60 { (secs / 60) / 60 } else { 0 };
|
||||
let mins = if secs >= 60 { (secs / 60) %60 } else { 0 };
|
||||
|
||||
|
||||
format!("{:02}:{:02}:{:02}", hours, mins, secs % 60)
|
||||
}
|
||||
|
||||
pub fn toggle_pause(&mut self) -> HResult<()> {
|
||||
let auto = AUTOPLAY.read()?.clone();
|
||||
let pos = self.position.lock()?.clone();
|
||||
|
||||
// This combination means only first frame show, since
|
||||
// self.paused will be false, even with autoplay off
|
||||
if pos == 0 && auto == false && self.paused == false {
|
||||
self.toggle_autoplay();
|
||||
|
||||
// Since GStreamer sucks, just create a new instace
|
||||
let mut view = MediaView::new_from_file(self.core.clone(),
|
||||
&self.file.clone(),
|
||||
self.media_type.clone());
|
||||
|
||||
// Insert buffer to prevent flicker
|
||||
let buffer = self.imgview.lock()?.buffer.clone();
|
||||
view.imgview.lock()?.buffer = buffer;
|
||||
|
||||
view.start_video()?;
|
||||
view.paused = false;
|
||||
view.play()?;
|
||||
std::mem::swap(self, &mut &mut view);
|
||||
|
||||
|
||||
return Ok(())
|
||||
}
|
||||
if self.paused {
|
||||
self.toggle_autoplay();
|
||||
self.play()?;
|
||||
self.paused = false;
|
||||
} else {
|
||||
self.pause()?;
|
||||
self.toggle_autoplay();
|
||||
self.paused = true;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn quit(&self) -> HResult<()> {
|
||||
Ok(self.controller.send(String::from("q"))?)
|
||||
}
|
||||
|
||||
pub fn seek_forward(&self) -> HResult<()> {
|
||||
Ok(self.controller.send(String::from(">"))?)
|
||||
}
|
||||
|
||||
pub fn seek_backward(&self) -> HResult<()> {
|
||||
Ok(self.controller.send(String::from("<"))?)
|
||||
}
|
||||
|
||||
pub fn autoplay(&self) -> bool {
|
||||
if let Ok(autoplay) = AUTOPLAY.read() {
|
||||
return *autoplay;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
pub fn mute(&self) -> bool {
|
||||
if let Ok(mute) = MUTE.read() {
|
||||
return *mute;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
pub fn toggle_autoplay(&self) {
|
||||
if let Ok(mut autoplay) = AUTOPLAY.write() {
|
||||
*autoplay = !*autoplay;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn toggle_mute(&self) {
|
||||
if let Ok(mut mute) = MUTE.write() {
|
||||
*mute = !*mute;
|
||||
if *mute {
|
||||
self.controller.send(String::from("m")).ok();
|
||||
} else {
|
||||
self.controller.send(String::from("u")).ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn kill(&mut self) -> HResult<()> {
|
||||
let proc = self.process.clone();
|
||||
std::thread::spawn(move || -> HResult<()> {
|
||||
proc.lock()?
|
||||
.as_mut()
|
||||
.map(|p| {
|
||||
p.kill().map_err(|e| HError::from(e)).log();
|
||||
p.wait().map_err(|e| HError::from(e)).log();
|
||||
});
|
||||
Ok(())
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Widget for MediaView {
|
||||
fn get_core(&self) -> HResult<&WidgetCore> {
|
||||
Ok(&self.core)
|
||||
}
|
||||
|
||||
fn get_core_mut(&mut self) -> HResult<&mut WidgetCore> {
|
||||
Ok(&mut self.core)
|
||||
}
|
||||
|
||||
fn refresh(&mut self) -> HResult<()> {
|
||||
self.start_video().log();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_drawlist(&self) -> HResult<String> {
|
||||
let (xpos, ypos) = self.core.coordinates.position_u();
|
||||
let progress_str = self.progress_string()?;
|
||||
let progress_bar = self.progress_bar()?;
|
||||
|
||||
let (frame, lines) = self.imgview
|
||||
.lock()
|
||||
.map(|img| (img.get_drawlist(), img.lines()))?;
|
||||
|
||||
let mut frame = frame?;
|
||||
|
||||
frame += &crate::term::goto_xy_u(xpos+1, ypos+lines);
|
||||
frame += &progress_str;
|
||||
frame += &self.get_icons(lines)?;
|
||||
frame += &crate::term::goto_xy_u(xpos+1, ypos+lines+1);
|
||||
frame += &progress_bar;
|
||||
|
||||
Ok(frame)
|
||||
}
|
||||
|
||||
fn on_key(&mut self, key: Key) -> HResult<()> {
|
||||
match key {
|
||||
Key::Alt('>') => self.seek_forward(),
|
||||
Key::Alt('<') => self.seek_backward(),
|
||||
Key::Alt('m') => self.toggle_pause(),
|
||||
Key::Alt('M') => Ok(self.toggle_mute()),
|
||||
_ => self.bad(Event::Key(key))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for MediaView {
|
||||
fn drop(&mut self) {
|
||||
self.stale.set_stale().ok();
|
||||
self.kill().log();
|
||||
|
||||
self.clear().log();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,412 @@
|
|||
// Based on https://github.com/jD91mZM2/termplay
|
||||
// MIT License
|
||||
|
||||
use image::{Pixel, FilterType, DynamicImage, GenericImageView};
|
||||
|
||||
use termion::{color::{Bg, Fg, Rgb},
|
||||
input::TermRead,
|
||||
event::Key};
|
||||
|
||||
#[cfg(feature = "video")]
|
||||
use gstreamer::{self, prelude::*};
|
||||
#[cfg(feature = "video")]
|
||||
use gstreamer_app;
|
||||
|
||||
use failure::{Error, format_err};
|
||||
|
||||
use rayon::prelude::*;
|
||||
|
||||
use std::io::Write;
|
||||
|
||||
pub type MResult<T> = Result<T, Error>;
|
||||
|
||||
fn main() -> MResult<()> {
|
||||
let args = std::env::args().collect::<Vec<String>>();
|
||||
let xsize: usize = args.get(1)
|
||||
.expect("Provide xsize")
|
||||
.parse::<usize>()
|
||||
.unwrap();
|
||||
let ysize = args.get(2)
|
||||
.expect("provide ysize")
|
||||
.parse()
|
||||
.unwrap();
|
||||
let preview_type = args.get(3)
|
||||
.expect("Provide preview type")
|
||||
.parse::<String>()
|
||||
.unwrap();
|
||||
let autoplay = args.get(4)
|
||||
.expect("Autoplay?")
|
||||
.parse::<bool>()
|
||||
.unwrap();
|
||||
let mute = args.get(5)
|
||||
.expect("Muted?")
|
||||
.parse::<bool>()
|
||||
.unwrap();
|
||||
let path = args.get(6).expect("Provide path");
|
||||
|
||||
#[cfg(feature = "video")]
|
||||
let result =
|
||||
match preview_type.as_ref() {
|
||||
"video" => video_preview(path, xsize, ysize, autoplay, mute),
|
||||
"image" => image_preview(path, xsize, ysize),
|
||||
"audio" => audio_preview(path, autoplay, mute),
|
||||
_ => { panic!("Available types: video/image/audio") }
|
||||
};
|
||||
|
||||
|
||||
|
||||
#[cfg(not(feature = "video"))]
|
||||
let result = image_preview(path, xsize, ysize);
|
||||
|
||||
if result.is_err() {
|
||||
println!("{:?}", &result);
|
||||
result
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn image_preview(path: &str,
|
||||
xsize: usize,
|
||||
ysize: usize) -> MResult<()> {
|
||||
let img = image::open(&path)?;
|
||||
|
||||
let renderer = Renderer {
|
||||
xsize,
|
||||
ysize
|
||||
};
|
||||
|
||||
renderer.send_image(img)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn video_preview(path: &String,
|
||||
xsize: usize,
|
||||
ysize: usize,
|
||||
autoplay: bool,
|
||||
mute: bool)
|
||||
-> MResult<()> {
|
||||
let (player, appsink) = make_gstreamer()?;
|
||||
|
||||
let uri = format!("file://{}", &path);
|
||||
|
||||
player.set_property("uri", &uri)?;
|
||||
|
||||
|
||||
let renderer = Renderer {
|
||||
xsize,
|
||||
ysize
|
||||
};
|
||||
|
||||
let p = player.clone();
|
||||
|
||||
appsink.set_callbacks(
|
||||
gstreamer_app::AppSinkCallbacks::new()
|
||||
.new_sample({
|
||||
move |sink| {
|
||||
let sample = match sink.pull_sample() {
|
||||
Some(sample) => sample,
|
||||
None => return gstreamer::FlowReturn::Eos,
|
||||
};
|
||||
|
||||
let position = p.query_position::<gstreamer::ClockTime>()
|
||||
.map(|p| p.seconds().unwrap_or(0))
|
||||
.unwrap_or(0);
|
||||
|
||||
let duration = p.query_duration::<gstreamer::ClockTime>()
|
||||
.map(|d| d.seconds().unwrap_or(0))
|
||||
.unwrap_or(0);
|
||||
|
||||
match renderer.send_frame(&*sample,
|
||||
position,
|
||||
duration) {
|
||||
Ok(()) => {
|
||||
if autoplay == false {
|
||||
// Just render first frame to get a static image
|
||||
match p.set_state(gstreamer::State::Paused)
|
||||
.into_result() {
|
||||
Ok(_) => gstreamer::FlowReturn::Eos,
|
||||
Err(_) => gstreamer::FlowReturn::Error
|
||||
}
|
||||
} else {
|
||||
gstreamer::FlowReturn::Ok
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
println!("{:?}", err);
|
||||
gstreamer::FlowReturn::Error
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
})
|
||||
.eos({
|
||||
move |_| {
|
||||
std::process::exit(0);
|
||||
}
|
||||
})
|
||||
.build()
|
||||
);
|
||||
|
||||
if mute == true || autoplay == false {
|
||||
player.set_property("volume", &0.0)?;
|
||||
}
|
||||
player.set_state(gstreamer::State::Playing).into_result()?;
|
||||
|
||||
|
||||
read_keys(player)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn read_keys(player: gstreamer::Element) -> MResult<()> {
|
||||
let seek_time = gstreamer::ClockTime::from_seconds(5);
|
||||
for key in std::io::stdin().keys() {
|
||||
match key {
|
||||
Ok(Key::Char('q')) => std::process::exit(0),
|
||||
Ok(Key::Char('>')) => {
|
||||
if let Some(mut time) = player.query_position::<gstreamer::ClockTime>() {
|
||||
time += seek_time;
|
||||
|
||||
player.seek_simple(
|
||||
gstreamer::SeekFlags::FLUSH,
|
||||
gstreamer::format::GenericFormattedValue::from_time(time)
|
||||
)?;
|
||||
}
|
||||
},
|
||||
Ok(Key::Char('<')) => {
|
||||
if let Some(mut time) = player.query_position::<gstreamer::ClockTime>() {
|
||||
if time >= seek_time {
|
||||
time -= seek_time;
|
||||
} else {
|
||||
time = gstreamer::ClockTime(Some(0));
|
||||
}
|
||||
|
||||
player.seek_simple(
|
||||
gstreamer::SeekFlags::FLUSH,
|
||||
gstreamer::format::GenericFormattedValue::from_time(time)
|
||||
)?;
|
||||
}
|
||||
}
|
||||
Ok(Key::Char('p')) => {
|
||||
player.set_state(gstreamer::State::Playing).into_result()?;
|
||||
|
||||
// To actually start playing again
|
||||
if let Some(time) = player.query_position::<gstreamer::ClockTime>() {
|
||||
player.seek_simple(
|
||||
gstreamer::SeekFlags::FLUSH,
|
||||
gstreamer::format::GenericFormattedValue::from_time(time)
|
||||
)?;
|
||||
}
|
||||
}
|
||||
Ok(Key::Char('a')) => {
|
||||
player.set_state(gstreamer::State::Paused).into_result()?;
|
||||
}
|
||||
Ok(Key::Char('m')) => {
|
||||
player.set_property("volume", &0.0)?;
|
||||
}
|
||||
Ok(Key::Char('u')) => {
|
||||
player.set_property("volume", &1.0)?;
|
||||
}
|
||||
|
||||
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn audio_preview(path: &String,
|
||||
autoplay: bool,
|
||||
mute: bool)
|
||||
-> MResult<()> {
|
||||
let (player, _) = make_gstreamer()?;
|
||||
|
||||
let uri = format!("file://{}", &path);
|
||||
|
||||
player.set_property("uri", &uri)?;
|
||||
let p = player.clone();
|
||||
|
||||
// Since events don't work with audio files...
|
||||
std::thread::spawn(move || -> MResult<()> {
|
||||
let mut last_pos = None;
|
||||
let sleep_duration = std::time::Duration::from_millis(50);
|
||||
let mut stdout = std::io::stdout();
|
||||
loop {
|
||||
std::thread::sleep(sleep_duration);
|
||||
|
||||
let position = p.query_position::<gstreamer::ClockTime>()
|
||||
.map(|p| p.seconds().unwrap_or(0))
|
||||
.unwrap_or(0);
|
||||
|
||||
let duration = p.query_duration::<gstreamer::ClockTime>()
|
||||
.map(|d| d.seconds().unwrap_or(0))
|
||||
.unwrap_or(0);
|
||||
|
||||
// Just redo loop until position changes
|
||||
if last_pos == Some(position) {
|
||||
continue
|
||||
}
|
||||
|
||||
last_pos = Some(position);
|
||||
|
||||
// MediaView needs empty line as separator
|
||||
writeln!(stdout, "")?;
|
||||
// Send position and duration
|
||||
writeln!(stdout, "{}", position)?;
|
||||
writeln!(stdout, "{}", duration)?;
|
||||
stdout.flush()?;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
if mute == true || autoplay == false{
|
||||
player.set_property("volume", &0.0)?;
|
||||
} else {
|
||||
player.set_state(gstreamer::State::Playing).into_result()?;
|
||||
}
|
||||
|
||||
read_keys(player)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn make_gstreamer() -> MResult<(gstreamer::Element,
|
||||
gstreamer_app::AppSink)> {
|
||||
gstreamer::init()?;
|
||||
|
||||
let player = gstreamer::ElementFactory::make("playbin", None)
|
||||
.ok_or(format_err!("Can't create playbin"))?;
|
||||
|
||||
let videorate = gstreamer::ElementFactory::make("videorate", None)
|
||||
.ok_or(format_err!("Can't create videorate element"))?;
|
||||
|
||||
let pnmenc = gstreamer::ElementFactory::make("pnmenc", None)
|
||||
.ok_or(format_err!("Can't create PNM-encoder"))?;
|
||||
|
||||
let sink = gstreamer::ElementFactory::make("appsink", None)
|
||||
.ok_or(format_err!("Can't create appsink"))?;
|
||||
|
||||
let appsink = sink.clone()
|
||||
.downcast::<gstreamer_app::AppSink>()
|
||||
.unwrap();
|
||||
|
||||
|
||||
videorate.set_property("max-rate", &60)?;
|
||||
|
||||
let elems = &[&videorate, &pnmenc, &sink];
|
||||
|
||||
let bin = gstreamer::Bin::new(None);
|
||||
bin.add_many(elems)?;
|
||||
gstreamer::Element::link_many(elems)?;
|
||||
|
||||
// make input for bin point to first element
|
||||
let sink = elems[0].get_static_pad("sink").unwrap();
|
||||
let ghost = gstreamer::GhostPad::new("sink", &sink)
|
||||
.ok_or(format_err!("Can't create GhostPad"))?;
|
||||
|
||||
ghost.set_active(true)?;
|
||||
bin.add_pad(&ghost)?;
|
||||
|
||||
player.set_property("video-sink", &bin.upcast::<gstreamer::Element>())?;
|
||||
|
||||
Ok((player, appsink))
|
||||
}
|
||||
|
||||
|
||||
struct Renderer {
|
||||
xsize: usize,
|
||||
ysize: usize
|
||||
}
|
||||
|
||||
impl Renderer {
|
||||
fn send_image(&self, image: DynamicImage) -> MResult<()> {
|
||||
let rendered_img = self.render_image(image);
|
||||
|
||||
for line in rendered_img {
|
||||
write!(std::io::stdout(), "{}\n", line)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
fn send_frame(&self,
|
||||
frame: &gstreamer::sample::SampleRef,
|
||||
position: u64,
|
||||
duration: u64)
|
||||
-> MResult<()> {
|
||||
let buffer = frame.get_buffer()
|
||||
.ok_or(format_err!("Couldn't get buffer from frame!"))?;
|
||||
let map = buffer.map_readable()
|
||||
.ok_or(format_err!("Couldn't get buffer from frame!"))?;
|
||||
|
||||
let img = image::load_from_memory_with_format(&map,
|
||||
image::ImageFormat::PNM)?;
|
||||
|
||||
let rendered_img = self.render_image(img);
|
||||
|
||||
for line in rendered_img {
|
||||
writeln!(std::io::stdout(), "{}", line)?;
|
||||
}
|
||||
|
||||
// Empty line means end of frame
|
||||
writeln!(std::io::stdout(), "")?;
|
||||
|
||||
// Send position and duration
|
||||
writeln!(std::io::stdout(), "{}", position)?;
|
||||
writeln!(std::io::stdout(), "{}", duration)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn render_image(&self, image: DynamicImage) -> Vec<String> {
|
||||
let (xsize, ysize) = self.max_size(&image);
|
||||
|
||||
let img = image.resize_exact(xsize as u32,
|
||||
ysize as u32,
|
||||
FilterType::Nearest).to_rgba();
|
||||
|
||||
|
||||
let rows = img.pixels()
|
||||
.collect::<Vec<_>>()
|
||||
.chunks(xsize as usize)
|
||||
.map(|line| line.to_vec())
|
||||
.collect::<Vec<Vec<_>>>();
|
||||
|
||||
rows.par_chunks(2)
|
||||
.map(|rows| {
|
||||
rows[0]
|
||||
.par_iter()
|
||||
.zip(rows[1].par_iter())
|
||||
.map(|(upper, lower)| {
|
||||
let upper_color = upper.to_rgb();
|
||||
let lower_color = lower.to_rgb();
|
||||
|
||||
format!("{}{}▀{}",
|
||||
Fg(Rgb(upper_color[0], upper_color[1], upper_color[2])),
|
||||
Bg(Rgb(lower_color[0], lower_color[1], lower_color[2])),
|
||||
termion::style::Reset
|
||||
)
|
||||
}).collect()
|
||||
}).collect()
|
||||
}
|
||||
|
||||
pub fn max_size(&self, image: &DynamicImage) -> (usize, usize)
|
||||
{
|
||||
let xsize = self.xsize;
|
||||
let img_xsize = image.width();
|
||||
let img_ysize = image.height();
|
||||
let img_ratio = img_xsize as f32 / img_ysize as f32;
|
||||
|
||||
let mut new_y = if img_ratio < 1 as f32 {
|
||||
xsize as f32 * img_ratio
|
||||
} else {
|
||||
xsize as f32 / img_ratio
|
||||
};
|
||||
if new_y as u32 % 2 == 1 {
|
||||
new_y += 1 as f32;
|
||||
}
|
||||
(xsize, new_y as usize)
|
||||
}
|
||||
}
|
160
src/preview.rs
160
src/preview.rs
|
@ -1,6 +1,7 @@
|
|||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use async_value::{Async, Stale};
|
||||
use termion::event::Key;
|
||||
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use crate::files::{File, Files, Kind};
|
||||
use crate::fscache::FsCache;
|
||||
|
@ -11,6 +12,11 @@ use crate::coordinates::Coordinates;
|
|||
use crate::fail::{HResult, HError, ErrorLog};
|
||||
use crate::dirty::Dirtyable;
|
||||
|
||||
#[cfg(feature = "img")]
|
||||
use crate::imgview::ImgView;
|
||||
#[cfg(feature = "video")]
|
||||
use crate::mediaview::MediaView;
|
||||
|
||||
|
||||
pub type AsyncWidgetFn<W> = FnOnce(&Stale, WidgetCore)
|
||||
-> HResult<W> + Send + Sync;
|
||||
|
@ -55,8 +61,10 @@ impl<W: Widget + Send + 'static> AsyncWidget<W> {
|
|||
let sender = Arc::new(Mutex::new(core.get_sender()));
|
||||
let mut widget = Async::new(move |stale|
|
||||
closure(stale).map_err(|e| e.into()));
|
||||
widget.on_ready(move |_, _| {
|
||||
sender.lock().map(|s| s.send(crate::widget::Events::WidgetReady)).ok();
|
||||
widget.on_ready(move |_, stale| {
|
||||
if !stale.is_stale()? {
|
||||
sender.lock().map(|s| s.send(crate::widget::Events::WidgetReady)).ok();
|
||||
}
|
||||
Ok(())
|
||||
}).log();
|
||||
widget.run().log();
|
||||
|
@ -80,7 +88,7 @@ impl<W: Widget + Send + 'static> AsyncWidget<W> {
|
|||
Ok(closure(stale, core.clone())?)
|
||||
});
|
||||
|
||||
widget.on_ready(move |_, _| {
|
||||
widget.on_ready(move |mut w, stale| {
|
||||
sender.lock().map(|s| s.send(crate::widget::Events::WidgetReady)).ok();
|
||||
Ok(())
|
||||
}).log();
|
||||
|
@ -187,7 +195,11 @@ impl PartialEq for Previewer {
|
|||
#[derive(PartialEq)]
|
||||
enum PreviewWidget {
|
||||
FileList(ListView<Files>),
|
||||
TextView(TextView)
|
||||
TextView(TextView),
|
||||
#[cfg(feature = "img")]
|
||||
ImgView(ImgView),
|
||||
#[cfg(feature = "video")]
|
||||
MediaView(MediaView)
|
||||
}
|
||||
|
||||
|
||||
|
@ -311,39 +323,73 @@ impl Previewer {
|
|||
self.animator.set_stale().ok();
|
||||
}
|
||||
|
||||
self.become_preview(Ok(AsyncWidget::new(&self.core,
|
||||
move |stale: &Stale| {
|
||||
kill_proc().unwrap();
|
||||
self.become_preview(Ok(AsyncWidget::new(
|
||||
&self.core,
|
||||
move |stale: &Stale|
|
||||
{
|
||||
kill_proc().unwrap();
|
||||
|
||||
if file.kind == Kind::Directory {
|
||||
let preview = Previewer::preview_dir(&file,
|
||||
cache,
|
||||
&core,
|
||||
&stale,
|
||||
&animator);
|
||||
return Ok(preview?);
|
||||
}
|
||||
if file.kind == Kind::Directory {
|
||||
let preview = Previewer::preview_dir(&file,
|
||||
cache,
|
||||
&core,
|
||||
&stale,
|
||||
&animator);
|
||||
return Ok(preview?);
|
||||
}
|
||||
|
||||
if file.is_text() {
|
||||
return Ok(Previewer::preview_text(&file,
|
||||
&core,
|
||||
&stale,
|
||||
&animator)?);
|
||||
}
|
||||
|
||||
let preview = Previewer::preview_external(&file,
|
||||
if file.is_text() {
|
||||
return Ok(Previewer::preview_text(&file,
|
||||
&core,
|
||||
&stale,
|
||||
&animator);
|
||||
if preview.is_ok() { return Ok(preview?); }
|
||||
else {
|
||||
let mut blank = TextView::new_blank(&core);
|
||||
blank.set_coordinates(&coordinates).log();
|
||||
blank.refresh().log();
|
||||
blank.animate_slide_up(Some(&animator)).log();
|
||||
return Ok(PreviewWidget::TextView(blank))
|
||||
}
|
||||
})))
|
||||
&animator)?);
|
||||
}
|
||||
|
||||
if let Some(mime) = file.get_mime() {
|
||||
let mime_type = mime.type_().as_str();
|
||||
let is_gif = mime.subtype() == "gif";
|
||||
|
||||
match mime_type {
|
||||
#[cfg(feature = "video")]
|
||||
_ if mime_type == "video" || is_gif => {
|
||||
let media_type = crate::mediaview::MediaType::Video;
|
||||
let mediaview = MediaView::new_from_file(core.clone(),
|
||||
&file.path,
|
||||
media_type);
|
||||
return Ok(PreviewWidget::MediaView(mediaview));
|
||||
}
|
||||
#[cfg(feature = "img")]
|
||||
"image" => {
|
||||
let imgview = ImgView::new_from_file(core.clone(),
|
||||
&file.path())?;
|
||||
return Ok(PreviewWidget::ImgView(imgview));
|
||||
}
|
||||
#[cfg(feature = "video")]
|
||||
"audio" => {
|
||||
let media_type = crate::mediaview::MediaType::Audio;
|
||||
let mediaview = MediaView::new_from_file(core.clone(),
|
||||
&file.path,
|
||||
media_type);
|
||||
return Ok(PreviewWidget::MediaView(mediaview));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let preview = Previewer::preview_external(&file,
|
||||
&core,
|
||||
&stale,
|
||||
&animator);
|
||||
if preview.is_ok() { return Ok(preview?); }
|
||||
else {
|
||||
let mut blank = TextView::new_blank(&core);
|
||||
blank.set_coordinates(&coordinates).log();
|
||||
blank.refresh().log();
|
||||
blank.animate_slide_up(Some(&animator)).log();
|
||||
return Ok(PreviewWidget::TextView(blank))
|
||||
}
|
||||
})))
|
||||
}
|
||||
|
||||
pub fn reload(&mut self) {
|
||||
|
@ -454,7 +500,6 @@ impl Previewer {
|
|||
}
|
||||
HError::preview_failed(file)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -487,37 +532,72 @@ impl Widget for Previewer {
|
|||
fn get_drawlist(&self) -> HResult<String> {
|
||||
self.widget.get_drawlist()
|
||||
}
|
||||
|
||||
fn on_key(&mut self, key: Key) -> HResult<()> {
|
||||
self.widget.on_key(key)
|
||||
}
|
||||
}
|
||||
|
||||
impl Widget for PreviewWidget {
|
||||
fn get_core(&self) -> HResult<&WidgetCore> {
|
||||
match self {
|
||||
PreviewWidget::FileList(widget) => widget.get_core(),
|
||||
PreviewWidget::TextView(widget) => widget.get_core()
|
||||
PreviewWidget::TextView(widget) => widget.get_core(),
|
||||
#[cfg(feature = "img")]
|
||||
PreviewWidget::ImgView(widget) => widget.get_core(),
|
||||
#[cfg(feature = "video")]
|
||||
PreviewWidget::MediaView(widget) => widget.get_core()
|
||||
}
|
||||
}
|
||||
fn get_core_mut(&mut self) -> HResult<&mut WidgetCore> {
|
||||
match self {
|
||||
PreviewWidget::FileList(widget) => widget.get_core_mut(),
|
||||
PreviewWidget::TextView(widget) => widget.get_core_mut()
|
||||
PreviewWidget::TextView(widget) => widget.get_core_mut(),
|
||||
#[cfg(feature = "img")]
|
||||
PreviewWidget::ImgView(widget) => widget.get_core_mut(),
|
||||
#[cfg(feature = "video")]
|
||||
PreviewWidget::MediaView(widget) => widget.get_core_mut()
|
||||
}
|
||||
}
|
||||
fn set_coordinates(&mut self, coordinates: &Coordinates) -> HResult<()> {
|
||||
match self {
|
||||
PreviewWidget::FileList(widget) => widget.set_coordinates(coordinates),
|
||||
PreviewWidget::TextView(widget) => widget.set_coordinates(coordinates),
|
||||
#[cfg(feature = "img")]
|
||||
PreviewWidget::ImgView(widget) => widget.set_coordinates(coordinates),
|
||||
#[cfg(feature = "video")]
|
||||
PreviewWidget::MediaView(widget) => widget.set_coordinates(coordinates),
|
||||
}
|
||||
}
|
||||
fn refresh(&mut self) -> HResult<()> {
|
||||
match self {
|
||||
PreviewWidget::FileList(widget) => widget.refresh(),
|
||||
PreviewWidget::TextView(widget) => widget.refresh()
|
||||
PreviewWidget::TextView(widget) => widget.refresh(),
|
||||
#[cfg(feature = "img")]
|
||||
PreviewWidget::ImgView(widget) => widget.refresh(),
|
||||
#[cfg(feature = "video")]
|
||||
PreviewWidget::MediaView(widget) => widget.refresh()
|
||||
}
|
||||
}
|
||||
fn get_drawlist(&self) -> HResult<String> {
|
||||
match self {
|
||||
PreviewWidget::FileList(widget) => widget.get_drawlist(),
|
||||
PreviewWidget::TextView(widget) => widget.get_drawlist()
|
||||
PreviewWidget::TextView(widget) => widget.get_drawlist(),
|
||||
#[cfg(feature = "img")]
|
||||
PreviewWidget::ImgView(widget) => widget.get_drawlist(),
|
||||
#[cfg(feature = "video")]
|
||||
PreviewWidget::MediaView(widget) => widget.get_drawlist()
|
||||
}
|
||||
}
|
||||
|
||||
fn on_key(&mut self, key: Key) -> HResult<()> {
|
||||
match self {
|
||||
PreviewWidget::FileList(widget) => widget.on_key(key),
|
||||
PreviewWidget::TextView(widget) => widget.on_key(key),
|
||||
#[cfg(feature = "img")]
|
||||
PreviewWidget::ImgView(widget) => widget.on_key(key),
|
||||
#[cfg(feature = "video")]
|
||||
PreviewWidget::MediaView(widget) => widget.on_key(key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -159,7 +159,7 @@ pub trait Widget {
|
|||
|
||||
fn on_key(&mut self, key: Key) -> HResult<()> {
|
||||
match key {
|
||||
_ => { self.bad(Event::Key(key)).unwrap() },
|
||||
_ => { self.bad(Event::Key(key))? },
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -179,7 +179,10 @@ pub trait Widget {
|
|||
}
|
||||
|
||||
fn bad(&mut self, event: Event) -> HResult<()> {
|
||||
self.show_status(&format!("Stop it!! {:?} does nothing!", event))
|
||||
self.show_status(&format!("Stop it!! {:?} does nothing!", event)).log();
|
||||
if let Event::Key(key) = event {
|
||||
HError::undefined_key(key)
|
||||
} else { Ok(()) }
|
||||
}
|
||||
|
||||
fn get_header_drawlist(&mut self) -> HResult<String> {
|
||||
|
|
Loading…
Reference in New Issue