mirror of
https://gitlab.gnome.org/World/Authenticator.git
synced 2025-03-04 00:34:40 +01:00
move the camera to use the portal
This commit is contained in:
parent
c74b509f56
commit
48822df359
14 changed files with 789 additions and 2236 deletions
512
Cargo.lock
generated
512
Cargo.lock
generated
|
@ -77,6 +77,15 @@ dependencies = [
|
|||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ansi_term"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.52"
|
||||
|
@ -105,6 +114,8 @@ dependencies = [
|
|||
"gdk4-wayland",
|
||||
"gdk4-x11",
|
||||
"gtk4",
|
||||
"libc",
|
||||
"pipewire",
|
||||
"rand 0.8.4",
|
||||
"serde",
|
||||
"serde_repr",
|
||||
|
@ -287,8 +298,8 @@ dependencies = [
|
|||
"diesel_migrations",
|
||||
"futures",
|
||||
"gettext-rs",
|
||||
"gst-plugin-gtk4",
|
||||
"gstreamer",
|
||||
"gstreamer-base",
|
||||
"gtk-macros",
|
||||
"gtk4",
|
||||
"hex",
|
||||
|
@ -337,12 +348,47 @@ version = "0.1.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "383d29d513d8764dcdc42ea295d979eb99c3c9f00607b3692cf68a431f7dca72"
|
||||
|
||||
[[package]]
|
||||
name = "bindgen"
|
||||
version = "0.59.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2bd2a9a458e8f4304c52c43ebb0cfbd520289f8379a52e329a38afda99bf8eb8"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cexpr",
|
||||
"clang-sys",
|
||||
"clap",
|
||||
"env_logger 0.9.0",
|
||||
"lazy_static",
|
||||
"lazycell",
|
||||
"log",
|
||||
"peeking_take_while",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex",
|
||||
"rustc-hash",
|
||||
"shlex",
|
||||
"which",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bitvec"
|
||||
version = "0.19.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55f93d0ef3363c364d5976646a38f04cf67cfe1d4c8d160cdea02cab2c116b33"
|
||||
dependencies = [
|
||||
"funty",
|
||||
"radium",
|
||||
"tap",
|
||||
"wyz",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "blake2b_simd"
|
||||
version = "0.5.11"
|
||||
|
@ -454,7 +500,7 @@ source = "git+https://github.com/gtk-rs/gtk-rs-core#bf49cc6c0d1c66e3d81ab5626cec
|
|||
dependencies = [
|
||||
"glib-sys",
|
||||
"libc",
|
||||
"system-deps",
|
||||
"system-deps 6.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -463,6 +509,24 @@ version = "1.0.72"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee"
|
||||
|
||||
[[package]]
|
||||
name = "cexpr"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
|
||||
dependencies = [
|
||||
"nom 7.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-expr"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b412e83326147c2bb881f8b40edfbf9905b9b8abaebd0e47ca190ba62fda8f0e"
|
||||
dependencies = [
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-expr"
|
||||
version = "0.9.0"
|
||||
|
@ -490,6 +554,16 @@ version = "1.0.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "17cc5e6b5ab06331c33589842070416baa137e8b0eb912b008cfd4a78ada7919"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
|
||||
dependencies = [
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cipher"
|
||||
version = "0.2.5"
|
||||
|
@ -499,6 +573,32 @@ dependencies = [
|
|||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clang-sys"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa66045b9cb23c2e9c1520732030608b02ee07e5cfaa5a521ec15ded7fa24c90"
|
||||
dependencies = [
|
||||
"glob",
|
||||
"libc",
|
||||
"libloading",
|
||||
]
|
||||
|
||||
[[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 = "color_quant"
|
||||
version = "1.1.0"
|
||||
|
@ -543,6 +643,12 @@ dependencies = [
|
|||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cookie-factory"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "396de984970346b0d9e93d1415082923c679e5ae5c3ee3dcbd104f5610af126b"
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.1"
|
||||
|
@ -839,12 +945,46 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"humantime",
|
||||
"humantime 1.3.0",
|
||||
"log",
|
||||
"regex",
|
||||
"termcolor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "env_logger"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"humantime 2.1.0",
|
||||
"log",
|
||||
"regex",
|
||||
"termcolor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1"
|
||||
dependencies = [
|
||||
"errno-dragonfly",
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "errno-dragonfly"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "event-listener"
|
||||
version = "2.5.1"
|
||||
|
@ -903,6 +1043,12 @@ version = "1.0.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "69a039c3498dc930fe810151a34ba0c1c70b02b8625035592e74432f678591f2"
|
||||
|
||||
[[package]]
|
||||
name = "funty"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7"
|
||||
|
||||
[[package]]
|
||||
name = "futures"
|
||||
version = "0.3.19"
|
||||
|
@ -1028,7 +1174,7 @@ dependencies = [
|
|||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"libc",
|
||||
"system-deps",
|
||||
"system-deps 6.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1058,7 +1204,7 @@ dependencies = [
|
|||
"gobject-sys",
|
||||
"libc",
|
||||
"pango-sys",
|
||||
"system-deps",
|
||||
"system-deps 6.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1080,7 +1226,7 @@ source = "git+https://github.com/gtk-rs/gtk4-rs#8a89be8dbda638ee280c9174078db7fa
|
|||
dependencies = [
|
||||
"glib-sys",
|
||||
"libc",
|
||||
"system-deps",
|
||||
"system-deps 6.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1103,7 +1249,7 @@ dependencies = [
|
|||
"gdk4-sys",
|
||||
"glib-sys",
|
||||
"libc",
|
||||
"system-deps",
|
||||
"system-deps 6.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1202,7 +1348,7 @@ dependencies = [
|
|||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"libc",
|
||||
"system-deps",
|
||||
"system-deps 6.0.0",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
|
@ -1245,9 +1391,15 @@ version = "0.15.0"
|
|||
source = "git+https://github.com/gtk-rs/gtk-rs-core#bf49cc6c0d1c66e3d81ab5626cecb7a8c6662d23"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"system-deps",
|
||||
"system-deps 6.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glob"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
|
||||
|
||||
[[package]]
|
||||
name = "gloo-timers"
|
||||
version = "0.2.2"
|
||||
|
@ -1268,7 +1420,7 @@ source = "git+https://github.com/gtk-rs/gtk-rs-core#bf49cc6c0d1c66e3d81ab5626cec
|
|||
dependencies = [
|
||||
"glib-sys",
|
||||
"libc",
|
||||
"system-deps",
|
||||
"system-deps 6.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1289,7 +1441,7 @@ dependencies = [
|
|||
"glib-sys",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
"system-deps",
|
||||
"system-deps 6.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1319,7 +1471,29 @@ dependencies = [
|
|||
"graphene-sys",
|
||||
"libc",
|
||||
"pango-sys",
|
||||
"system-deps",
|
||||
"system-deps 6.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gst-plugin-gtk4"
|
||||
version = "0.1.0"
|
||||
source = "git+https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/#8bab034bc8bd81ce2f97ecc614d0894d5318d4ca"
|
||||
dependencies = [
|
||||
"fragile",
|
||||
"gst-plugin-version-helper",
|
||||
"gstreamer",
|
||||
"gstreamer-base",
|
||||
"gstreamer-video",
|
||||
"gtk4",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gst-plugin-version-helper"
|
||||
version = "0.8.0"
|
||||
source = "git+https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/#8bab034bc8bd81ce2f97ecc614d0894d5318d4ca"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1368,7 +1542,7 @@ dependencies = [
|
|||
"gobject-sys",
|
||||
"gstreamer-sys",
|
||||
"libc",
|
||||
"system-deps",
|
||||
"system-deps 6.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1379,7 +1553,37 @@ dependencies = [
|
|||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"libc",
|
||||
"system-deps",
|
||||
"system-deps 6.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gstreamer-video"
|
||||
version = "0.18.0"
|
||||
source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs.git#1dae136ae3b0d935f4cf336f111d8aad2feab723"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg-if 1.0.0",
|
||||
"fragile",
|
||||
"futures-channel",
|
||||
"glib",
|
||||
"gstreamer",
|
||||
"gstreamer-base",
|
||||
"gstreamer-video-sys",
|
||||
"libc",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gstreamer-video-sys"
|
||||
version = "0.18.0"
|
||||
source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs.git#1dae136ae3b0d935f4cf336f111d8aad2feab723"
|
||||
dependencies = [
|
||||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"gstreamer-base-sys",
|
||||
"gstreamer-sys",
|
||||
"libc",
|
||||
"system-deps 6.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1438,7 +1642,7 @@ dependencies = [
|
|||
"gsk4-sys",
|
||||
"libc",
|
||||
"pango-sys",
|
||||
"system-deps",
|
||||
"system-deps 6.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1548,6 +1752,12 @@ dependencies = [
|
|||
"quick-error",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "humantime"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "0.2.3"
|
||||
|
@ -1616,6 +1826,15 @@ dependencies = [
|
|||
"waker-fn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.10.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "0.4.8"
|
||||
|
@ -1661,6 +1880,25 @@ version = "1.4.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "lazycell"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
||||
|
||||
[[package]]
|
||||
name = "lexical-core"
|
||||
version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bitflags",
|
||||
"cfg-if 1.0.0",
|
||||
"ryu",
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libadwaita"
|
||||
version = "0.1.0-alpha-6"
|
||||
|
@ -1688,7 +1926,7 @@ dependencies = [
|
|||
"gobject-sys",
|
||||
"gtk4-sys",
|
||||
"libc",
|
||||
"system-deps",
|
||||
"system-deps 6.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1697,6 +1935,16 @@ version = "0.2.112"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125"
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "afe203d669ec979b7128619bae5a63b7b42e9203c1b29146079ee05e2f604b52"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libnghttp2-sys"
|
||||
version = "0.1.7+1.45.0"
|
||||
|
@ -1707,6 +1955,32 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libspa"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aeb373e8b03740369c5fe48a557c6408b6898982d57e17940de144375d472743"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cc",
|
||||
"cookie-factory",
|
||||
"errno",
|
||||
"libc",
|
||||
"libspa-sys",
|
||||
"nom 6.1.2",
|
||||
"system-deps 3.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libspa-sys"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d301a2fc2fed0a97c13836408a4d98f419af0c2695ecf74e634a214c17beefa6"
|
||||
dependencies = [
|
||||
"bindgen",
|
||||
"system-deps 3.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libsqlite3-sys"
|
||||
version = "0.22.2"
|
||||
|
@ -1828,6 +2102,12 @@ dependencies = [
|
|||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "minimal-lexical"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.3.7"
|
||||
|
@ -1863,6 +2143,19 @@ dependencies = [
|
|||
"socket2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.14.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c722bee1037d430d0f8e687bbdbf222f27cc6e4e68d5caf630857bb2b6dbdce"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cc",
|
||||
"cfg-if 0.1.10",
|
||||
"libc",
|
||||
"void",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.17.0"
|
||||
|
@ -1889,6 +2182,30 @@ dependencies = [
|
|||
"memoffset",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "6.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7413f999671bd4745a7b624bd370a569fb6bc574b23c83a3c5ed2e453f3d5e2"
|
||||
dependencies = [
|
||||
"bitvec",
|
||||
"funty",
|
||||
"lexical-core",
|
||||
"memchr",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "7.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b1d11e1ef389c76fe5b81bcaf2ea32cf88b62bc494e19f493d0b30e7a930109"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"minimal-lexical",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num"
|
||||
version = "0.3.1"
|
||||
|
@ -2096,7 +2413,7 @@ dependencies = [
|
|||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"libc",
|
||||
"system-deps",
|
||||
"system-deps 6.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2136,6 +2453,12 @@ version = "1.0.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0744126afe1a6dd7f394cb50a716dbe086cb06e255e53d8d0185d82828358fb5"
|
||||
|
||||
[[package]]
|
||||
name = "peeking_take_while"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.1.0"
|
||||
|
@ -2183,6 +2506,35 @@ version = "0.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||
|
||||
[[package]]
|
||||
name = "pipewire"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5de050d879e7b8d9313429ec314b88b26fe48ba29a6ecc3bc8289d3673fee6c8"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bitflags",
|
||||
"errno",
|
||||
"libc",
|
||||
"libspa",
|
||||
"libspa-sys",
|
||||
"once_cell",
|
||||
"pipewire-sys",
|
||||
"signal",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pipewire-sys"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b4aa5ef9f3afef7dbb335106f69bd6bb541259e8796c693810cde20db1eb949"
|
||||
dependencies = [
|
||||
"bindgen",
|
||||
"libspa-sys",
|
||||
"system-deps 3.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.24"
|
||||
|
@ -2243,7 +2595,7 @@ version = "0.4.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "926d36b9553851b8b0005f1275891b392ee4d2d833852c417ed025477350fb9d"
|
||||
dependencies = [
|
||||
"env_logger",
|
||||
"env_logger 0.7.1",
|
||||
"log",
|
||||
]
|
||||
|
||||
|
@ -2350,6 +2702,12 @@ dependencies = [
|
|||
"scheduled-thread-pool",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "radium"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8"
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.7.3"
|
||||
|
@ -2518,6 +2876,12 @@ dependencies = [
|
|||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.2.3"
|
||||
|
@ -2716,6 +3080,22 @@ dependencies = [
|
|||
"opaque-debug",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3"
|
||||
|
||||
[[package]]
|
||||
name = "signal"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2f6ce83b159ab6984d2419f495134972b48754d13ff2e3f8c998339942b56ed9"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"nix 0.14.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.5"
|
||||
|
@ -2828,6 +3208,30 @@ version = "0.1.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||
|
||||
[[package]]
|
||||
name = "strum"
|
||||
version = "0.21.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aaf86bbcfd1fa9670b7a129f64fc0c9fcbbfe4f1bc4210e9e98fe71ffc12cde2"
|
||||
|
||||
[[package]]
|
||||
name = "strum_macros"
|
||||
version = "0.21.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d06aaeeee809dbc59eb4556183dd927df67db1540de5be8d3ec0b6636358a5ec"
|
||||
dependencies = [
|
||||
"heck 0.3.3",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "subtle"
|
||||
version = "2.4.1"
|
||||
|
@ -2880,19 +3284,43 @@ dependencies = [
|
|||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "system-deps"
|
||||
version = "3.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "480c269f870722b3b08d2f13053ce0c2ab722839f472863c3e2d61ff3a1c2fa6"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cfg-expr 0.8.1",
|
||||
"heck 0.3.3",
|
||||
"itertools",
|
||||
"pkg-config",
|
||||
"strum",
|
||||
"strum_macros",
|
||||
"thiserror",
|
||||
"toml",
|
||||
"version-compare 0.0.11",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "system-deps"
|
||||
version = "6.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b1487aaddaacbc5d60a2a507ba1617c5ca66c57dd0dd07d0c5efd5b693841d4"
|
||||
dependencies = [
|
||||
"cfg-expr",
|
||||
"cfg-expr 0.9.0",
|
||||
"heck 0.3.3",
|
||||
"pkg-config",
|
||||
"toml",
|
||||
"version-compare",
|
||||
"version-compare 0.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tap"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
|
||||
|
||||
[[package]]
|
||||
name = "temp-dir"
|
||||
version = "0.1.11"
|
||||
|
@ -2908,6 +3336,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.30"
|
||||
|
@ -3086,6 +3523,12 @@ version = "1.8.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.2"
|
||||
|
@ -3137,6 +3580,18 @@ version = "0.2.15"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
||||
|
||||
[[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.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1c18c859eead79d8b95d09e4678566e8d70105c4e7b251f707a03df32442661b"
|
||||
|
||||
[[package]]
|
||||
name = "version-compare"
|
||||
version = "0.1.0"
|
||||
|
@ -3264,6 +3719,17 @@ dependencies = [
|
|||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "which"
|
||||
version = "4.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea187a8ef279bc014ec368c27a920da2024d2a711109bfbe3440585d5cf27ad9"
|
||||
dependencies = [
|
||||
"either",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
|
@ -3295,6 +3761,12 @@ version = "0.4.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "wyz"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214"
|
||||
|
||||
[[package]]
|
||||
name = "xmlparser"
|
||||
version = "0.13.3"
|
||||
|
|
|
@ -6,7 +6,7 @@ version = "0.1.0"
|
|||
[dependencies]
|
||||
adw = {package = "libadwaita", git = "https://gitlab.gnome.org/World/Rust/libadwaita-rs"}
|
||||
anyhow = "1.0"
|
||||
ashpd = {git = "https://github.com/bilelmoussaoui/ashpd", features = ["feature_gtk4"]}
|
||||
ashpd = {git = "https://github.com/bilelmoussaoui/ashpd", features = ["feature_pipewire", "feature_gtk4"]}
|
||||
async-std = "1.10"
|
||||
binascii = "0.1"
|
||||
diesel = {version = "1.4", features = ["sqlite", "r2d2"]}
|
||||
|
@ -14,7 +14,7 @@ diesel_migrations = {version = "1.4", features = ["sqlite"]}
|
|||
futures = "0.3"
|
||||
gettext-rs = {version = "0.7", features = ["gettext-system"]}
|
||||
gst = {package = "gstreamer", git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs.git"}
|
||||
gst_base = {package = "gstreamer-base", git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs.git"}
|
||||
gst4gtk = { package = "gst-plugin-gtk4", git = "https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/"}
|
||||
gtk = {git = "https://github.com/gtk-rs/gtk4-rs", package = "gtk4"}
|
||||
gtk-macros = "0.3"
|
||||
hex = "0.4"
|
||||
|
|
1952
build-aux/767.patch
1952
build-aux/767.patch
File diff suppressed because it is too large
Load diff
|
@ -4,24 +4,24 @@
|
|||
"runtime-version": "master",
|
||||
"sdk": "org.gnome.Sdk",
|
||||
"sdk-extensions": [
|
||||
"org.freedesktop.Sdk.Extension.rust-stable"
|
||||
"org.freedesktop.Sdk.Extension.rust-stable",
|
||||
"org.freedesktop.Sdk.Extension.llvm12"
|
||||
],
|
||||
"command": "authenticator",
|
||||
"finish-args": [
|
||||
"--socket=pulseaudio",
|
||||
"--device=all",
|
||||
"--share=network",
|
||||
"--share=ipc",
|
||||
"--socket=fallback-x11",
|
||||
"--socket=wayland",
|
||||
"--talk-name=org.a11y.Bus",
|
||||
"--device=dri",
|
||||
"--talk-name=org.freedesktop.secrets",
|
||||
"--env=RUST_LOG=authenticator=debug",
|
||||
"--env=G_MESSAGES_DEBUG=none",
|
||||
"--env=GST_PLUGIN_SYSTEM_PATH=/app/lib/gstreamer-1.0"
|
||||
"--env=RUST_LOG=authenticator=debug,ashpd=debug",
|
||||
"--env=G_MESSAGES_DEBUG=none"
|
||||
],
|
||||
"build-options": {
|
||||
"append-path": "/usr/lib/sdk/rust-stable/bin",
|
||||
"prepend-path": "/usr/lib/sdk/llvm12/bin",
|
||||
"prepend-ld-library-path": "/usr/lib/sdk/llvm12/lib",
|
||||
"build-args": [
|
||||
"--share=network"
|
||||
],
|
||||
|
@ -61,29 +61,6 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "gst-plugins-good",
|
||||
"buildsystem": "meson",
|
||||
"config-opts": [
|
||||
"-Dgtk3=disabled",
|
||||
"-Dgtk4=enabled",
|
||||
"-Dgtk4-experiments=true",
|
||||
"-Ddoc=disabled",
|
||||
"-Dexamples=disabled",
|
||||
"-Dtests=disabled"
|
||||
],
|
||||
"sources": [
|
||||
{
|
||||
"type": "git",
|
||||
"branch": "1.18",
|
||||
"url": "https://gitlab.freedesktop.org/gstreamer/gst-plugins-good.git"
|
||||
},
|
||||
{
|
||||
"type": "patch",
|
||||
"path": "767.patch"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "gst-bad-plugins",
|
||||
"buildsystem": "meson",
|
||||
|
@ -118,4 +95,4 @@
|
|||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,35 +66,7 @@
|
|||
<object class="GtkStackPage">
|
||||
<property name="name">stream</property>
|
||||
<property name="child">
|
||||
<object class="GtkOverlay" id="overlay">
|
||||
<child type="overlay">
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">horizontal</property>
|
||||
<property name="valign">end</property>
|
||||
<property name="halign">fill</property>
|
||||
<property name="margin-start">18</property>
|
||||
<property name="margin-end">18</property>
|
||||
<property name="margin-bottom">18</property>
|
||||
<property name="spacing">6</property>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="icon-name">qrscanner-symbolic</property>
|
||||
<property name="tooltip-text" translatable="yes">Capture from a screenshot</property>
|
||||
<property name="width-request">44</property>
|
||||
<property name="height-request">44</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="action-name">camera.screenshot-scan</property>
|
||||
<style>
|
||||
<class name="osd" />
|
||||
<class name="circular-button" />
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkPicture" id="picture" />
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
|
|
|
@ -29,6 +29,7 @@ fn main() {
|
|||
pretty_env_logger::init();
|
||||
gtk::init().expect("failed to init gtk");
|
||||
gst::init().expect("failed to init gstreamer");
|
||||
gst4gtk::plugin_register_static().expect("Failed to register gstgtk4 plugin");
|
||||
|
||||
if let Err(err) = init_i18n() {
|
||||
error!("Failed to initialize i18n {}", err);
|
||||
|
|
|
@ -56,6 +56,7 @@ sources = files(
|
|||
'widgets/providers/page.rs',
|
||||
'widgets/providers/row.rs',
|
||||
'widgets/camera.rs',
|
||||
'widgets/camera_paintable.rs',
|
||||
'widgets/error_revealer.rs',
|
||||
'widgets/mod.rs',
|
||||
'widgets/progress_icon.rs',
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
use super::account::Account;
|
||||
use gtk::glib;
|
||||
|
||||
mod imp {
|
||||
use super::*;
|
||||
use glib::subclass::prelude::*;
|
||||
use gtk::subclass::sorter::SorterImpl;
|
||||
use crate::models::Account;
|
||||
use gtk::subclass::prelude::*;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct AccountSorter;
|
||||
|
|
|
@ -3,8 +3,7 @@ use gtk::glib;
|
|||
|
||||
mod imp {
|
||||
use super::*;
|
||||
use glib::subclass::prelude::*;
|
||||
use gtk::subclass::sorter::SorterImpl;
|
||||
use gtk::subclass::prelude::*;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct ProviderSorter;
|
||||
|
|
|
@ -126,9 +126,8 @@ impl AccountAddDialog {
|
|||
|
||||
fn scan_from_camera(&self) {
|
||||
let imp = self.imp();
|
||||
imp.camera.from_camera();
|
||||
imp.deck.set_visible_child_name("camera");
|
||||
|
||||
imp.camera.start();
|
||||
}
|
||||
|
||||
fn set_from_otp_uri(&self, otp_uri: OTPUri) {
|
||||
|
|
|
@ -1,31 +1,20 @@
|
|||
use glib::{Receiver, Sender};
|
||||
use crate::widgets::CameraPaintable;
|
||||
use gst::prelude::*;
|
||||
use gtk::{
|
||||
gio,
|
||||
glib::{self, clone},
|
||||
glib::{self, clone, Receiver},
|
||||
prelude::*,
|
||||
subclass::prelude::*,
|
||||
CompositeTemplate,
|
||||
};
|
||||
use gtk_macros::{send, spawn};
|
||||
use gtk_macros::spawn;
|
||||
use once_cell::sync::Lazy;
|
||||
/// Fancy Camera with QR code detection using ZBar
|
||||
///
|
||||
/// Pipeline:
|
||||
/// queue -- videoconvert -- zbar -- fakesink
|
||||
/// /
|
||||
/// device sink -- tee
|
||||
/// \
|
||||
/// queue -- glsinkbin
|
||||
///
|
||||
///
|
||||
|
||||
static PIPELINE_NAME: Lazy<glib::GString> = Lazy::new(|| glib::GString::from("camera"));
|
||||
use std::os::unix::prelude::RawFd;
|
||||
|
||||
mod screenshot {
|
||||
use super::*;
|
||||
use anyhow::Result;
|
||||
use ashpd::{desktop::screenshot::ScreenshotProxy, zbus, WindowIdentifier};
|
||||
use gtk::{gio, prelude::*};
|
||||
use gtk::gio;
|
||||
use image::GenericImageView;
|
||||
use zbar_rust::ZBarImageScanner;
|
||||
|
||||
|
@ -50,32 +39,42 @@ mod screenshot {
|
|||
anyhow::bail!("Invalid QR code")
|
||||
}
|
||||
|
||||
pub async fn capture<F: FnOnce(gio::File)>(window: gtk::Window, callback: F) -> Result<()> {
|
||||
pub async fn capture(window: gtk::Window) -> Result<gio::File> {
|
||||
let connection = zbus::Connection::session().await?;
|
||||
let proxy = ScreenshotProxy::new(&connection).await?;
|
||||
let uri = proxy
|
||||
.screenshot(&WindowIdentifier::from_native(&window).await, true, true)
|
||||
.await?;
|
||||
callback(gio::File::for_uri(&uri));
|
||||
Ok(())
|
||||
Ok(gio::File::for_uri(&uri))
|
||||
}
|
||||
|
||||
pub async fn stream() -> Result<(RawFd, u32)> {
|
||||
let connection = zbus::Connection::session().await?;
|
||||
let proxy = ashpd::desktop::camera::CameraProxy::new(&connection).await?;
|
||||
proxy.access_camera().await?;
|
||||
let stream_fd = proxy.open_pipe_wire_remote().await?;
|
||||
let node_id = ashpd::desktop::camera::pipewire_node_id(stream_fd).await?;
|
||||
Ok((stream_fd, node_id))
|
||||
}
|
||||
|
||||
pub async fn camera_available() -> Result<bool> {
|
||||
let connection = zbus::Connection::session().await?;
|
||||
let proxy = ashpd::desktop::camera::CameraProxy::new(&connection).await?;
|
||||
Ok(proxy.is_camera_present().await?)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum CameraEvent {
|
||||
CodeDetected(String),
|
||||
DeviceAdded(gst::Device),
|
||||
DeviceSelected(gst::Device),
|
||||
DeviceRemoved(gst::Device),
|
||||
StreamStarted,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum CameraState {
|
||||
Loading,
|
||||
NotFound,
|
||||
Ready,
|
||||
Paused,
|
||||
Loading,
|
||||
}
|
||||
|
||||
mod imp {
|
||||
|
@ -86,17 +85,12 @@ mod imp {
|
|||
#[derive(Debug, CompositeTemplate)]
|
||||
#[template(resource = "/com/belmoussaoui/Authenticator/camera.ui")]
|
||||
pub struct Camera {
|
||||
pub sender: Sender<CameraEvent>,
|
||||
pub paintable: CameraPaintable,
|
||||
pub receiver: RefCell<Option<Receiver<CameraEvent>>>,
|
||||
pub pipeline: gst::Pipeline,
|
||||
pub sink: gst::Element,
|
||||
pub selected_device: RefCell<Option<gst::Device>>,
|
||||
pub devices: gio::ListStore,
|
||||
pub monitor: gst::DeviceMonitor,
|
||||
#[template_child]
|
||||
pub stack: TemplateChild<gtk::Stack>,
|
||||
#[template_child]
|
||||
pub overlay: TemplateChild<gtk::Overlay>,
|
||||
pub picture: TemplateChild<gtk::Picture>,
|
||||
#[template_child]
|
||||
pub spinner: TemplateChild<gtk::Spinner>,
|
||||
}
|
||||
|
@ -117,22 +111,15 @@ mod imp {
|
|||
}
|
||||
|
||||
fn new() -> Self {
|
||||
let pipeline = gst::Pipeline::new(Some(&*PIPELINE_NAME));
|
||||
let sink = gst::ElementFactory::make("gtk4glsink", None).unwrap();
|
||||
let (sender, r) = glib::MainContext::channel(glib::PRIORITY_DEFAULT);
|
||||
let receiver = RefCell::new(Some(r));
|
||||
|
||||
Self {
|
||||
sink,
|
||||
sender,
|
||||
paintable: CameraPaintable::new(sender),
|
||||
receiver,
|
||||
pipeline,
|
||||
selected_device: RefCell::default(),
|
||||
spinner: TemplateChild::default(),
|
||||
stack: TemplateChild::default(),
|
||||
overlay: TemplateChild::default(),
|
||||
monitor: gst::DeviceMonitor::new(),
|
||||
devices: gio::ListStore::new(gst::Device::static_type()),
|
||||
picture: TemplateChild::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -153,12 +140,11 @@ mod imp {
|
|||
|
||||
fn constructed(&self, obj: &Self::Type) {
|
||||
obj.init_widgets();
|
||||
obj.init_monitor();
|
||||
self.parent_constructed(obj);
|
||||
}
|
||||
fn dispose(&self, _obj: &Self::Type) {
|
||||
self.monitor.stop();
|
||||
self.pipeline.set_state(gst::State::Null).unwrap();
|
||||
fn dispose(&self, paintable: &Self::Type) {
|
||||
self.paintable.close_pipeline();
|
||||
self.stack.unparent();
|
||||
}
|
||||
}
|
||||
impl WidgetImpl for Camera {}
|
||||
|
@ -174,150 +160,29 @@ impl Camera {
|
|||
glib::Object::new(&[]).expect("Failed to create a Camera")
|
||||
}
|
||||
|
||||
fn init_monitor(&self) {
|
||||
let imp = self.imp();
|
||||
let caps = gst::Caps::new_simple("video/x-raw", &[]);
|
||||
imp.monitor.add_filter(Some("Video/Source"), Some(&caps));
|
||||
|
||||
imp.monitor.start().unwrap();
|
||||
let bus = imp.monitor.bus();
|
||||
bus.add_watch_local(clone!(@strong imp.sender as sender => move |_, msg| {
|
||||
use gst::MessageView;
|
||||
match msg.view() {
|
||||
MessageView::DeviceAdded(event) => {
|
||||
let device = event.device();
|
||||
send!(sender, CameraEvent::DeviceAdded(device));
|
||||
}
|
||||
MessageView::DeviceRemoved(event) => {
|
||||
let device = event.device();
|
||||
send!(sender, CameraEvent::DeviceRemoved(device));
|
||||
}
|
||||
_ => (),
|
||||
};
|
||||
|
||||
glib::Continue(true)
|
||||
}))
|
||||
.expect("Failed to attach a monitor");
|
||||
}
|
||||
|
||||
fn init_pipelines(&self, source_element: gst::Element) {
|
||||
let imp = self.imp();
|
||||
|
||||
let tee = gst::ElementFactory::make("tee", None).unwrap();
|
||||
let queue = gst::ElementFactory::make("queue", None).unwrap();
|
||||
let videoconvert = gst::ElementFactory::make("videoconvert", None).unwrap();
|
||||
let zbar = gst::ElementFactory::make("zbar", None).unwrap();
|
||||
let fakesink = gst::ElementFactory::make("fakesink", None).unwrap();
|
||||
let queue2 = gst::ElementFactory::make("queue", None).unwrap();
|
||||
let glsinkbin = gst::ElementFactory::make("glsinkbin", None).unwrap();
|
||||
glsinkbin.set_property("sink", &imp.sink);
|
||||
|
||||
imp.pipeline
|
||||
.add_many(&[
|
||||
&source_element,
|
||||
&tee,
|
||||
&queue,
|
||||
&videoconvert,
|
||||
&zbar,
|
||||
&fakesink,
|
||||
&queue2,
|
||||
&glsinkbin,
|
||||
])
|
||||
.unwrap();
|
||||
|
||||
gst::Element::link_many(&[
|
||||
&source_element,
|
||||
&tee,
|
||||
&queue,
|
||||
&videoconvert,
|
||||
&zbar,
|
||||
&fakesink,
|
||||
])
|
||||
.unwrap();
|
||||
tee.link_pads(None, &queue2, None).unwrap();
|
||||
gst::Element::link_many(&[&queue2, &glsinkbin]).unwrap();
|
||||
|
||||
let bus = imp.pipeline.bus().unwrap();
|
||||
bus.add_watch_local(clone!(@strong imp.sender as sender => move |_, msg| {
|
||||
use gst::MessageView;
|
||||
match msg.view() {
|
||||
MessageView::StateChanged(state) => {
|
||||
if Some(&*PIPELINE_NAME) == state.src().map(|s| s.name()).as_ref() {
|
||||
let structure = state.structure().unwrap();
|
||||
let new_state = structure.get::<gst::State>("new-state")
|
||||
.unwrap();
|
||||
if new_state == gst::State::Playing {
|
||||
send!(sender, CameraEvent::StreamStarted);
|
||||
}
|
||||
}
|
||||
}
|
||||
MessageView::Element(e) => {
|
||||
if let Some(s) = e.structure() {
|
||||
if let Ok(symbol) = s.get::<String>("symbol") {
|
||||
send!(sender, CameraEvent::CodeDetected(symbol));
|
||||
}
|
||||
}
|
||||
}
|
||||
MessageView::Error(err) => {
|
||||
error!(
|
||||
"Error from {:?}: {} ({:?})",
|
||||
err.src().map(|s| s.path_string()),
|
||||
err.error(),
|
||||
err.debug()
|
||||
);
|
||||
}
|
||||
_ => (),
|
||||
};
|
||||
|
||||
glib::Continue(true)
|
||||
}))
|
||||
.expect("Failed to add bus watch");
|
||||
}
|
||||
|
||||
fn set_state(&self, state: CameraState) {
|
||||
let imp = self.imp();
|
||||
info!("The camera state changed to {:#?}", state);
|
||||
match state {
|
||||
CameraState::NotFound => {
|
||||
imp.stack.get().set_visible_child_name("not-found");
|
||||
imp.stack.set_visible_child_name("not-found");
|
||||
}
|
||||
CameraState::Ready => {
|
||||
imp.stack.get().set_visible_child_name("stream");
|
||||
imp.spinner.get().stop();
|
||||
imp.stack.set_visible_child_name("stream");
|
||||
imp.spinner.stop();
|
||||
}
|
||||
CameraState::Loading => {
|
||||
imp.stack.get().set_visible_child_name("loading");
|
||||
imp.spinner.get().start();
|
||||
imp.stack.set_visible_child_name("loading");
|
||||
imp.spinner.start();
|
||||
}
|
||||
CameraState::Paused => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn do_event(&self, event: CameraEvent) -> glib::Continue {
|
||||
let imp = self.imp();
|
||||
match event {
|
||||
CameraEvent::CodeDetected(code) => {
|
||||
self.emit_by_name::<()>("code-detected", &[&code]);
|
||||
}
|
||||
CameraEvent::DeviceAdded(device) => {
|
||||
info!("Camera source added: {}", device.display_name());
|
||||
imp.devices.append(&device);
|
||||
if imp.selected_device.borrow_mut().is_none() {
|
||||
send!(imp.sender, CameraEvent::DeviceSelected(device));
|
||||
}
|
||||
}
|
||||
CameraEvent::DeviceSelected(device) => {
|
||||
info!("Camera source selected: {}", device.display_name());
|
||||
// TODO: allow selecting a device and update the sink on the pipeline
|
||||
self.set_state(CameraState::Loading);
|
||||
let element = device.create_element(None).unwrap();
|
||||
self.init_pipelines(element);
|
||||
imp.selected_device.replace(Some(device));
|
||||
}
|
||||
CameraEvent::DeviceRemoved(device) => {
|
||||
info!("Camera source removed: {}", device.display_name());
|
||||
imp.devices.append(&device);
|
||||
}
|
||||
CameraEvent::StreamStarted => {
|
||||
self.set_state(CameraState::Ready);
|
||||
}
|
||||
|
@ -327,33 +192,34 @@ impl Camera {
|
|||
}
|
||||
|
||||
pub fn start(&self) {
|
||||
let imp = self.imp();
|
||||
if let Err(err) = imp.pipeline.set_state(gst::State::Playing) {
|
||||
log::error!("Failed to start the camera stream: {}", err);
|
||||
}
|
||||
self.imp().paintable.start();
|
||||
self.set_state(CameraState::Ready);
|
||||
}
|
||||
|
||||
pub fn stop(&self) {
|
||||
let imp = self.imp();
|
||||
self.set_state(CameraState::Paused);
|
||||
if let Err(err) = imp.pipeline.set_state(gst::State::Null) {
|
||||
log::error!("Failed to stop the camera stream: {}", err);
|
||||
}
|
||||
self.imp().paintable.stop();
|
||||
}
|
||||
|
||||
pub fn from_camera(&self) {
|
||||
spawn!(clone!(@weak self as camera => async move {
|
||||
match screenshot::stream().await {
|
||||
Ok((stream_fd, node_id)) => {
|
||||
camera.imp().paintable.set_pipewire_node_id(stream_fd, node_id);
|
||||
camera.start();
|
||||
},
|
||||
Err(e) => log::error!("Failed to stream {}", e),
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
pub fn from_screenshot(&self) {
|
||||
spawn!(clone!(@weak self as this => async move {
|
||||
let imp = this.imp();
|
||||
let window = this.root().unwrap().downcast::<gtk::Window>().unwrap();
|
||||
if let Err(err) = screenshot::capture(
|
||||
let screenshot_file = screenshot::capture(
|
||||
window,
|
||||
clone!(@strong imp.sender as sender => move |file| {
|
||||
if let Ok(code) = screenshot::scan(&file) {
|
||||
send!(sender, CameraEvent::CodeDetected(code));
|
||||
}
|
||||
}),
|
||||
).await {
|
||||
log::warn!("Failed to take a screenshot: {}", err);
|
||||
).await.unwrap();
|
||||
if let Ok(code) = screenshot::scan(&screenshot_file) {
|
||||
this.emit_by_name::<()>("code-detected", &[&code]);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
@ -366,9 +232,6 @@ impl Camera {
|
|||
None,
|
||||
glib::clone!(@weak self as camera => @default-return glib::Continue(false), move |action| camera.do_event(action)),
|
||||
);
|
||||
|
||||
let widget = imp.sink.property::<gtk::Widget>("widget");
|
||||
widget.set_property("force-aspect-ratio", &false);
|
||||
imp.overlay.get().set_child(Some(&widget));
|
||||
imp.picture.set_paintable(Some(&imp.paintable));
|
||||
}
|
||||
}
|
||||
|
|
220
src/widgets/camera_paintable.rs
Normal file
220
src/widgets/camera_paintable.rs
Normal file
|
@ -0,0 +1,220 @@
|
|||
use std::os::unix::io::AsRawFd;
|
||||
|
||||
use crate::widgets::camera::CameraEvent;
|
||||
use gst::prelude::*;
|
||||
use gtk::prelude::*;
|
||||
use gtk::subclass::prelude::*;
|
||||
use gtk::{
|
||||
gdk,
|
||||
glib::{self, clone, Sender},
|
||||
graphene,
|
||||
};
|
||||
use gtk_macros::send;
|
||||
use once_cell::sync::Lazy;
|
||||
static PIPELINE_NAME: Lazy<glib::GString> = Lazy::new(|| glib::GString::from("camera"));
|
||||
/// Fancy Camera with QR code detection using ZBar
|
||||
///
|
||||
/// Pipeline:
|
||||
/// queue -- videoconvert -- zbar -- fakesink
|
||||
/// /
|
||||
/// pipewiresrc -- tee
|
||||
/// \
|
||||
/// queue -- glsinkbin
|
||||
///
|
||||
///
|
||||
mod imp {
|
||||
use std::cell::RefCell;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct CameraPaintable {
|
||||
pub sender: RefCell<Option<Sender<CameraEvent>>>,
|
||||
pub pipeline: RefCell<Option<gst::Pipeline>>,
|
||||
pub sink_paintable: RefCell<Option<gdk::Paintable>>,
|
||||
}
|
||||
|
||||
#[glib::object_subclass]
|
||||
impl ObjectSubclass for CameraPaintable {
|
||||
const NAME: &'static str = "CameraPaintable";
|
||||
type Type = super::CameraPaintable;
|
||||
type Interfaces = (gdk::Paintable,);
|
||||
}
|
||||
|
||||
impl ObjectImpl for CameraPaintable {
|
||||
fn dispose(&self, paintable: &Self::Type) {
|
||||
paintable.close_pipeline();
|
||||
}
|
||||
}
|
||||
|
||||
impl PaintableImpl for CameraPaintable {
|
||||
fn intrinsic_height(&self, _paintable: &Self::Type) -> i32 {
|
||||
if let Some(ref paintable) = *self.sink_paintable.borrow() {
|
||||
paintable.intrinsic_height()
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
fn intrinsic_width(&self, _paintable: &Self::Type) -> i32 {
|
||||
if let Some(ref paintable) = *self.sink_paintable.borrow() {
|
||||
paintable.intrinsic_width()
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
fn snapshot(
|
||||
&self,
|
||||
_paintable: &Self::Type,
|
||||
snapshot: &gdk::Snapshot,
|
||||
width: f64,
|
||||
height: f64,
|
||||
) {
|
||||
if let Some(ref image) = *self.sink_paintable.borrow() {
|
||||
image.snapshot(snapshot, width, height);
|
||||
} else {
|
||||
let snapshot = snapshot.downcast_ref::<gtk::Snapshot>().unwrap();
|
||||
snapshot.append_color(
|
||||
&gdk::RGBA::BLACK,
|
||||
&graphene::Rect::new(0f32, 0f32, width as f32, height as f32),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glib::wrapper! {
|
||||
pub struct CameraPaintable(ObjectSubclass<imp::CameraPaintable>) @implements gdk::Paintable;
|
||||
}
|
||||
|
||||
impl CameraPaintable {
|
||||
pub fn new(sender: Sender<CameraEvent>) -> Self {
|
||||
let paintable = glib::Object::new::<Self>(&[]).expect("Failed to create a CameraPaintable");
|
||||
paintable.imp().sender.replace(Some(sender));
|
||||
paintable
|
||||
}
|
||||
|
||||
pub fn set_pipewire_node_id<F: AsRawFd>(&self, fd: F, node_id: u32) {
|
||||
let raw_fd = fd.as_raw_fd();
|
||||
log::debug!("Loading PipeWire Node ID: {} with FD: {}", node_id, raw_fd);
|
||||
let pipewire_element = gst::ElementFactory::make("pipewiresrc", None).unwrap();
|
||||
pipewire_element.set_property("fd", &raw_fd);
|
||||
pipewire_element.set_property("path", &node_id.to_string());
|
||||
self.init_pipeline(pipewire_element);
|
||||
}
|
||||
|
||||
fn init_pipeline(&self, pipewire_src: gst::Element) {
|
||||
log::debug!("Init pipeline");
|
||||
let imp = self.imp();
|
||||
let pipeline = gst::Pipeline::new(None);
|
||||
|
||||
let sink = gst::ElementFactory::make("gtk4paintablesink", None).unwrap();
|
||||
let paintable = sink.property::<gdk::Paintable>("paintable");
|
||||
|
||||
paintable.connect_invalidate_contents(clone!(@weak self as pt => move |_| {
|
||||
pt.invalidate_contents();
|
||||
}));
|
||||
|
||||
paintable.connect_invalidate_size(clone!(@weak self as pt => move |_| {
|
||||
pt.invalidate_size ();
|
||||
}));
|
||||
imp.sink_paintable.replace(Some(paintable));
|
||||
let tee = gst::ElementFactory::make("tee", None).unwrap();
|
||||
let videoconvert1 = gst::ElementFactory::make("videoconvert", None).unwrap();
|
||||
let videoconvert2 = gst::ElementFactory::make("videoconvert", None).unwrap();
|
||||
let queue1 = gst::ElementFactory::make("queue", None).unwrap();
|
||||
let queue2 = gst::ElementFactory::make("queue", None).unwrap();
|
||||
let zbar = gst::ElementFactory::make("zbar", None).unwrap();
|
||||
let fakesink = gst::ElementFactory::make("fakesink", None).unwrap();
|
||||
|
||||
pipeline
|
||||
.add_many(&[
|
||||
&pipewire_src,
|
||||
&tee,
|
||||
&queue1,
|
||||
&videoconvert1,
|
||||
&zbar,
|
||||
&fakesink,
|
||||
&queue2,
|
||||
&videoconvert2,
|
||||
&sink,
|
||||
])
|
||||
.unwrap();
|
||||
|
||||
gst::Element::link_many(&[
|
||||
&pipewire_src,
|
||||
&tee,
|
||||
&queue1,
|
||||
&videoconvert1,
|
||||
&zbar,
|
||||
&fakesink,
|
||||
])
|
||||
.unwrap();
|
||||
tee.link_pads(None, &queue2, None).unwrap();
|
||||
gst::Element::link_many(&[&queue2, &videoconvert2, &sink]).unwrap();
|
||||
|
||||
let bus = pipeline.bus().unwrap();
|
||||
bus.add_watch_local(
|
||||
clone!(@weak self as paintable => @default-return glib::Continue(false), move |_, msg| {
|
||||
use gst::MessageView;
|
||||
let sender = paintable.imp().sender.borrow().as_ref().unwrap().clone();
|
||||
match msg.view() {
|
||||
MessageView::Error(err) => {
|
||||
log::error!(
|
||||
"Error from {:?}: {} ({:?})",
|
||||
err.src().map(|s| s.path_string()),
|
||||
err.error(),
|
||||
err.debug()
|
||||
);
|
||||
}
|
||||
MessageView::StateChanged(state) => {
|
||||
if Some(&*PIPELINE_NAME) == state.src().map(|s| s.name()).as_ref() {
|
||||
let structure = state.structure().unwrap();
|
||||
let new_state = structure.get::<gst::State>("new-state")
|
||||
.unwrap();
|
||||
if new_state == gst::State::Playing {
|
||||
send!(sender, CameraEvent::StreamStarted);
|
||||
}
|
||||
}
|
||||
}
|
||||
MessageView::Element(e) => {
|
||||
if let Some(s) = e.structure() {
|
||||
if let Ok(symbol) = s.get::<String>("symbol") {
|
||||
send!(sender, CameraEvent::CodeDetected(symbol));
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
glib::Continue(true)
|
||||
|
||||
}),
|
||||
)
|
||||
.expect("Failed to add bus watch");
|
||||
imp.pipeline.replace(Some(pipeline));
|
||||
}
|
||||
|
||||
pub fn close_pipeline(&self) {
|
||||
log::debug!("Closing pipeline");
|
||||
if let Some(pipeline) = self.imp().pipeline.borrow_mut().take() {
|
||||
pipeline.set_state(gst::State::Null).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start(&self) {
|
||||
if let Some(pipeline) = &*self.imp().pipeline.borrow() {
|
||||
if let Err(err) = pipeline.set_state(gst::State::Playing) {
|
||||
log::error!("Failed to start the camera stream: {}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stop(&self) {
|
||||
if let Some(pipeline) = &*self.imp().pipeline.borrow() {
|
||||
if let Err(err) = pipeline.set_state(gst::State::Null) {
|
||||
log::error!("Failed to stop the camera stream: {}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
mod accounts;
|
||||
mod camera;
|
||||
mod camera_paintable;
|
||||
mod error_revealer;
|
||||
mod preferences;
|
||||
mod progress_icon;
|
||||
|
@ -9,7 +10,8 @@ mod window;
|
|||
|
||||
pub use self::{
|
||||
accounts::{AccountAddDialog, QRCodeData},
|
||||
camera::Camera,
|
||||
camera::{Camera, CameraEvent},
|
||||
camera_paintable::CameraPaintable,
|
||||
error_revealer::ErrorRevealer,
|
||||
preferences::PreferencesWindow,
|
||||
progress_icon::{ProgressIcon, ProgressIconExt},
|
||||
|
|
|
@ -24,7 +24,7 @@ pub enum View {
|
|||
|
||||
mod imp {
|
||||
use super::*;
|
||||
use adw::subclass::application_window::AdwApplicationWindowImpl;
|
||||
use adw::subclass::prelude::*;
|
||||
use glib::subclass;
|
||||
|
||||
#[derive(Debug, CompositeTemplate)]
|
||||
|
|
Loading…
Add table
Reference in a new issue