From 268ec1df81f733b8c15a781b238b0f26c896842e Mon Sep 17 00:00:00 2001 From: Ivan Li Date: Mon, 5 Jun 2023 22:34:32 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BD=BF=E7=94=A8=20ScreenCaptureKit?= =?UTF-8?q?=20=E8=8E=B7=E5=8F=96=E5=B1=8F=E5=B9=95=E5=B8=A7=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src-tauri/Cargo.lock | 499 +++++++++++------------ src-tauri/Cargo.toml | 1 + src-tauri/src/ambient_light/publisher.rs | 97 ++--- src-tauri/src/main.rs | 279 +++++++------ src-tauri/src/screenshot.rs | 22 +- src-tauri/src/screenshot_manager.rs | 168 ++++---- src-tauri/tauri.conf.json | 5 +- 7 files changed, 511 insertions(+), 560 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index a76d273..35faa5b 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -41,6 +41,12 @@ dependencies = [ "alloc-no-stdlib", ] +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + [[package]] name = "android_system_properties" version = "0.1.5" @@ -88,7 +94,7 @@ dependencies = [ "glib-sys", "gobject-sys", "libc", - "system-deps 6.0.5", + "system-deps 6.1.0", ] [[package]] @@ -105,9 +111,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.0" +version = "0.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" +checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" [[package]] name = "bindgen" @@ -173,9 +179,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d4260bcc2e8fc9df1eac4919a720effeb63a3f0952f5bf4944adfa18897f09" +checksum = "a246e68bb43f6cd9db24bea052a53e40405417c5fb372e3d1a8a7f770a564ef5" dependencies = [ "memchr 2.5.0", "serde", @@ -183,9 +189,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.12.1" +version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b1ce199063694f33ffb7dd4e0ee620741495c32833cde5aa08f02a0bf96f0c8" +checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" [[package]] name = "bytemuck" @@ -226,17 +232,17 @@ checksum = "3c55d429bef56ac9172d25fecb85dc8068307d17acd74b377866b7a1ef25d3c8" dependencies = [ "glib-sys", "libc", - "system-deps 6.0.5", + "system-deps 6.1.0", ] [[package]] name = "cargo_toml" -version = "0.15.2" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f83bc2e401ed041b7057345ebc488c005efa0341d5541ce7004d30458d0090b" +checksum = "497049e9477329f8f6a559972ee42e117487d01d1e8c2cc9f836ea6fa23a9e1a" dependencies = [ "serde", - "toml 0.7.3", + "toml 0.5.11", ] [[package]] @@ -282,9 +288,9 @@ dependencies = [ [[package]] name = "cfg-expr" -version = "0.15.1" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8790cf1286da485c72cf5fc7aeba308438800036ec67d89425924c4807268c9" +checksum = "e70d3ad08698a0568b0562f22710fe6bfc1f4a61a367c77d0398c562eadd453a" dependencies = [ "smallvec", "target-lexicon", @@ -298,12 +304,12 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.24" +version = "0.4.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b" +checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" dependencies = [ + "android-tzdata", "iana-time-zone", - "num-integer", "num-traits", "serde", "winapi", @@ -360,16 +366,6 @@ dependencies = [ "objc", ] -[[package]] -name = "codespan-reporting" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" -dependencies = [ - "termcolor", - "unicode-width", -] - [[package]] name = "color_quant" version = "1.1.0" @@ -540,12 +536,12 @@ dependencies = [ [[package]] name = "cssparser-macros" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfae75de57f2b2e85e8768c3ea840fd159c8f33e2b6522c7835b7abac81be16e" +checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn 1.0.109", + "syn 2.0.18", ] [[package]] @@ -558,50 +554,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "cxx" -version = "1.0.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f61f1b6389c3fe1c316bf8a4dccc90a38208354b330925bce1f74a6c4756eb93" -dependencies = [ - "cc", - "cxxbridge-flags", - "cxxbridge-macro", - "link-cplusplus", -] - -[[package]] -name = "cxx-build" -version = "1.0.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12cee708e8962df2aeb38f594aae5d827c022b6460ac71a7a3e2c3c2aae5a07b" -dependencies = [ - "cc", - "codespan-reporting", - "once_cell", - "proc-macro2", - "quote", - "scratch", - "syn 2.0.15", -] - -[[package]] -name = "cxxbridge-flags" -version = "1.0.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7944172ae7e4068c533afbb984114a56c46e9ccddda550499caa222902c7f7bb" - -[[package]] -name = "cxxbridge-macro" -version = "1.0.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2345488264226bf682893e25de0769f3360aac9957980ec49361b083ddaa5bc5" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.15", -] - [[package]] name = "darling" version = "0.20.1" @@ -623,7 +575,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.15", + "syn 2.0.18", ] [[package]] @@ -634,7 +586,7 @@ checksum = "29a358ff9f12ec09c3e61fef9b5a9902623a695a46a917b07f269bff1445611a" dependencies = [ "darling_core", "quote", - "syn 2.0.15", + "syn 2.0.18", ] [[package]] @@ -703,6 +655,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "derive_more" version = "0.99.17" @@ -718,9 +681,9 @@ dependencies = [ [[package]] name = "digest" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", "crypto-common", @@ -755,15 +718,15 @@ checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" [[package]] name = "display-info" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15453e90755c09fc70a6dbc9a307b0d4ec0fa65c5e36fb7cf8246109c442c331" +checksum = "06d9c500164fbeb11a2d7dc1df709882dad868a56240c5c972b460b3e6058d42" dependencies = [ "anyhow", "core-graphics", "fxhash", "widestring", - "windows 0.44.0", + "windows 0.48.0", "xcb", ] @@ -803,19 +766,6 @@ version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" -[[package]] -name = "embed-resource" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80663502655af01a2902dff3f06869330782267924bf1788410b74edcd93770a" -dependencies = [ - "cc", - "rustc_version", - "toml 0.7.3", - "vswhom", - "winreg", -] - [[package]] name = "embed_plist" version = "1.2.2" @@ -891,9 +841,9 @@ dependencies = [ [[package]] name = "field-offset" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3cf3a800ff6e860c863ca6d4b16fd999db8b752819c1606884047b73e468535" +checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f" dependencies = [ "memoffset", "rustc_version", @@ -1029,7 +979,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.18", ] [[package]] @@ -1116,7 +1066,7 @@ dependencies = [ "glib-sys", "gobject-sys", "libc", - "system-deps 6.0.5", + "system-deps 6.1.0", ] [[package]] @@ -1133,7 +1083,7 @@ dependencies = [ "libc", "pango-sys", "pkg-config", - "system-deps 6.0.5", + "system-deps 6.1.0", ] [[package]] @@ -1145,7 +1095,7 @@ dependencies = [ "gdk-sys", "glib-sys", "libc", - "system-deps 6.0.5", + "system-deps 6.1.0", "x11", ] @@ -1220,7 +1170,7 @@ dependencies = [ "glib-sys", "gobject-sys", "libc", - "system-deps 6.0.5", + "system-deps 6.1.0", "winapi", ] @@ -1266,7 +1216,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef4b192f8e65e9cf76cbf4ea71fa8e3be4a0e18ffe3d68b8da6836974cc5bad4" dependencies = [ "libc", - "system-deps 6.0.5", + "system-deps 6.1.0", ] [[package]] @@ -1296,7 +1246,7 @@ checksum = "0d57ce44246becd17153bd035ab4d32cfee096a657fc01f2231c9278378d1e0a" dependencies = [ "glib-sys", "libc", - "system-deps 6.0.5", + "system-deps 6.1.0", ] [[package]] @@ -1337,7 +1287,7 @@ dependencies = [ "gobject-sys", "libc", "pango-sys", - "system-deps 6.0.5", + "system-deps 6.1.0", ] [[package]] @@ -1482,12 +1432,11 @@ dependencies = [ [[package]] name = "iana-time-zone-haiku" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" dependencies = [ - "cxx", - "cxx-build", + "cc", ] [[package]] @@ -1598,9 +1547,9 @@ dependencies = [ [[package]] name = "io-lifetimes" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ "hermit-abi 0.3.1", "libc", @@ -1685,9 +1634,9 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "js-sys" -version = "0.3.61" +version = "0.3.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" +checksum = "2f37a4a5928311ac501dee68b3c7613a1037d0edb30c8e5427bd832d55d1b790" dependencies = [ "wasm-bindgen", ] @@ -1741,9 +1690,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.143" +version = "0.2.144" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edc207893e85c5d6be840e969b496b53d94cec8be2d501b214f50daa97fa8024" +checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" [[package]] name = "libloading" @@ -1774,15 +1723,6 @@ dependencies = [ "safemem", ] -[[package]] -name = "link-cplusplus" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" -dependencies = [ - "cc", -] - [[package]] name = "linked-hash-map" version = "0.5.6" @@ -1791,9 +1731,9 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "linux-raw-sys" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ece97ea872ece730aed82664c424eb4c8291e1ff2480247ccf7409044bc6479f" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] name = "lock_api" @@ -1807,12 +1747,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.17" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] +checksum = "518ef76f2f87365916b142844c16d8fefd85039bc5699050210a7778ee1cd1de" [[package]] name = "loom" @@ -1953,9 +1890,9 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memoffset" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" dependencies = [ "autocfg", ] @@ -1978,14 +1915,13 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.6" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" +checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", - "log", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] @@ -2170,9 +2106,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.17.1" +version = "1.17.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +checksum = "9670a07f94779e00908f3e686eab508878ebb390ba6e604d3a284c00e8d0487b" [[package]] name = "open" @@ -2186,9 +2122,9 @@ dependencies = [ [[package]] name = "openssl-sys" -version = "0.9.87" +version = "0.9.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e17f59264b2809d77ae94f0e1ebabc434773f370d6ca667bd223ea10e06cc7e" +checksum = "c2ce0f250f34a308dcfdbb351f511359857d4ed2134ba715a4eadd46e1ffd617" dependencies = [ "cc", "libc", @@ -2250,7 +2186,7 @@ dependencies = [ "glib-sys", "gobject-sys", "libc", - "system-deps 6.0.5", + "system-deps 6.1.0", ] [[package]] @@ -2406,22 +2342,22 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.0.12" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" +checksum = "c95a7476719eab1e366eaf73d0260af3021184f18177925b07f54b30089ceead" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.0.12" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" +checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.18", ] [[package]] @@ -2448,7 +2384,7 @@ version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9bd9647b268a3d3e14ff09c23201133a62589c658db02bb7388c7246aafe0590" dependencies = [ - "base64 0.21.0", + "base64 0.21.2", "indexmap", "line-wrap", "quick-xml", @@ -2539,9 +2475,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.56" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" +checksum = "6aeca18b86b413c660b781aa319e4e2648a3e6f9eadc9b47e9038e6fe9f3451b" dependencies = [ "unicode-ident", ] @@ -2557,9 +2493,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.26" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" dependencies = [ "proc-macro2", ] @@ -2682,13 +2618,13 @@ dependencies = [ [[package]] name = "regex" -version = "1.8.1" +version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370" +checksum = "81ca098a9821bd52d6b24fd8b10bd081f47d39c22778cafaa75a2857a62c6390" dependencies = [ "aho-corasick 1.0.1", "memchr 2.5.0", - "regex-syntax 0.7.1", + "regex-syntax 0.7.2", ] [[package]] @@ -2708,9 +2644,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c" +checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" [[package]] name = "resize-slice" @@ -2721,6 +2657,21 @@ dependencies = [ "uninitialized", ] +[[package]] +name = "rust_swift_screencapture" +version = "0.1.1" +dependencies = [ + "derivative", + "env_logger", + "futures-util", + "log", + "once_cell", + "swift-bridge", + "swift-bridge-build", + "tokio", + "tokio-stream", +] + [[package]] name = "rustc-hash" version = "1.1.0" @@ -2789,12 +2740,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" -[[package]] -name = "scratch" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1" - [[package]] name = "selectors" version = "0.22.0" @@ -2826,22 +2771,22 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.160" +version = "1.0.163" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c" +checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.160" +version = "1.0.163" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df" +checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.18", ] [[package]] @@ -2863,14 +2808,14 @@ checksum = "bcec881020c684085e55a25f7fd888954d56609ef363479dc5a1305eb0d40cab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.18", ] [[package]] name = "serde_spanned" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0efd8caf556a6cebd3b285caf480045fcc1ac04f6bd786b09a6f11af30c4fcf4" +checksum = "93107647184f6027e3b7dcb2e11034cf95ffa1e3a682c67951963ac69c1c007d" dependencies = [ "serde", ] @@ -2900,7 +2845,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.18", ] [[package]] @@ -3103,6 +3048,51 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "swift-bridge" +version = "0.1.51" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa07c7cd2b2d7ca48d96f5abd159e3fd3eee3457e7bd03adc1994bfbdabd2f" +dependencies = [ + "swift-bridge-build", + "swift-bridge-macro", +] + +[[package]] +name = "swift-bridge-build" +version = "0.1.51" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "286f727dc922736a1ed74c06bebf43d08b8295a7ba38c77326c74e2b9dfd43df" +dependencies = [ + "proc-macro2", + "swift-bridge-ir", + "syn 1.0.109", + "tempfile", +] + +[[package]] +name = "swift-bridge-ir" +version = "0.1.51" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b4de97e9abde20abc1c01f6d4faa8072d723c73aba288264481a83a1e2787dc" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "swift-bridge-macro" +version = "0.1.51" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64fabad38a0fc643ceeafefed79e08408c30eeec325b629e426a15b13d055d0a" +dependencies = [ + "proc-macro2", + "quote", + "swift-bridge-ir", + "syn 1.0.109", +] + [[package]] name = "syn" version = "1.0.109" @@ -3116,9 +3106,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.15" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822" +checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e" dependencies = [ "proc-macro2", "quote", @@ -3140,14 +3130,14 @@ dependencies = [ [[package]] name = "system-deps" -version = "6.0.5" +version = "6.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0fe581ad25d11420b873cf9aedaca0419c2b411487b134d4d21065f3d092055" +checksum = "e5fa6fb9ee296c0dc2df41a656ca7948546d061958115ddb0bcaae43ad0d17d2" dependencies = [ - "cfg-expr 0.15.1", + "cfg-expr 0.15.2", "heck 0.4.1", "pkg-config", - "toml 0.7.3", + "toml 0.7.4", "version-compare 0.1.1", ] @@ -3263,20 +3253,18 @@ dependencies = [ [[package]] name = "tauri-build" -version = "1.3.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "929b3bd1248afc07b63e33a6a53c3f82c32d0b0a5e216e4530e94c467e019389" +checksum = "8807c85d656b2b93927c19fe5a5f1f1f348f96c2de8b90763b3c2d561511f9b4" dependencies = [ "anyhow", "cargo_toml", "heck 0.4.1", - "json-patch 1.0.0", + "json-patch 0.2.7", "semver", - "serde", "serde_json", "tauri-utils", - "tauri-winres", - "winnow", + "winres", ] [[package]] @@ -3389,16 +3377,6 @@ dependencies = [ "windows 0.39.0", ] -[[package]] -name = "tauri-winres" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5993dc129e544393574288923d1ec447c857f3f644187f4fbf7d9a875fbfc4fb" -dependencies = [ - "embed-resource", - "toml 0.7.3", -] - [[package]] name = "tempfile" version = "3.5.0" @@ -3452,6 +3430,7 @@ dependencies = [ "paho-mqtt", "paris", "percent-encoding", + "rust_swift_screencapture", "serde", "serde_json", "tauri", @@ -3459,7 +3438,7 @@ dependencies = [ "time", "tokio", "tokio-stream", - "toml 0.7.3", + "toml 0.7.4", "url-build-parse", ] @@ -3486,7 +3465,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.18", ] [[package]] @@ -3501,9 +3480,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.20" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd0cbfecb4d19b5ea75bb31ad904eb5b9fa13f21079c3b92017ebdf4999a5890" +checksum = "8f3403384eaacbca9923fa06940178ac13e4edb725486d70e8e15881d0c836cc" dependencies = [ "itoa 1.0.6", "serde", @@ -3513,15 +3492,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" +checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" [[package]] name = "time-macros" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd80a657e71da814b8e5d60d3374fc6d35045062245d80224748ae522dd76f36" +checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b" dependencies = [ "time-core", ] @@ -3543,9 +3522,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.28.0" +version = "1.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3c786bf8134e5a3a166db9b29ab8f48134739014a3eca7bc6bfa95d673b136f" +checksum = "94d7b1cfd2aa4011f2de74c2c4c63665e27a71006b0a192dcd2710272e73dfa2" dependencies = [ "autocfg", "bytes", @@ -3568,7 +3547,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.18", ] [[package]] @@ -3580,6 +3559,20 @@ dependencies = [ "futures-core", "pin-project-lite", "tokio", + "tokio-util", +] + +[[package]] +name = "tokio-util" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", ] [[package]] @@ -3593,9 +3586,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b403acf6f2bb0859c93c7f0d967cb4a75a7ac552100f9322faf64dc047669b21" +checksum = "d6135d499e69981f9ff0ef2167955a5333c35e36f6937d382974566b3d5b94ec" dependencies = [ "serde", "serde_spanned", @@ -3605,18 +3598,18 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622" +checksum = "5a76a9312f5ba4c2dec6b9161fdf25d87ad8a09256ccea5a556fef03c706a10f" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.19.8" +version = "0.19.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "239410c8609e8125456927e6707163a3b1fdb40561e4b803bc041f466ccfdc13" +checksum = "2380d56e8670370eee6566b0bfd4265f65b3f432e8c6d85623f728d4fa31f739" dependencies = [ "indexmap", "serde", @@ -3645,14 +3638,14 @@ checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.18", ] [[package]] name = "tracing-core" -version = "0.1.30" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" +checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" dependencies = [ "once_cell", "valuable", @@ -3729,9 +3722,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" +checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" [[package]] name = "unicode-normalization" @@ -3748,12 +3741,6 @@ version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" -[[package]] -name = "unicode-width" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" - [[package]] name = "uninitialized" version = "0.0.2" @@ -3795,9 +3782,9 @@ checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" [[package]] name = "uuid" -version = "1.3.2" +version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dad5567ad0cf5b760e5665964bec1b47dfd077ba8a2544b513f3556d3d239a2" +checksum = "345444e32442451b267fc254ae85a209c64be56d2890e601a0c37ff0c3c5ecd2" dependencies = [ "getrandom 0.2.9", ] @@ -3838,26 +3825,6 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -[[package]] -name = "vswhom" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be979b7f07507105799e854203b470ff7c78a1639e330a58f183b5fea574608b" -dependencies = [ - "libc", - "vswhom-sys", -] - -[[package]] -name = "vswhom-sys" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3b17ae1f6c8a2b28506cd96d412eebf83b4a0ff2cbefeeb952f2f9dfa44ba18" -dependencies = [ - "cc", - "libc", -] - [[package]] name = "walkdir" version = "2.3.3" @@ -3882,9 +3849,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.84" +version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" +checksum = "5bba0e8cb82ba49ff4e229459ff22a191bbe9a1cb3a341610c9c33efc27ddf73" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -3892,24 +3859,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.84" +version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" +checksum = "19b04bc93f9d6bdee709f6bd2118f57dd6679cf1176a1af464fca3ab0d66d8fb" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.18", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.84" +version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" +checksum = "14d6b024f1a526bb0234f52840389927257beb670610081360e5a03c5df9c258" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3917,22 +3884,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.84" +version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" +checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.18", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.84" +version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" +checksum = "ed9d5b4305409d1fc9482fee2d7f9bcbf24b3972bf59817ef757e23982242a93" [[package]] name = "webkit2gtk" @@ -3978,7 +3945,7 @@ dependencies = [ "pango-sys", "pkg-config", "soup2-sys", - "system-deps 6.0.5", + "system-deps 6.1.0", ] [[package]] @@ -4070,15 +4037,6 @@ dependencies = [ "windows_x86_64_msvc 0.39.0", ] -[[package]] -name = "windows" -version = "0.44.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e745dab35a0c4c77aa3ce42d595e13d2003d6902d6b08c9ef5fc326d08da12b" -dependencies = [ - "windows-targets 0.42.2", -] - [[package]] name = "windows" version = "0.48.0" @@ -4299,21 +4257,20 @@ checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" [[package]] name = "winnow" -version = "0.4.1" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae8970b36c66498d8ff1d66685dc86b91b29db0c7739899012f63a63814b4b28" +checksum = "61de7bac303dc551fe038e2b3cef0f571087a47571ea6e79a87692ac99b99699" dependencies = [ "memchr 2.5.0", ] [[package]] -name = "winreg" -version = "0.11.0" +name = "winres" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76a1a57ff50e9b408431e8f97d5456f2807f8eb2a2cd79b06068fc87f8ecf189" +checksum = "b68db261ef59e9e52806f688020631e987592bd83619edccda9c47d42cde4f6c" dependencies = [ - "cfg-if", - "winapi", + "toml 0.5.11", ] [[package]] diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index ae4a880..d921574 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -37,6 +37,7 @@ mdns-sd = "0.7.2" futures = "0.3.28" ddc-hi = "0.4.1" coreaudio-rs = "0.11.2" +rust_swift_screencapture = { version = "0.1.1", path = "../../../../demo/rust-swift-screencapture" } [features] # this feature is used for production builds or when `devPath` points to the filesystem diff --git a/src-tauri/src/ambient_light/publisher.rs b/src-tauri/src/ambient_light/publisher.rs index e72b619..70aa6c4 100644 --- a/src-tauri/src/ambient_light/publisher.rs +++ b/src-tauri/src/ambient_light/publisher.rs @@ -1,4 +1,4 @@ -use std::{collections::HashMap, sync::Arc, time::Duration}; +use std::{collections::HashMap, sync::Arc, time::Duration, borrow::Borrow}; use paris::warn; use tauri::async_runtime::RwLock; @@ -11,8 +11,9 @@ use tokio::{ use crate::{ ambient_light::{config, ConfigManager}, led_color::LedColor, - screenshot::LedSamplePoints, - screenshot_manager::{self, ScreenshotManager}, rpc::UdpRpc, + rpc::UdpRpc, + screenshot::{self, LedSamplePoints}, + screenshot_manager::{self, ScreenshotManager}, }; use itertools::Itertools; @@ -48,60 +49,33 @@ impl LedColorsPublisher { .await } - fn start_one_display_colors_fetcher( + async fn start_one_display_colors_fetcher( &self, display_id: u32, - sample_points: Vec>, + sample_points: Vec, bound_scale_factor: f32, mappers: Vec, display_colors_tx: broadcast::Sender<(u32, Vec)>, ) { let internal_tasks_version = self.inner_tasks_version.clone(); + let screenshot_manager = ScreenshotManager::global().await; + + let screenshot_rx = screenshot_manager.subscribe_by_display_id(display_id).await; + + if let Err(err) = screenshot_rx { + log::error!("{}", err); + return; + } + let mut screenshot_rx = screenshot_rx.unwrap(); tokio::spawn(async move { - let colors = screenshot_manager::get_display_colors( - display_id, - &sample_points, - bound_scale_factor, - ); - - if let Err(err) = colors { - warn!("Failed to get colors: {}", err); - return; - } - - let mut interval = tokio::time::interval(Duration::from_millis(33)); let init_version = internal_tasks_version.read().await.clone(); - loop { - interval.tick().await; - tokio::time::sleep(Duration::from_millis(1)).await; - - let version = internal_tasks_version.read().await.clone(); - - if version != init_version { - log::info!( - "inner task version changed, stop. {} != {}", - internal_tasks_version.read().await.clone(), - init_version - ); - - break; - } - - let colors = screenshot_manager::get_display_colors( - display_id, - &sample_points, - bound_scale_factor, - ); - - if let Err(err) = colors { - warn!("Failed to get colors: {}", err); - sleep(Duration::from_millis(100)).await; - continue; - } - - let colors: Vec = colors.unwrap(); + while screenshot_rx.changed().await.is_ok() { + let screenshot = screenshot_rx.borrow().clone(); + let colors = screenshot + .get_colors_by_sample_points(&sample_points) + .await; let colors_copy = colors.clone(); @@ -133,6 +107,18 @@ impl LedColorsPublisher { warn!("Failed to send display_colors: {}", err); } }; + + // Check if the inner task version changed + let version = internal_tasks_version.read().await.clone(); + if version != init_version { + log::info!( + "inner task version changed, stop. {} != {}", + internal_tasks_version.read().await.clone(), + init_version + ); + + break; + } } }); } @@ -247,13 +233,15 @@ impl LedColorsPublisher { let display_id = sample_point_group.display_id; let sample_points = sample_point_group.points; let bound_scale_factor = sample_point_group.bound_scale_factor; - publisher.start_one_display_colors_fetcher( - display_id, - sample_points, - bound_scale_factor, - sample_point_group.mappers, - display_colors_tx.clone(), - ); + publisher + .start_one_display_colors_fetcher( + display_id, + sample_points, + bound_scale_factor, + sample_point_group.mappers, + display_colors_tx.clone(), + ) + .await; } let display_ids = configs.sample_point_groups; @@ -402,6 +390,7 @@ impl LedColorsPublisher { let points: Vec<_> = led_strip_configs .clone() .map(|(_, config)| screenshot.get_sample_points(&config)) + .flatten() .collect(); if points.len() == 0 { @@ -451,7 +440,7 @@ pub struct AllColorConfig { #[derive(Debug, Clone)] pub struct DisplaySamplePointGroup { pub display_id: u32, - pub points: Vec>, + pub points: Vec, pub bound_scale_factor: f32, pub mappers: Vec, } diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index fd04964..f40cd80 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -88,7 +88,7 @@ async fn get_led_strips_sample_points( let screenshot_manager = ScreenshotManager::global().await; let channels = screenshot_manager.channels.read().await; if let Some(rx) = channels.get(&config.display_id) { - let rx = rx.clone(); + let rx = rx.read().await; let screenshot = rx.borrow().clone(); let sample_points = screenshot.get_sample_points(&config); Ok(sample_points) @@ -105,7 +105,7 @@ async fn get_one_edge_colors( let screenshot_manager = ScreenshotManager::global().await; let channels = screenshot_manager.channels.read().await; if let Some(rx) = channels.get(&display_id) { - let rx = rx.clone(); + let rx = rx.read().await; let screenshot = rx.borrow().clone(); let bytes = screenshot.bytes.read().await.to_owned(); let colors = @@ -217,8 +217,12 @@ async fn get_displays() -> Vec { async fn main() { env_logger::init(); - let screenshot_manager = ScreenshotManager::global().await; - screenshot_manager.start().unwrap(); + tokio::spawn(async move { + let screenshot_manager = ScreenshotManager::global().await; + screenshot_manager.start().await.unwrap_or_else(|e| { + error!("can not start screenshot manager: {}", e); + }) + }); let led_color_publisher = ambient_light::LedColorsPublisher::global().await; led_color_publisher.start(); @@ -282,77 +286,86 @@ async fn main() { let bytes = tokio::task::block_in_place(move || { tauri::async_runtime::block_on(async move { let screenshot_manager = ScreenshotManager::global().await; - let channels = screenshot_manager.channels.read().await; - if let Some(rx) = channels.get(&display_id) { - let rx = rx.clone(); - let screenshot = rx.borrow().clone(); - let bytes = screenshot.bytes.read().await; + let rx: Result, anyhow::Error> = screenshot_manager.subscribe_by_display_id(display_id).await; - let (scale_factor_x, scale_factor_y, width, height) = if url.query.is_some() - && url.query.as_ref().unwrap().contains_key("height") - && url.query.as_ref().unwrap().contains_key("width") - { - let width = url.query.as_ref().unwrap()["width"] - .parse::() - .map_err(|err| { - warn!("width parse error: {}", err); - err - })?; - let height = url.query.as_ref().unwrap()["height"] - .parse::() - .map_err(|err| { - warn!("height parse error: {}", err); - err - })?; - ( - screenshot.width as f32 / width as f32, - screenshot.height as f32 / height as f32, - width, - height, - ) - } else { - log::debug!("scale by scale_factor"); - let scale_factor = screenshot.scale_factor; - ( - scale_factor, - scale_factor, - (screenshot.width as f32 / scale_factor) as u32, - (screenshot.height as f32 / scale_factor) as u32, - ) - }; - log::debug!( - "scale by query. width: {}, height: {}, scale_factor: {}, len: {}", + if let Err(err) = rx { + anyhow::bail!("Display#{}: not found. {}", display_id, err); + } + let mut rx = rx.unwrap(); + + if rx.changed().await.is_err() { + anyhow::bail!("Display#{}: no more screenshot.", display_id); + } + let screenshot = rx.borrow().clone(); + let bytes = screenshot.bytes.read().await; + if bytes.len() == 0 { + anyhow::bail!("Display#{}: no screenshot.", display_id); + } + + log::debug!("Display#{}: screenshot size: {}", display_id, bytes.len()); + + let (scale_factor_x, scale_factor_y, width, height) = if url.query.is_some() + && url.query.as_ref().unwrap().contains_key("height") + && url.query.as_ref().unwrap().contains_key("width") + { + let width = url.query.as_ref().unwrap()["width"] + .parse::() + .map_err(|err| { + warn!("width parse error: {}", err); + err + })?; + let height = url.query.as_ref().unwrap()["height"] + .parse::() + .map_err(|err| { + warn!("height parse error: {}", err); + err + })?; + ( + screenshot.width as f32 / width as f32, + screenshot.height as f32 / height as f32, width, height, - screenshot.width as f32 / width as f32, - width * height * 4, - ); - - let bytes_per_row = screenshot.bytes_per_row as f32; - - let mut rgba_buffer = vec![0u8; (width * height * 4) as usize]; - - for y in 0..height { - for x in 0..width { - let offset = ((y as f32) * scale_factor_y).floor() as usize - * bytes_per_row as usize - + ((x as f32) * scale_factor_x).floor() as usize * 4; - let b = bytes[offset]; - let g = bytes[offset + 1]; - let r = bytes[offset + 2]; - let a = bytes[offset + 3]; - let offset_2 = (y * width + x) as usize * 4; - rgba_buffer[offset_2] = r; - rgba_buffer[offset_2 + 1] = g; - rgba_buffer[offset_2 + 2] = b; - rgba_buffer[offset_2 + 3] = a; - } - } - - Ok(rgba_buffer.clone()) + ) } else { - anyhow::bail!("Display#{}: not found", display_id); + log::debug!("scale by scale_factor"); + let scale_factor = screenshot.scale_factor; + ( + scale_factor, + scale_factor, + (screenshot.width as f32 / scale_factor) as u32, + (screenshot.height as f32 / scale_factor) as u32, + ) + }; + log::debug!( + "scale by query. width: {}, height: {}, scale_factor: {}, len: {}", + width, + height, + screenshot.width as f32 / width as f32, + width * height * 4, + ); + + let bytes_per_row = screenshot.bytes_per_row as f32; + + let mut rgba_buffer = vec![0u8; (width * height * 4) as usize]; + + for y in 0..height { + for x in 0..width { + let offset = ((y as f32) * scale_factor_y).floor() as usize + * bytes_per_row as usize + + ((x as f32) * scale_factor_x).floor() as usize * 4; + let b = bytes[offset]; + let g = bytes[offset + 1]; + let r = bytes[offset + 2]; + let a = bytes[offset + 3]; + let offset_2 = (y * width + x) as usize * 4; + rgba_buffer[offset_2] = r; + rgba_buffer[offset_2 + 1] = g; + rgba_buffer[offset_2 + 2] = b; + rgba_buffer[offset_2 + 3] = a; + } } + + Ok(rgba_buffer.clone()) }) }); @@ -388,82 +401,82 @@ async fn main() { } }); - let app_handle = app.handle().clone(); - tokio::spawn(async move { - let publisher = ambient_light::LedColorsPublisher::global().await; - let mut publisher_update_receiver = publisher.clone_sorted_colors_receiver().await; - loop { - if let Err(err) = publisher_update_receiver.changed().await { - error!("publisher update receiver changed error: {}", err); - return; - } + // let app_handle = app.handle().clone(); + // tokio::spawn(async move { + // let publisher = ambient_light::LedColorsPublisher::global().await; + // let mut publisher_update_receiver = publisher.clone_sorted_colors_receiver().await; + // loop { + // if let Err(err) = publisher_update_receiver.changed().await { + // error!("publisher update receiver changed error: {}", err); + // return; + // } - let publisher = publisher_update_receiver.borrow().clone(); + // let publisher = publisher_update_receiver.borrow().clone(); - app_handle - .emit_all("led_sorted_colors_changed", publisher) - .unwrap(); - } - }); + // app_handle + // .emit_all("led_sorted_colors_changed", publisher) + // .unwrap(); + // } + // }); - let app_handle = app.handle().clone(); - tokio::spawn(async move { - let publisher = ambient_light::LedColorsPublisher::global().await; - let mut publisher_update_receiver = publisher.clone_colors_receiver().await; - loop { - if let Err(err) = publisher_update_receiver.changed().await { - error!("publisher update receiver changed error: {}", err); - return; - } + // let app_handle = app.handle().clone(); + // tokio::spawn(async move { + // let publisher = ambient_light::LedColorsPublisher::global().await; + // let mut publisher_update_receiver = publisher.clone_colors_receiver().await; + // loop { + // if let Err(err) = publisher_update_receiver.changed().await { + // error!("publisher update receiver changed error: {}", err); + // return; + // } - let publisher = publisher_update_receiver.borrow().clone(); + // let publisher = publisher_update_receiver.borrow().clone(); - app_handle - .emit_all("led_colors_changed", publisher) - .unwrap(); - } - }); + // app_handle + // .emit_all("led_colors_changed", publisher) + // .unwrap(); + // } + // }); - let app_handle = app.handle().clone(); - tokio::spawn(async move { - loop { - match UdpRpc::global().await { - Ok(udp_rpc) => { - let mut receiver = udp_rpc.subscribe_boards_change(); - loop { - if let Err(err) = receiver.changed().await { - error!("boards change receiver changed error: {}", err); - return; - } + // let app_handle = app.handle().clone(); + // tokio::spawn(async move { + // loop { + // match UdpRpc::global().await { + // Ok(udp_rpc) => { + // let mut receiver = udp_rpc.subscribe_boards_change(); + // loop { + // if let Err(err) = receiver.changed().await { + // error!("boards change receiver changed error: {}", err); + // return; + // } - let boards = receiver.borrow().clone(); + // let boards = receiver.borrow().clone(); - let boards = boards.into_iter().collect::>(); + // let boards = boards.into_iter().collect::>(); - app_handle.emit_all("boards_changed", boards).unwrap(); - } - } - Err(err) => { - error!("udp rpc error: {}", err); - return; - } - } - } - }); + // app_handle.emit_all("boards_changed", boards).unwrap(); + // } + // } + // Err(err) => { + // error!("udp rpc error: {}", err); + // return; + // } + // } + // } + // }); - let app_handle = app.handle().clone(); - tokio::spawn(async move { - let display_manager = DisplayManager::global().await; - let mut rx =display_manager.subscribe_displays_changed(); + // let app_handle = app.handle().clone(); + // tokio::spawn(async move { + // let display_manager = DisplayManager::global().await; + // let mut rx = display_manager.subscribe_displays_changed(); - while rx.changed().await.is_ok() { - let displays = rx.borrow().clone(); + // while rx.changed().await.is_ok() { + // let displays = rx.borrow().clone(); - log::info!("displays changed. emit displays_changed event."); + // log::info!("displays changed. emit displays_changed event."); - app_handle.emit_all("displays_changed", displays).unwrap(); - } - }); + // app_handle.emit_all("displays_changed", displays).unwrap(); + // } + // }); Ok(()) }) diff --git a/src-tauri/src/screenshot.rs b/src-tauri/src/screenshot.rs index ff8602f..3633861 100644 --- a/src-tauri/src/screenshot.rs +++ b/src-tauri/src/screenshot.rs @@ -1,5 +1,6 @@ -use std::iter; +use std::fmt::Formatter; +use std::{iter, fmt::Debug}; use std::sync::Arc; use serde::{Deserialize, Serialize}; @@ -7,17 +8,30 @@ use tauri::async_runtime::RwLock; use crate::{ambient_light::LedStripConfig, led_color::LedColor}; -#[derive(Debug, Clone)] +#[derive(Clone)] pub struct Screenshot { pub display_id: u32, pub height: u32, pub width: u32, pub bytes_per_row: usize, - pub bytes: Arc>>, + pub bytes: Arc>>>, pub scale_factor: f32, pub bound_scale_factor: f32, } +impl Debug for Screenshot { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Screenshot") + .field("display_id", &self.display_id) + .field("height", &self.height) + .field("width", &self.width) + .field("bytes_per_row", &self.bytes_per_row) + .field("scale_factor", &self.scale_factor) + .field("bound_scale_factor", &self.bound_scale_factor) + .finish() + } +} + static SINGLE_AXIS_POINTS: usize = 5; impl Screenshot { @@ -26,7 +40,7 @@ impl Screenshot { height: u32, width: u32, bytes_per_row: usize, - bytes: Vec, + bytes: Arc>, scale_factor: f32, bound_scale_factor: f32, ) -> Self { diff --git a/src-tauri/src/screenshot_manager.rs b/src-tauri/src/screenshot_manager.rs index 3d0c9e3..c2c398f 100644 --- a/src-tauri/src/screenshot_manager.rs +++ b/src-tauri/src/screenshot_manager.rs @@ -5,47 +5,14 @@ use core_graphics::display::{ }; use core_graphics::geometry::{CGPoint, CGRect, CGSize}; use paris::warn; +use rust_swift_screencapture::display::CGDisplayId; use tauri::async_runtime::RwLock; -use tokio::sync::{broadcast, watch, OnceCell}; -use tokio::time::{self, Duration}; +use tokio::sync::{broadcast, watch, Mutex, OnceCell}; +use tokio::task::yield_now; use crate::screenshot::LedSamplePoints; use crate::{ambient_light::SamplePointMapper, led_color::LedColor, screenshot::Screenshot}; -pub fn take_screenshot(display_id: u32, scale_factor: f32) -> anyhow::Result { - log::debug!("take_screenshot"); - - let cg_display = CGDisplay::new(display_id); - let cg_image = CGDisplay::screenshot( - cg_display.bounds(), - kCGWindowListOptionOnScreenOnly, - kCGNullWindowID, - kCGWindowImageDefault, - ) - .ok_or_else(|| anyhow::anyhow!("Display#{}: take screenshot failed", display_id))?; - - let buffer = cg_image.data(); - let bytes_per_row = cg_image.bytes_per_row(); - - let height = cg_image.height(); - let width = cg_image.width(); - - let bytes = buffer.bytes().to_owned(); - - let cg_display = CGDisplay::new(display_id); - let bound_scale_factor = (cg_display.bounds().size.width / width as f64) as f32; - - Ok(Screenshot::new( - display_id, - height as u32, - width as u32, - bytes_per_row, - bytes, - scale_factor, - bound_scale_factor, - )) -} - pub fn get_display_colors( display_id: u32, sample_points: &Vec>, @@ -114,7 +81,7 @@ pub fn get_display_colors( } pub struct ScreenshotManager { - pub channels: Arc>>>, + pub channels: Arc>>>>>, merged_screenshot_tx: Arc>>, } @@ -134,75 +101,70 @@ impl ScreenshotManager { .await } - pub fn start(&self) -> anyhow::Result<()> { + pub async fn start(&self) -> anyhow::Result<()> { let displays = display_info::DisplayInfo::all()?; - for display in displays { - self.start_one(display.id, display.scale_factor)?; - } - Ok(()) - } - fn start_one(&self, display_id: u32, scale_factor: f32) -> anyhow::Result<()> { - let channels = self.channels.to_owned(); - let merged_screenshot_tx = self.merged_screenshot_tx.clone(); - tokio::spawn(async move { - let screenshot = take_screenshot(display_id, scale_factor); - - if screenshot.is_err() { - warn!("take_screenshot_loop: {}", screenshot.err().unwrap()); - return; - } - let mut interval = time::interval(Duration::from_millis(1000)); - - let screenshot = screenshot.unwrap(); - let (screenshot_tx, screenshot_rx) = watch::channel(screenshot); - { - let channels = channels.clone(); - let mut channels = channels.write().await; - channels.insert(display_id, screenshot_rx.clone()); - } - - let merged_screenshot_tx = merged_screenshot_tx.read().await.clone(); - - loop { - Self::take_screenshot_loop( - display_id, - scale_factor, - &screenshot_tx, - &merged_screenshot_tx, - ) - .await; - interval.tick().await; - tokio::time::sleep(Duration::from_millis(1)).await; - } + let futures = displays.iter().map(|display| async { + self.start_one(display.id, display.scale_factor) + .await + .unwrap_or_else(|err| { + warn!("start_one failed: display_id: {}, err: {}", display.id, err); + }); }); + futures::future::join_all(futures).await; Ok(()) } - async fn take_screenshot_loop( - display_id: u32, - scale_factor: f32, - screenshot_tx: &watch::Sender, - merged_screenshot_tx: &broadcast::Sender, - ) { - let screenshot = take_screenshot(display_id, scale_factor); - if let Ok(screenshot) = screenshot { - match merged_screenshot_tx.send(screenshot.clone()) { - Ok(_) => { - log::info!( - "take_screenshot_loop: merged_screenshot_tx.send success. display#{}", - display_id - ); - } - Err(_) => { - } + async fn start_one(&self, display_id: u32, scale_factor: f32) -> anyhow::Result<()> { + let mut channels = self.channels.write().await; + let merged_screenshot_tx = self.merged_screenshot_tx.clone(); + let display = rust_swift_screencapture::display::Display::new(display_id); + + display.start_capture().await; + + let mut frame_rx = display.subscribe_frame().await; + + let (tx, _) = watch::channel(Screenshot::new( + display_id, + 0, + 0, + 0, + Arc::new(vec![]), + scale_factor, + scale_factor, + )); + let tx = Arc::new(RwLock::new(tx)); + channels.insert(display_id, tx.clone()); + drop(channels); + + let tx_for_send = tx.read().await; + + while frame_rx.changed().await.is_ok() { + let frame = frame_rx.borrow().clone(); + let screenshot = Screenshot::new( + display_id, + frame.height as u32, + frame.width as u32, + frame.bytes_per_row as usize, + frame.bytes, + scale_factor, + scale_factor, + ); + let merged_screenshot_tx = merged_screenshot_tx.write().await; + if let Err(err) = merged_screenshot_tx.send(screenshot.clone()) { + // log::warn!("merged_screenshot_tx.send failed: {}", err); } - screenshot_tx.send(screenshot).unwrap(); - // log::info!("take_screenshot_loop: send success. display#{}", display_id) - } else { - warn!("take_screenshot_loop: {}", screenshot.err().unwrap()); + if let Err(err) = tx_for_send.send(screenshot.clone()) { + log::warn!("display {} screenshot_tx.send failed: {}", display_id, err); + } else { + log::debug!("screenshot: {:?}", screenshot); + } + + yield_now().await; } + + Ok(()) } pub fn get_sorted_colors(colors: &Vec, mappers: &Vec) -> Vec { @@ -257,4 +219,16 @@ impl ScreenshotManager { pub async fn clone_merged_screenshot_rx(&self) -> broadcast::Receiver { self.merged_screenshot_tx.read().await.subscribe() } + + pub async fn subscribe_by_display_id( + &self, + display_id: CGDisplayId, + ) -> anyhow::Result> { + let channels = self.channels.read().await; + if let Some(tx) = channels.get(&display_id) { + Ok(tx.read().await.subscribe()) + } else { + Err(anyhow::anyhow!("display_id: {} not found", display_id)) + } + } } diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 3b2747d..1bba3eb 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -28,7 +28,10 @@ "icons/icon.ico" ], "identifier": "cc.ivanli.ambient-light.desktop", - "targets": "all" + "targets": "all", + "macOS": { + "minimumSystemVersion": "13" + } }, "security": { "csp": null