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 @@ -90,28 +90,61 @@ info - vertical + vertical - - True - 0.0 - True - 10 - 10 - - - - - True - False - True - True - Finish Recording - 15 + + True + 0.0 + True + 10 + 10 + + - + + delay_window + True + main_window + False + True + 200 + 200 + False + False + + + vertical + + + delay_window_title + True + Start Recording in… + 10 + + + + + delay_window_label + True + True + True + + + + + True + True + True + 10 + 10 + 10 + Stop + + + + 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) +}