screencapturekit/ffi/
mod.rs

1//! Swift FFI bridge to `ScreenCaptureKit`
2use std::ffi::c_void;
3
4// MARK: - FFI Packed Data Structures
5
6/// Packed `CGRect` for efficient FFI transfer (32 bytes)
7#[repr(C)]
8#[derive(Debug, Clone, Copy, Default)]
9pub struct FFIRect {
10    pub x: f64,
11    pub y: f64,
12    pub width: f64,
13    pub height: f64,
14}
15
16/// Packed display data for batch retrieval (48 bytes)
17#[repr(C)]
18#[derive(Debug, Clone, Copy)]
19pub struct FFIDisplayData {
20    pub display_id: u32,
21    pub width: i32,
22    pub height: i32,
23    pub frame: FFIRect,
24}
25
26/// Packed window data for batch retrieval
27#[repr(C)]
28#[derive(Debug, Clone, Copy)]
29pub struct FFIWindowData {
30    pub window_id: u32,
31    pub window_layer: i32,
32    pub is_on_screen: bool,
33    pub is_active: bool,
34    pub frame: FFIRect,
35    pub title_offset: u32,
36    pub title_length: u32,
37    pub owning_app_index: i32,
38    #[doc(hidden)]
39    pub _padding: i32,
40}
41
42/// Packed application data for batch retrieval
43#[repr(C)]
44#[derive(Debug, Clone, Copy)]
45pub struct FFIApplicationData {
46    pub process_id: i32,
47    #[doc(hidden)]
48    pub _padding: i32,
49    pub bundle_id_offset: u32,
50    pub bundle_id_length: u32,
51    pub app_name_offset: u32,
52    pub app_name_length: u32,
53}
54
55// MARK: - CoreGraphics Initialization
56extern "C" {
57    /// Force CoreGraphics initialization by calling `CGMainDisplayID`
58    /// This prevents `CGS_REQUIRE_INIT` crashes on headless systems
59    pub fn sc_initialize_core_graphics();
60}
61
62// MARK: - SCShareableContent
63extern "C" {
64    /// Synchronous blocking call to get shareable content
65    /// Returns content pointer on success, or writes error to `error_buffer`
66    pub fn sc_shareable_content_get_sync(
67        exclude_desktop_windows: bool,
68        on_screen_windows_only: bool,
69        error_buffer: *mut i8,
70        error_buffer_size: isize,
71    ) -> *const c_void;
72
73    /// Async callback-based shareable content retrieval with options
74    pub fn sc_shareable_content_get_with_options(
75        exclude_desktop_windows: bool,
76        on_screen_windows_only: bool,
77        callback: extern "C" fn(*const c_void, *const i8, *mut c_void),
78        user_data: *mut c_void,
79    );
80
81    pub fn sc_shareable_content_get(
82        callback: extern "C" fn(*const c_void, *const i8, *mut c_void),
83        user_data: *mut c_void,
84    );
85    pub fn sc_shareable_content_get_current_process_displays(
86        callback: extern "C" fn(*const c_void, *const i8, *mut c_void),
87        user_data: *mut c_void,
88    );
89    pub fn sc_shareable_content_get_below_window(
90        exclude_desktop_windows: bool,
91        reference_window: *const c_void,
92        callback: extern "C" fn(*const c_void, *const i8, *mut c_void),
93        user_data: *mut c_void,
94    );
95    pub fn sc_shareable_content_get_above_window(
96        exclude_desktop_windows: bool,
97        reference_window: *const c_void,
98        callback: extern "C" fn(*const c_void, *const i8, *mut c_void),
99        user_data: *mut c_void,
100    );
101    pub fn sc_shareable_content_retain(content: *const c_void) -> *const c_void;
102    pub fn sc_shareable_content_release(content: *const c_void);
103    pub fn sc_shareable_content_get_displays_count(content: *const c_void) -> isize;
104    pub fn sc_shareable_content_get_display_at(
105        content: *const c_void,
106        index: isize,
107    ) -> *const c_void;
108    pub fn sc_shareable_content_get_windows_count(content: *const c_void) -> isize;
109    pub fn sc_shareable_content_get_window_at(
110        content: *const c_void,
111        index: isize,
112    ) -> *const c_void;
113    pub fn sc_shareable_content_get_applications_count(content: *const c_void) -> isize;
114    pub fn sc_shareable_content_get_application_at(
115        content: *const c_void,
116        index: isize,
117    ) -> *const c_void;
118
119    // Batch retrieval functions (optimized FFI)
120    pub fn sc_shareable_content_get_displays_batch(
121        content: *const c_void,
122        buffer: *mut c_void, // Actually *mut FFIDisplayData
123        max_displays: isize,
124    ) -> isize;
125
126    pub fn sc_shareable_content_get_applications_batch(
127        content: *const c_void,
128        buffer: *mut c_void, // Actually *mut FFIApplicationData
129        max_apps: isize,
130        string_buffer: *mut i8,
131        string_buffer_size: isize,
132        string_buffer_used: *mut isize,
133    ) -> isize;
134
135    pub fn sc_shareable_content_get_windows_batch(
136        content: *const c_void,
137        buffer: *mut c_void, // Actually *mut FFIWindowData
138        max_windows: isize,
139        string_buffer: *mut i8,
140        string_buffer_size: isize,
141        string_buffer_used: *mut isize,
142        app_pointers: *mut *const c_void,
143        max_apps: isize,
144        app_count: *mut isize,
145    ) -> isize;
146}
147
148// MARK: - SCDisplay
149extern "C" {
150    pub fn sc_display_retain(display: *const c_void) -> *const c_void;
151    pub fn sc_display_release(display: *const c_void);
152    pub fn sc_display_get_display_id(display: *const c_void) -> u32;
153    pub fn sc_display_get_width(display: *const c_void) -> isize;
154    pub fn sc_display_get_height(display: *const c_void) -> isize;
155    pub fn sc_display_get_frame(
156        display: *const c_void,
157        x: *mut f64,
158        y: *mut f64,
159        width: *mut f64,
160        height: *mut f64,
161    );
162    /// Get display frame (same as `sc_display_get_frame`, kept for API compatibility)
163    pub fn sc_display_get_frame_packed(
164        display: *const c_void,
165        x: *mut f64,
166        y: *mut f64,
167        width: *mut f64,
168        height: *mut f64,
169    );
170}
171
172// MARK: - SCWindow
173extern "C" {
174    pub fn sc_window_retain(window: *const c_void) -> *const c_void;
175    pub fn sc_window_release(window: *const c_void);
176    pub fn sc_window_get_window_id(window: *const c_void) -> u32;
177    pub fn sc_window_get_frame(
178        window: *const c_void,
179        x: *mut f64,
180        y: *mut f64,
181        width: *mut f64,
182        height: *mut f64,
183    );
184    /// Get window frame (same as `sc_window_get_frame`, kept for API compatibility)
185    pub fn sc_window_get_frame_packed(
186        window: *const c_void,
187        x: *mut f64,
188        y: *mut f64,
189        width: *mut f64,
190        height: *mut f64,
191    );
192    pub fn sc_window_get_title(window: *const c_void, buffer: *mut i8, buffer_size: isize) -> bool;
193    /// Get window title as owned string (caller must free with `sc_free_string`)
194    pub fn sc_window_get_title_owned(window: *const c_void) -> *mut i8;
195    pub fn sc_window_get_window_layer(window: *const c_void) -> isize;
196    pub fn sc_window_is_on_screen(window: *const c_void) -> bool;
197    pub fn sc_window_get_owning_application(window: *const c_void) -> *const c_void;
198    pub fn sc_window_is_active(window: *const c_void) -> bool;
199}
200
201// MARK: - SCRunningApplication
202extern "C" {
203    pub fn sc_running_application_retain(app: *const c_void) -> *const c_void;
204    pub fn sc_running_application_release(app: *const c_void);
205    pub fn sc_running_application_get_bundle_identifier(
206        app: *const c_void,
207        buffer: *mut i8,
208        buffer_size: isize,
209    ) -> bool;
210    /// Get bundle identifier as owned string (caller must free with `sc_free_string`)
211    pub fn sc_running_application_get_bundle_identifier_owned(app: *const c_void) -> *mut i8;
212    pub fn sc_running_application_get_application_name(
213        app: *const c_void,
214        buffer: *mut i8,
215        buffer_size: isize,
216    ) -> bool;
217    /// Get application name as owned string (caller must free with `sc_free_string`)
218    pub fn sc_running_application_get_application_name_owned(app: *const c_void) -> *mut i8;
219    pub fn sc_running_application_get_process_id(app: *const c_void) -> i32;
220}
221
222// MARK: - String memory management
223extern "C" {
224    /// Free a string allocated by Swift (strdup)
225    pub fn sc_free_string(str: *mut i8);
226}
227
228// MARK: - SCStreamConfiguration
229extern "C" {
230    pub fn sc_stream_configuration_create() -> *const c_void;
231    pub fn sc_stream_configuration_retain(config: *const c_void) -> *const c_void;
232    pub fn sc_stream_configuration_release(config: *const c_void);
233
234    pub fn sc_stream_configuration_set_width(config: *const c_void, width: isize);
235    pub fn sc_stream_configuration_get_width(config: *const c_void) -> isize;
236
237    pub fn sc_stream_configuration_set_height(config: *const c_void, height: isize);
238    pub fn sc_stream_configuration_get_height(config: *const c_void) -> isize;
239
240    pub fn sc_stream_configuration_set_shows_cursor(config: *const c_void, shows_cursor: bool);
241    pub fn sc_stream_configuration_get_shows_cursor(config: *const c_void) -> bool;
242
243    pub fn sc_stream_configuration_set_scales_to_fit(config: *const c_void, scales_to_fit: bool);
244    pub fn sc_stream_configuration_get_scales_to_fit(config: *const c_void) -> bool;
245
246    pub fn sc_stream_configuration_set_captures_audio(config: *const c_void, captures_audio: bool);
247    pub fn sc_stream_configuration_get_captures_audio(config: *const c_void) -> bool;
248
249    pub fn sc_stream_configuration_set_sample_rate(config: *const c_void, sample_rate: isize);
250    pub fn sc_stream_configuration_get_sample_rate(config: *const c_void) -> isize;
251
252    pub fn sc_stream_configuration_set_channel_count(config: *const c_void, channel_count: isize);
253    pub fn sc_stream_configuration_get_channel_count(config: *const c_void) -> isize;
254
255    pub fn sc_stream_configuration_set_queue_depth(config: *const c_void, queue_depth: isize);
256    pub fn sc_stream_configuration_get_queue_depth(config: *const c_void) -> isize;
257
258    pub fn sc_stream_configuration_set_pixel_format(config: *const c_void, pixel_format: u32);
259    pub fn sc_stream_configuration_get_pixel_format(config: *const c_void) -> u32;
260
261    pub fn sc_stream_configuration_set_minimum_frame_interval(
262        config: *const c_void,
263        value: i64,
264        timescale: i32,
265        flags: u32,
266        epoch: i64,
267    );
268    pub fn sc_stream_configuration_get_minimum_frame_interval(
269        config: *const c_void,
270        value: *mut i64,
271        timescale: *mut i32,
272        flags: *mut u32,
273        epoch: *mut i64,
274    );
275
276    pub fn sc_stream_configuration_set_source_rect(
277        config: *const c_void,
278        x: f64,
279        y: f64,
280        width: f64,
281        height: f64,
282    );
283    pub fn sc_stream_configuration_get_source_rect(
284        config: *const c_void,
285        x: *mut f64,
286        y: *mut f64,
287        width: *mut f64,
288        height: *mut f64,
289    );
290
291    pub fn sc_stream_configuration_set_destination_rect(
292        config: *const c_void,
293        x: f64,
294        y: f64,
295        width: f64,
296        height: f64,
297    );
298    pub fn sc_stream_configuration_get_destination_rect(
299        config: *const c_void,
300        x: *mut f64,
301        y: *mut f64,
302        width: *mut f64,
303        height: *mut f64,
304    );
305
306    pub fn sc_stream_configuration_set_preserves_aspect_ratio(
307        config: *const c_void,
308        preserves_aspect_ratio: bool,
309    );
310    pub fn sc_stream_configuration_get_preserves_aspect_ratio(config: *const c_void) -> bool;
311
312    pub fn sc_stream_configuration_set_ignores_shadows_single_window(
313        config: *const c_void,
314        ignores_shadows: bool,
315    );
316    pub fn sc_stream_configuration_get_ignores_shadows_single_window(config: *const c_void)
317        -> bool;
318
319    pub fn sc_stream_configuration_set_should_be_opaque(
320        config: *const c_void,
321        should_be_opaque: bool,
322    );
323    pub fn sc_stream_configuration_get_should_be_opaque(config: *const c_void) -> bool;
324
325    pub fn sc_stream_configuration_set_includes_child_windows(
326        config: *const c_void,
327        includes_child_windows: bool,
328    );
329    pub fn sc_stream_configuration_get_includes_child_windows(config: *const c_void) -> bool;
330
331    pub fn sc_stream_configuration_set_presenter_overlay_privacy_alert_setting(
332        config: *const c_void,
333        setting: i32,
334    );
335    pub fn sc_stream_configuration_get_presenter_overlay_privacy_alert_setting(
336        config: *const c_void,
337    ) -> i32;
338
339    pub fn sc_stream_configuration_set_background_color(
340        config: *const c_void,
341        r: f32,
342        g: f32,
343        b: f32,
344    );
345    pub fn sc_stream_configuration_set_color_space_name(config: *const c_void, name: *const i8);
346    pub fn sc_stream_configuration_set_color_matrix(config: *const c_void, matrix: *const i8);
347    pub fn sc_stream_configuration_get_color_matrix(
348        config: *const c_void,
349        buffer: *mut i8,
350        buffer_size: usize,
351    ) -> bool;
352
353    // macOS 14.0+ - capture resolution type
354    pub fn sc_stream_configuration_set_capture_resolution_type(config: *const c_void, value: i32);
355    pub fn sc_stream_configuration_get_capture_resolution_type(config: *const c_void) -> i32;
356
357    pub fn sc_stream_configuration_set_ignores_shadow_display_configuration(
358        config: *const c_void,
359        ignores_shadow: bool,
360    );
361    pub fn sc_stream_configuration_get_ignores_shadow_display_configuration(
362        config: *const c_void,
363    ) -> bool;
364
365    pub fn sc_stream_configuration_set_preserve_aspect_ratio(config: *const c_void, preserve: bool);
366    pub fn sc_stream_configuration_get_preserve_aspect_ratio(config: *const c_void) -> bool;
367
368    pub fn sc_stream_configuration_set_captures_shadows_only(
369        config: *const c_void,
370        captures_shadows_only: bool,
371    );
372    pub fn sc_stream_configuration_get_captures_shadows_only(config: *const c_void) -> bool;
373
374    pub fn sc_stream_configuration_set_captures_microphone(
375        config: *const c_void,
376        captures_microphone: bool,
377    );
378    pub fn sc_stream_configuration_get_captures_microphone(config: *const c_void) -> bool;
379
380    pub fn sc_stream_configuration_set_excludes_current_process_audio(
381        config: *const c_void,
382        excludes: bool,
383    );
384    pub fn sc_stream_configuration_get_excludes_current_process_audio(
385        config: *const c_void,
386    ) -> bool;
387
388    pub fn sc_stream_configuration_set_microphone_capture_device_id(
389        config: *const c_void,
390        device_id: *const i8,
391    );
392    pub fn sc_stream_configuration_get_microphone_capture_device_id(
393        config: *const c_void,
394        buffer: *mut i8,
395        buffer_size: isize,
396    ) -> bool;
397
398    pub fn sc_stream_configuration_set_stream_name(config: *const c_void, name: *const i8);
399    pub fn sc_stream_configuration_get_stream_name(
400        config: *const c_void,
401        buffer: *mut i8,
402        buffer_size: isize,
403    ) -> bool;
404
405    pub fn sc_stream_configuration_set_capture_dynamic_range(config: *const c_void, value: i32);
406    pub fn sc_stream_configuration_get_capture_dynamic_range(config: *const c_void) -> i32;
407}
408
409// MARK: - SCContentFilter
410extern "C" {
411    pub fn sc_content_filter_create_with_desktop_independent_window(
412        window: *const c_void,
413    ) -> *const c_void;
414    pub fn sc_content_filter_create_with_display_excluding_windows(
415        display: *const c_void,
416        windows: *const *const c_void,
417        windows_count: isize,
418    ) -> *const c_void;
419    pub fn sc_content_filter_create_with_display_including_windows(
420        display: *const c_void,
421        windows: *const *const c_void,
422        windows_count: isize,
423    ) -> *const c_void;
424    pub fn sc_content_filter_create_with_display_including_applications_excepting_windows(
425        display: *const c_void,
426        apps: *const *const c_void,
427        apps_count: isize,
428        windows: *const *const c_void,
429        windows_count: isize,
430    ) -> *const c_void;
431    pub fn sc_content_filter_create_with_display_excluding_applications_excepting_windows(
432        display: *const c_void,
433        apps: *const *const c_void,
434        apps_count: isize,
435        windows: *const *const c_void,
436        windows_count: isize,
437    ) -> *const c_void;
438    pub fn sc_content_filter_retain(filter: *const c_void) -> *const c_void;
439    pub fn sc_content_filter_release(filter: *const c_void);
440    pub fn sc_content_filter_set_content_rect(
441        filter: *const c_void,
442        x: f64,
443        y: f64,
444        width: f64,
445        height: f64,
446    );
447    pub fn sc_content_filter_get_content_rect(
448        filter: *const c_void,
449        x: *mut f64,
450        y: *mut f64,
451        width: *mut f64,
452        height: *mut f64,
453    );
454    /// Get content filter content rect (same as `sc_content_filter_get_content_rect`)
455    pub fn sc_content_filter_get_content_rect_packed(
456        filter: *const c_void,
457        x: *mut f64,
458        y: *mut f64,
459        width: *mut f64,
460        height: *mut f64,
461    );
462}
463
464// MARK: - SCStream
465extern "C" {
466    pub fn sc_stream_create(
467        filter: *const c_void,
468        config: *const c_void,
469        error_callback: extern "C" fn(*const c_void, i32, *const i8),
470    ) -> *const c_void;
471    pub fn sc_stream_add_stream_output(
472        stream: *const c_void,
473        output_type: i32,
474        sample_buffer_callback: extern "C" fn(*const c_void, *const c_void, i32),
475    ) -> bool;
476    pub fn sc_stream_add_stream_output_with_queue(
477        stream: *const c_void,
478        output_type: i32,
479        sample_buffer_callback: extern "C" fn(*const c_void, *const c_void, i32),
480        dispatch_queue: *const c_void,
481    ) -> bool;
482    pub fn sc_stream_remove_stream_output(stream: *const c_void, output_type: i32) -> bool;
483    pub fn sc_stream_start_capture(
484        stream: *const c_void,
485        context: *mut c_void,
486        callback: extern "C" fn(*mut c_void, bool, *const i8),
487    );
488    pub fn sc_stream_stop_capture(
489        stream: *const c_void,
490        context: *mut c_void,
491        callback: extern "C" fn(*mut c_void, bool, *const i8),
492    );
493    pub fn sc_stream_update_configuration(
494        stream: *const c_void,
495        config: *const c_void,
496        context: *mut c_void,
497        callback: extern "C" fn(*mut c_void, bool, *const i8),
498    );
499    pub fn sc_stream_update_content_filter(
500        stream: *const c_void,
501        filter: *const c_void,
502        context: *mut c_void,
503        callback: extern "C" fn(*mut c_void, bool, *const i8),
504    );
505    pub fn sc_stream_add_recording_output(
506        stream: *const c_void,
507        recording_output: *const c_void,
508        callback: extern "C" fn(*mut c_void, bool, *const i8),
509        context: *mut c_void,
510    );
511    pub fn sc_stream_remove_recording_output(
512        stream: *const c_void,
513        recording_output: *const c_void,
514        callback: extern "C" fn(*mut c_void, bool, *const i8),
515        context: *mut c_void,
516    );
517    pub fn sc_stream_retain(stream: *const c_void) -> *const c_void;
518    pub fn sc_stream_release(stream: *const c_void);
519
520    // macOS 13.0+ - synchronizationClock
521    pub fn sc_stream_get_synchronization_clock(stream: *const c_void) -> *const c_void;
522}
523
524// MARK: - Dispatch Queue
525extern "C" {
526    pub fn dispatch_queue_create(label: *const i8, qos: i32) -> *const c_void;
527    pub fn dispatch_queue_release(queue: *const c_void);
528    pub fn dispatch_queue_retain(queue: *const c_void) -> *const c_void;
529}
530
531// MARK: - IOSurface
532extern "C" {
533    pub fn cv_pixel_buffer_get_iosurface(pixel_buffer: *const c_void) -> *const c_void;
534    pub fn cv_pixel_buffer_is_backed_by_iosurface(pixel_buffer: *const c_void) -> bool;
535    pub fn iosurface_get_width(iosurface: *const c_void) -> isize;
536    pub fn iosurface_get_height(iosurface: *const c_void) -> isize;
537    pub fn iosurface_get_bytes_per_row(iosurface: *const c_void) -> isize;
538    pub fn iosurface_get_pixel_format(iosurface: *const c_void) -> u32;
539    pub fn iosurface_get_base_address(iosurface: *const c_void) -> *mut u8;
540    pub fn iosurface_lock(iosurface: *const c_void, options: u32) -> i32;
541    pub fn iosurface_unlock(iosurface: *const c_void, options: u32) -> i32;
542    pub fn iosurface_is_in_use(iosurface: *const c_void) -> bool;
543    pub fn iosurface_release(iosurface: *const c_void);
544
545    // Plane functions (for multi-planar formats like YCbCr 420)
546    pub fn iosurface_get_plane_count(iosurface: *const c_void) -> isize;
547    pub fn iosurface_get_width_of_plane(iosurface: *const c_void, plane: isize) -> isize;
548    pub fn iosurface_get_height_of_plane(iosurface: *const c_void, plane: isize) -> isize;
549    pub fn iosurface_get_bytes_per_row_of_plane(iosurface: *const c_void, plane: isize) -> isize;
550
551    // IOSurface creation (for testing)
552    pub fn io_surface_create(
553        width: usize,
554        height: usize,
555        pixel_format: u32,
556        bytes_per_element: usize,
557        surface_out: *mut *mut c_void,
558    ) -> i32;
559
560    // IOSurface creation with full properties (for multi-planar formats)
561    pub fn io_surface_create_with_properties(
562        width: usize,
563        height: usize,
564        pixel_format: u32,
565        bytes_per_element: usize,
566        bytes_per_row: usize,
567        alloc_size: usize,
568        plane_count: usize,
569        plane_widths: *const usize,
570        plane_heights: *const usize,
571        plane_bytes_per_row: *const usize,
572        plane_bytes_per_element: *const usize,
573        plane_offsets: *const usize,
574        plane_sizes: *const usize,
575        surface_out: *mut *mut c_void,
576    ) -> i32;
577}
578
579// MARK: - SCContentSharingPicker (macOS 14.0+)
580extern "C" {
581    pub fn sc_content_sharing_picker_configuration_create() -> *const c_void;
582    pub fn sc_content_sharing_picker_configuration_set_allowed_picker_modes(
583        config: *const c_void,
584        modes: *const i32,
585        count: usize,
586    );
587    pub fn sc_content_sharing_picker_configuration_set_allows_changing_selected_content(
588        config: *const c_void,
589        allows: bool,
590    );
591    pub fn sc_content_sharing_picker_configuration_get_allows_changing_selected_content(
592        config: *const c_void,
593    ) -> bool;
594    pub fn sc_content_sharing_picker_configuration_set_excluded_bundle_ids(
595        config: *const c_void,
596        bundle_ids: *const *const i8,
597        count: usize,
598    );
599    pub fn sc_content_sharing_picker_configuration_get_excluded_bundle_ids_count(
600        config: *const c_void,
601    ) -> usize;
602    pub fn sc_content_sharing_picker_configuration_get_excluded_bundle_id_at(
603        config: *const c_void,
604        index: usize,
605        buffer: *mut i8,
606        buffer_size: usize,
607    ) -> bool;
608    pub fn sc_content_sharing_picker_configuration_set_excluded_window_ids(
609        config: *const c_void,
610        window_ids: *const u32,
611        count: usize,
612    );
613    pub fn sc_content_sharing_picker_configuration_get_excluded_window_ids_count(
614        config: *const c_void,
615    ) -> usize;
616    pub fn sc_content_sharing_picker_configuration_get_excluded_window_id_at(
617        config: *const c_void,
618        index: usize,
619    ) -> u32;
620    pub fn sc_content_sharing_picker_configuration_retain(config: *const c_void) -> *const c_void;
621    pub fn sc_content_sharing_picker_configuration_release(config: *const c_void);
622
623    // Picker maximum stream count
624    pub fn sc_content_sharing_picker_set_maximum_stream_count(count: usize);
625    pub fn sc_content_sharing_picker_get_maximum_stream_count() -> usize;
626
627    pub fn sc_content_sharing_picker_show(
628        config: *const c_void,
629        callback: extern "C" fn(i32, *const c_void, *mut c_void),
630        user_data: *mut c_void,
631    );
632    pub fn sc_content_sharing_picker_show_with_result(
633        config: *const c_void,
634        callback: extern "C" fn(i32, *const c_void, *mut c_void),
635        user_data: *mut c_void,
636    );
637    pub fn sc_content_sharing_picker_show_for_stream(
638        config: *const c_void,
639        stream: *const c_void,
640        callback: extern "C" fn(i32, *const c_void, *mut c_void),
641        user_data: *mut c_void,
642    );
643    pub fn sc_content_sharing_picker_show_using_style(
644        config: *const c_void,
645        style: i32,
646        callback: extern "C" fn(i32, *const c_void, *mut c_void),
647        user_data: *mut c_void,
648    );
649    pub fn sc_content_sharing_picker_show_for_stream_using_style(
650        config: *const c_void,
651        stream: *const c_void,
652        style: i32,
653        callback: extern "C" fn(i32, *const c_void, *mut c_void),
654        user_data: *mut c_void,
655    );
656    pub fn sc_picker_result_get_filter(result: *const c_void) -> *const c_void;
657    pub fn sc_picker_result_get_content_rect(
658        result: *const c_void,
659        x: *mut f64,
660        y: *mut f64,
661        width: *mut f64,
662        height: *mut f64,
663    );
664    pub fn sc_picker_result_get_scale(result: *const c_void) -> f64;
665    pub fn sc_picker_result_get_windows_count(result: *const c_void) -> usize;
666    pub fn sc_picker_result_get_window_at(result: *const c_void, index: usize) -> *const c_void;
667    pub fn sc_picker_result_get_displays_count(result: *const c_void) -> usize;
668    pub fn sc_picker_result_get_display_at(result: *const c_void, index: usize) -> *const c_void;
669    pub fn sc_picker_result_get_applications_count(result: *const c_void) -> usize;
670    pub fn sc_picker_result_get_application_at(
671        result: *const c_void,
672        index: usize,
673    ) -> *const c_void;
674    pub fn sc_picker_result_release(result: *const c_void);
675}
676
677// MARK: - SCRecordingOutput (macOS 15.0+)
678extern "C" {
679    pub fn sc_recording_output_configuration_create() -> *const c_void;
680    pub fn sc_recording_output_configuration_set_output_url(config: *const c_void, path: *const i8);
681    pub fn sc_recording_output_configuration_set_video_codec(config: *const c_void, codec: i32);
682    pub fn sc_recording_output_configuration_retain(config: *const c_void) -> *const c_void;
683    pub fn sc_recording_output_configuration_release(config: *const c_void);
684    pub fn sc_recording_output_create(config: *const c_void) -> *const c_void;
685    pub fn sc_recording_output_retain(output: *const c_void) -> *const c_void;
686    pub fn sc_recording_output_release(output: *const c_void);
687}
688
689// MARK: - SCScreenshotManager (macOS 14.0+)
690extern "C" {
691    pub fn sc_screenshot_manager_capture_image(
692        content_filter: *const c_void,
693        config: *const c_void,
694        callback: extern "C" fn(*const c_void, *const i8, *mut c_void),
695        user_data: *mut c_void,
696    );
697    pub fn sc_screenshot_manager_capture_sample_buffer(
698        content_filter: *const c_void,
699        config: *const c_void,
700        callback: extern "C" fn(*const c_void, *const i8, *mut c_void),
701        user_data: *mut c_void,
702    );
703    pub fn sc_screenshot_manager_capture_image_in_rect(
704        x: f64,
705        y: f64,
706        width: f64,
707        height: f64,
708        callback: extern "C" fn(*const c_void, *const i8, *mut c_void),
709        user_data: *mut c_void,
710    );
711    pub fn cgimage_get_width(image: *const c_void) -> usize;
712    pub fn cgimage_get_height(image: *const c_void) -> usize;
713    pub fn cgimage_get_data(
714        image: *const c_void,
715        out_ptr: *mut *const u8,
716        out_length: *mut usize,
717    ) -> bool;
718    pub fn cgimage_free_data(ptr: *mut u8);
719    pub fn cgimage_release(image: *const c_void);
720    pub fn cgimage_save_png(image: *const c_void, path: *const i8) -> bool;
721    pub fn cgimage_save_to_file(
722        image: *const c_void,
723        path: *const i8,
724        format: i32,
725        quality: f32,
726    ) -> bool;
727}
728
729// MARK: - SCScreenshotConfiguration (macOS 26.0+)
730extern "C" {
731    pub fn sc_screenshot_configuration_create() -> *const c_void;
732    pub fn sc_screenshot_configuration_set_width(config: *const c_void, width: isize);
733    pub fn sc_screenshot_configuration_set_height(config: *const c_void, height: isize);
734    pub fn sc_screenshot_configuration_set_shows_cursor(config: *const c_void, shows_cursor: bool);
735    pub fn sc_screenshot_configuration_set_source_rect(
736        config: *const c_void,
737        x: f64,
738        y: f64,
739        width: f64,
740        height: f64,
741    );
742    pub fn sc_screenshot_configuration_set_destination_rect(
743        config: *const c_void,
744        x: f64,
745        y: f64,
746        width: f64,
747        height: f64,
748    );
749    pub fn sc_screenshot_configuration_set_ignore_shadows(
750        config: *const c_void,
751        ignore_shadows: bool,
752    );
753    pub fn sc_screenshot_configuration_set_ignore_clipping(
754        config: *const c_void,
755        ignore_clipping: bool,
756    );
757    pub fn sc_screenshot_configuration_set_include_child_windows(
758        config: *const c_void,
759        include_child_windows: bool,
760    );
761    pub fn sc_screenshot_configuration_set_display_intent(
762        config: *const c_void,
763        display_intent: i32,
764    );
765    pub fn sc_screenshot_configuration_set_dynamic_range(config: *const c_void, dynamic_range: i32);
766    pub fn sc_screenshot_configuration_set_file_url(config: *const c_void, path: *const i8);
767    pub fn sc_screenshot_configuration_release(config: *const c_void);
768
769    // Content type support (macOS 26.0+)
770    pub fn sc_screenshot_configuration_set_content_type(
771        config: *const c_void,
772        identifier: *const i8,
773    );
774    pub fn sc_screenshot_configuration_get_content_type(
775        config: *const c_void,
776        buffer: *mut i8,
777        buffer_size: usize,
778    ) -> bool;
779    pub fn sc_screenshot_configuration_get_supported_content_types_count() -> usize;
780    pub fn sc_screenshot_configuration_get_supported_content_type_at(
781        index: usize,
782        buffer: *mut i8,
783        buffer_size: usize,
784    ) -> bool;
785}
786
787// MARK: - SCScreenshotOutput (macOS 26.0+)
788extern "C" {
789    pub fn sc_screenshot_output_get_sdr_image(output: *const c_void) -> *const c_void;
790    pub fn sc_screenshot_output_get_hdr_image(output: *const c_void) -> *const c_void;
791    pub fn sc_screenshot_output_get_file_url(
792        output: *const c_void,
793        buffer: *mut i8,
794        buffer_size: isize,
795    ) -> bool;
796    pub fn sc_screenshot_output_release(output: *const c_void);
797
798    pub fn sc_screenshot_manager_capture_screenshot(
799        content_filter: *const c_void,
800        config: *const c_void,
801        callback: extern "C" fn(*const c_void, *const i8, *mut c_void),
802        user_data: *mut c_void,
803    );
804    pub fn sc_screenshot_manager_capture_screenshot_in_rect(
805        x: f64,
806        y: f64,
807        width: f64,
808        height: f64,
809        config: *const c_void,
810        callback: extern "C" fn(*const c_void, *const i8, *mut c_void),
811        user_data: *mut c_void,
812    );
813}
814
815// MARK: - SCStreamConfiguration additional properties
816extern "C" {
817    // macOS 15.0+ - showMouseClicks
818    pub fn sc_stream_configuration_set_shows_mouse_clicks(config: *const c_void, value: bool);
819    pub fn sc_stream_configuration_get_shows_mouse_clicks(config: *const c_void) -> bool;
820
821    // macOS 14.0+ - ignoreShadowsDisplay
822    pub fn sc_stream_configuration_set_ignores_shadows_display(config: *const c_void, value: bool);
823    pub fn sc_stream_configuration_get_ignores_shadows_display(config: *const c_void) -> bool;
824
825    // macOS 14.0+ - ignoreGlobalClipDisplay
826    pub fn sc_stream_configuration_set_ignore_global_clip_display(
827        config: *const c_void,
828        value: bool,
829    );
830    pub fn sc_stream_configuration_get_ignore_global_clip_display(config: *const c_void) -> bool;
831
832    // macOS 14.0+ - ignoreGlobalClipSingleWindow
833    pub fn sc_stream_configuration_set_ignore_global_clip_single_window(
834        config: *const c_void,
835        value: bool,
836    );
837    pub fn sc_stream_configuration_get_ignore_global_clip_single_window(
838        config: *const c_void,
839    ) -> bool;
840
841    // macOS 15.0+ - preset-based configuration
842    pub fn sc_stream_configuration_create_with_preset(preset: i32) -> *const c_void;
843}
844
845// MARK: - SCContentFilter additional properties
846extern "C" {
847    // macOS 14.0+ - style and pointPixelScale
848    pub fn sc_content_filter_get_style(filter: *const c_void) -> i32;
849    pub fn sc_content_filter_get_point_pixel_scale(filter: *const c_void) -> f32;
850    pub fn sc_content_filter_get_stream_type(filter: *const c_void) -> i32;
851
852    // macOS 14.2+ - includeMenuBar
853    pub fn sc_content_filter_set_include_menu_bar(filter: *const c_void, include: bool);
854    pub fn sc_content_filter_get_include_menu_bar(filter: *const c_void) -> bool;
855
856    // macOS 15.2+ - included content arrays
857    pub fn sc_content_filter_get_included_displays_count(filter: *const c_void) -> isize;
858    pub fn sc_content_filter_get_included_display_at(
859        filter: *const c_void,
860        index: isize,
861    ) -> *const c_void;
862    pub fn sc_content_filter_get_included_windows_count(filter: *const c_void) -> isize;
863    pub fn sc_content_filter_get_included_window_at(
864        filter: *const c_void,
865        index: isize,
866    ) -> *const c_void;
867    pub fn sc_content_filter_get_included_applications_count(filter: *const c_void) -> isize;
868    pub fn sc_content_filter_get_included_application_at(
869        filter: *const c_void,
870        index: isize,
871    ) -> *const c_void;
872}
873
874// MARK: - SCShareableContentInfo (macOS 14.0+)
875extern "C" {
876    pub fn sc_shareable_content_info_for_filter(filter: *const c_void) -> *const c_void;
877    pub fn sc_shareable_content_info_get_style(info: *const c_void) -> i32;
878    pub fn sc_shareable_content_info_get_point_pixel_scale(info: *const c_void) -> f32;
879    pub fn sc_shareable_content_info_get_content_rect(
880        info: *const c_void,
881        x: *mut f64,
882        y: *mut f64,
883        width: *mut f64,
884        height: *mut f64,
885    );
886    /// Get shareable content info rect (same as `sc_shareable_content_info_get_content_rect`)
887    pub fn sc_shareable_content_info_get_content_rect_packed(
888        info: *const c_void,
889        x: *mut f64,
890        y: *mut f64,
891        width: *mut f64,
892        height: *mut f64,
893    );
894    pub fn sc_shareable_content_info_retain(info: *const c_void) -> *const c_void;
895    pub fn sc_shareable_content_info_release(info: *const c_void);
896}
897
898// MARK: - SCRecordingOutput additional (macOS 15.0+)
899extern "C" {
900    pub fn sc_recording_output_configuration_set_output_file_type(
901        config: *const c_void,
902        file_type: i32,
903    );
904    pub fn sc_recording_output_configuration_get_output_file_type(config: *const c_void) -> i32;
905    pub fn sc_recording_output_configuration_get_video_codec(config: *const c_void) -> i32;
906    pub fn sc_recording_output_configuration_get_available_video_codecs_count(
907        config: *const c_void,
908    ) -> isize;
909    pub fn sc_recording_output_configuration_get_available_video_codec_at(
910        config: *const c_void,
911        index: isize,
912    ) -> i32;
913    pub fn sc_recording_output_configuration_get_available_output_file_types_count(
914        config: *const c_void,
915    ) -> isize;
916    pub fn sc_recording_output_configuration_get_available_output_file_type_at(
917        config: *const c_void,
918        index: isize,
919    ) -> i32;
920    pub fn sc_recording_output_create_with_delegate(
921        config: *const c_void,
922        started_callback: Option<extern "C" fn(*mut c_void)>,
923        failed_callback: Option<extern "C" fn(*mut c_void, i32, *const i8)>,
924        finished_callback: Option<extern "C" fn(*mut c_void)>,
925        context: *mut c_void,
926    ) -> *const c_void;
927    pub fn sc_recording_output_get_recorded_duration(
928        output: *const c_void,
929        value: *mut i64,
930        timescale: *mut i32,
931    );
932    pub fn sc_recording_output_get_recorded_file_size(output: *const c_void) -> i64;
933}
934
935// MARK: - Audio Input Devices (AVFoundation)
936extern "C" {
937    /// Get the count of available audio input devices
938    pub fn sc_audio_get_input_device_count() -> isize;
939
940    /// Get audio input device ID at index into buffer
941    pub fn sc_audio_get_input_device_id(index: isize, buffer: *mut i8, buffer_size: isize) -> bool;
942
943    /// Get audio input device name at index into buffer
944    pub fn sc_audio_get_input_device_name(
945        index: isize,
946        buffer: *mut i8,
947        buffer_size: isize,
948    ) -> bool;
949
950    /// Check if the device at index is the default audio input device
951    pub fn sc_audio_is_default_input_device(index: isize) -> bool;
952
953    /// Get the default audio input device ID into buffer
954    pub fn sc_audio_get_default_input_device_id(buffer: *mut i8, buffer_size: isize) -> bool;
955
956    /// Get the default audio input device name into buffer
957    pub fn sc_audio_get_default_input_device_name(buffer: *mut i8, buffer_size: isize) -> bool;
958}