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        context: *mut c_void,
470        error_callback: extern "C" fn(*mut c_void, i32, *const i8),
471        sample_callback: extern "C" fn(*mut c_void, *const c_void, i32),
472    ) -> *const c_void;
473    pub fn sc_stream_add_stream_output(stream: *const c_void, output_type: i32) -> bool;
474    pub fn sc_stream_add_stream_output_with_queue(
475        stream: *const c_void,
476        output_type: i32,
477        dispatch_queue: *const c_void,
478    ) -> bool;
479    pub fn sc_stream_remove_stream_output(stream: *const c_void, output_type: i32) -> bool;
480    pub fn sc_stream_start_capture(
481        stream: *const c_void,
482        context: *mut c_void,
483        callback: extern "C" fn(*mut c_void, bool, *const i8),
484    );
485    pub fn sc_stream_stop_capture(
486        stream: *const c_void,
487        context: *mut c_void,
488        callback: extern "C" fn(*mut c_void, bool, *const i8),
489    );
490    pub fn sc_stream_update_configuration(
491        stream: *const c_void,
492        config: *const c_void,
493        context: *mut c_void,
494        callback: extern "C" fn(*mut c_void, bool, *const i8),
495    );
496    pub fn sc_stream_update_content_filter(
497        stream: *const c_void,
498        filter: *const c_void,
499        context: *mut c_void,
500        callback: extern "C" fn(*mut c_void, bool, *const i8),
501    );
502    pub fn sc_stream_add_recording_output(
503        stream: *const c_void,
504        recording_output: *const c_void,
505        callback: extern "C" fn(*mut c_void, bool, *const i8),
506        context: *mut c_void,
507    );
508    pub fn sc_stream_remove_recording_output(
509        stream: *const c_void,
510        recording_output: *const c_void,
511        callback: extern "C" fn(*mut c_void, bool, *const i8),
512        context: *mut c_void,
513    );
514    pub fn sc_stream_retain(stream: *const c_void) -> *const c_void;
515    pub fn sc_stream_release(stream: *const c_void);
516
517    // macOS 13.0+ - synchronizationClock
518    pub fn sc_stream_get_synchronization_clock(stream: *const c_void) -> *const c_void;
519}
520
521// MARK: - Dispatch Queue
522extern "C" {
523    pub fn dispatch_queue_create(label: *const i8, qos: i32) -> *const c_void;
524    pub fn dispatch_queue_release(queue: *const c_void);
525    pub fn dispatch_queue_retain(queue: *const c_void) -> *const c_void;
526}
527
528// MARK: - IOSurface
529extern "C" {
530    pub fn cv_pixel_buffer_get_iosurface(pixel_buffer: *const c_void) -> *const c_void;
531    pub fn cv_pixel_buffer_is_backed_by_iosurface(pixel_buffer: *const c_void) -> bool;
532    pub fn iosurface_get_width(iosurface: *const c_void) -> isize;
533    pub fn iosurface_get_height(iosurface: *const c_void) -> isize;
534    pub fn iosurface_get_bytes_per_row(iosurface: *const c_void) -> isize;
535    pub fn iosurface_get_pixel_format(iosurface: *const c_void) -> u32;
536    pub fn iosurface_get_base_address(iosurface: *const c_void) -> *mut u8;
537    pub fn iosurface_lock(iosurface: *const c_void, options: u32) -> i32;
538    pub fn iosurface_unlock(iosurface: *const c_void, options: u32) -> i32;
539    pub fn iosurface_is_in_use(iosurface: *const c_void) -> bool;
540    pub fn iosurface_release(iosurface: *const c_void);
541
542    // Plane functions (for multi-planar formats like YCbCr 420)
543    pub fn iosurface_get_plane_count(iosurface: *const c_void) -> isize;
544    pub fn iosurface_get_width_of_plane(iosurface: *const c_void, plane: isize) -> isize;
545    pub fn iosurface_get_height_of_plane(iosurface: *const c_void, plane: isize) -> isize;
546    pub fn iosurface_get_bytes_per_row_of_plane(iosurface: *const c_void, plane: isize) -> isize;
547
548    // IOSurface creation (for testing)
549    pub fn io_surface_create(
550        width: usize,
551        height: usize,
552        pixel_format: u32,
553        bytes_per_element: usize,
554        surface_out: *mut *mut c_void,
555    ) -> i32;
556
557    // IOSurface creation with full properties (for multi-planar formats)
558    pub fn io_surface_create_with_properties(
559        width: usize,
560        height: usize,
561        pixel_format: u32,
562        bytes_per_element: usize,
563        bytes_per_row: usize,
564        alloc_size: usize,
565        plane_count: usize,
566        plane_widths: *const usize,
567        plane_heights: *const usize,
568        plane_bytes_per_row: *const usize,
569        plane_bytes_per_element: *const usize,
570        plane_offsets: *const usize,
571        plane_sizes: *const usize,
572        surface_out: *mut *mut c_void,
573    ) -> i32;
574}
575
576// MARK: - SCContentSharingPicker (macOS 14.0+)
577extern "C" {
578    pub fn sc_content_sharing_picker_configuration_create() -> *const c_void;
579    pub fn sc_content_sharing_picker_configuration_set_allowed_picker_modes(
580        config: *const c_void,
581        modes: *const i32,
582        count: usize,
583    );
584    pub fn sc_content_sharing_picker_configuration_set_allows_changing_selected_content(
585        config: *const c_void,
586        allows: bool,
587    );
588    pub fn sc_content_sharing_picker_configuration_get_allows_changing_selected_content(
589        config: *const c_void,
590    ) -> bool;
591    pub fn sc_content_sharing_picker_configuration_set_excluded_bundle_ids(
592        config: *const c_void,
593        bundle_ids: *const *const i8,
594        count: usize,
595    );
596    pub fn sc_content_sharing_picker_configuration_get_excluded_bundle_ids_count(
597        config: *const c_void,
598    ) -> usize;
599    pub fn sc_content_sharing_picker_configuration_get_excluded_bundle_id_at(
600        config: *const c_void,
601        index: usize,
602        buffer: *mut i8,
603        buffer_size: usize,
604    ) -> bool;
605    pub fn sc_content_sharing_picker_configuration_set_excluded_window_ids(
606        config: *const c_void,
607        window_ids: *const u32,
608        count: usize,
609    );
610    pub fn sc_content_sharing_picker_configuration_get_excluded_window_ids_count(
611        config: *const c_void,
612    ) -> usize;
613    pub fn sc_content_sharing_picker_configuration_get_excluded_window_id_at(
614        config: *const c_void,
615        index: usize,
616    ) -> u32;
617    pub fn sc_content_sharing_picker_configuration_retain(config: *const c_void) -> *const c_void;
618    pub fn sc_content_sharing_picker_configuration_release(config: *const c_void);
619
620    // Picker maximum stream count
621    pub fn sc_content_sharing_picker_set_maximum_stream_count(count: usize);
622    pub fn sc_content_sharing_picker_get_maximum_stream_count() -> usize;
623
624    pub fn sc_content_sharing_picker_show(
625        config: *const c_void,
626        callback: extern "C" fn(i32, *const c_void, *mut c_void),
627        user_data: *mut c_void,
628    );
629    pub fn sc_content_sharing_picker_show_with_result(
630        config: *const c_void,
631        callback: extern "C" fn(i32, *const c_void, *mut c_void),
632        user_data: *mut c_void,
633    );
634    pub fn sc_content_sharing_picker_show_for_stream(
635        config: *const c_void,
636        stream: *const c_void,
637        callback: extern "C" fn(i32, *const c_void, *mut c_void),
638        user_data: *mut c_void,
639    );
640    pub fn sc_content_sharing_picker_show_using_style(
641        config: *const c_void,
642        style: i32,
643        callback: extern "C" fn(i32, *const c_void, *mut c_void),
644        user_data: *mut c_void,
645    );
646    pub fn sc_content_sharing_picker_show_for_stream_using_style(
647        config: *const c_void,
648        stream: *const c_void,
649        style: i32,
650        callback: extern "C" fn(i32, *const c_void, *mut c_void),
651        user_data: *mut c_void,
652    );
653    pub fn sc_picker_result_get_filter(result: *const c_void) -> *const c_void;
654    pub fn sc_picker_result_get_content_rect(
655        result: *const c_void,
656        x: *mut f64,
657        y: *mut f64,
658        width: *mut f64,
659        height: *mut f64,
660    );
661    pub fn sc_picker_result_get_scale(result: *const c_void) -> f64;
662    pub fn sc_picker_result_get_windows_count(result: *const c_void) -> usize;
663    pub fn sc_picker_result_get_window_at(result: *const c_void, index: usize) -> *const c_void;
664    pub fn sc_picker_result_get_displays_count(result: *const c_void) -> usize;
665    pub fn sc_picker_result_get_display_at(result: *const c_void, index: usize) -> *const c_void;
666    pub fn sc_picker_result_get_applications_count(result: *const c_void) -> usize;
667    pub fn sc_picker_result_get_application_at(
668        result: *const c_void,
669        index: usize,
670    ) -> *const c_void;
671    pub fn sc_picker_result_release(result: *const c_void);
672}
673
674// MARK: - SCRecordingOutput (macOS 15.0+)
675extern "C" {
676    pub fn sc_recording_output_configuration_create() -> *const c_void;
677    pub fn sc_recording_output_configuration_set_output_url(config: *const c_void, path: *const i8);
678    pub fn sc_recording_output_configuration_set_video_codec(config: *const c_void, codec: i32);
679    pub fn sc_recording_output_configuration_retain(config: *const c_void) -> *const c_void;
680    pub fn sc_recording_output_configuration_release(config: *const c_void);
681    pub fn sc_recording_output_create(config: *const c_void) -> *const c_void;
682    pub fn sc_recording_output_retain(output: *const c_void) -> *const c_void;
683    pub fn sc_recording_output_release(output: *const c_void);
684}
685
686// MARK: - SCScreenshotManager (macOS 14.0+)
687extern "C" {
688    pub fn sc_screenshot_manager_capture_image(
689        content_filter: *const c_void,
690        config: *const c_void,
691        callback: extern "C" fn(*const c_void, *const i8, *mut c_void),
692        user_data: *mut c_void,
693    );
694    pub fn sc_screenshot_manager_capture_sample_buffer(
695        content_filter: *const c_void,
696        config: *const c_void,
697        callback: extern "C" fn(*const c_void, *const i8, *mut c_void),
698        user_data: *mut c_void,
699    );
700    pub fn sc_screenshot_manager_capture_image_in_rect(
701        x: f64,
702        y: f64,
703        width: f64,
704        height: f64,
705        callback: extern "C" fn(*const c_void, *const i8, *mut c_void),
706        user_data: *mut c_void,
707    );
708    pub fn cgimage_get_width(image: *const c_void) -> usize;
709    pub fn cgimage_get_height(image: *const c_void) -> usize;
710    pub fn cgimage_get_data(
711        image: *const c_void,
712        out_ptr: *mut *const u8,
713        out_length: *mut usize,
714    ) -> bool;
715    pub fn cgimage_free_data(ptr: *mut u8);
716    pub fn cgimage_release(image: *const c_void);
717    pub fn cgimage_save_png(image: *const c_void, path: *const i8) -> bool;
718    pub fn cgimage_save_to_file(
719        image: *const c_void,
720        path: *const i8,
721        format: i32,
722        quality: f32,
723    ) -> bool;
724}
725
726// MARK: - SCScreenshotConfiguration (macOS 26.0+)
727extern "C" {
728    pub fn sc_screenshot_configuration_create() -> *const c_void;
729    pub fn sc_screenshot_configuration_set_width(config: *const c_void, width: isize);
730    pub fn sc_screenshot_configuration_set_height(config: *const c_void, height: isize);
731    pub fn sc_screenshot_configuration_set_shows_cursor(config: *const c_void, shows_cursor: bool);
732    pub fn sc_screenshot_configuration_set_source_rect(
733        config: *const c_void,
734        x: f64,
735        y: f64,
736        width: f64,
737        height: f64,
738    );
739    pub fn sc_screenshot_configuration_set_destination_rect(
740        config: *const c_void,
741        x: f64,
742        y: f64,
743        width: f64,
744        height: f64,
745    );
746    pub fn sc_screenshot_configuration_set_ignore_shadows(
747        config: *const c_void,
748        ignore_shadows: bool,
749    );
750    pub fn sc_screenshot_configuration_set_ignore_clipping(
751        config: *const c_void,
752        ignore_clipping: bool,
753    );
754    pub fn sc_screenshot_configuration_set_include_child_windows(
755        config: *const c_void,
756        include_child_windows: bool,
757    );
758    pub fn sc_screenshot_configuration_set_display_intent(
759        config: *const c_void,
760        display_intent: i32,
761    );
762    pub fn sc_screenshot_configuration_set_dynamic_range(config: *const c_void, dynamic_range: i32);
763    pub fn sc_screenshot_configuration_set_file_url(config: *const c_void, path: *const i8);
764    pub fn sc_screenshot_configuration_release(config: *const c_void);
765
766    // Content type support (macOS 26.0+)
767    pub fn sc_screenshot_configuration_set_content_type(
768        config: *const c_void,
769        identifier: *const i8,
770    );
771    pub fn sc_screenshot_configuration_get_content_type(
772        config: *const c_void,
773        buffer: *mut i8,
774        buffer_size: usize,
775    ) -> bool;
776    pub fn sc_screenshot_configuration_get_supported_content_types_count() -> usize;
777    pub fn sc_screenshot_configuration_get_supported_content_type_at(
778        index: usize,
779        buffer: *mut i8,
780        buffer_size: usize,
781    ) -> bool;
782}
783
784// MARK: - SCScreenshotOutput (macOS 26.0+)
785extern "C" {
786    pub fn sc_screenshot_output_get_sdr_image(output: *const c_void) -> *const c_void;
787    pub fn sc_screenshot_output_get_hdr_image(output: *const c_void) -> *const c_void;
788    pub fn sc_screenshot_output_get_file_url(
789        output: *const c_void,
790        buffer: *mut i8,
791        buffer_size: isize,
792    ) -> bool;
793    pub fn sc_screenshot_output_release(output: *const c_void);
794
795    pub fn sc_screenshot_manager_capture_screenshot(
796        content_filter: *const c_void,
797        config: *const c_void,
798        callback: extern "C" fn(*const c_void, *const i8, *mut c_void),
799        user_data: *mut c_void,
800    );
801    pub fn sc_screenshot_manager_capture_screenshot_in_rect(
802        x: f64,
803        y: f64,
804        width: f64,
805        height: f64,
806        config: *const c_void,
807        callback: extern "C" fn(*const c_void, *const i8, *mut c_void),
808        user_data: *mut c_void,
809    );
810}
811
812// MARK: - SCStreamConfiguration additional properties
813extern "C" {
814    // macOS 15.0+ - showMouseClicks
815    pub fn sc_stream_configuration_set_shows_mouse_clicks(config: *const c_void, value: bool);
816    pub fn sc_stream_configuration_get_shows_mouse_clicks(config: *const c_void) -> bool;
817
818    // macOS 14.0+ - ignoreShadowsDisplay
819    pub fn sc_stream_configuration_set_ignores_shadows_display(config: *const c_void, value: bool);
820    pub fn sc_stream_configuration_get_ignores_shadows_display(config: *const c_void) -> bool;
821
822    // macOS 14.0+ - ignoreGlobalClipDisplay
823    pub fn sc_stream_configuration_set_ignore_global_clip_display(
824        config: *const c_void,
825        value: bool,
826    );
827    pub fn sc_stream_configuration_get_ignore_global_clip_display(config: *const c_void) -> bool;
828
829    // macOS 14.0+ - ignoreGlobalClipSingleWindow
830    pub fn sc_stream_configuration_set_ignore_global_clip_single_window(
831        config: *const c_void,
832        value: bool,
833    );
834    pub fn sc_stream_configuration_get_ignore_global_clip_single_window(
835        config: *const c_void,
836    ) -> bool;
837
838    // macOS 15.0+ - preset-based configuration
839    pub fn sc_stream_configuration_create_with_preset(preset: i32) -> *const c_void;
840}
841
842// MARK: - SCContentFilter additional properties
843extern "C" {
844    // macOS 14.0+ - style and pointPixelScale
845    pub fn sc_content_filter_get_style(filter: *const c_void) -> i32;
846    pub fn sc_content_filter_get_point_pixel_scale(filter: *const c_void) -> f32;
847    pub fn sc_content_filter_get_stream_type(filter: *const c_void) -> i32;
848
849    // macOS 14.2+ - includeMenuBar
850    pub fn sc_content_filter_set_include_menu_bar(filter: *const c_void, include: bool);
851    pub fn sc_content_filter_get_include_menu_bar(filter: *const c_void) -> bool;
852
853    // macOS 15.2+ - included content arrays
854    pub fn sc_content_filter_get_included_displays_count(filter: *const c_void) -> isize;
855    pub fn sc_content_filter_get_included_display_at(
856        filter: *const c_void,
857        index: isize,
858    ) -> *const c_void;
859    pub fn sc_content_filter_get_included_windows_count(filter: *const c_void) -> isize;
860    pub fn sc_content_filter_get_included_window_at(
861        filter: *const c_void,
862        index: isize,
863    ) -> *const c_void;
864    pub fn sc_content_filter_get_included_applications_count(filter: *const c_void) -> isize;
865    pub fn sc_content_filter_get_included_application_at(
866        filter: *const c_void,
867        index: isize,
868    ) -> *const c_void;
869}
870
871// MARK: - SCShareableContentInfo (macOS 14.0+)
872extern "C" {
873    pub fn sc_shareable_content_info_for_filter(filter: *const c_void) -> *const c_void;
874    pub fn sc_shareable_content_info_get_style(info: *const c_void) -> i32;
875    pub fn sc_shareable_content_info_get_point_pixel_scale(info: *const c_void) -> f32;
876    pub fn sc_shareable_content_info_get_content_rect(
877        info: *const c_void,
878        x: *mut f64,
879        y: *mut f64,
880        width: *mut f64,
881        height: *mut f64,
882    );
883    /// Get shareable content info rect (same as `sc_shareable_content_info_get_content_rect`)
884    pub fn sc_shareable_content_info_get_content_rect_packed(
885        info: *const c_void,
886        x: *mut f64,
887        y: *mut f64,
888        width: *mut f64,
889        height: *mut f64,
890    );
891    pub fn sc_shareable_content_info_retain(info: *const c_void) -> *const c_void;
892    pub fn sc_shareable_content_info_release(info: *const c_void);
893}
894
895// MARK: - SCRecordingOutput additional (macOS 15.0+)
896extern "C" {
897    pub fn sc_recording_output_configuration_set_output_file_type(
898        config: *const c_void,
899        file_type: i32,
900    );
901    pub fn sc_recording_output_configuration_get_output_file_type(config: *const c_void) -> i32;
902    pub fn sc_recording_output_configuration_get_video_codec(config: *const c_void) -> i32;
903    pub fn sc_recording_output_configuration_get_available_video_codecs_count(
904        config: *const c_void,
905    ) -> isize;
906    pub fn sc_recording_output_configuration_get_available_video_codec_at(
907        config: *const c_void,
908        index: isize,
909    ) -> i32;
910    pub fn sc_recording_output_configuration_get_available_output_file_types_count(
911        config: *const c_void,
912    ) -> isize;
913    pub fn sc_recording_output_configuration_get_available_output_file_type_at(
914        config: *const c_void,
915        index: isize,
916    ) -> i32;
917    pub fn sc_recording_output_create_with_delegate(
918        config: *const c_void,
919        started_callback: Option<extern "C" fn(*mut c_void)>,
920        failed_callback: Option<extern "C" fn(*mut c_void, i32, *const i8)>,
921        finished_callback: Option<extern "C" fn(*mut c_void)>,
922        context: *mut c_void,
923    ) -> *const c_void;
924    pub fn sc_recording_output_get_recorded_duration(
925        output: *const c_void,
926        value: *mut i64,
927        timescale: *mut i32,
928    );
929    pub fn sc_recording_output_get_recorded_file_size(output: *const c_void) -> i64;
930}
931
932// MARK: - Audio Input Devices (AVFoundation)
933extern "C" {
934    /// Get the count of available audio input devices
935    pub fn sc_audio_get_input_device_count() -> isize;
936
937    /// Get audio input device ID at index into buffer
938    pub fn sc_audio_get_input_device_id(index: isize, buffer: *mut i8, buffer_size: isize) -> bool;
939
940    /// Get audio input device name at index into buffer
941    pub fn sc_audio_get_input_device_name(
942        index: isize,
943        buffer: *mut i8,
944        buffer_size: isize,
945    ) -> bool;
946
947    /// Check if the device at index is the default audio input device
948    pub fn sc_audio_is_default_input_device(index: isize) -> bool;
949
950    /// Get the default audio input device ID into buffer
951    pub fn sc_audio_get_default_input_device_id(buffer: *mut i8, buffer_size: isize) -> bool;
952
953    /// Get the default audio input device name into buffer
954    pub fn sc_audio_get_default_input_device_name(buffer: *mut i8, buffer_size: isize) -> bool;
955}