1use serde::{Deserialize, Serialize};
10use wasm_bindgen::JsValue;
11use wasm_bindgen::prelude::*;
12
13#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
15pub struct DisplaySourceView {
16 pub id: String,
18 pub label: String,
20 pub width: u32,
22 pub height: u32,
24 pub is_primary: bool,
26}
27
28#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
30pub struct WindowSourceView {
31 pub id: String,
33 pub label: String,
35 pub width: u32,
37 pub height: u32,
39 pub bundle_id: String,
41 pub display_name: String,
43}
44
45#[derive(Debug)]
48pub enum ScreenSourcesResult<T> {
49 Ok(Vec<T>),
51 Err(String),
53}
54
55#[wasm_bindgen]
56extern "C" {
57 #[wasm_bindgen(js_name = __screenListScreenDisplays, catch)]
59 pub async fn list_screen_displays_js() -> Result<JsValue, JsValue>;
60
61 #[wasm_bindgen(js_name = __screenListScreenWindows, catch)]
63 pub async fn list_screen_windows_js() -> Result<JsValue, JsValue>;
64
65 #[wasm_bindgen(js_name = __screenStartScreenCapture, catch)]
70 pub async fn start_screen_capture_js(source_id: JsValue) -> Result<JsValue, JsValue>;
71
72 #[wasm_bindgen(js_name = __screenStopScreenCapture, catch)]
74 pub async fn stop_screen_capture_js() -> Result<JsValue, JsValue>;
75
76 #[wasm_bindgen(js_name = __screenScreenCaptureStatus, catch)]
78 pub async fn screen_capture_status_js() -> Result<JsValue, JsValue>;
79
80 #[wasm_bindgen(js_name = __screenScreenCaptureFrameCount, catch)]
82 pub async fn screen_capture_frame_count_js() -> Result<JsValue, JsValue>;
83
84 #[wasm_bindgen(js_name = __screenRequestScreenRecordingPermission, catch)]
87 pub async fn request_screen_recording_permission_js() -> Result<JsValue, JsValue>;
88
89 #[wasm_bindgen(js_name = __screenOpenSettingsScreenRecording, catch)]
92 pub async fn open_settings_screen_recording_js() -> Result<JsValue, JsValue>;
93}
94
95pub async fn list_screen_displays() -> ScreenSourcesResult<DisplaySourceView> {
97 match list_screen_displays_js().await {
98 Ok(value) => match serde_wasm_bindgen::from_value(value) {
99 Ok(v) => ScreenSourcesResult::Ok(v),
100 Err(err) => ScreenSourcesResult::Err(format!("decode failed: {err}")),
101 },
102 Err(err) => ScreenSourcesResult::Err(js_error_string(&err)),
103 }
104}
105
106pub async fn list_screen_windows() -> ScreenSourcesResult<WindowSourceView> {
108 match list_screen_windows_js().await {
109 Ok(value) => match serde_wasm_bindgen::from_value(value) {
110 Ok(v) => ScreenSourcesResult::Ok(v),
111 Err(err) => ScreenSourcesResult::Err(format!("decode failed: {err}")),
112 },
113 Err(err) => ScreenSourcesResult::Err(js_error_string(&err)),
114 }
115}
116
117pub async fn start_screen_capture(source_id: Option<String>) -> Result<(), String> {
122 let arg = match source_id {
123 Some(id) => JsValue::from_str(&id),
124 None => JsValue::NULL,
125 };
126 start_screen_capture_js(arg)
127 .await
128 .map(|_| ())
129 .map_err(|err| js_error_string(&err))
130}
131
132pub async fn stop_screen_capture() {
134 let _ = stop_screen_capture_js().await;
135}
136
137pub async fn screen_capture_status() -> bool {
139 match screen_capture_status_js().await {
140 Ok(value) => serde_wasm_bindgen::from_value(value).unwrap_or(false),
141 Err(_) => false,
142 }
143}
144
145pub async fn screen_capture_frame_count() -> u64 {
147 match screen_capture_frame_count_js().await {
148 Ok(value) => serde_wasm_bindgen::from_value(value).unwrap_or(0),
149 Err(_) => 0,
150 }
151}
152
153pub async fn request_screen_recording_permission() {
156 let _ = request_screen_recording_permission_js().await;
157}
158
159pub async fn open_settings_screen_recording() {
162 let _ = open_settings_screen_recording_js().await;
163}
164
165fn js_error_string(err: &JsValue) -> String {
166 err.as_string().unwrap_or_else(|| format!("{err:?}"))
167}