screencapturekit/ffi/
mod.rs

1//! Swift FFI bridge to `ScreenCaptureKit`
2use std::ffi::c_void;
3
4// MARK: - CoreGraphics Initialization
5extern "C" {
6    /// Force CoreGraphics initialization by calling `CGMainDisplayID`
7    /// This prevents `CGS_REQUIRE_INIT` crashes on headless systems
8    pub fn sc_initialize_core_graphics();
9}
10
11// MARK: - SCShareableContent
12extern "C" {
13    /// Synchronous blocking call to get shareable content
14    /// Returns content pointer on success, or writes error to `error_buffer`
15    pub fn sc_shareable_content_get_sync(
16        exclude_desktop_windows: bool,
17        on_screen_windows_only: bool,
18        error_buffer: *mut i8,
19        error_buffer_size: isize,
20    ) -> *const c_void;
21
22    /// Async callback-based shareable content retrieval with options
23    pub fn sc_shareable_content_get_with_options(
24        exclude_desktop_windows: bool,
25        on_screen_windows_only: bool,
26        callback: extern "C" fn(*const c_void, *const i8, *mut c_void),
27        user_data: *mut c_void,
28    );
29
30    pub fn sc_shareable_content_get(callback: extern "C" fn(*const c_void, *const i8));
31    pub fn sc_shareable_content_get_current_process_displays(
32        callback: extern "C" fn(*const c_void, *const i8),
33    );
34    pub fn sc_shareable_content_retain(content: *const c_void) -> *const c_void;
35    pub fn sc_shareable_content_release(content: *const c_void);
36    pub fn sc_shareable_content_get_displays_count(content: *const c_void) -> isize;
37    pub fn sc_shareable_content_get_display_at(
38        content: *const c_void,
39        index: isize,
40    ) -> *const c_void;
41    pub fn sc_shareable_content_get_windows_count(content: *const c_void) -> isize;
42    pub fn sc_shareable_content_get_window_at(
43        content: *const c_void,
44        index: isize,
45    ) -> *const c_void;
46    pub fn sc_shareable_content_get_applications_count(content: *const c_void) -> isize;
47    pub fn sc_shareable_content_get_application_at(
48        content: *const c_void,
49        index: isize,
50    ) -> *const c_void;
51}
52
53// MARK: - SCDisplay
54extern "C" {
55    pub fn sc_display_retain(display: *const c_void) -> *const c_void;
56    pub fn sc_display_release(display: *const c_void);
57    pub fn sc_display_get_display_id(display: *const c_void) -> u32;
58    pub fn sc_display_get_width(display: *const c_void) -> isize;
59    pub fn sc_display_get_height(display: *const c_void) -> isize;
60    pub fn sc_display_get_frame(
61        display: *const c_void,
62        x: *mut f64,
63        y: *mut f64,
64        width: *mut f64,
65        height: *mut f64,
66    );
67}
68
69// MARK: - SCWindow
70extern "C" {
71    pub fn sc_window_retain(window: *const c_void) -> *const c_void;
72    pub fn sc_window_release(window: *const c_void);
73    pub fn sc_window_get_window_id(window: *const c_void) -> u32;
74    pub fn sc_window_get_frame(
75        window: *const c_void,
76        x: *mut f64,
77        y: *mut f64,
78        width: *mut f64,
79        height: *mut f64,
80    );
81    pub fn sc_window_get_title(window: *const c_void, buffer: *mut i8, buffer_size: isize) -> bool;
82    pub fn sc_window_get_window_layer(window: *const c_void) -> isize;
83    pub fn sc_window_is_on_screen(window: *const c_void) -> bool;
84    pub fn sc_window_get_owning_application(window: *const c_void) -> *const c_void;
85    pub fn sc_window_is_active(window: *const c_void) -> bool;
86}
87
88// MARK: - SCRunningApplication
89extern "C" {
90    pub fn sc_running_application_retain(app: *const c_void) -> *const c_void;
91    pub fn sc_running_application_release(app: *const c_void);
92    pub fn sc_running_application_get_bundle_identifier(
93        app: *const c_void,
94        buffer: *mut i8,
95        buffer_size: isize,
96    ) -> bool;
97    pub fn sc_running_application_get_application_name(
98        app: *const c_void,
99        buffer: *mut i8,
100        buffer_size: isize,
101    ) -> bool;
102    pub fn sc_running_application_get_process_id(app: *const c_void) -> i32;
103}
104
105// MARK: - SCStreamConfiguration
106extern "C" {
107    pub fn sc_stream_configuration_create() -> *const c_void;
108    pub fn sc_stream_configuration_retain(config: *const c_void) -> *const c_void;
109    pub fn sc_stream_configuration_release(config: *const c_void);
110
111    pub fn sc_stream_configuration_set_width(config: *const c_void, width: isize);
112    pub fn sc_stream_configuration_get_width(config: *const c_void) -> isize;
113
114    pub fn sc_stream_configuration_set_height(config: *const c_void, height: isize);
115    pub fn sc_stream_configuration_get_height(config: *const c_void) -> isize;
116
117    pub fn sc_stream_configuration_set_shows_cursor(config: *const c_void, shows_cursor: bool);
118    pub fn sc_stream_configuration_get_shows_cursor(config: *const c_void) -> bool;
119
120    pub fn sc_stream_configuration_set_scales_to_fit(config: *const c_void, scales_to_fit: bool);
121    pub fn sc_stream_configuration_get_scales_to_fit(config: *const c_void) -> bool;
122
123    pub fn sc_stream_configuration_set_captures_audio(config: *const c_void, captures_audio: bool);
124    pub fn sc_stream_configuration_get_captures_audio(config: *const c_void) -> bool;
125
126    pub fn sc_stream_configuration_set_sample_rate(config: *const c_void, sample_rate: isize);
127    pub fn sc_stream_configuration_get_sample_rate(config: *const c_void) -> isize;
128
129    pub fn sc_stream_configuration_set_channel_count(config: *const c_void, channel_count: isize);
130    pub fn sc_stream_configuration_get_channel_count(config: *const c_void) -> isize;
131
132    pub fn sc_stream_configuration_set_queue_depth(config: *const c_void, queue_depth: isize);
133    pub fn sc_stream_configuration_get_queue_depth(config: *const c_void) -> isize;
134
135    pub fn sc_stream_configuration_set_pixel_format(config: *const c_void, pixel_format: u32);
136    pub fn sc_stream_configuration_get_pixel_format(config: *const c_void) -> u32;
137
138    pub fn sc_stream_configuration_set_minimum_frame_interval(
139        config: *const c_void,
140        value: i64,
141        timescale: i32,
142        flags: u32,
143        epoch: i64,
144    );
145    pub fn sc_stream_configuration_get_minimum_frame_interval(
146        config: *const c_void,
147        value: *mut i64,
148        timescale: *mut i32,
149        flags: *mut u32,
150        epoch: *mut i64,
151    );
152
153    pub fn sc_stream_configuration_set_source_rect(
154        config: *const c_void,
155        x: f64,
156        y: f64,
157        width: f64,
158        height: f64,
159    );
160    pub fn sc_stream_configuration_get_source_rect(
161        config: *const c_void,
162        x: *mut f64,
163        y: *mut f64,
164        width: *mut f64,
165        height: *mut f64,
166    );
167
168    pub fn sc_stream_configuration_set_destination_rect(
169        config: *const c_void,
170        x: f64,
171        y: f64,
172        width: f64,
173        height: f64,
174    );
175    pub fn sc_stream_configuration_get_destination_rect(
176        config: *const c_void,
177        x: *mut f64,
178        y: *mut f64,
179        width: *mut f64,
180        height: *mut f64,
181    );
182
183    pub fn sc_stream_configuration_set_preserves_aspect_ratio(
184        config: *const c_void,
185        preserves_aspect_ratio: bool,
186    );
187    pub fn sc_stream_configuration_get_preserves_aspect_ratio(config: *const c_void) -> bool;
188
189    pub fn sc_stream_configuration_set_ignore_fraction_of_screen(
190        config: *const c_void,
191        ignore_fraction: f64,
192    );
193    pub fn sc_stream_configuration_get_ignore_fraction_of_screen(config: *const c_void) -> f64;
194
195    pub fn sc_stream_configuration_set_ignores_shadows_single_window(
196        config: *const c_void,
197        ignores_shadows: bool,
198    );
199    pub fn sc_stream_configuration_get_ignores_shadows_single_window(config: *const c_void)
200        -> bool;
201
202    pub fn sc_stream_configuration_set_should_be_opaque(
203        config: *const c_void,
204        should_be_opaque: bool,
205    );
206    pub fn sc_stream_configuration_get_should_be_opaque(config: *const c_void) -> bool;
207
208    pub fn sc_stream_configuration_set_includes_child_windows(
209        config: *const c_void,
210        includes_child_windows: bool,
211    );
212    pub fn sc_stream_configuration_get_includes_child_windows(config: *const c_void) -> bool;
213
214    pub fn sc_stream_configuration_set_presenter_overlay_privacy_alert_setting(
215        config: *const c_void,
216        setting: i32,
217    );
218    pub fn sc_stream_configuration_get_presenter_overlay_privacy_alert_setting(
219        config: *const c_void,
220    ) -> i32;
221
222    pub fn sc_stream_configuration_set_background_color(
223        config: *const c_void,
224        r: f32,
225        g: f32,
226        b: f32,
227    );
228    pub fn sc_stream_configuration_set_color_space_name(config: *const c_void, name: *const i8);
229    pub fn sc_stream_configuration_set_color_matrix(config: *const c_void, matrix: *const i8);
230
231    pub fn sc_stream_configuration_set_ignore_global_clipboard(config: *const c_void, ignore: bool);
232    pub fn sc_stream_configuration_get_ignore_global_clipboard(config: *const c_void) -> bool;
233
234    pub fn sc_stream_configuration_set_capture_resolution(
235        config: *const c_void,
236        width: isize,
237        height: isize,
238    );
239    pub fn sc_stream_configuration_get_capture_resolution(
240        config: *const c_void,
241        width: *mut isize,
242        height: *mut isize,
243    );
244
245    pub fn sc_stream_configuration_set_ignores_shadow_display_configuration(
246        config: *const c_void,
247        ignores_shadow: bool,
248    );
249    pub fn sc_stream_configuration_get_ignores_shadow_display_configuration(
250        config: *const c_void,
251    ) -> bool;
252
253    pub fn sc_stream_configuration_set_preserve_aspect_ratio(config: *const c_void, preserve: bool);
254    pub fn sc_stream_configuration_get_preserve_aspect_ratio(config: *const c_void) -> bool;
255
256    pub fn sc_stream_configuration_set_increase_resolution_for_retina_displays(
257        config: *const c_void,
258        increase: bool,
259    );
260    pub fn sc_stream_configuration_get_increase_resolution_for_retina_displays(
261        config: *const c_void,
262    ) -> bool;
263
264    pub fn sc_stream_configuration_set_captures_shadows_only(
265        config: *const c_void,
266        captures_shadows_only: bool,
267    );
268    pub fn sc_stream_configuration_get_captures_shadows_only(config: *const c_void) -> bool;
269
270    pub fn sc_stream_configuration_set_captures_microphone(
271        config: *const c_void,
272        captures_microphone: bool,
273    );
274    pub fn sc_stream_configuration_get_captures_microphone(config: *const c_void) -> bool;
275
276    pub fn sc_stream_configuration_set_excludes_current_process_audio(
277        config: *const c_void,
278        excludes: bool,
279    );
280    pub fn sc_stream_configuration_get_excludes_current_process_audio(
281        config: *const c_void,
282    ) -> bool;
283
284    pub fn sc_stream_configuration_set_microphone_capture_device_id(
285        config: *const c_void,
286        device_id: *const i8,
287    );
288    pub fn sc_stream_configuration_get_microphone_capture_device_id(
289        config: *const c_void,
290        buffer: *mut i8,
291        buffer_size: isize,
292    ) -> bool;
293
294    pub fn sc_stream_configuration_set_stream_name(config: *const c_void, name: *const i8);
295    pub fn sc_stream_configuration_get_stream_name(
296        config: *const c_void,
297        buffer: *mut i8,
298        buffer_size: isize,
299    ) -> bool;
300
301    pub fn sc_stream_configuration_set_capture_dynamic_range(config: *const c_void, value: i32);
302    pub fn sc_stream_configuration_get_capture_dynamic_range(config: *const c_void) -> i32;
303}
304
305// MARK: - SCContentFilter
306extern "C" {
307    pub fn sc_content_filter_create_with_desktop_independent_window(
308        window: *const c_void,
309    ) -> *const c_void;
310    pub fn sc_content_filter_create_with_display_excluding_windows(
311        display: *const c_void,
312        windows: *const *const c_void,
313        windows_count: isize,
314    ) -> *const c_void;
315    pub fn sc_content_filter_create_with_display_including_windows(
316        display: *const c_void,
317        windows: *const *const c_void,
318        windows_count: isize,
319    ) -> *const c_void;
320    pub fn sc_content_filter_create_with_display_including_applications_excepting_windows(
321        display: *const c_void,
322        apps: *const *const c_void,
323        apps_count: isize,
324        windows: *const *const c_void,
325        windows_count: isize,
326    ) -> *const c_void;
327    pub fn sc_content_filter_retain(filter: *const c_void) -> *const c_void;
328    pub fn sc_content_filter_release(filter: *const c_void);
329    pub fn sc_content_filter_set_content_rect(
330        filter: *const c_void,
331        x: f64,
332        y: f64,
333        width: f64,
334        height: f64,
335    );
336    pub fn sc_content_filter_get_content_rect(
337        filter: *const c_void,
338        x: *mut f64,
339        y: *mut f64,
340        width: *mut f64,
341        height: *mut f64,
342    );
343}
344
345// MARK: - SCStream
346extern "C" {
347    pub fn sc_stream_create(
348        filter: *const c_void,
349        config: *const c_void,
350        error_callback: extern "C" fn(*const c_void, *const i8),
351    ) -> *const c_void;
352    pub fn sc_stream_add_stream_output(
353        stream: *const c_void,
354        output_type: i32,
355        sample_buffer_callback: extern "C" fn(*const c_void, *const c_void, i32),
356    ) -> bool;
357    pub fn sc_stream_add_stream_output_with_queue(
358        stream: *const c_void,
359        output_type: i32,
360        sample_buffer_callback: extern "C" fn(*const c_void, *const c_void, i32),
361        dispatch_queue: *const c_void,
362    ) -> bool;
363    pub fn sc_stream_start_capture(
364        stream: *const c_void,
365        context: *mut c_void,
366        callback: extern "C" fn(*mut c_void, bool, *const i8),
367    );
368    pub fn sc_stream_stop_capture(
369        stream: *const c_void,
370        context: *mut c_void,
371        callback: extern "C" fn(*mut c_void, bool, *const i8),
372    );
373    pub fn sc_stream_update_configuration(
374        stream: *const c_void,
375        config: *const c_void,
376        context: *mut c_void,
377        callback: extern "C" fn(*mut c_void, bool, *const i8),
378    );
379    pub fn sc_stream_update_content_filter(
380        stream: *const c_void,
381        filter: *const c_void,
382        context: *mut c_void,
383        callback: extern "C" fn(*mut c_void, bool, *const i8),
384    );
385    pub fn sc_stream_retain(stream: *const c_void) -> *const c_void;
386    pub fn sc_stream_release(stream: *const c_void);
387}
388
389// MARK: - Dispatch Queue
390extern "C" {
391    pub fn dispatch_queue_create(label: *const i8, qos: i32) -> *const c_void;
392    pub fn dispatch_queue_release(queue: *const c_void);
393}
394
395// MARK: - IOSurface
396extern "C" {
397    pub fn cv_pixel_buffer_get_iosurface(pixel_buffer: *const c_void) -> *const c_void;
398    pub fn cv_pixel_buffer_is_backed_by_iosurface(pixel_buffer: *const c_void) -> bool;
399    pub fn iosurface_get_width(iosurface: *const c_void) -> isize;
400    pub fn iosurface_get_height(iosurface: *const c_void) -> isize;
401    pub fn iosurface_get_bytes_per_row(iosurface: *const c_void) -> isize;
402    pub fn iosurface_get_pixel_format(iosurface: *const c_void) -> u32;
403    pub fn iosurface_get_base_address(iosurface: *const c_void) -> *mut u8;
404    pub fn iosurface_lock(iosurface: *const c_void, options: u32) -> i32;
405    pub fn iosurface_unlock(iosurface: *const c_void, options: u32) -> i32;
406    pub fn iosurface_is_in_use(iosurface: *const c_void) -> bool;
407    pub fn iosurface_release(iosurface: *const c_void);
408}
409
410// MARK: - SCContentSharingPicker (macOS 14.0+)
411extern "C" {
412    pub fn sc_content_sharing_picker_configuration_create() -> *const c_void;
413    pub fn sc_content_sharing_picker_configuration_set_allowed_picker_modes(
414        config: *const c_void,
415        modes: *const i32,
416        count: usize,
417    );
418    pub fn sc_content_sharing_picker_configuration_retain(config: *const c_void) -> *const c_void;
419    pub fn sc_content_sharing_picker_configuration_release(config: *const c_void);
420    pub fn sc_content_sharing_picker_show(
421        config: *const c_void,
422        callback: extern "C" fn(i32, *const c_void, *mut c_void),
423        user_data: *mut c_void,
424    );
425}
426
427// MARK: - SCRecordingOutput (macOS 15.0+)
428extern "C" {
429    pub fn sc_recording_output_configuration_create() -> *const c_void;
430    pub fn sc_recording_output_configuration_set_output_url(config: *const c_void, path: *const i8);
431    pub fn sc_recording_output_configuration_set_video_codec(config: *const c_void, codec: i32);
432    pub fn sc_recording_output_configuration_set_average_bitrate(
433        config: *const c_void,
434        bitrate: i64,
435    );
436    pub fn sc_recording_output_configuration_retain(config: *const c_void) -> *const c_void;
437    pub fn sc_recording_output_configuration_release(config: *const c_void);
438    pub fn sc_recording_output_create(config: *const c_void) -> *const c_void;
439    pub fn sc_recording_output_retain(output: *const c_void) -> *const c_void;
440    pub fn sc_recording_output_release(output: *const c_void);
441}
442
443// MARK: - SCScreenshotManager (macOS 14.0+)
444extern "C" {
445    pub fn sc_screenshot_manager_capture_image(
446        content_filter: *const c_void,
447        config: *const c_void,
448        callback: extern "C" fn(*const c_void, *const i8, *mut c_void),
449        user_data: *mut c_void,
450    );
451    pub fn sc_screenshot_manager_capture_sample_buffer(
452        content_filter: *const c_void,
453        config: *const c_void,
454        callback: extern "C" fn(*const c_void, *const i8, *mut c_void),
455        user_data: *mut c_void,
456    );
457    pub fn cgimage_get_width(image: *const c_void) -> usize;
458    pub fn cgimage_get_height(image: *const c_void) -> usize;
459    pub fn cgimage_get_data(
460        image: *const c_void,
461        out_ptr: *mut *const u8,
462        out_length: *mut usize,
463    ) -> bool;
464    pub fn cgimage_free_data(ptr: *mut u8);
465    pub fn cgimage_release(image: *const c_void);
466}