screencapturekit/
dispatch_queue.rs

1//! Dispatch Queue wrapper for custom queue management
2//!
3//! This module provides a safe Rust wrapper around GCD (Grand Central Dispatch) queues
4//! that can be used with `ScreenCaptureKit` streams.
5
6use std::ffi::{c_void, CString};
7use std::fmt;
8
9/// Quality of Service levels for dispatch queues
10///
11/// These `QoS` levels help the system prioritize work appropriately.
12///
13/// # Examples
14///
15/// ```
16/// use screencapturekit::dispatch_queue::{DispatchQueue, DispatchQoS};
17///
18/// // High priority for UI-affecting work
19/// let queue = DispatchQueue::new("com.myapp.ui", DispatchQoS::UserInteractive);
20///
21/// // Lower priority for background tasks
22/// let bg_queue = DispatchQueue::new("com.myapp.background", DispatchQoS::Background);
23/// ```
24#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
25pub enum DispatchQoS {
26    /// Background `QoS` - for maintenance or cleanup tasks
27    Background = 0,
28    /// Utility `QoS` - for tasks that may take some time
29    Utility = 1,
30    /// Default `QoS` - standard priority
31    #[default]
32    Default = 2,
33    /// User Initiated `QoS` - for tasks initiated by the user
34    UserInitiated = 3,
35    /// User Interactive `QoS` - for tasks that affect the UI
36    UserInteractive = 4,
37}
38
39/// A wrapper around GCD `DispatchQueue`
40///
41/// This allows you to provide a custom dispatch queue for stream output handling
42/// instead of using the default queue.
43///
44/// # Example
45///
46/// ```no_run
47/// use screencapturekit::dispatch_queue::{DispatchQueue, DispatchQoS};
48///
49/// let queue = DispatchQueue::new("com.myapp.capture", DispatchQoS::UserInteractive);
50/// ```
51pub struct DispatchQueue {
52    ptr: *const c_void,
53}
54
55unsafe impl Send for DispatchQueue {}
56unsafe impl Sync for DispatchQueue {}
57
58impl DispatchQueue {
59    /// Creates a new dispatch queue with the specified label and `QoS`
60    ///
61    /// # Arguments
62    ///
63    /// * `label` - A string label for the queue (e.g., "com.myapp.capture")
64    /// * `qos` - The quality of service level for the queue
65    ///
66    /// # Examples
67    ///
68    /// ```
69    /// use screencapturekit::dispatch_queue::{DispatchQueue, DispatchQoS};
70    ///
71    /// let queue = DispatchQueue::new("com.myapp.capture", DispatchQoS::UserInteractive);
72    /// // Use the queue with SCStream's add_output_handler_with_queue
73    /// ```
74    ///
75    /// # Panics
76    ///
77    /// Panics if the label contains null bytes or if queue creation fails
78    pub fn new(label: &str, qos: DispatchQoS) -> Self {
79        let c_label = CString::new(label).expect("Label contains null byte");
80        let ptr = unsafe { crate::ffi::dispatch_queue_create(c_label.as_ptr(), qos as i32) };
81        assert!(!ptr.is_null(), "Failed to create dispatch queue");
82        Self { ptr }
83    }
84
85    /// Returns the raw pointer to the dispatch queue
86    ///
87    /// This is used internally for FFI calls (and for testing)
88    pub fn as_ptr(&self) -> *const c_void {
89        self.ptr
90    }
91}
92
93impl Drop for DispatchQueue {
94    fn drop(&mut self) {
95        unsafe {
96            crate::ffi::dispatch_queue_release(self.ptr);
97        }
98    }
99}
100
101impl fmt::Debug for DispatchQueue {
102    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
103        f.debug_struct("DispatchQueue")
104            .field("ptr", &self.ptr)
105            .finish()
106    }
107}
108
109impl fmt::Display for DispatchQueue {
110    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
111        write!(f, "DispatchQueue")
112    }
113}