Prevent screen turning off during playback
Closes: #157 XDG portals expose a D-Bus interface allowing apps to prevent screen idling, user switching, and other actions. That interface, org.freedesktop.portal.Inhibit, does all of the heavy lifting here. Idling = the screen dimming or shutting off. Idling is inhibited when a video is actively playing. Idling is NOT inhibited when videos aren't playing - this includes paused or stopped videos.
This commit is contained in:
parent
fa1637fe51
commit
bb087578df
10 changed files with 331 additions and 40 deletions
213
Cargo.lock
generated
213
Cargo.lock
generated
|
|
@ -109,7 +109,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
|
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"getrandom",
|
"getrandom 0.2.15",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"version_check",
|
"version_check",
|
||||||
"zerocopy",
|
"zerocopy",
|
||||||
|
|
@ -249,7 +249,7 @@ dependencies = [
|
||||||
"enumflags2",
|
"enumflags2",
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"rand",
|
"rand 0.8.5",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_repr",
|
"serde_repr",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
|
@ -266,7 +266,7 @@ dependencies = [
|
||||||
"enumflags2",
|
"enumflags2",
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"rand",
|
"rand 0.8.5",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_repr",
|
"serde_repr",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
|
@ -274,6 +274,23 @@ dependencies = [
|
||||||
"zbus 4.4.0",
|
"zbus 4.4.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ashpd"
|
||||||
|
version = "0.12.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "da0986d5b4f0802160191ad75f8d33ada000558757db3defb70299ca95d9fcbd"
|
||||||
|
dependencies = [
|
||||||
|
"enumflags2",
|
||||||
|
"futures-channel",
|
||||||
|
"futures-util",
|
||||||
|
"rand 0.9.2",
|
||||||
|
"serde",
|
||||||
|
"serde_repr",
|
||||||
|
"tokio",
|
||||||
|
"url",
|
||||||
|
"zbus 5.4.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-broadcast"
|
name = "async-broadcast"
|
||||||
version = "0.5.1"
|
version = "0.5.1"
|
||||||
|
|
@ -1005,7 +1022,7 @@ version = "0.1.16"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e"
|
checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom",
|
"getrandom 0.2.15",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"tiny-keccak",
|
"tiny-keccak",
|
||||||
]
|
]
|
||||||
|
|
@ -1082,6 +1099,7 @@ dependencies = [
|
||||||
name = "cosmic-player"
|
name = "cosmic-player"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"ashpd 0.12.0",
|
||||||
"clap_lex",
|
"clap_lex",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"fork",
|
"fork",
|
||||||
|
|
@ -1984,6 +2002,18 @@ dependencies = [
|
||||||
"wasi",
|
"wasi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.3.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"r-efi",
|
||||||
|
"wasip2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gif"
|
name = "gif"
|
||||||
version = "0.12.0"
|
version = "0.12.0"
|
||||||
|
|
@ -4063,7 +4093,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d"
|
checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"phf_shared",
|
"phf_shared",
|
||||||
"rand",
|
"rand 0.8.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -4279,6 +4309,12 @@ dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "r-efi"
|
||||||
|
version = "5.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand"
|
name = "rand"
|
||||||
version = "0.8.5"
|
version = "0.8.5"
|
||||||
|
|
@ -4286,8 +4322,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"rand_chacha",
|
"rand_chacha 0.3.1",
|
||||||
"rand_core",
|
"rand_core 0.6.4",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand"
|
||||||
|
version = "0.9.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1"
|
||||||
|
dependencies = [
|
||||||
|
"rand_chacha 0.9.0",
|
||||||
|
"rand_core 0.9.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -4297,7 +4343,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ppv-lite86",
|
"ppv-lite86",
|
||||||
"rand_core",
|
"rand_core 0.6.4",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_chacha"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
|
||||||
|
dependencies = [
|
||||||
|
"ppv-lite86",
|
||||||
|
"rand_core 0.9.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -4306,7 +4362,16 @@ version = "0.6.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom",
|
"getrandom 0.2.15",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.9.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom 0.3.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -4405,7 +4470,7 @@ version = "0.4.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43"
|
checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom",
|
"getrandom 0.2.15",
|
||||||
"libredox",
|
"libredox",
|
||||||
"thiserror 1.0.69",
|
"thiserror 1.0.69",
|
||||||
]
|
]
|
||||||
|
|
@ -5118,7 +5183,7 @@ checksum = "9a8a559c81686f576e8cd0290cd2a24a2a9ad80c98b3478856500fcbd7acd704"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"fastrand 2.3.0",
|
"fastrand 2.3.0",
|
||||||
"getrandom",
|
"getrandom 0.2.15",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"rustix 0.38.43",
|
"rustix 0.38.43",
|
||||||
"windows-sys 0.59.0",
|
"windows-sys 0.59.0",
|
||||||
|
|
@ -5700,6 +5765,15 @@ version = "0.11.0+wasi-snapshot-preview1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasip2"
|
||||||
|
version = "1.0.1+wasi-0.2.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7"
|
||||||
|
dependencies = [
|
||||||
|
"wit-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen"
|
name = "wasm-bindgen"
|
||||||
version = "0.2.99"
|
version = "0.2.99"
|
||||||
|
|
@ -6426,6 +6500,21 @@ dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winnow"
|
||||||
|
version = "0.7.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wit-bindgen"
|
||||||
|
version = "0.46.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "write16"
|
name = "write16"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
|
|
@ -6600,7 +6689,7 @@ dependencies = [
|
||||||
"nix 0.26.4",
|
"nix 0.26.4",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"ordered-stream",
|
"ordered-stream",
|
||||||
"rand",
|
"rand 0.8.5",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_repr",
|
"serde_repr",
|
||||||
"sha1",
|
"sha1",
|
||||||
|
|
@ -6638,7 +6727,7 @@ dependencies = [
|
||||||
"hex",
|
"hex",
|
||||||
"nix 0.29.0",
|
"nix 0.29.0",
|
||||||
"ordered-stream",
|
"ordered-stream",
|
||||||
"rand",
|
"rand 0.8.5",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_repr",
|
"serde_repr",
|
||||||
"sha1",
|
"sha1",
|
||||||
|
|
@ -6653,6 +6742,36 @@ dependencies = [
|
||||||
"zvariant 4.2.0",
|
"zvariant 4.2.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zbus"
|
||||||
|
version = "5.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cbddd8b6cb25d5d8ec1b23277b45299a98bfb220f1761ca11e186d5c702507f8"
|
||||||
|
dependencies = [
|
||||||
|
"async-broadcast 0.7.2",
|
||||||
|
"async-recursion",
|
||||||
|
"async-trait",
|
||||||
|
"enumflags2",
|
||||||
|
"event-listener 5.4.0",
|
||||||
|
"futures-core",
|
||||||
|
"futures-util",
|
||||||
|
"hex",
|
||||||
|
"nix 0.29.0",
|
||||||
|
"ordered-stream",
|
||||||
|
"serde",
|
||||||
|
"serde_repr",
|
||||||
|
"static_assertions",
|
||||||
|
"tokio",
|
||||||
|
"tracing",
|
||||||
|
"uds_windows",
|
||||||
|
"windows-sys 0.59.0",
|
||||||
|
"winnow 0.7.13",
|
||||||
|
"xdg-home",
|
||||||
|
"zbus_macros 5.4.0",
|
||||||
|
"zbus_names 4.2.0",
|
||||||
|
"zvariant 5.8.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zbus_macros"
|
name = "zbus_macros"
|
||||||
version = "3.15.2"
|
version = "3.15.2"
|
||||||
|
|
@ -6680,6 +6799,21 @@ dependencies = [
|
||||||
"zvariant_utils 2.1.0",
|
"zvariant_utils 2.1.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zbus_macros"
|
||||||
|
version = "5.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dac404d48b4e9cf193c8b49589f3280ceca5ff63519e7e64f55b4cf9c47ce146"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro-crate 3.2.0",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.96",
|
||||||
|
"zbus_names 4.2.0",
|
||||||
|
"zvariant 5.8.0",
|
||||||
|
"zvariant_utils 3.2.1",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zbus_names"
|
name = "zbus_names"
|
||||||
version = "2.6.1"
|
version = "2.6.1"
|
||||||
|
|
@ -6702,6 +6836,18 @@ dependencies = [
|
||||||
"zvariant 4.2.0",
|
"zvariant 4.2.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zbus_names"
|
||||||
|
version = "4.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7be68e64bf6ce8db94f63e72f0c7eb9a60d733f7e0499e628dfab0f84d6bcb97"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
"static_assertions",
|
||||||
|
"winnow 0.7.13",
|
||||||
|
"zvariant 5.8.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zeno"
|
name = "zeno"
|
||||||
version = "0.3.2"
|
version = "0.3.2"
|
||||||
|
|
@ -6809,6 +6955,21 @@ dependencies = [
|
||||||
"zvariant_derive 4.2.0",
|
"zvariant_derive 4.2.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zvariant"
|
||||||
|
version = "5.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2be61892e4f2b1772727be11630a62664a1826b62efa43a6fe7449521cb8744c"
|
||||||
|
dependencies = [
|
||||||
|
"endi",
|
||||||
|
"enumflags2",
|
||||||
|
"serde",
|
||||||
|
"url",
|
||||||
|
"winnow 0.7.13",
|
||||||
|
"zvariant_derive 5.8.0",
|
||||||
|
"zvariant_utils 3.2.1",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zvariant_derive"
|
name = "zvariant_derive"
|
||||||
version = "3.15.2"
|
version = "3.15.2"
|
||||||
|
|
@ -6835,6 +6996,19 @@ dependencies = [
|
||||||
"zvariant_utils 2.1.0",
|
"zvariant_utils 2.1.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zvariant_derive"
|
||||||
|
version = "5.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "da58575a1b2b20766513b1ec59d8e2e68db2745379f961f86650655e862d2006"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro-crate 3.2.0",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.96",
|
||||||
|
"zvariant_utils 3.2.1",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zvariant_utils"
|
name = "zvariant_utils"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
|
|
@ -6856,3 +7030,16 @@ dependencies = [
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.96",
|
"syn 2.0.96",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zvariant_utils"
|
||||||
|
version = "3.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c6949d142f89f6916deca2232cf26a8afacf2b9fdc35ce766105e104478be599"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"serde",
|
||||||
|
"syn 2.0.96",
|
||||||
|
"winnow 0.7.13",
|
||||||
|
]
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,13 @@
|
||||||
[package]
|
[package]
|
||||||
name = "cosmic-player"
|
name = "cosmic-player"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2024"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
vergen = { version = "8", features = ["git", "gitcl"] }
|
vergen = { version = "8", features = ["git", "gitcl"] }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
ashpd = { version = "0.12", optional = true }
|
||||||
gstreamer-tag = "0.23"
|
gstreamer-tag = "0.23"
|
||||||
image = "0.24.9"
|
image = "0.24.9"
|
||||||
serde = { version = "1", features = ["serde_derive"] }
|
serde = { version = "1", features = ["serde_derive"] }
|
||||||
|
|
@ -48,7 +49,7 @@ fork = "0.2"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["mpris-server", "xdg-portal", "wgpu"]
|
default = ["mpris-server", "xdg-portal", "wgpu"]
|
||||||
xdg-portal = ["libcosmic/xdg-portal"]
|
xdg-portal = ["ashpd", "libcosmic/xdg-portal"]
|
||||||
wgpu = ["iced_video_player/wgpu", "libcosmic/wgpu"]
|
wgpu = ["iced_video_player/wgpu", "libcosmic/wgpu"]
|
||||||
|
|
||||||
[profile.release-with-debug]
|
[profile.release-with-debug]
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
use cosmic::{
|
use cosmic::{
|
||||||
cosmic_config::{self, cosmic_config_derive::CosmicConfigEntry, CosmicConfigEntry},
|
cosmic_config::{self, CosmicConfigEntry, cosmic_config_derive::CosmicConfigEntry},
|
||||||
theme,
|
theme,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,8 @@ use std::str::FromStr;
|
||||||
use std::sync::OnceLock;
|
use std::sync::OnceLock;
|
||||||
|
|
||||||
use i18n_embed::{
|
use i18n_embed::{
|
||||||
fluent::{fluent_language_loader, FluentLanguageLoader},
|
|
||||||
DefaultLocalizer, LanguageLoader, Localizer,
|
DefaultLocalizer, LanguageLoader, Localizer,
|
||||||
|
fluent::{FluentLanguageLoader, fluent_language_loader},
|
||||||
};
|
};
|
||||||
use icu_collator::{Collator, CollatorOptions, Numeric};
|
use icu_collator::{Collator, CollatorOptions, Numeric};
|
||||||
use icu_provider::DataLocale;
|
use icu_provider::DataLocale;
|
||||||
|
|
|
||||||
58
src/main.rs
58
src/main.rs
|
|
@ -2,23 +2,25 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
use cosmic::{
|
use cosmic::{
|
||||||
app::{command, message, Command, Core, Settings},
|
Application, ApplicationExt, Element,
|
||||||
|
app::{Command, Core, Settings, command, message},
|
||||||
cosmic_config::{self, CosmicConfigEntry},
|
cosmic_config::{self, CosmicConfigEntry},
|
||||||
cosmic_theme, executor, font,
|
cosmic_theme, executor, font,
|
||||||
iced::{
|
iced::{
|
||||||
|
Alignment, Background, Border, Color, ContentFit, Length, Limits,
|
||||||
event::{self, Event},
|
event::{self, Event},
|
||||||
keyboard::{Event as KeyEvent, Key, Modifiers},
|
keyboard::{Event as KeyEvent, Key, Modifiers},
|
||||||
mouse::{Event as MouseEvent, ScrollDelta},
|
mouse::{Event as MouseEvent, ScrollDelta},
|
||||||
subscription::Subscription,
|
subscription::Subscription,
|
||||||
window, Alignment, Background, Border, Color, ContentFit, Length, Limits,
|
window,
|
||||||
},
|
},
|
||||||
iced_style, theme,
|
iced_style, theme,
|
||||||
widget::{self, menu::action::MenuAction, nav_bar, segmented_button, Slider},
|
widget::{self, Slider, menu::action::MenuAction, nav_bar, segmented_button},
|
||||||
Application, ApplicationExt, Element,
|
|
||||||
};
|
};
|
||||||
use iced_video_player::{
|
use iced_video_player::{
|
||||||
|
Video, VideoPlayer,
|
||||||
gst::{self, prelude::*},
|
gst::{self, prelude::*},
|
||||||
gst_pbutils, Video, VideoPlayer,
|
gst_pbutils,
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
any::TypeId,
|
any::TypeId,
|
||||||
|
|
@ -32,8 +34,8 @@ use std::{
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
config::{Config, ConfigState, CONFIG_VERSION},
|
config::{CONFIG_VERSION, Config, ConfigState},
|
||||||
key_bind::{key_binds, KeyBind},
|
key_bind::{KeyBind, key_binds},
|
||||||
project::ProjectNode,
|
project::ProjectNode,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -47,6 +49,8 @@ mod mpris;
|
||||||
mod project;
|
mod project;
|
||||||
mod thumbnail;
|
mod thumbnail;
|
||||||
mod video;
|
mod video;
|
||||||
|
#[cfg(feature = "xdg-portal")]
|
||||||
|
mod xdg_portals;
|
||||||
|
|
||||||
static CONTROLS_TIMEOUT: Duration = Duration::new(2, 0);
|
static CONTROLS_TIMEOUT: Duration = Duration::new(2, 0);
|
||||||
|
|
||||||
|
|
@ -141,6 +145,7 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||||
settings = settings.theme(config.app_theme.theme());
|
settings = settings.theme(config.app_theme.theme());
|
||||||
settings = settings.size_limits(Limits::NONE.min_width(360.0).min_height(180.0));
|
settings = settings.size_limits(Limits::NONE.min_width(360.0).min_height(180.0));
|
||||||
|
|
||||||
|
|
||||||
let flags = Flags {
|
let flags = Flags {
|
||||||
config,
|
config,
|
||||||
config_state_handler,
|
config_state_handler,
|
||||||
|
|
@ -313,6 +318,8 @@ pub struct App {
|
||||||
current_audio: i32,
|
current_audio: i32,
|
||||||
text_codes: Vec<TextCode>,
|
text_codes: Vec<TextCode>,
|
||||||
current_text: Option<i32>,
|
current_text: Option<i32>,
|
||||||
|
#[cfg(feature = "xdg-portal")]
|
||||||
|
inhibit: tokio::sync::watch::Sender<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
|
|
@ -339,6 +346,7 @@ impl App {
|
||||||
self.current_text = None;
|
self.current_text = None;
|
||||||
self.update_mpris_meta();
|
self.update_mpris_meta();
|
||||||
self.update_nav_bar_active();
|
self.update_nav_bar_active();
|
||||||
|
self.allow_idle();
|
||||||
was_open
|
was_open
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -363,7 +371,7 @@ impl App {
|
||||||
|
|
||||||
let video = match video::new_video(&url) {
|
let video = match video::new_video(&url) {
|
||||||
Ok(ok) => ok,
|
Ok(ok) => ok,
|
||||||
Err(err) => return err
|
Err(err) => return err,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.duration = video.duration().as_secs_f64();
|
self.duration = video.duration().as_secs_f64();
|
||||||
|
|
@ -420,6 +428,7 @@ impl App {
|
||||||
self.current_text = None;
|
self.current_text = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.inhibit_idle();
|
||||||
self.update_flags();
|
self.update_flags();
|
||||||
self.update_mpris_meta();
|
self.update_mpris_meta();
|
||||||
self.update_title()
|
self.update_title()
|
||||||
|
|
@ -792,6 +801,20 @@ impl App {
|
||||||
let title = "COSMIC Media Player";
|
let title = "COSMIC Media Player";
|
||||||
self.set_window_title(title.to_string())
|
self.set_window_title(title.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Allow screen to dim or turn off if there is no input from the user.
|
||||||
|
///
|
||||||
|
/// Basically, undo [`Self::inhibit_idle`].
|
||||||
|
fn allow_idle(&self) {
|
||||||
|
#[cfg(feature = "xdg-portal")]
|
||||||
|
let _ = self.inhibit.send(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Prevent screen from dimming or turning off if there is no keyboard/mouse input.
|
||||||
|
fn inhibit_idle(&self) {
|
||||||
|
#[cfg(feature = "xdg-portal")]
|
||||||
|
let _ = self.inhibit.send(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Implement [`cosmic::Application`] to integrate with COSMIC.
|
/// Implement [`cosmic::Application`] to integrate with COSMIC.
|
||||||
|
|
@ -820,6 +843,13 @@ impl Application for App {
|
||||||
fn init(mut core: Core, flags: Self::Flags) -> (Self, Command<Self::Message>) {
|
fn init(mut core: Core, flags: Self::Flags) -> (Self, Command<Self::Message>) {
|
||||||
core.window.content_container = false;
|
core.window.content_container = false;
|
||||||
|
|
||||||
|
#[cfg(feature = "xdg-portal")]
|
||||||
|
let inhibit = {
|
||||||
|
let (tx, rx) = tokio::sync::watch::channel(false);
|
||||||
|
std::mem::drop(tokio::spawn(crate::xdg_portals::inhibit(rx)));
|
||||||
|
tx
|
||||||
|
};
|
||||||
|
|
||||||
let mut app = App {
|
let mut app = App {
|
||||||
core,
|
core,
|
||||||
flags,
|
flags,
|
||||||
|
|
@ -843,6 +873,8 @@ impl Application for App {
|
||||||
current_audio: -1,
|
current_audio: -1,
|
||||||
text_codes: Vec::new(),
|
text_codes: Vec::new(),
|
||||||
current_text: None,
|
current_text: None,
|
||||||
|
#[cfg(feature = "xdg-portal")]
|
||||||
|
inhibit,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Do not show nav bar by default. Will be opened by open_project if needed
|
// Do not show nav bar by default. Will be opened by open_project if needed
|
||||||
|
|
@ -1176,12 +1208,18 @@ impl Application for App {
|
||||||
self.dropdown_opt = None;
|
self.dropdown_opt = None;
|
||||||
|
|
||||||
if let Some(video) = &mut self.video_opt {
|
if let Some(video) = &mut self.video_opt {
|
||||||
video.set_paused(match message {
|
let pause = match message {
|
||||||
Message::Play => false,
|
Message::Play => false,
|
||||||
Message::Pause => true,
|
Message::Pause => true,
|
||||||
_ => !video.paused(),
|
_ => !video.paused(),
|
||||||
});
|
};
|
||||||
|
video.set_paused(pause);
|
||||||
self.update_controls(true);
|
self.update_controls(true);
|
||||||
|
if pause {
|
||||||
|
self.allow_idle();
|
||||||
|
} else {
|
||||||
|
self.inhibit_idle();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Message::Scrolled(delta) => {
|
Message::Scrolled(delta) => {
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,12 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
use cosmic::{
|
use cosmic::{
|
||||||
theme,
|
Element, theme,
|
||||||
widget::menu::{self, key_bind::KeyBind, ItemHeight, ItemWidth, MenuBar},
|
widget::menu::{self, ItemHeight, ItemWidth, MenuBar, key_bind::KeyBind},
|
||||||
Element,
|
|
||||||
};
|
};
|
||||||
use std::{collections::HashMap, path::PathBuf};
|
use std::{collections::HashMap, path::PathBuf};
|
||||||
|
|
||||||
use crate::{fl, Action, Config, ConfigState, Message};
|
use crate::{Action, Config, ConfigState, Message, fl};
|
||||||
|
|
||||||
pub fn menu_bar<'a>(
|
pub fn menu_bar<'a>(
|
||||||
_config: &Config,
|
_config: &Config,
|
||||||
|
|
|
||||||
|
|
@ -3,12 +3,12 @@ use cosmic::iced::{
|
||||||
subscription::{self, Subscription},
|
subscription::{self, Subscription},
|
||||||
};
|
};
|
||||||
use mpris_server::{
|
use mpris_server::{
|
||||||
zbus::{fdo, Result},
|
|
||||||
LoopStatus, Metadata, PlaybackRate, PlaybackStatus, PlayerInterface, Property, RootInterface,
|
LoopStatus, Metadata, PlaybackRate, PlaybackStatus, PlayerInterface, Property, RootInterface,
|
||||||
Server, Signal, Time, TrackId, Volume,
|
Server, Signal, Time, TrackId, Volume,
|
||||||
|
zbus::{Result, fdo},
|
||||||
};
|
};
|
||||||
use std::{any::TypeId, future, process};
|
use std::{any::TypeId, future, process};
|
||||||
use tokio::sync::{mpsc, Mutex};
|
use tokio::sync::{Mutex, mpsc};
|
||||||
|
|
||||||
use crate::{Message, MprisEvent, MprisMeta, MprisState};
|
use crate::{Message, MprisEvent, MprisMeta, MprisState};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use cosmic::iced_core::image::Data;
|
use cosmic::iced_core::image::Data;
|
||||||
use iced_video_player::{Position};
|
use iced_video_player::Position;
|
||||||
use image::{DynamicImage, ImageFormat, RgbaImage};
|
use image::{DynamicImage, ImageFormat, RgbaImage};
|
||||||
use std::{error::Error, num::NonZero, path::Path, time::Duration};
|
use std::{error::Error, num::NonZero, path::Path, time::Duration};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
@ -15,7 +15,7 @@ pub fn main(
|
||||||
let thumbnails = {
|
let thumbnails = {
|
||||||
let mut video = match video::new_video(input) {
|
let mut video = match video::new_video(input) {
|
||||||
Ok(ok) => ok,
|
Ok(ok) => ok,
|
||||||
Err(_err) => return Err(Into::into(format!("missing required plugin")))
|
Err(_err) => return Err(Into::into(format!("missing required plugin"))),
|
||||||
};
|
};
|
||||||
|
|
||||||
let duration = video.duration();
|
let duration = video.duration();
|
||||||
|
|
|
||||||
15
src/video.rs
15
src/video.rs
|
|
@ -1,12 +1,14 @@
|
||||||
|
|
||||||
use iced_video_player::{
|
use iced_video_player::{
|
||||||
|
Video,
|
||||||
gst::{self, prelude::*},
|
gst::{self, prelude::*},
|
||||||
gst_app, gst_pbutils, Video,
|
gst_app, gst_pbutils,
|
||||||
};
|
};
|
||||||
|
|
||||||
use cosmic::app::{Command, message};
|
use cosmic::app::{Command, message};
|
||||||
|
|
||||||
pub fn new_video(url: &url::Url) -> Result<Video, cosmic::Command<cosmic::app::Message<super::Message>>> {
|
pub fn new_video(
|
||||||
|
url: &url::Url,
|
||||||
|
) -> Result<Video, cosmic::Command<cosmic::app::Message<super::Message>>> {
|
||||||
//TODO: this code came from iced_video_player::Video::new and has been modified to stop the pipeline on error
|
//TODO: this code came from iced_video_player::Video::new and has been modified to stop the pipeline on error
|
||||||
//TODO: remove unwraps and enable playback of files with only audio.
|
//TODO: remove unwraps and enable playback of files with only audio.
|
||||||
gst::init().unwrap();
|
gst::init().unwrap();
|
||||||
|
|
@ -26,7 +28,10 @@ pub fn new_video(url: &url::Url) -> Result<Video, cosmic::Command<cosmic::app::M
|
||||||
};
|
};
|
||||||
if let Some(factory) = elem.factory() {
|
if let Some(factory) = elem.factory() {
|
||||||
if factory.name() == "souphttpsrc" {
|
if factory.name() == "souphttpsrc" {
|
||||||
elem.set_property("user-agent", "Mozilla/5.0 (X11; Linux x86_64; rv:142.0) Gecko/20100101 Firefox/142.0");
|
elem.set_property(
|
||||||
|
"user-agent",
|
||||||
|
"Mozilla/5.0 (X11; Linux x86_64; rv:142.0) Gecko/20100101 Firefox/142.0",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
|
|
@ -71,4 +76,4 @@ pub fn new_video(url: &url::Url) -> Result<Video, cosmic::Command<cosmic::app::M
|
||||||
Err(Command::batch(commands))
|
Err(Command::batch(commands))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
61
src/xdg_portals.rs
Normal file
61
src/xdg_portals.rs
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
// Copyright 2023 System76 <info@system76.com>
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
|
//! Integrations with XDG portals.
|
||||||
|
|
||||||
|
use ashpd::{
|
||||||
|
desktop::inhibit::{InhibitFlags, InhibitProxy},
|
||||||
|
enumflags2::{BitFlags, make_bitflags},
|
||||||
|
};
|
||||||
|
use log::{debug, warn};
|
||||||
|
use tokio::sync::watch::Receiver;
|
||||||
|
|
||||||
|
// Actions to inhibit. Currently, COSMIC defaults to the GTK portal for Inhibit. That
|
||||||
|
// implementation only supports inhibiting idling and trying to inhibit anything else causes the
|
||||||
|
// D-Bus call to silently fail. We will only inhibit idling until COSMIC gets a bespoke Inhibit.
|
||||||
|
const INHIBIT_FLAGS: BitFlags<InhibitFlags> = make_bitflags!(InhibitFlags::{Idle});
|
||||||
|
|
||||||
|
/// Inhibit idle and user switching while media is played.
|
||||||
|
///
|
||||||
|
/// # Usage
|
||||||
|
/// Enable the inhibitor by setting the watcher to `true`. Disable the inhibitor by sending a
|
||||||
|
/// `false`. Sending multiple consecutive trues/falses is safe and guarded internally.
|
||||||
|
///
|
||||||
|
/// Portal:
|
||||||
|
/// https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.Inhibit.html
|
||||||
|
pub async fn inhibit(mut signal: Receiver<bool>) -> ashpd::Result<()> {
|
||||||
|
let proxy = InhibitProxy::new().await?;
|
||||||
|
// Mark the watcher's value as unseen so a temporary or mutable bool isn't needed in the loop.
|
||||||
|
signal.mark_changed();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
if signal.wait_for(|&status| status).await.is_err() {
|
||||||
|
// The watcher will likely only be closed when the app is closed.
|
||||||
|
debug!("Inhibit task's watcher is closed");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Copying the bool is important or else we would needlessly hold the lock below.
|
||||||
|
let should_inhibit = *signal.borrow_and_update();
|
||||||
|
|
||||||
|
if should_inhibit
|
||||||
|
&& let Some(inhibit_handle) = proxy
|
||||||
|
.inhibit(None, INHIBIT_FLAGS, "")
|
||||||
|
.await
|
||||||
|
.inspect_err(|e| warn!("Failed to call inhibit portal endpoint: {e}"))
|
||||||
|
.ok()
|
||||||
|
{
|
||||||
|
// We don't have to check the bool because it's already checked to be false in the
|
||||||
|
// closure. We also don't have to break on error because the next iteration of the loop
|
||||||
|
// would break anyway.
|
||||||
|
let _ = signal.wait_for(|&status| !status).await;
|
||||||
|
if let Err(e) = inhibit_handle.close().await {
|
||||||
|
// This should only happen if the inhibit portal silently fails which GTK (and
|
||||||
|
// others!) apparently do.
|
||||||
|
warn!("Removing the inhibitor failed: {e}");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue