-
Notifications
You must be signed in to change notification settings - Fork 27
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into use_core_foundation_types
* main: v0.2.6 Update rust.yml chore: fix warnings fix error handling (#37) cargo fmt (#38) docs: add krzykro2 as a contributor for code (#36) make safe StreamConfiguration defaults equal to unsafe (#35) Revert "test ci" test ci
- Loading branch information
Showing
17 changed files
with
542 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
pub trait AsPtr { | ||
fn as_ptr(&self) -> *const Self { | ||
self as *const Self | ||
} | ||
} | ||
pub trait AsMutPtr { | ||
fn as_mut_ptr(&self) -> *mut Self { | ||
self as *const _ as *mut Self | ||
} | ||
} | ||
|
||
impl<T> AsPtr for T {} | ||
impl<T> AsMutPtr for T {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
pub mod as_ptr; | ||
pub mod audio_buffer; | ||
pub mod cm_block_buffer_ref; | ||
pub mod cm_format_description_ref; | ||
pub mod cm_sample_buffer_ref; | ||
pub mod content_filter; | ||
pub mod cv_image_buffer_ref; | ||
pub mod cv_pixel_buffer_ref; | ||
pub mod macros; | ||
pub mod os_types; | ||
pub mod sc_stream_frame_info; | ||
pub mod shareable_content; | ||
pub mod stream; | ||
pub mod stream_configuration; | ||
pub mod stream_error_handler; | ||
pub mod stream_output_handler; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
pub mod base; | ||
pub mod four_char_code; | ||
pub mod geometry; | ||
pub mod graphics; | ||
pub mod rc; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
use std::{ | ||
ascii, | ||
fmt::{self}, | ||
}; | ||
|
||
#[repr(transparent)] | ||
#[derive(Copy, Clone, Default, Ord, PartialOrd, Eq, PartialEq, Hash)] | ||
pub struct FourCharCode(u32); | ||
|
||
impl fmt::Display for FourCharCode { | ||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
f.write_str(&self.format()) | ||
} | ||
} | ||
|
||
impl fmt::Debug for FourCharCode { | ||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
write!(f, "\"")?; | ||
f.write_str(&self.format())?; | ||
write!(f, "\"") | ||
} | ||
} | ||
|
||
impl FourCharCode { | ||
#[inline] | ||
fn format(&self) -> String { | ||
// Format as escaped ASCII string. | ||
|
||
let raw = self | ||
.into_chars() | ||
.into_iter() | ||
.flat_map(ascii::escape_default) | ||
.collect::<Vec<u8>>(); | ||
|
||
String::from_utf8(raw).unwrap() | ||
} | ||
/// Returns an instance from the integer value. | ||
#[inline] | ||
pub const fn from_int(int: u32) -> Self { | ||
Self(int) | ||
} | ||
|
||
/// Returns an instance from the 4-character code. | ||
#[inline] | ||
pub const fn from_chars(chars: [u8; 4]) -> Self { | ||
Self(u32::from_be_bytes(chars)) | ||
} | ||
|
||
/// Returns this descriptor's integer value. | ||
#[inline] | ||
pub const fn into_int(self) -> u32 { | ||
self.0 | ||
} | ||
|
||
/// Returns this descriptor's 4-character code. | ||
#[inline] | ||
pub const fn into_chars(self) -> [u8; 4] { | ||
self.0.to_be_bytes() | ||
} | ||
|
||
/// Returns `true` if all of the characters in `self` are ASCII. | ||
#[inline] | ||
pub const fn is_ascii(&self) -> bool { | ||
const NON_ASCII: u32 = u32::from_be_bytes([128; 4]); | ||
|
||
self.0 & NON_ASCII == 0 | ||
} | ||
|
||
/// Returns `true` if all of the characters in `self` are ASCII graphic | ||
/// characters: U+0021 '!' ..= U+007E '~'. | ||
#[inline] | ||
pub const fn is_ascii_graphic(&self) -> bool { | ||
matches!( | ||
self.into_chars(), | ||
[b'!'..=b'~', b'!'..=b'~', b'!'..=b'~', b'!'..=b'~'], | ||
) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
use std::sync::Once; | ||
|
||
use objc::{ | ||
class, | ||
declare::ClassDecl, | ||
runtime::{Class, Object, Sel}, | ||
Message, *, | ||
}; | ||
use objc_foundation::INSObject; | ||
use objc_id::Id; | ||
|
||
pub trait UnsafeSCStreamError: Send + Sync + 'static { | ||
fn handle_error(&self); | ||
} | ||
|
||
#[repr(C)] | ||
pub(crate) struct UnsafeSCStreamErrorHandler {} | ||
|
||
unsafe impl Message for UnsafeSCStreamErrorHandler {} | ||
|
||
use once_cell::sync::Lazy; | ||
use std::collections::HashMap; | ||
use std::sync::RwLock; | ||
static ERROR_HANDLERS: Lazy<RwLock<HashMap<usize, Box<dyn UnsafeSCStreamError + Send + Sync>>>> = | ||
Lazy::new(|| RwLock::new(HashMap::new())); | ||
|
||
impl INSObject for UnsafeSCStreamErrorHandler { | ||
fn class() -> &'static Class { | ||
static REGISTER_UNSAFE_SC_ERROR_HANDLER: Once = Once::new(); | ||
REGISTER_UNSAFE_SC_ERROR_HANDLER.call_once(|| { | ||
let mut decl = ClassDecl::new("SCStreamErrorHandler", class!(NSObject)).unwrap(); | ||
decl.add_ivar::<usize>("_hash"); | ||
|
||
extern "C" fn stream_error( | ||
this: &mut Object, | ||
_cmd: Sel, | ||
_stream: *mut Object, | ||
_error: *mut Object, | ||
) { | ||
unsafe { | ||
let hash = this.get_ivar::<usize>("_hash"); | ||
let lookup = ERROR_HANDLERS.read().unwrap(); | ||
let error_handler = lookup.get(hash).unwrap(); | ||
error_handler.handle_error(); | ||
}; | ||
} | ||
unsafe { | ||
let stream_error_method: extern "C" fn(&mut Object, Sel, *mut Object, *mut Object) = | ||
stream_error; | ||
|
||
decl.add_method(sel!(stream:didStopWithError:), stream_error_method); | ||
} | ||
|
||
decl.register(); | ||
}); | ||
class!(SCStreamErrorHandler) | ||
} | ||
} | ||
|
||
impl UnsafeSCStreamErrorHandler { | ||
fn store_error_handler(&mut self, error_handler: impl UnsafeSCStreamError) { | ||
unsafe { | ||
let obj = &mut *(self as *mut _ as *mut Object); | ||
let hash = self.hash_code(); | ||
ERROR_HANDLERS | ||
.write() | ||
.unwrap() | ||
.insert(hash, Box::new(error_handler)); | ||
obj.set_ivar("_hash", hash); | ||
} | ||
} | ||
// Error handlers passed into here will currently live forever inside the statically | ||
// allocated map. | ||
// TODO: Remove the handler from the HashMap whenever the associated stream is dropped. | ||
pub fn init(error_handler: impl UnsafeSCStreamError) -> Id<Self> { | ||
let mut handle = Self::new(); | ||
handle.store_error_handler(error_handler); | ||
handle | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use std::ptr; | ||
use std::sync::mpsc::{sync_channel, SyncSender}; | ||
|
||
use super::*; | ||
|
||
struct TestHandler { | ||
error_tx: SyncSender<()>, | ||
} | ||
impl UnsafeSCStreamError for TestHandler { | ||
fn handle_error(&self) { | ||
eprintln!("ERROR!"); | ||
if let Err(e) = self.error_tx.send(()) { | ||
panic!("can't send error message back on the channel: {:?}", e); | ||
} | ||
} | ||
} | ||
|
||
#[test] | ||
fn test_sc_stream_error_handler() { | ||
let (error_tx, error_rx) = sync_channel(1); | ||
let handle = UnsafeSCStreamErrorHandler::init(TestHandler { error_tx }); | ||
unsafe { | ||
msg_send![handle, stream: ptr::null_mut::<Object>() didStopWithError: ptr::null_mut::<Object>()] | ||
} | ||
if let Err(e) = error_rx.recv_timeout(std::time::Duration::from_millis(250)) { | ||
panic!("failed to hear back from the error channel: {:?}", e); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
[package] | ||
name = "screencapturekit" | ||
description = "Safe wrapper for Apple's ScreenCaptureKit" | ||
categories = [ | ||
"api-bindings", | ||
"multimedia", | ||
"multimedia::video", | ||
"os::macos-apis", | ||
] | ||
readme = "README.md" | ||
repository = "https://github.com/svtlabs/screencapturekit-rs/tree/main/screencapturekit" | ||
|
||
edition.workspace = true | ||
version.workspace = true | ||
authors.workspace = true | ||
license.workspace = true | ||
keywords.workspace = true | ||
homepage.workspace = true | ||
rust-version.workspace = true | ||
|
||
[features] | ||
ci = [] | ||
|
||
[lib] | ||
path = "./src/lib.rs" | ||
|
||
[dependencies] | ||
screencapturekit-sys = { version = "0.2.6", path = "../screencapturekit-sys" } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
use screencapturekit_sys::stream_error_handler::UnsafeSCStreamError; | ||
|
||
// TODO: It might make sense to be a little more precise with lifetimes, than 'static. | ||
// The lifetime could be potentially only as long as the relevant Stream, if the | ||
// handler was dropped correctly together with the stream. For now the handler is never | ||
// dropped and lives forever inside a statically allocated HashMap. See the relevant | ||
// code in screencapturekit-sys crate. | ||
pub trait StreamErrorHandler: Send + Sync + 'static { | ||
fn on_error(&self); | ||
} | ||
|
||
pub(crate) struct StreamErrorHandlerWrapper<T: StreamErrorHandler>(T); | ||
|
||
impl<T: StreamErrorHandler> StreamErrorHandlerWrapper<T> { | ||
pub fn new(error_handler: T) -> Self { | ||
StreamErrorHandlerWrapper(error_handler) | ||
} | ||
} | ||
|
||
impl<T: StreamErrorHandler> UnsafeSCStreamError for StreamErrorHandlerWrapper<T> { | ||
fn handle_error(&self) { | ||
self.0.on_error(); | ||
} | ||
} |
Oops, something went wrong.