Skip to content

Commit

Permalink
feat(SCStreamDelegate): add missing delegate methods
Browse files Browse the repository at this point in the history
  • Loading branch information
1313 committed Oct 24, 2024
1 parent 6fe026a commit 6fb76a5
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 17 deletions.
17 changes: 11 additions & 6 deletions src/stream/internal/sc_stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ use crate::{
utils::{
block::{new_void_completion_handler, CompletionHandler},
error::create_sc_error,
objc::get_concrete_from_void,
},
};
use core_foundation::error::CFError;
Expand Down Expand Up @@ -52,8 +51,8 @@ impl SCStream {
unsafe {
let delegate = delegate.map_or(ptr::null_mut(), stream_delegate::get_handler);
let inner: *mut Object = msg_send![class!(SCStream), alloc];
let inner: *mut Object = msg_send![inner, initWithFilter: filter.clone().as_CFTypeRef() configuration: configuration.clone().as_CFTypeRef() delegate: delegate];
get_concrete_from_void(inner.cast())
let inner: SCStreamRef = msg_send![inner, initWithFilter: filter.clone().as_CFTypeRef() configuration: configuration.clone().as_CFTypeRef() delegate: delegate];
Self::wrap_under_create_rule(inner)
}
}

Expand Down Expand Up @@ -135,6 +134,7 @@ mod test {
shareable_content::sc_shareable_content::SCShareableContent,
stream::{
sc_content_filter::SCContentFilter, sc_stream_configuration::SCStreamConfiguration,
sc_stream_delegate_trait::SCStreamDelegateTrait,
sc_stream_output_trait::SCStreamOutputTrait, sc_stream_output_type::SCStreamOutputType,
},
};
Expand All @@ -156,17 +156,22 @@ mod test {
println!("Output type 2: {of_type:?}");
}
}
impl SCStreamDelegateTrait for OutputHandler<'_> {}

#[test]
fn create() -> Result<(), CFError> {
let output = "Audio";
let config = SCStreamConfiguration::new()
.set_captures_audio(true)?
.set_width(100)?
.set_height(100)?;
let display = SCShareableContent::get()?.displays().remove(0);
let filter = SCContentFilter::new().with_display_excluding_windows(&display, &[]);
let mut stream = SCStream::internal_init_with_filter(&filter, &config);

let output = "Audio";
let mut stream = SCStream::internal_init_with_filter_and_delegate(
&filter,
&config,
Some(OutputHandler { output }),
);

stream.internal_add_output_handler(OutputHandler { output }, SCStreamOutputType::Audio);

Expand Down
62 changes: 51 additions & 11 deletions src/stream/internal/stream_delegate.rs
Original file line number Diff line number Diff line change
@@ -1,33 +1,73 @@
use std::{ffi::c_void, sync::Once};

use core_foundation::error::CFError;
use objc::{
class,
declare::ClassDecl,
runtime::{self, Object, Sel},
sel, sel_impl,
};

use crate::{declare_trait_wrapper, stream::sc_stream_delegate_trait::SCStreamDelegateTrait};
use crate::{
declare_trait_wrapper, stream::sc_stream_delegate_trait::SCStreamDelegateTrait,
utils::objc::get_concrete_from_void,
};

use super::sc_stream::SCStream;

declare_trait_wrapper!(StreamDelegateTraitWrapper, SCStreamDelegateTrait);

type DidStopWithErrorMethod = extern "C" fn(&Object, Sel, *const c_void, *const c_void);
const extern "C" fn did_stop_with_error(
_this: &Object,
extern "C" fn did_stop_with_error(
this: &Object,
_cmd: Sel,
stream_ref: *const c_void,
error: *const c_void,
) {
let handler = unsafe { this.get_ivar::<StreamDelegateTraitWrapper>("stream_delegate_wrapper") };
let stream = unsafe { get_concrete_from_void::<SCStream>(stream_ref) };
let error: CFError = unsafe { get_concrete_from_void(error) };
handler.did_stop_with_error(stream, error);
}

type OutputVideoEffectDidStartForStreamMethod = extern "C" fn(&Object, Sel, *const c_void);
extern "C" fn output_video_effect_did_start_for_stream(
this: &Object,
_cmd: Sel,
stream_ref: *const c_void,
) {
let handler = unsafe { this.get_ivar::<StreamDelegateTraitWrapper>("stream_delegate_wrapper") };
let stream = unsafe { get_concrete_from_void::<SCStream>(stream_ref) };
handler.output_video_effect_did_start_for_stream(stream);
}
type OutputVideoEffectDidStopForStreamMethod = extern "C" fn(&Object, Sel, *const c_void);
extern "C" fn output_video_effect_did_stop_for_stream(
this: &Object,
_cmd: Sel,
_stream_ref: *const c_void,
_error: *const c_void,
stream_ref: *const c_void,
) {
todo!();
let handler = unsafe { this.get_ivar::<StreamDelegateTraitWrapper>("stream_delegate_wrapper") };
let stream = unsafe { get_concrete_from_void::<SCStream>(stream_ref) };
handler.output_video_effect_did_stop_for_stream(stream);
}

fn register() {
let mut decl =
ClassDecl::new("StreamDelegate", class!(NSObject)).expect("Could not register class");
unsafe {
let output_handler: DidStopWithErrorMethod = did_stop_with_error;
decl.add_ivar::<StreamDelegateTraitWrapper>("stream_delegate_wrapper");
decl.add_method(sel!(stream:didOutputSampleBuffer:ofType:), output_handler);
decl.add_method(
sel!(stream:didStopWithError:),
did_stop_with_error as DidStopWithErrorMethod,
);
decl.add_method(
sel!(outputVideoEffectDidStartForStream:),
output_video_effect_did_start_for_stream as OutputVideoEffectDidStartForStreamMethod,
);
decl.add_method(
sel!(outputVideoEffectDidStopForStream:),
output_video_effect_did_stop_for_stream as OutputVideoEffectDidStopForStreamMethod,
);
decl.register();
}
}
Expand All @@ -37,9 +77,9 @@ pub fn get_handler<'a>(handler: impl SCStreamDelegateTrait + 'a) -> *mut Object
REGISTER_ONCE.call_once(register);

unsafe {
let sc_handler = runtime::class_createInstance(class!(StreamOutput), 0);
let error_delegate = runtime::class_createInstance(class!(StreamDelegate), 0);
let wrapper = StreamDelegateTraitWrapper::new(handler);
(*sc_handler).set_ivar("stream_delegate_wrapper", wrapper);
sc_handler
(*error_delegate).set_ivar("stream_delegate_wrapper", wrapper);
error_delegate
}
}

0 comments on commit 6fb76a5

Please sign in to comment.