@@ -1,18 +1,22 @@
mod bindings;
-use std::{slice, str, ptr::{self}};
-
+use crate::bindings::{dispatch_queue_create, NSObject, SCStreamOutputType};
use block::ConcreteBlock;
use cocoa::{
- base::{id, nil},
- foundation::{NSArray, NSString, NSUInteger, NSInteger},
+ base::{id, nil, YES},
+ foundation::{NSArray, NSBundle, NSString, NSUInteger},
};
use gpui::{actions, elements::*, keymap::Binding, Menu, MenuItem};
use log::LevelFilter;
-use objc::{class, msg_send, sel, sel_impl, declare::ClassDecl, runtime::{Protocol, Object, Sel}};
+use objc::{
+ class,
+ declare::ClassDecl,
+ msg_send,
+ runtime::{Object, Protocol, Sel},
+ sel, sel_impl,
+};
use simplelog::SimpleLogger;
-
-use crate::bindings::{dispatch_get_main_queue, dispatch_queue_create, NSObject, CMSampleBufferRef};
+use std::{ptr, slice, str};
#[allow(non_upper_case_globals)]
const NSUTF8StringEncoding: NSUInteger = 4;
@@ -41,72 +45,51 @@ fn main() {
println!("ERROR {}", string_from_objc(msg_send![error, localizedDescription]));
return;
}
-
+
+ let applications: id = msg_send![content, applications];
let displays: id = msg_send![content, displays];
-
- if let Some(display) = (0..displays.count())
- .map(|ix| displays.objectAtIndex(ix))
- .next()
- {
-
- let display_id: u32 = msg_send![display, displayID];
- println!("display id {:?}", display_id);
-
- // let mut decl = ClassDecl::new("CaptureOutput", class!(NSObject)).unwrap();
- // decl.add_protocol(Protocol::get("SCStreamOutput").unwrap());
- // decl.add_protocol(Protocol::get("SCStreamDelegate").unwrap());
- // decl.add_method(sel!(stream:didOutputSampleBuffer:ofType:), sample_output as extern "C" fn(&Object, Sel, id, id, NSInteger));
- // decl.add_method(sel!(stream:didStopWithError:), did_stop_with_error as extern "C" fn(&Object, Sel, id, id));
- // let capture_output_class = decl.register();
-
- // let output: id = msg_send![capture_output_class, alloc];
- // let output: id = msg_send![output, init];
-
- let output: id = msg_send![class!(MyClass), alloc];
- let output: id = msg_send![output, init];
-
- // Do we conform to the protocol?
- let conforms: bool = msg_send![output, conformsToProtocol: Protocol::get("SCStreamOutput").unwrap()];
- dbg!(conforms);
- assert!(conforms, "expect CaptureOutput instance to conform to SCStreamOutput protocol");
-
- // Confirm we can send the protocol message to the object
- let _: () = msg_send![output, stream:NSObject(ptr::null_mut()) didOutputSampleBuffer:NSObject(ptr::null_mut()) ofType:0];
-
- let excluded_windows: id = msg_send![class!(NSArray), array];
- let filter: id = msg_send![class!(SCContentFilter), alloc];
- let filter: id = msg_send![filter, initWithDisplay: display excludingWindows: excluded_windows];
- let config: id = msg_send![class!(SCStreamConfiguration), alloc];
- let config: id = msg_send![config, init];
- // Configure the display content width and height.
- let _: () = msg_send![config, setWidth: 800];
- let _: () = msg_send![config, setHeight: 600];
- let _: () = msg_send![config, setMinimumFrameInterval: bindings::CMTimeMake(1, 60)];
- let _: () = msg_send![config, setQueueDepth: 5];
-
- let stream: id = msg_send![class!(SCStream), alloc];
- let stream: id = msg_send![stream, initWithFilter: filter configuration: config delegate: output];
- let error: id = nil;
- let queue = dispatch_queue_create(ptr::null(), NSObject(ptr::null_mut()));
-
- let _: () = msg_send![stream,
- addStreamOutput: output type: bindings::SCStreamOutputType_SCStreamOutputTypeScreen
- sampleHandlerQueue: queue
- error: &error
- ];
-
- let start_capture_completion = ConcreteBlock::new(move |error: id| {
- if !error.is_null() {
- println!("error starting capture... error? {}", string_from_objc(msg_send![error, localizedDescription]));
- return;
- }
-
- println!("starting capture");
- });
-
- assert!(!stream.is_null());
- let _: () = msg_send![stream, startCaptureWithCompletionHandler: start_capture_completion];
- }
+ let display: id = displays.objectAtIndex(0);
+
+ let mut decl = ClassDecl::new("CaptureOutput", class!(NSObject)).unwrap();
+ decl.add_protocol(Protocol::get("SCStreamOutput").unwrap());
+ decl.add_method(sel!(stream:didOutputSampleBuffer:ofType:), sample_output as extern "C" fn(&Object, Sel, id, id, SCStreamOutputType));
+ let capture_output_class = decl.register();
+
+ let output: id = msg_send![capture_output_class, alloc];
+ let output: id = msg_send![output, init];
+
+ let filter: id = msg_send![class!(SCContentFilter), alloc];
+ let filter: id = msg_send![filter, initWithDisplay: display includingApplications: applications exceptingWindows: nil];
+ // let filter: id = msg_send![filter, initWithDesktopIndependentWindow: window];
+ let config: id = msg_send![class!(SCStreamConfiguration), alloc];
+ let config: id = msg_send![config, init];
+ let _: () = msg_send![config, setMinimumFrameInterval: bindings::CMTimeMake(1, 60)];
+ let _: () = msg_send![config, setQueueDepth: 6];
+ let _: () = msg_send![config, setShowsCursor: YES];
+
+ let stream: id = msg_send![class!(SCStream), alloc];
+ let stream: id = msg_send![stream, initWithFilter: filter configuration: config delegate: output];
+ let error: id = nil;
+ let queue = dispatch_queue_create(ptr::null(), NSObject(ptr::null_mut()));
+
+ let _: () = msg_send![stream,
+ addStreamOutput: output type: bindings::SCStreamOutputType_SCStreamOutputTypeScreen
+ sampleHandlerQueue: queue
+ error: &error
+ ];
+
+ let start_capture_completion = ConcreteBlock::new(move |error: id| {
+ if !error.is_null() {
+ println!("error starting capture... error? {}", string_from_objc(msg_send![error, localizedDescription]));
+ return;
+ }
+
+ println!("starting capture");
+ });
+
+ assert!(!stream.is_null());
+ let _: () = msg_send![stream, startCaptureWithCompletionHandler: start_capture_completion];
+
});
let _: id = msg_send![
@@ -136,18 +119,24 @@ impl gpui::View for ScreenCaptureView {
}
pub unsafe fn string_from_objc(string: id) -> String {
- let len = msg_send![string, lengthOfBytesUsingEncoding: NSUTF8StringEncoding];
- let bytes = string.UTF8String() as *const u8;
- str::from_utf8(slice::from_raw_parts(bytes, len))
- .unwrap()
- .to_string()
-}
-
-extern "C" fn did_stop_with_error(this: &Object, _: Sel, stream: id, error: id) {
- println!("did_stop_with_error");
+ if string.is_null() {
+ Default::default()
+ } else {
+ let len = msg_send![string, lengthOfBytesUsingEncoding: NSUTF8StringEncoding];
+ let bytes = string.UTF8String() as *const u8;
+ str::from_utf8(slice::from_raw_parts(bytes, len))
+ .unwrap()
+ .to_string()
+ }
}
-extern "C" fn sample_output(this: &Object, _: Sel, stream: id, buffer: id, kind: NSInteger) {
+extern "C" fn sample_output(
+ _: &Object,
+ _: Sel,
+ _stream: id,
+ _buffer: id,
+ _kind: SCStreamOutputType,
+) {
println!("sample output");
}