diff --git a/Cargo.lock b/Cargo.lock
index 12b08ce..dba51a2 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -27,10 +27,19 @@ dependencies = [
]
[[package]]
-name = "anyhow"
-version = "1.0.65"
+name = "ansi_term"
+version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "98161a4e3e2184da77bb14f02184cdd111e83bbbcc9979dfee3c44b9a85f5602"
+checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "anyhow"
+version = "1.0.66"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6"
[[package]]
name = "atk-sys"
@@ -41,7 +50,18 @@ dependencies = [
"glib-sys 0.15.10",
"gobject-sys 0.15.10",
"libc",
- "system-deps 6.0.2",
+ "system-deps 6.0.3",
+]
+
+[[package]]
+name = "atty"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
+dependencies = [
+ "hermit-abi",
+ "libc",
+ "winapi",
]
[[package]]
@@ -69,22 +89,24 @@ dependencies = [
"chrono",
"dirs",
"gdk-pixbuf 0.9.0",
- "gdk4 0.5.0",
+ "gdk4 0.6.0",
"gettext-rs",
"gio 0.15.12",
"glib 0.10.3",
"gtk-sys",
"gtk4",
+ "ksni",
"regex",
"rust-ini",
+ "secfmt",
"subprocess",
]
[[package]]
name = "bumpalo"
-version = "3.11.0"
+version = "3.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d"
+checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba"
[[package]]
name = "cairo-rs"
@@ -101,12 +123,12 @@ dependencies = [
[[package]]
name = "cairo-rs"
-version = "0.16.0"
-source = "git+https://github.com/gtk-rs/gtk-rs-core#588a146fd86fd6adaa7e682505f3b65f036bd2bf"
+version = "0.17.0"
+source = "git+https://github.com/gtk-rs/gtk-rs-core#8f989cc26bb8021a2b7b22c0ee7654bf501924d2"
dependencies = [
"bitflags",
- "cairo-sys-rs 0.16.0",
- "glib 0.16.0",
+ "cairo-sys-rs 0.17.0",
+ "glib 0.17.0",
"libc",
"once_cell",
"thiserror",
@@ -120,30 +142,30 @@ checksum = "3c55d429bef56ac9172d25fecb85dc8068307d17acd74b377866b7a1ef25d3c8"
dependencies = [
"glib-sys 0.15.10",
"libc",
- "system-deps 6.0.2",
+ "system-deps 6.0.3",
]
[[package]]
name = "cairo-sys-rs"
-version = "0.16.0"
-source = "git+https://github.com/gtk-rs/gtk-rs-core#588a146fd86fd6adaa7e682505f3b65f036bd2bf"
+version = "0.17.0"
+source = "git+https://github.com/gtk-rs/gtk-rs-core#8f989cc26bb8021a2b7b22c0ee7654bf501924d2"
dependencies = [
- "glib-sys 0.16.0",
+ "glib-sys 0.17.0",
"libc",
- "system-deps 6.0.2",
+ "system-deps 6.0.3",
]
[[package]]
name = "cc"
-version = "1.0.73"
+version = "1.0.76"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
+checksum = "76a284da2e6fe2092f2353e51713435363112dfd60030e22add80be333fb928f"
[[package]]
name = "cfg-expr"
-version = "0.10.3"
+version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0aacacf4d96c24b2ad6eb8ee6df040e4f27b0d0b39a5710c30091baa830485db"
+checksum = "b0357a6402b295ca3a86bc148e84df46c02e41f41fef186bda662557ef6328aa"
dependencies = [
"smallvec",
]
@@ -162,9 +184,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
-version = "0.4.22"
+version = "0.4.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1"
+checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f"
dependencies = [
"iana-time-zone",
"js-sys",
@@ -175,6 +197,21 @@ dependencies = [
"winapi",
]
+[[package]]
+name = "clap"
+version = "2.34.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
+dependencies = [
+ "ansi_term",
+ "atty",
+ "bitflags",
+ "strsim",
+ "textwrap",
+ "unicode-width",
+ "vec_map",
+]
+
[[package]]
name = "codespan-reporting"
version = "0.11.1"
@@ -193,9 +230,9 @@ checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
[[package]]
name = "cxx"
-version = "1.0.78"
+version = "1.0.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19f39818dcfc97d45b03953c1292efc4e80954e1583c4aa770bac1383e2310a4"
+checksum = "97abf9f0eca9e52b7f81b945524e76710e6cb2366aead23b7d4fbf72e281f888"
dependencies = [
"cc",
"cxxbridge-flags",
@@ -205,9 +242,9 @@ dependencies = [
[[package]]
name = "cxx-build"
-version = "1.0.78"
+version = "1.0.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3e580d70777c116df50c390d1211993f62d40302881e54d4b79727acb83d0199"
+checksum = "7cc32cc5fea1d894b77d269ddb9f192110069a8a9c1f1d441195fba90553dea3"
dependencies = [
"cc",
"codespan-reporting",
@@ -220,21 +257,52 @@ dependencies = [
[[package]]
name = "cxxbridge-flags"
-version = "1.0.78"
+version = "1.0.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "56a46460b88d1cec95112c8c363f0e2c39afdb237f60583b0b36343bf627ea9c"
+checksum = "8ca220e4794c934dc6b1207c3b42856ad4c302f2df1712e9f8d2eec5afaacf1f"
[[package]]
name = "cxxbridge-macro"
-version = "1.0.78"
+version = "1.0.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "747b608fecf06b0d72d440f27acc99288207324b793be2c17991839f3d4995ea"
+checksum = "b846f081361125bfc8dc9d3940c84e1fd83ba54bbca7b17cd29483c828be0704"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
+[[package]]
+name = "dbus"
+version = "0.9.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f8bcdd56d2e5c4ed26a529c5a9029f5db8290d433497506f958eae3be148eb6"
+dependencies = [
+ "libc",
+ "libdbus-sys",
+ "winapi",
+]
+
+[[package]]
+name = "dbus-codegen"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a49da9fdfbe872d4841d56605dc42efa5e6ca3291299b87f44e1cde91a28617c"
+dependencies = [
+ "clap",
+ "dbus",
+ "xml-rs",
+]
+
+[[package]]
+name = "dbus-tree"
+version = "0.9.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f456e698ae8e54575e19ddb1f9b7bce2298568524f215496b248eb9498b4f508"
+dependencies = [
+ "dbus",
+]
+
[[package]]
name = "dirs"
version = "4.0.0"
@@ -282,9 +350,9 @@ dependencies = [
[[package]]
name = "futures"
-version = "0.3.24"
+version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f21eda599937fba36daeb58a22e8f5cee2d14c4a17b5b7739c7c8e5e3b8230c"
+checksum = "38390104763dc37a5145a53c29c63c1290b5d316d6086ec32c293f6736051bb0"
dependencies = [
"futures-channel",
"futures-core",
@@ -297,9 +365,9 @@ dependencies = [
[[package]]
name = "futures-channel"
-version = "0.3.24"
+version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "30bdd20c28fadd505d0fd6712cdfcb0d4b5648baf45faef7f852afb2399bb050"
+checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed"
dependencies = [
"futures-core",
"futures-sink",
@@ -307,15 +375,15 @@ dependencies = [
[[package]]
name = "futures-core"
-version = "0.3.24"
+version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4e5aa3de05362c3fb88de6531e6296e85cde7739cccad4b9dfeeb7f6ebce56bf"
+checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac"
[[package]]
name = "futures-executor"
-version = "0.3.24"
+version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9ff63c23854bee61b6e9cd331d523909f238fc7636290b96826e9cfa5faa00ab"
+checksum = "7acc85df6714c176ab5edf386123fafe217be88c0840ec11f199441134a074e2"
dependencies = [
"futures-core",
"futures-task",
@@ -324,15 +392,15 @@ dependencies = [
[[package]]
name = "futures-io"
-version = "0.3.24"
+version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbf4d2a7a308fd4578637c0b17c7e1c7ba127b8f6ba00b29f717e9655d85eb68"
+checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb"
[[package]]
name = "futures-macro"
-version = "0.3.24"
+version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42cd15d1c7456c04dbdf7e88bcd69760d74f3a798d6444e16974b505b0e62f17"
+checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d"
dependencies = [
"proc-macro2",
"quote",
@@ -341,21 +409,21 @@ dependencies = [
[[package]]
name = "futures-sink"
-version = "0.3.24"
+version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "21b20ba5a92e727ba30e72834706623d94ac93a725410b6a6b6fbc1b07f7ba56"
+checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9"
[[package]]
name = "futures-task"
-version = "0.3.24"
+version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a6508c467c73851293f390476d4491cf4d227dbabcd4170f3bb6044959b294f1"
+checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea"
[[package]]
name = "futures-util"
-version = "0.3.24"
+version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44fb6cb1be61cc1d2e43b262516aafcf63b241cffdb1d3fa115f91d9c7b09c90"
+checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6"
dependencies = [
"futures-channel",
"futures-core",
@@ -399,13 +467,13 @@ dependencies = [
[[package]]
name = "gdk-pixbuf"
-version = "0.16.0"
-source = "git+https://github.com/gtk-rs/gtk-rs-core#588a146fd86fd6adaa7e682505f3b65f036bd2bf"
+version = "0.17.0"
+source = "git+https://github.com/gtk-rs/gtk-rs-core#8f989cc26bb8021a2b7b22c0ee7654bf501924d2"
dependencies = [
"bitflags",
- "gdk-pixbuf-sys 0.16.0",
- "gio 0.16.0",
- "glib 0.16.0",
+ "gdk-pixbuf-sys 0.17.0",
+ "gio 0.17.0",
+ "glib 0.17.0",
"libc",
]
@@ -432,19 +500,19 @@ dependencies = [
"glib-sys 0.15.10",
"gobject-sys 0.15.10",
"libc",
- "system-deps 6.0.2",
+ "system-deps 6.0.3",
]
[[package]]
name = "gdk-pixbuf-sys"
-version = "0.16.0"
-source = "git+https://github.com/gtk-rs/gtk-rs-core#588a146fd86fd6adaa7e682505f3b65f036bd2bf"
+version = "0.17.0"
+source = "git+https://github.com/gtk-rs/gtk-rs-core#8f989cc26bb8021a2b7b22c0ee7654bf501924d2"
dependencies = [
- "gio-sys 0.16.0",
- "glib-sys 0.16.0",
- "gobject-sys 0.16.0",
+ "gio-sys 0.17.0",
+ "glib-sys 0.17.0",
+ "gobject-sys 0.17.0",
"libc",
- "system-deps 6.0.2",
+ "system-deps 6.0.3",
]
[[package]]
@@ -461,7 +529,7 @@ dependencies = [
"libc",
"pango-sys 0.15.10",
"pkg-config",
- "system-deps 6.0.2",
+ "system-deps 6.0.3",
]
[[package]]
@@ -482,17 +550,17 @@ dependencies = [
[[package]]
name = "gdk4"
-version = "0.5.0"
-source = "git+https://github.com/gtk-rs/gtk4-rs.git#8dfb3a93de747137cf213e077902c2d993796c15"
+version = "0.6.0"
+source = "git+https://github.com/gtk-rs/gtk4-rs.git#1c00c6d48d8e6f3b1a97714c26c23478dc8bbd22"
dependencies = [
"bitflags",
- "cairo-rs 0.16.0",
- "gdk-pixbuf 0.16.0",
- "gdk4-sys 0.5.0",
- "gio 0.16.0",
- "glib 0.16.0",
+ "cairo-rs 0.17.0",
+ "gdk-pixbuf 0.17.0",
+ "gdk4-sys 0.6.0",
+ "gio 0.17.0",
+ "glib 0.17.0",
"libc",
- "pango 0.16.0",
+ "pango 0.17.0",
]
[[package]]
@@ -509,30 +577,30 @@ dependencies = [
"libc",
"pango-sys 0.15.10",
"pkg-config",
- "system-deps 6.0.2",
+ "system-deps 6.0.3",
]
[[package]]
name = "gdk4-sys"
-version = "0.5.0"
-source = "git+https://github.com/gtk-rs/gtk4-rs.git#8dfb3a93de747137cf213e077902c2d993796c15"
+version = "0.6.0"
+source = "git+https://github.com/gtk-rs/gtk4-rs.git#1c00c6d48d8e6f3b1a97714c26c23478dc8bbd22"
dependencies = [
- "cairo-sys-rs 0.16.0",
- "gdk-pixbuf-sys 0.16.0",
- "gio-sys 0.16.0",
- "glib-sys 0.16.0",
- "gobject-sys 0.16.0",
+ "cairo-sys-rs 0.17.0",
+ "gdk-pixbuf-sys 0.17.0",
+ "gio-sys 0.17.0",
+ "glib-sys 0.17.0",
+ "gobject-sys 0.17.0",
"libc",
- "pango-sys 0.16.0",
+ "pango-sys 0.17.0",
"pkg-config",
- "system-deps 6.0.2",
+ "system-deps 6.0.3",
]
[[package]]
name = "getrandom"
-version = "0.2.7"
+version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
+checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
dependencies = [
"cfg-if 1.0.0",
"libc",
@@ -599,16 +667,16 @@ dependencies = [
[[package]]
name = "gio"
-version = "0.16.0"
-source = "git+https://github.com/gtk-rs/gtk-rs-core#588a146fd86fd6adaa7e682505f3b65f036bd2bf"
+version = "0.17.0"
+source = "git+https://github.com/gtk-rs/gtk-rs-core#8f989cc26bb8021a2b7b22c0ee7654bf501924d2"
dependencies = [
"bitflags",
"futures-channel",
"futures-core",
"futures-io",
"futures-util",
- "gio-sys 0.16.0",
- "glib 0.16.0",
+ "gio-sys 0.17.0",
+ "glib 0.17.0",
"libc",
"once_cell",
"pin-project-lite",
@@ -638,19 +706,19 @@ dependencies = [
"glib-sys 0.15.10",
"gobject-sys 0.15.10",
"libc",
- "system-deps 6.0.2",
+ "system-deps 6.0.3",
"winapi",
]
[[package]]
name = "gio-sys"
-version = "0.16.0"
-source = "git+https://github.com/gtk-rs/gtk-rs-core#588a146fd86fd6adaa7e682505f3b65f036bd2bf"
+version = "0.17.0"
+source = "git+https://github.com/gtk-rs/gtk-rs-core#8f989cc26bb8021a2b7b22c0ee7654bf501924d2"
dependencies = [
- "glib-sys 0.16.0",
- "gobject-sys 0.16.0",
+ "glib-sys 0.17.0",
+ "gobject-sys 0.17.0",
"libc",
- "system-deps 6.0.2",
+ "system-deps 6.0.3",
"winapi",
]
@@ -695,8 +763,8 @@ dependencies = [
[[package]]
name = "glib"
-version = "0.16.0"
-source = "git+https://github.com/gtk-rs/gtk-rs-core#588a146fd86fd6adaa7e682505f3b65f036bd2bf"
+version = "0.17.0"
+source = "git+https://github.com/gtk-rs/gtk-rs-core#8f989cc26bb8021a2b7b22c0ee7654bf501924d2"
dependencies = [
"bitflags",
"futures-channel",
@@ -704,10 +772,10 @@ dependencies = [
"futures-executor",
"futures-task",
"futures-util",
- "gio-sys 0.16.0",
- "glib-macros 0.16.0",
- "glib-sys 0.16.0",
- "gobject-sys 0.16.0",
+ "gio-sys 0.17.0",
+ "glib-macros 0.17.0",
+ "glib-sys 0.17.0",
+ "gobject-sys 0.17.0",
"libc",
"once_cell",
"smallvec",
@@ -747,8 +815,8 @@ dependencies = [
[[package]]
name = "glib-macros"
-version = "0.16.0"
-source = "git+https://github.com/gtk-rs/gtk-rs-core#588a146fd86fd6adaa7e682505f3b65f036bd2bf"
+version = "0.17.0"
+source = "git+https://github.com/gtk-rs/gtk-rs-core#8f989cc26bb8021a2b7b22c0ee7654bf501924d2"
dependencies = [
"anyhow",
"heck 0.4.0",
@@ -776,16 +844,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef4b192f8e65e9cf76cbf4ea71fa8e3be4a0e18ffe3d68b8da6836974cc5bad4"
dependencies = [
"libc",
- "system-deps 6.0.2",
+ "system-deps 6.0.3",
]
[[package]]
name = "glib-sys"
-version = "0.16.0"
-source = "git+https://github.com/gtk-rs/gtk-rs-core#588a146fd86fd6adaa7e682505f3b65f036bd2bf"
+version = "0.17.0"
+source = "git+https://github.com/gtk-rs/gtk-rs-core#8f989cc26bb8021a2b7b22c0ee7654bf501924d2"
dependencies = [
"libc",
- "system-deps 6.0.2",
+ "system-deps 6.0.3",
]
[[package]]
@@ -807,17 +875,17 @@ checksum = "0d57ce44246becd17153bd035ab4d32cfee096a657fc01f2231c9278378d1e0a"
dependencies = [
"glib-sys 0.15.10",
"libc",
- "system-deps 6.0.2",
+ "system-deps 6.0.3",
]
[[package]]
name = "gobject-sys"
-version = "0.16.0"
-source = "git+https://github.com/gtk-rs/gtk-rs-core#588a146fd86fd6adaa7e682505f3b65f036bd2bf"
+version = "0.17.0"
+source = "git+https://github.com/gtk-rs/gtk-rs-core#8f989cc26bb8021a2b7b22c0ee7654bf501924d2"
dependencies = [
- "glib-sys 0.16.0",
+ "glib-sys 0.17.0",
"libc",
- "system-deps 6.0.2",
+ "system-deps 6.0.3",
]
[[package]]
@@ -840,7 +908,7 @@ dependencies = [
"glib-sys 0.15.10",
"libc",
"pkg-config",
- "system-deps 6.0.2",
+ "system-deps 6.0.3",
]
[[package]]
@@ -872,7 +940,7 @@ dependencies = [
"graphene-sys",
"libc",
"pango-sys 0.15.10",
- "system-deps 6.0.2",
+ "system-deps 6.0.3",
]
[[package]]
@@ -890,7 +958,7 @@ dependencies = [
"gobject-sys 0.15.10",
"libc",
"pango-sys 0.15.10",
- "system-deps 6.0.2",
+ "system-deps 6.0.3",
]
[[package]]
@@ -947,7 +1015,7 @@ dependencies = [
"gsk4-sys",
"libc",
"pango-sys 0.15.10",
- "system-deps 6.0.2",
+ "system-deps 6.0.3",
]
[[package]]
@@ -975,10 +1043,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
[[package]]
-name = "iana-time-zone"
-version = "0.1.51"
+name = "hermit-abi"
+version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f5a6ef98976b22b3b7f2f3a806f858cb862044cfa66805aa3ad84cb3d3b785ed"
+checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "iana-time-zone"
+version = "0.1.53"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765"
dependencies = [
"android_system_properties",
"core-foundation-sys",
@@ -990,9 +1067,9 @@ dependencies = [
[[package]]
name = "iana-time-zone-haiku"
-version = "0.1.0"
+version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fde6edd6cef363e9359ed3c98ba64590ba9eecba2293eb5a723ab32aee8926aa"
+checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca"
dependencies = [
"cxx",
"cxx-build",
@@ -1016,6 +1093,18 @@ dependencies = [
"wasm-bindgen",
]
+[[package]]
+name = "ksni"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "48b786146a6b576a000a289d8e1a834a3de60db75973f43ebbfec733270973f0"
+dependencies = [
+ "dbus",
+ "dbus-codegen",
+ "dbus-tree",
+ "thiserror",
+]
+
[[package]]
name = "lazy_static"
version = "1.4.0"
@@ -1024,9 +1113,18 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
-version = "0.2.134"
+version = "0.2.137"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "329c933548736bc49fd575ee68c89e8be4d260064184389a5b77517cddd99ffb"
+checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89"
+
+[[package]]
+name = "libdbus-sys"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c185b5b7ad900923ef3a8ff594083d4d9b5aea80bb4f32b8342363138c0d456b"
+dependencies = [
+ "pkg-config",
+]
[[package]]
name = "link-cplusplus"
@@ -1133,9 +1231,9 @@ dependencies = [
[[package]]
name = "once_cell"
-version = "1.15.0"
+version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1"
+checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
[[package]]
name = "ordered-multimap"
@@ -1162,15 +1260,15 @@ dependencies = [
[[package]]
name = "pango"
-version = "0.16.0"
-source = "git+https://github.com/gtk-rs/gtk-rs-core#588a146fd86fd6adaa7e682505f3b65f036bd2bf"
+version = "0.17.0"
+source = "git+https://github.com/gtk-rs/gtk-rs-core#8f989cc26bb8021a2b7b22c0ee7654bf501924d2"
dependencies = [
"bitflags",
- "gio 0.16.0",
- "glib 0.16.0",
+ "gio 0.17.0",
+ "glib 0.17.0",
"libc",
"once_cell",
- "pango-sys 0.16.0",
+ "pango-sys 0.17.0",
]
[[package]]
@@ -1182,25 +1280,25 @@ dependencies = [
"glib-sys 0.15.10",
"gobject-sys 0.15.10",
"libc",
- "system-deps 6.0.2",
+ "system-deps 6.0.3",
]
[[package]]
name = "pango-sys"
-version = "0.16.0"
-source = "git+https://github.com/gtk-rs/gtk-rs-core#588a146fd86fd6adaa7e682505f3b65f036bd2bf"
+version = "0.17.0"
+source = "git+https://github.com/gtk-rs/gtk-rs-core#8f989cc26bb8021a2b7b22c0ee7654bf501924d2"
dependencies = [
- "glib-sys 0.16.0",
- "gobject-sys 0.16.0",
+ "glib-sys 0.17.0",
+ "gobject-sys 0.17.0",
"libc",
- "system-deps 6.0.2",
+ "system-deps 6.0.3",
]
[[package]]
name = "pest"
-version = "2.4.0"
+version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dbc7bc69c062e492337d74d59b120c274fd3d261b6bf6d3207d499b4b379c41a"
+checksum = "a528564cc62c19a7acac4d81e01f39e53e25e17b934878f4c6d25cc2836e62f8"
dependencies = [
"thiserror",
"ucd-trie",
@@ -1220,15 +1318,15 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "pkg-config"
-version = "0.3.25"
+version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
+checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
[[package]]
name = "ppv-lite86"
-version = "0.2.16"
+version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
+checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "proc-macro-crate"
@@ -1276,9 +1374,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
-version = "1.0.46"
+version = "1.0.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94e2ef8dbfc347b10c094890f778ee2e36ca9bb4262e86dc99cd217e35f3470b"
+checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
dependencies = [
"unicode-ident",
]
@@ -1353,9 +1451,9 @@ dependencies = [
[[package]]
name = "regex"
-version = "1.6.0"
+version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
+checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a"
dependencies = [
"aho-corasick",
"memchr",
@@ -1364,9 +1462,9 @@ dependencies = [
[[package]]
name = "regex-syntax"
-version = "0.6.27"
+version = "0.6.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
+checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
[[package]]
name = "rust-ini"
@@ -1393,6 +1491,12 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898"
+[[package]]
+name = "secfmt"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c8c73432861711997c5d0a1f61275cb4e875884c820da5ff2cffad3d3577201c"
+
[[package]]
name = "semver"
version = "0.11.0"
@@ -1413,9 +1517,9 @@ dependencies = [
[[package]]
name = "serde"
-version = "1.0.145"
+version = "1.0.147"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b"
+checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965"
[[package]]
name = "slab"
@@ -1432,6 +1536,12 @@ version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
+[[package]]
+name = "strsim"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
+
[[package]]
name = "strum"
version = "0.18.0"
@@ -1462,9 +1572,9 @@ dependencies = [
[[package]]
name = "syn"
-version = "1.0.102"
+version = "1.0.103"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3fcd952facd492f9be3ef0d0b7032a6e442ee9b361d4acc2b1d0c4aaa5f613a1"
+checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d"
dependencies = [
"proc-macro2",
"quote",
@@ -1488,15 +1598,15 @@ dependencies = [
[[package]]
name = "system-deps"
-version = "6.0.2"
+version = "6.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1a45a1c4c9015217e12347f2a411b57ce2c4fc543913b14b6fe40483328e709"
+checksum = "2955b1fe31e1fa2fbd1976b71cc69a606d7d4da16f6de3333d0c92d51419aeff"
dependencies = [
"cfg-expr",
"heck 0.4.0",
"pkg-config",
"toml",
- "version-compare 0.1.0",
+ "version-compare 0.1.1",
]
[[package]]
@@ -1514,6 +1624,15 @@ dependencies = [
"winapi-util",
]
+[[package]]
+name = "textwrap"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
+dependencies = [
+ "unicode-width",
+]
+
[[package]]
name = "thiserror"
version = "1.0.37"
@@ -1578,6 +1697,12 @@ version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
+[[package]]
+name = "vec_map"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
+
[[package]]
name = "version-compare"
version = "0.0.10"
@@ -1586,9 +1711,9 @@ checksum = "d63556a25bae6ea31b52e640d7c41d1ab27faba4ccb600013837a3d0b3994ca1"
[[package]]
name = "version-compare"
-version = "0.1.0"
+version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fe88247b92c1df6b6de80ddc290f3976dbdf2f5f5d3fd049a9fb598c6dd5ca73"
+checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29"
[[package]]
name = "version_check"
@@ -1692,3 +1817,9 @@ name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
+name = "xml-rs"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3"
diff --git a/Cargo.toml b/Cargo.toml
index 42c9c26..c0a228e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -16,6 +16,7 @@ gtk-sys = "0.15"
glib = "0.10.3"
rust-ini = "0.16"
regex = "1.4.3"
+secfmt = "0.1.1"
subprocess = "0.2.6"
[dependencies.gio]
diff --git a/interfaces/main.ui b/interfaces/main.ui
index eb95a5d..f8d67a8 100644
--- a/interfaces/main.ui
+++ b/interfaces/main.ui
@@ -35,9 +35,9 @@
412
584
False
+ False
True
True
- blue-recorder
-
+
True
@@ -562,6 +595,12 @@
+
+
+ False
+ True
+
+
media-playback-start
diff --git a/src/area_capture.rs b/src/area_capture.rs
index 1490caf..c2f1798 100644
--- a/src/area_capture.rs
+++ b/src/area_capture.rs
@@ -2,7 +2,7 @@ extern crate regex;
use regex::Regex;
use std::process::Command;
-// this struct use "xwininfo" to get area x, y, width and height
+// This struct use "xwininfo" to get area x, y, width and height
#[derive(Debug, Copy, Clone)]
pub struct AreaCapture {
pub x: u16,
diff --git a/src/config_management.rs b/src/config_management.rs
index 73e9428..e48e741 100755
--- a/src/config_management.rs
+++ b/src/config_management.rs
@@ -12,7 +12,7 @@ pub fn initialize() -> PathBuf {
.join("blue-recorder")
.join("config.ini");
- // fatch and make the config file
+ // Fatch and make the config file
if !&config_path.exists() {
let config_directories = &mut config_path.to_owned();
config_directories.pop();
@@ -53,7 +53,7 @@ fn merge_previous_version() -> Option {
.join("blue-recorder")
.join("config.ini");
- // return none if config.ini not exists
+ // Return none if config.ini not exists
if !&config_path.exists() {
return None;
}
diff --git a/src/ffmpeg_interface.rs b/src/ffmpeg_interface.rs
index 3202e21..07c6bba 100644
--- a/src/ffmpeg_interface.rs
+++ b/src/ffmpeg_interface.rs
@@ -1,9 +1,9 @@
extern crate subprocess;
+
use chrono::prelude::*;
use gettextrs::gettext;
-use gio::File;
use gtk::prelude::*;
-use gtk::{Button, CheckButton, ComboBoxText, Entry, ProgressBar, SpinButton, Window};
+use gtk::{CheckButton, ComboBoxText, Entry, FileChooserNative, ProgressBar, SpinButton, Window};
use gtk::{ButtonsType, DialogFlags, MessageDialog, MessageType, ResponseType};
use std::path::PathBuf;
use std::process::Command;
@@ -16,19 +16,16 @@ use subprocess::Exec;
pub struct ProgressWidget {
pub progress_dialog: MessageDialog,
pub progressbar: ProgressBar,
- pub progress_button: Button,
}
impl ProgressWidget {
pub fn new(
progress_dialog: MessageDialog,
progressbar: ProgressBar,
- progress_button: Button,
) -> ProgressWidget {
ProgressWidget {
progress_dialog,
progressbar,
- progress_button,
}
}
@@ -44,21 +41,19 @@ impl ProgressWidget {
}
pub fn hide(&self) {
- self.progress_button.set_sensitive(true);
self.progress_dialog.hide();
}
}
#[derive(Clone)]
pub struct Ffmpeg {
- pub filename: (File, Entry, ComboBoxText),
+ pub filename: (FileChooserNative, Entry, ComboBoxText),
pub record_video: CheckButton,
pub record_audio: CheckButton,
pub audio_id: ComboBoxText,
pub record_mouse: CheckButton,
pub follow_mouse: CheckButton,
pub record_frames: SpinButton,
- pub record_delay: SpinButton,
pub command: Entry,
pub video_process_id: Option,
pub audio_process_id: Option,
@@ -80,6 +75,8 @@ impl Ffmpeg {
self.saved_filename = Some(
self.filename
.0
+ .file()
+ .unwrap()
.path()
.unwrap()
.join(PathBuf::from(format!(
@@ -138,7 +135,7 @@ impl Ffmpeg {
if self.record_video.is_active() {
let mut ffmpeg_command: Command = Command::new("ffmpeg");
- // record video with specified width and hight
+ // Record video with specified width and hight
ffmpeg_command.arg("-video_size");
ffmpeg_command.arg(format!("{}x{}", width, height));
ffmpeg_command.arg("-framerate");
@@ -155,7 +152,7 @@ impl Ffmpeg {
y
));
- // if show mouse switch is enabled, draw the mouse to video
+ // If show mouse switch is enabled, draw the mouse to video
ffmpeg_command.arg("-draw_mouse");
if self.record_mouse.is_active() {
ffmpeg_command.arg("1");
@@ -163,7 +160,7 @@ impl Ffmpeg {
ffmpeg_command.arg("0");
}
- // if follow mouse switch is enabled, follow the mouse
+ // If follow mouse switch is enabled, follow the mouse
if self.follow_mouse.is_active() {
ffmpeg_command.arg("-follow_mouse");
ffmpeg_command.arg("centered");
@@ -172,9 +169,7 @@ impl Ffmpeg {
ffmpeg_command.arg("1");
ffmpeg_command.arg(self.saved_filename.as_ref().unwrap());
ffmpeg_command.arg("-y");
- // sleep for delay
- sleep(Duration::from_secs(self.record_delay.value() as u64));
- // start recording and return the process id
+ // Start recording and return the process id
self.video_process_id = Some(ffmpeg_command.spawn().unwrap().id());
return (self.video_process_id, self.audio_process_id);
}
@@ -184,7 +179,7 @@ impl Ffmpeg {
pub fn stop_record(&self) {
self.progress_widget.show();
- // kill the process to stop recording
+ // Kill the process to stop recording
self.progress_widget.set_progress("".to_string(), 1, 6);
if self.video_process_id.is_some() {
@@ -246,7 +241,7 @@ impl Ffmpeg {
self.progress_widget.set_progress("".to_string(), 4, 6);
- // if audio record, then merge video with audio
+ // If audio record, then merge video with audio
if is_audio_record {
self.progress_widget
.set_progress("Save Audio Recording".to_string(), 4, 6);
@@ -283,32 +278,10 @@ impl Ffmpeg {
.unwrap();
}
}
- // if only audio is recording then convert it to chosen format
- else if is_audio_record {
- self.progress_widget
- .set_progress("Convert Audio to choosen format".to_string(), 4, 6);
- sleep(Duration::from_secs(1));
- Command::new("ffmpeg")
- .arg("-f")
- .arg("ogg")
- .arg("-i")
- .arg(format!(
- "{}.temp.audio",
- self.saved_filename.as_ref().unwrap()
- ))
- .arg(self.saved_filename.as_ref().unwrap())
- .output()
- .unwrap();
- std::fs::remove_file(format!(
- "{}.temp.audio",
- self.saved_filename.as_ref().unwrap()
- ))
- .unwrap();
- }
self.progress_widget.set_progress("".to_string(), 5, 6);
- // execute command after finish recording
+ // Execute command after finish recording
if self.command.text().trim() != "" {
self.progress_widget.set_progress(
"execute custom command after finish".to_string(),
@@ -326,7 +299,7 @@ impl Ffmpeg {
pub fn play_record(self) {
if self.saved_filename.is_some() {
if is_snap() {
- // open the video using snapctrl for snap package
+ // Open the video using snapctrl for snap package
Command::new("snapctl")
.arg("user-open")
.arg(self.saved_filename.unwrap())
diff --git a/src/indicator.rs b/src/indicator.rs
deleted file mode 100644
index 2a71c9f..0000000
--- a/src/indicator.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-// TODO: add timer
-// https://docs.rs/stray/0.1.1/stray/index.html
diff --git a/src/main.rs b/src/main.rs
index 350e75b..2f7d018 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -5,26 +5,29 @@ extern crate gtk;
mod area_capture;
mod config_management;
mod ffmpeg_interface;
+mod timer;
use ffmpeg_interface::{Ffmpeg, ProgressWidget};
use gettextrs::{bindtextdomain, gettext, LocaleCategory, setlocale, textdomain};
-use gtk::{prelude::*, Application};
-use gtk::{AboutDialog, Builder, Button, CheckButton, ComboBoxText, CssProvider, Entry, FileChooserNative, FileChooserAction, Image, Label, MessageDialog, ProgressBar, SpinButton, ToggleButton, Window};
+use gtk::{AboutDialog, Application, Builder, Button, CheckButton, ComboBoxText, CssProvider, Entry, FileChooserNative, FileChooserAction, Image, Label, MessageDialog, ProgressBar, SpinButton, ToggleButton, Window};
+use gtk::prelude::*;
+use gtk::glib;
use std::cell::RefCell;
use std::ops::Add;
use std::path::Path;
use std::process::{Command, Stdio};
use std::rc::Rc;
+use timer::{recording_delay, start_timer, stop_timer};
fn main() {
- //create new application
+ // Create new application
let application = Application::new(Some("sa.sy.blue-recorder"), Default::default(),);
application.connect_activate(build_ui);
application.run();
}
pub fn build_ui(application: &Application) {
- // use "GDK_BACKEND=x11" to make xwininfo work in Wayland by using XWayland
+ // Use "GDK_BACKEND=x11" to make xwininfo work in Wayland by using XWayland
std::env::set_var("GDK_BACKEND", "x11");
if gtk::init().is_err() {
println!("Failed to initialize GTK.");
@@ -34,7 +37,7 @@ pub fn build_ui(application: &Application) {
let ui_src = include_str!("../interfaces/main.ui").to_string();
let builder: Builder = Builder::from_string(ui_src.as_str());
- // translate
+ // Translate
let mut po_path_abs = {
let mut current_exec_dir = std::env::current_exe().unwrap();
current_exec_dir.pop();
@@ -53,10 +56,10 @@ pub fn build_ui(application: &Application) {
bindtextdomain("blue-recorder", po_path_abs.to_str().unwrap()).unwrap();
textdomain("blue-recorder").unwrap();
- // config initialize
+ // Config initialize
config_management::initialize();
- // get Objects from UI
+ // Get Objects from UI
let area_chooser_window: Window = builder.object("area_chooser_window").unwrap();
let area_grab_button: ToggleButton = builder.object("area_grab_button").unwrap();
let area_grab_icon: Image = builder.object("area_grab_icon").unwrap();
@@ -70,6 +73,9 @@ pub fn build_ui(application: &Application) {
let command_label: Label = builder.object("command_label").unwrap();
let delay_label: Label = builder.object("delay_label").unwrap();
let delay_spin: SpinButton = builder.object("delay").unwrap();
+ let delay_window: Window = builder.object("delay_window").unwrap();
+ let delay_window_label: Label = builder.object("delay_window_label").unwrap();
+ let delay_window_button: ToggleButton = builder.object("delay_window_stopbutton").unwrap();
let filename_entry: Entry = builder.object("filename").unwrap();
let folder_chooser_button: Button = builder.object("folder_chooser").unwrap();
let folder_chooser_image: Image = builder.object("folder_chooser_image").unwrap();
@@ -82,10 +88,10 @@ pub fn build_ui(application: &Application) {
let mouse_switch: CheckButton = builder.object("mouseswitch").unwrap();
let overwrite_switch: CheckButton = builder.object("overwriteswitch").unwrap();
let play_button: Button = builder.object("playbutton").unwrap();
- let progress_button: Button = builder.object("progressbutton").unwrap();
let progress_dialog: MessageDialog = builder.object("progress_dialog").unwrap();
let progressbar: ProgressBar = builder.object("progressbar").unwrap();
let record_button: Button = builder.object("recordbutton").unwrap();
+ let record_time_label: Label = builder.object("record_time_label").unwrap();
let screen_grab_button: ToggleButton = builder.object("screen_grab_button").unwrap();
let screen_grab_icon: Image = builder.object("screen_grab_icon").unwrap();
let stop_button: Button = builder.object("stopbutton").unwrap();
@@ -97,12 +103,17 @@ pub fn build_ui(application: &Application) {
// Windows
main_window.set_title(Some(&gettext("Blue Recorder")));
main_window.set_application(Some(application));
- area_chooser_window.set_title(Some(&gettext("Area Chooser"))); //title is hidden
+ area_chooser_window.set_title(Some(&gettext("Area Chooser"))); // Title is hidden
- //hide stop & play buttons
+ // Hide stop & play buttons
stop_button.hide();
play_button.hide();
+ // Hide window grab button in Wayland
+ if is_wayland() {
+ window_grab_button.hide();
+ }
+
// Entries
filename_entry.set_placeholder_text(Some(&gettext("Default filename:")));
command_entry.set_placeholder_text(Some(&gettext("Default command:")));
@@ -110,19 +121,19 @@ pub fn build_ui(application: &Application) {
command_entry.set_text(&config_management::get("default", "command"));
// CheckBox
- //format_chooser_combobox.append(Some("webm"), &gettext("WEBM (Open Web Media File)"));
- format_chooser_combobox.append(Some("mp4"), &gettext("MP4 (MPEG-4 Part 14)"));
- //format_chooser_combobox.append(Some("gif"), &gettext("GIF (Graphics Interchange Format)"));
format_chooser_combobox.append(
Some("mkv"),
&gettext("MKV (Matroska multimedia container format)"),
);
- //format_chooser_combobox.append(Some("avi"), &gettext("AVI (Audio Video Interleaved)"));
- //format_chooser_combobox.append(Some("wmv"), &gettext("WMV (Windows Media Video)"));
- //format_chooser_combobox.append(Some("nut"), &gettext("NUT (NUT Recording Format)"));
+ format_chooser_combobox.append(Some("mp4"), &gettext("MP4 (MPEG-4 Part 14)"));
+ format_chooser_combobox.append(Some("webm"), &gettext("WEBM (Open Web Media File)"));
+ format_chooser_combobox.append(Some("gif"), &gettext("GIF (Graphics Interchange Format)"));
+ format_chooser_combobox.append(Some("avi"), &gettext("AVI (Audio Video Interleaved)"));
+ format_chooser_combobox.append(Some("wmv"), &gettext("WMV (Windows Media Video)"));
+ format_chooser_combobox.append(Some("nut"), &gettext("NUT (NUT Recording Format)"));
format_chooser_combobox.set_active(Some(0));
- // get audio sources
+ // Get audio sources
let sources_descriptions: Vec = {
let list_sources_child = Command::new("pactl")
.args(&["list", "sources"])
@@ -272,6 +283,18 @@ pub fn build_ui(application: &Application) {
audio_source_label.set_label(&gettext("Audio Input Source:"));
// Spin
+ frames_spin.set_value(
+ config_management::get("default", "frame")
+ .parse::()
+ .unwrap(),
+ );
+
+ delay_spin.set_value(
+ config_management::get("default", "delay")
+ .parse::()
+ .unwrap(),
+ );
+
let _frames_spin = frames_spin.to_owned();
frames_spin.connect_value_changed(move |_| {
config_management::set(
@@ -297,29 +320,32 @@ pub fn build_ui(application: &Application) {
Some("Select"),
Some("Cancel"),
);
+ folder_chooser_native.set_transient_for(Some(&main_window));
folder_chooser_native.set_modal(true);
+ folder_chooser_native.set_file(&gio::File::for_uri(&config_management::get("default", "folder"))).unwrap();
let folder_chooser = Some(gio::File::for_uri(&config_management::get("default", "folder"))).unwrap();
let folder_chooser_name = folder_chooser.basename().unwrap();
folder_chooser_label.set_label(&folder_chooser_name.to_string_lossy());
let folder_chooser_icon = config_management::folder_icon(folder_chooser_name.to_str());
folder_chooser_image.set_icon_name(Some(folder_chooser_icon));
- // show file chooser dialog
+ // Show file chooser dialog
folder_chooser_button.connect_clicked(glib::clone!(@strong folder_chooser_native => move |_| {
folder_chooser_native.connect_response(glib::clone!(@strong folder_chooser_native, @strong folder_chooser_label, @strong folder_chooser_image => move |_, response| {
- if response == gtk::ResponseType::Accept {
- let folder_chooser = folder_chooser_native.file().unwrap();
- let folder_chooser_name = folder_chooser.basename().unwrap();
- folder_chooser_label.set_label(&folder_chooser_name.to_string_lossy());
- let folder_chooser_icon = config_management::folder_icon(folder_chooser_name.to_str());
- folder_chooser_image.set_icon_name(Some(folder_chooser_icon));
- };
- folder_chooser_native.destroy();
+ if response == gtk::ResponseType::Accept {
+ folder_chooser_native.file().unwrap();
+ let folder_chooser = folder_chooser_native.file().unwrap();
+ let folder_chooser_name = folder_chooser.basename().unwrap();
+ folder_chooser_label.set_label(&folder_chooser_name.to_string_lossy());
+ let folder_chooser_icon = config_management::folder_icon(folder_chooser_name.to_str());
+ folder_chooser_image.set_icon_name(Some(folder_chooser_icon));
+ };
+ folder_chooser_native.hide();
}));
- folder_chooser_native.show();
+ folder_chooser_native.show();
}));
// --- connections
- // show dialog window when about button clicked then hide it after close
+ // Show dialog window when about button clicked then hide it after close
let _about_dialog: AboutDialog = about_dialog.to_owned();
about_button.connect_clicked(move |_| {
_about_dialog.show();
@@ -359,63 +385,79 @@ pub fn build_ui(application: &Application) {
_area_capture.borrow_mut().get_area();
});
- let _progress_button = progress_button.clone();
- let _progress_dialog = progress_dialog.clone();
- _progress_button.connect_clicked(move |_| {
- _progress_dialog.hide();
- });
-
- // init record struct
+ // Init record struct
let ffmpeg_record_interface: Rc> = Rc::new(RefCell::new(Ffmpeg {
- filename: (folder_chooser, filename_entry, format_chooser_combobox),
+ filename: (folder_chooser_native, filename_entry, format_chooser_combobox),
record_video: video_switch,
record_audio: audio_switch,
audio_id: audio_source_combobox,
record_mouse: mouse_switch,
follow_mouse: follow_mouse_switch,
record_frames: frames_spin,
- record_delay: delay_spin,
command: command_entry,
video_process_id: None,
audio_process_id: None,
saved_filename: None,
unbound: None,
- progress_widget: ProgressWidget::new(progress_dialog, progressbar, progress_button),
+ progress_widget: ProgressWidget::new(progress_dialog, progressbar),
window: main_window.clone(),
overwrite: overwrite_switch,
}));
+ // Record Button
+ let _delay_window = delay_window.clone();
+ let _delay_window_button = delay_window_button.clone();
let mut _ffmpeg_record_interface = ffmpeg_record_interface.clone();
- let _stop_button = stop_button.clone();
+ let _play_button = play_button.clone();
let _record_button = record_button.clone();
+ let _record_time_label = record_time_label.clone();
+ let _stop_button = stop_button.clone();
record_button.connect_clicked(move |_| {
- let _area_capture = area_capture.borrow_mut();
- match _ffmpeg_record_interface.borrow_mut().start_record(
- _area_capture.x,
- _area_capture.y,
- _area_capture.width,
- _area_capture.height,
- ) {
- (None, None) => {
- // do nothing if the start_record function return nothing
+ _delay_window_button.set_active(false);
+ if delay_spin.value()as u64 > 0 {
+ recording_delay(delay_spin.clone(), delay_spin.value()as u64, delay_window.clone(), _delay_window_button.clone(), delay_window_label.clone(), _record_button.clone());
+ }
+ if delay_spin.value()as u64 == 0 {
+ let _area_capture = area_capture.borrow_mut();
+ match _ffmpeg_record_interface.borrow_mut().start_record(
+ _area_capture.x,
+ _area_capture.y,
+ _area_capture.width,
+ _area_capture.height,
+ ) {
+ (None, None) => {
+ // Do nothing if the start_record function return nothing
}
- _ => {
- _record_button.hide();
- _stop_button.show();
+ _ => {
+ start_timer(record_time_label.clone());
+ record_time_label.set_visible(true);
+ _play_button.hide();
+ _record_button.hide();
+ _stop_button.show();
+ }
}
}
});
+ // Stop Record Button
let mut _ffmpeg_record_interface = ffmpeg_record_interface.clone();
- let _stop_button = stop_button.clone();
let _play_button = play_button.clone();
+ let _stop_button = stop_button.clone();
stop_button.connect_clicked(move |_| {
+ _record_time_label.set_visible(false);
+ stop_timer(_record_time_label.clone());
_ffmpeg_record_interface.borrow_mut().clone().stop_record();
record_button.show();
_stop_button.hide();
_play_button.show();
});
+ // Delay Window Button
+ let _delay_window_button = delay_window_button.clone();
+ delay_window_button.connect_clicked(move |_| {
+ });
+
+ // Play Button
let mut _ffmpeg_record_interface = ffmpeg_record_interface.clone();
play_button.connect_clicked(move |_| {
_ffmpeg_record_interface.borrow_mut().clone().play_record();
@@ -463,22 +505,22 @@ pub fn build_ui(application: &Application) {
about_dialog.set_modal(true);
// Windows
- // hide area chooser after it deleted.
+ // Hide area chooser after it deleted.
let _area_chooser_window = area_chooser_window.clone();
area_chooser_window.connect_close_request (move |_| {
_area_chooser_window.hide();
gtk::Inhibit(true)
});
- // close the application when main window destroy
+ // Close the application when main window destroy
main_window.connect_destroy(move |main_window| {
let mut _ffmpeg_record_interface = ffmpeg_record_interface.clone();
- // stop recording before close the application
+ // Stop recording before close the application
_ffmpeg_record_interface.borrow_mut().clone().stop_record();
main_window.close();
});
- // apply css
+ // Apply CSS
let provider = CssProvider::new();
provider
.load_from_data(include_str!("styles/global.css").as_bytes());
@@ -488,5 +530,11 @@ pub fn build_ui(application: &Application) {
gtk::STYLE_PROVIDER_PRIORITY_APPLICATION,
);
+ fn is_wayland() -> bool {
+ std::env::var("XDG_SESSION_TYPE")
+ .unwrap_or_default()
+ .eq_ignore_ascii_case("wayland")
+ }
+
main_window.show();
}
diff --git a/src/styles/global.css b/src/styles/global.css
index e4bd359..fe7309c 100644
--- a/src/styles/global.css
+++ b/src/styles/global.css
@@ -1,6 +1,7 @@
#area_chooser_window {
background-color: alpha(@theme_selected_bg_color, 0.1);
border: 3px dashed @theme_selected_bg_color;
+ border-radius: 0px;
}
#area_set_button {
@@ -8,17 +9,30 @@
background: @theme_selected_bg_color;
}
-#area_grab_button:checked{
+#area_grab_button:checked {
color: @theme_selected_fg_color;
background: @theme_selected_bg_color;
}
-#screen_grab_button:checked{
+#screen_grab_button:checked {
color: @theme_selected_fg_color;
background: @theme_selected_bg_color;
}
-#window_grab_button:checked{
+#window_grab_button:checked {
color: @theme_selected_fg_color;
background: @theme_selected_bg_color;
}
+
+#delay_window {
+ border: 3px solid @theme_selected_bg_color;
+}
+#delay_window_label {
+ font-size: 350%;
+ font-weight: 250;
+}
+
+#delay_window_title {
+ font-size: 120%;
+ font-weight: 50;
+}
diff --git a/src/timer.rs b/src/timer.rs
index e6d2789..a0fa2a5 100644
--- a/src/timer.rs
+++ b/src/timer.rs
@@ -1 +1,65 @@
-// TODO: add timer
+extern crate secfmt;
+
+use gtk::glib;
+use gtk::{Button, ToggleButton, Label, SpinButton, Window};
+use gtk::prelude::*;
+
+pub fn recording_delay(delay_spin: SpinButton, mut delay_time: u64, delay_window: Window, delay_window_button: ToggleButton, delay_window_label: Label, record_button: Button) {
+ // Keep time label alive and update every 1sec
+ let default_value = delay_time;
+ let capture_delay_label = move || {
+ // Show delay window if delay time is not zero
+ delay_window.show();
+ if delay_time > 0 {
+ delay_window_label.set_text(¤t_delay_time(delay_time));
+ delay_time -= 1;
+ if delay_window_button.is_active() {
+ delay_window.hide();
+ glib::source::Continue(false)
+ } else {
+ glib::source::Continue(true)
+ }
+ } else {
+ // Hide delay window and start recording
+ delay_window.hide();
+ delay_spin.set_value(0.0);
+ record_button.emit_clicked();
+ // Keep the input value
+ delay_spin.set_value(default_value as f64);
+ glib::source::Continue(false)
+ }
+ };
+ // Execute capture_label every 1sec
+ glib::source::timeout_add_seconds_local(1, capture_delay_label);
+}
+
+pub fn start_timer(record_time_label: Label) {
+ let mut start_time = 1;
+ let capture_record_label = move || {
+ if record_time_label.is_visible() {
+ record_time_label.set_text(¤t_record_time(start_time));
+ start_time += 1;
+ glib::source::Continue(true)
+ } else {
+ glib::source::Continue(false)
+ }
+ };
+ // Execute capture_record_label every 1sec
+ glib::source::timeout_add_seconds_local(1, capture_record_label);
+}
+
+pub fn stop_timer(record_time_label: Label) {
+ let stop_time = 0;
+ record_time_label.set_text(¤t_record_time(stop_time));
+}
+
+
+fn current_delay_time(delay_time: u64) -> String {
+ let delay = secfmt::from(delay_time);
+ format!("{:02}:{:02}", delay.minutes, delay.seconds)
+}
+
+fn current_record_time(start_time: u64) -> String {
+ let start = secfmt::from(start_time);
+ format!("{:02}:{:02}:{:02}", start.hours, start.minutes, start.seconds)
+}