fix: 临时避免 CPU 占用率高的问题。

This commit is contained in:
Ivan Li 2023-06-10 21:09:36 +08:00
parent 268ec1df81
commit bab3b8941e
8 changed files with 551 additions and 566 deletions

View File

@ -14,20 +14,20 @@
"@solidjs/router": "^0.8.2",
"@tauri-apps/api": "^1.3.0",
"debug": "^4.3.4",
"solid-icons": "^1.0.4",
"solid-js": "^1.7.5",
"solid-icons": "^1.0.8",
"solid-js": "^1.7.6",
"solid-tippy": "^0.2.1",
"tippy.js": "^6.3.7"
},
"devDependencies": {
"@tauri-apps/cli": "^1.3.1",
"@types/debug": "^4.1.7",
"@types/node": "^18.16.6",
"@types/debug": "^4.1.8",
"@types/node": "^18.16.17",
"autoprefixer": "^10.4.14",
"postcss": "^8.4.23",
"postcss": "^8.4.24",
"tailwindcss": "^3.3.2",
"typescript": "^4.9.5",
"vite": "^4.3.5",
"vite": "^4.3.9",
"vite-plugin-solid": "^2.7.0"
}
}

File diff suppressed because it is too large Load Diff

127
src-tauri/Cargo.lock generated
View File

@ -19,9 +19,9 @@ dependencies = [
[[package]]
name = "aho-corasick"
version = "1.0.1"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04"
checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41"
dependencies = [
"memchr 2.5.0",
]
@ -737,12 +737,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0"
[[package]]
name = "dtoa-short"
version = "0.3.3"
name = "dtoa"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bde03329ae10e79ede66c9ce4dc930aa8599043b0743008548680f25b91502d6"
checksum = "65d09067bfacaa79114679b279d7f5885b53295b1e2cfb4e79c8e4bd3d633169"
[[package]]
name = "dtoa-short"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dbaceec3c6e4211c79e7b1800fb9680527106beb2f9c51904a3210c03a448c74"
dependencies = [
"dtoa",
"dtoa 1.0.6",
]
[[package]]
@ -906,9 +912,9 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
[[package]]
name = "form_urlencoded"
version = "1.1.0"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8"
checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652"
dependencies = [
"percent-encoding",
]
@ -1135,9 +1141,9 @@ dependencies = [
[[package]]
name = "getrandom"
version = "0.2.9"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4"
checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
dependencies = [
"cfg-if",
"libc",
@ -1418,9 +1424,9 @@ dependencies = [
[[package]]
name = "iana-time-zone"
version = "0.1.56"
version = "0.1.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0722cd7114b7de04316e7ea5456a0bbb20e4adb46fd27a3697adb812cff0f37c"
checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613"
dependencies = [
"android_system_properties",
"core-foundation-sys 0.8.4",
@ -1457,9 +1463,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "idna"
version = "0.3.0"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6"
checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c"
dependencies = [
"unicode-bidi",
"unicode-normalization",
@ -1690,9 +1696,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]]
name = "libc"
version = "0.2.144"
version = "0.2.146"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1"
checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b"
[[package]]
name = "libloading"
@ -1737,9 +1743,9 @@ checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
[[package]]
name = "lock_api"
version = "0.4.9"
version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"
checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16"
dependencies = [
"autocfg",
"scopeguard",
@ -2106,9 +2112,9 @@ dependencies = [
[[package]]
name = "once_cell"
version = "1.17.2"
version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9670a07f94779e00908f3e686eab508878ebb390ba6e604d3a284c00e8d0487b"
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
[[package]]
name = "open"
@ -2207,15 +2213,15 @@ dependencies = [
[[package]]
name = "parking_lot_core"
version = "0.9.7"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521"
checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447"
dependencies = [
"cfg-if",
"libc",
"redox_syscall 0.2.16",
"redox_syscall 0.3.5",
"smallvec",
"windows-sys 0.45.0",
"windows-targets",
]
[[package]]
@ -2238,9 +2244,9 @@ checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
[[package]]
name = "percent-encoding"
version = "2.2.0"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
[[package]]
name = "phf"
@ -2475,9 +2481,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
[[package]]
name = "proc-macro2"
version = "1.0.59"
version = "1.0.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6aeca18b86b413c660b781aa319e4e2648a3e6f9eadc9b47e9038e6fe9f3451b"
checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406"
dependencies = [
"unicode-ident",
]
@ -2560,7 +2566,7 @@ version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom 0.2.9",
"getrandom 0.2.10",
]
[[package]]
@ -2611,18 +2617,18 @@ version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
dependencies = [
"getrandom 0.2.9",
"getrandom 0.2.10",
"redox_syscall 0.2.16",
"thiserror",
]
[[package]]
name = "regex"
version = "1.8.3"
version = "1.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81ca098a9821bd52d6b24fd8b10bd081f47d39c22778cafaa75a2857a62c6390"
checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f"
dependencies = [
"aho-corasick 1.0.1",
"aho-corasick 1.0.2",
"memchr 2.5.0",
"regex-syntax 0.7.2",
]
@ -2771,18 +2777,18 @@ dependencies = [
[[package]]
name = "serde"
version = "1.0.163"
version = "1.0.164"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2"
checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.163"
version = "1.0.164"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e"
checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68"
dependencies = [
"proc-macro2",
"quote",
@ -2854,7 +2860,7 @@ version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef8099d3df28273c99a1728190c7a9f19d444c941044f64adf986bee7ec53051"
dependencies = [
"dtoa",
"dtoa 0.4.8",
"linked-hash-map",
"serde",
"yaml-rust",
@ -3379,15 +3385,16 @@ dependencies = [
[[package]]
name = "tempfile"
version = "3.5.0"
version = "3.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998"
checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6"
dependencies = [
"autocfg",
"cfg-if",
"fastrand",
"redox_syscall 0.3.5",
"rustix",
"windows-sys 0.45.0",
"windows-sys 0.48.0",
]
[[package]]
@ -3480,9 +3487,9 @@ dependencies = [
[[package]]
name = "time"
version = "0.3.21"
version = "0.3.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f3403384eaacbca9923fa06940178ac13e4edb725486d70e8e15881d0c836cc"
checksum = "ea9e1b3cf1243ae005d9e74085d4d542f3125458f3a81af210d901dcd7411efd"
dependencies = [
"itoa 1.0.6",
"serde",
@ -3749,9 +3756,9 @@ checksum = "74c1aa4511c38276c548406f0b1f5f8b793f000cfb51e18f278a102abd057e81"
[[package]]
name = "url"
version = "2.3.1"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643"
checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb"
dependencies = [
"form_urlencoded",
"idna",
@ -3786,7 +3793,7 @@ version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "345444e32442451b267fc254ae85a209c64be56d2890e601a0c37ff0c3c5ecd2"
dependencies = [
"getrandom 0.2.9",
"getrandom 0.2.10",
]
[[package]]
@ -4043,7 +4050,7 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f"
dependencies = [
"windows-targets 0.48.0",
"windows-targets",
]
[[package]]
@ -4087,37 +4094,13 @@ dependencies = [
"windows_x86_64_msvc 0.42.2",
]
[[package]]
name = "windows-sys"
version = "0.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
dependencies = [
"windows-targets 0.42.2",
]
[[package]]
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets 0.48.0",
]
[[package]]
name = "windows-targets"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
dependencies = [
"windows_aarch64_gnullvm 0.42.2",
"windows_aarch64_msvc 0.42.2",
"windows_i686_gnu 0.42.2",
"windows_i686_msvc 0.42.2",
"windows_x86_64_gnu 0.42.2",
"windows_x86_64_gnullvm 0.42.2",
"windows_x86_64_msvc 0.42.2",
"windows-targets",
]
[[package]]

View File

@ -1,4 +1,4 @@
use std::{collections::HashMap, sync::Arc, time::Duration, borrow::Borrow};
use std::{borrow::Borrow, collections::HashMap, sync::Arc, time::Duration};
use paris::warn;
use tauri::async_runtime::RwLock;
@ -73,15 +73,12 @@ impl LedColorsPublisher {
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 = screenshot.get_colors_by_sample_points(&sample_points).await;
let colors_copy = colors.clone();
let mappers = mappers.clone();
tokio::spawn(async move {
match Self::send_colors_by_display(colors, mappers).await {
Ok(_) => {
// log::info!("sent colors: #{: >15}", display_id);
@ -90,23 +87,22 @@ impl LedColorsPublisher {
warn!("Failed to send colors: #{: >15}\t{}", display_id, err);
}
}
});
match display_colors_tx.send((
display_id,
colors_copy
.into_iter()
.map(|color| color.get_rgb())
.flatten()
.collect::<Vec<_>>(),
)) {
Ok(_) => {
// log::info!("sent colors: {:?}", color_len);
}
Err(err) => {
warn!("Failed to send display_colors: {}", err);
}
};
// match display_colors_tx.send((
// display_id,
// colors_copy
// .into_iter()
// .map(|color| color.get_rgb())
// .flatten()
// .collect::<Vec<_>>(),
// )) {
// Ok(_) => {
// // log::info!("sent colors: {:?}", color_len);
// }
// Err(err) => {
// warn!("Failed to send display_colors: {}", err);
// }
// };
// Check if the inner task version changed
let version = internal_tasks_version.read().await.clone();
@ -198,26 +194,31 @@ impl LedColorsPublisher {
});
}
pub fn start(&self) {
let inner_tasks_version = self.inner_tasks_version.clone();
tokio::spawn(async move {
let publisher = Self::global().await;
pub async fn start(&self) {
log::info!("start colors worker");
let config_manager = ConfigManager::global().await;
let mut config_receiver = config_manager.clone_config_update_receiver();
let configs = config_receiver.borrow().clone();
self.handle_config_change(configs).await;
log::info!("waiting for config update...");
while config_receiver.changed().await.is_ok() {
log::info!("config updated, restart inner tasks...");
let configs = config_receiver.borrow().clone();
self.handle_config_change(configs).await;
}
}
async fn handle_config_change(&self, configs: LedStripConfigGroup) {
let inner_tasks_version = self.inner_tasks_version.clone();
let configs = Self::get_colors_configs(&configs).await;
if let Err(err) = configs {
warn!("Failed to get configs: {}", err);
sleep(Duration::from_millis(100)).await;
continue;
return;
}
let configs = configs.unwrap();
@ -226,15 +227,13 @@ impl LedColorsPublisher {
*inner_tasks_version = inner_tasks_version.overflowing_add(1).0;
drop(inner_tasks_version);
let (display_colors_tx, display_colors_rx) =
broadcast::channel::<(u32, Vec<u8>)>(8);
let (display_colors_tx, display_colors_rx) = broadcast::channel::<(u32, Vec<u8>)>(8);
for sample_point_group in configs.sample_point_groups.clone() {
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(
self.start_one_display_colors_fetcher(
display_id,
sample_points,
bound_scale_factor,
@ -245,14 +244,12 @@ impl LedColorsPublisher {
}
let display_ids = configs.sample_point_groups;
publisher.start_all_colors_worker(
self.start_all_colors_worker(
display_ids.iter().map(|c| c.display_id).collect(),
configs.mappers,
display_colors_rx,
);
}
});
}
pub async fn send_colors(offset: u16, mut payload: Vec<u8>) -> anyhow::Result<()> {
// let mqtt = MqttRpc::global().await;

View File

@ -224,8 +224,10 @@ async fn main() {
})
});
tokio::spawn(async move {
let led_color_publisher = ambient_light::LedColorsPublisher::global().await;
led_color_publisher.start();
led_color_publisher.start().await;
});
let _volume = VolumeManager::global().await;
@ -286,7 +288,8 @@ 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 rx: Result<tokio::sync::watch::Receiver<Screenshot>, anyhow::Error> = screenshot_manager.subscribe_by_display_id(display_id).await;
let rx: Result<tokio::sync::watch::Receiver<Screenshot>, anyhow::Error> =
screenshot_manager.subscribe_by_display_id(display_id).await;
if let Err(err) = rx {
anyhow::bail!("Display#{}: not found. {}", display_id, err);
@ -401,82 +404,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::<Vec<_>>();
let boards = boards.into_iter().collect::<Vec<_>>();
// 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(())
})

View File

@ -54,7 +54,7 @@ impl Board {
board_message_channels.volume_setting_request_sender.clone();
loop {
match socket.try_recv(&mut buf) {
match socket.recv(&mut buf).await {
Ok(len) => {
log::info!("recv: {:?}", &buf[..len]);
if buf[0] == 3 {

View File

@ -99,7 +99,9 @@ impl UdpRpc {
}
if boards.insert(board_info.fullname.clone(), board).is_some() {
info!("added board {:?}", board_info);
info!("replace board {:?}", board_info);
} else {
info!("add board {:?}", board_info);
}
let tx_boards = boards

View File

@ -121,7 +121,7 @@ impl ScreenshotManager {
let merged_screenshot_tx = self.merged_screenshot_tx.clone();
let display = rust_swift_screencapture::display::Display::new(display_id);
display.start_capture().await;
display.start_capture(30).await;
let mut frame_rx = display.subscribe_frame().await;
@ -156,7 +156,7 @@ impl ScreenshotManager {
// log::warn!("merged_screenshot_tx.send failed: {}", err);
}
if let Err(err) = tx_for_send.send(screenshot.clone()) {
log::warn!("display {} screenshot_tx.send failed: {}", display_id, err);
// log::warn!("display {} screenshot_tx.send failed: {}", display_id, err);
} else {
log::debug!("screenshot: {:?}", screenshot);
}