WIP: Start pushing native surface to Scene
This is segfaulting for some reason, so that's the next step to figure out.
This commit is contained in:
parent
d30e360664
commit
71d9a880d6
3 changed files with 79 additions and 25 deletions
3
Cargo.lock
generated
3
Cargo.lock
generated
|
@ -761,10 +761,13 @@ dependencies = [
|
||||||
"core-foundation",
|
"core-foundation",
|
||||||
"core-graphics",
|
"core-graphics",
|
||||||
"foreign-types",
|
"foreign-types",
|
||||||
|
"futures",
|
||||||
"gpui",
|
"gpui",
|
||||||
"io_surface",
|
"io_surface",
|
||||||
"log",
|
"log",
|
||||||
"objc",
|
"objc",
|
||||||
|
"parking_lot 0.11.2",
|
||||||
|
"postage",
|
||||||
"simplelog",
|
"simplelog",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -17,8 +17,11 @@ cocoa = "0.24"
|
||||||
core-foundation = "0.9.3"
|
core-foundation = "0.9.3"
|
||||||
core-graphics = "0.22.3"
|
core-graphics = "0.22.3"
|
||||||
foreign-types = "0.3"
|
foreign-types = "0.3"
|
||||||
|
futures = "0.3"
|
||||||
log = { version = "0.4.16", features = ["kv_unstable_serde"] }
|
log = { version = "0.4.16", features = ["kv_unstable_serde"] }
|
||||||
objc = "0.2"
|
objc = "0.2"
|
||||||
|
parking_lot = "0.11.1"
|
||||||
|
postage = { version = "0.4.1", features = ["futures-traits"] }
|
||||||
simplelog = "0.9"
|
simplelog = "0.9"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
|
|
|
@ -8,8 +8,15 @@ use cocoa::{
|
||||||
};
|
};
|
||||||
use core_foundation::{base::TCFType, number::CFNumberRef, string::CFStringRef};
|
use core_foundation::{base::TCFType, number::CFNumberRef, string::CFStringRef};
|
||||||
use core_media::{CMSampleBuffer, CMSampleBufferRef};
|
use core_media::{CMSampleBuffer, CMSampleBufferRef};
|
||||||
use gpui::elements::Canvas;
|
use futures::StreamExt;
|
||||||
use gpui::{actions, elements::*, keymap::Binding, Menu, MenuItem};
|
use gpui::{
|
||||||
|
actions,
|
||||||
|
elements::{Canvas, *},
|
||||||
|
keymap::Binding,
|
||||||
|
platform::current::Surface,
|
||||||
|
Menu, MenuItem, ViewContext,
|
||||||
|
};
|
||||||
|
use io_surface::IOSurface;
|
||||||
use log::LevelFilter;
|
use log::LevelFilter;
|
||||||
use objc::{
|
use objc::{
|
||||||
class,
|
class,
|
||||||
|
@ -18,8 +25,9 @@ use objc::{
|
||||||
runtime::{Object, Sel},
|
runtime::{Object, Sel},
|
||||||
sel, sel_impl,
|
sel, sel_impl,
|
||||||
};
|
};
|
||||||
|
use parking_lot::Mutex;
|
||||||
use simplelog::SimpleLogger;
|
use simplelog::SimpleLogger;
|
||||||
use std::{ffi::c_void, slice, str};
|
use std::{cell::RefCell, ffi::c_void, slice, str};
|
||||||
|
|
||||||
#[allow(non_upper_case_globals)]
|
#[allow(non_upper_case_globals)]
|
||||||
const NSUTF8StringEncoding: NSUInteger = 4;
|
const NSUTF8StringEncoding: NSUInteger = 4;
|
||||||
|
@ -42,10 +50,29 @@ fn main() {
|
||||||
}],
|
}],
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
|
cx.add_window(Default::default(), |cx| ScreenCaptureView::new(cx));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ScreenCaptureView {
|
||||||
|
surface: Option<io_surface::IOSurface>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl gpui::Entity for ScreenCaptureView {
|
||||||
|
type Event = ();
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ScreenCaptureView {
|
||||||
|
pub fn new(cx: &mut ViewContext<Self>) -> Self {
|
||||||
|
let (surface_tx, mut surface_rx) = postage::watch::channel::<Option<IOSurface>>();
|
||||||
|
let surface_tx = RefCell::new(surface_tx);
|
||||||
unsafe {
|
unsafe {
|
||||||
let block = ConcreteBlock::new(move |content: id, error: id| {
|
let block = ConcreteBlock::new(move |content: id, error: id| {
|
||||||
if !error.is_null() {
|
if !error.is_null() {
|
||||||
println!("ERROR {}", string_from_objc(msg_send![error, localizedDescription]));
|
println!(
|
||||||
|
"ERROR {}",
|
||||||
|
string_from_objc(msg_send![error, localizedDescription])
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,11 +84,16 @@ fn main() {
|
||||||
|
|
||||||
let mut decl = ClassDecl::new("CaptureOutput", class!(NSObject)).unwrap();
|
let mut decl = ClassDecl::new("CaptureOutput", class!(NSObject)).unwrap();
|
||||||
decl.add_ivar::<*mut c_void>("callback");
|
decl.add_ivar::<*mut c_void>("callback");
|
||||||
decl.add_method(sel!(stream:didOutputSampleBuffer:ofType:), sample_output as extern "C" fn(&Object, Sel, id, id, SCStreamOutputType));
|
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 capture_output_class = decl.register();
|
||||||
|
|
||||||
let output: id = msg_send![capture_output_class, alloc];
|
let output: id = msg_send![capture_output_class, alloc];
|
||||||
let output: id = msg_send![output, init];
|
let output: id = msg_send![output, init];
|
||||||
|
|
||||||
|
// TODO: we could probably move this into a background queue.
|
||||||
let callback = Box::new(|buffer: CMSampleBufferRef| {
|
let callback = Box::new(|buffer: CMSampleBufferRef| {
|
||||||
let buffer = CMSampleBuffer::wrap_under_get_rule(buffer);
|
let buffer = CMSampleBuffer::wrap_under_get_rule(buffer);
|
||||||
let attachments = buffer.attachments();
|
let attachments = buffer.attachments();
|
||||||
|
@ -79,8 +111,11 @@ fn main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
let image_buffer = buffer.image_buffer();
|
let image_buffer = buffer.image_buffer();
|
||||||
dbg!(image_buffer.width(), image_buffer.height());
|
|
||||||
let io_surface = image_buffer.io_surface();
|
let io_surface = image_buffer.io_surface();
|
||||||
|
println!("before segfault");
|
||||||
|
*surface_tx.borrow_mut().borrow_mut() = Some(io_surface);
|
||||||
|
|
||||||
|
println!("!!!!!!!!!!!!!!!!!");
|
||||||
}) as Box<dyn FnMut(CMSampleBufferRef)>;
|
}) as Box<dyn FnMut(CMSampleBufferRef)>;
|
||||||
let callback = Box::into_raw(Box::new(callback));
|
let callback = Box::into_raw(Box::new(callback));
|
||||||
(*output).set_ivar("callback", callback as *mut c_void);
|
(*output).set_ivar("callback", callback as *mut c_void);
|
||||||
|
@ -109,7 +144,10 @@ fn main() {
|
||||||
|
|
||||||
let start_capture_completion = ConcreteBlock::new(move |error: id| {
|
let start_capture_completion = ConcreteBlock::new(move |error: id| {
|
||||||
if !error.is_null() {
|
if !error.is_null() {
|
||||||
println!("error starting capture... error? {}", string_from_objc(msg_send![error, localizedDescription]));
|
println!(
|
||||||
|
"error starting capture... error? {}",
|
||||||
|
string_from_objc(msg_send![error, localizedDescription])
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,8 +155,10 @@ fn main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
assert!(!stream.is_null());
|
assert!(!stream.is_null());
|
||||||
let _: () = msg_send![stream, startCaptureWithCompletionHandler: start_capture_completion];
|
let _: () = msg_send![
|
||||||
|
stream,
|
||||||
|
startCaptureWithCompletionHandler: start_capture_completion
|
||||||
|
];
|
||||||
});
|
});
|
||||||
|
|
||||||
let _: id = msg_send![
|
let _: id = msg_send![
|
||||||
|
@ -127,31 +167,39 @@ fn main() {
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
// cx.add_window(Default::default(), |_| ScreenCaptureView);
|
cx.spawn_weak(|this, mut cx| async move {
|
||||||
});
|
while let Some(surface) = surface_rx.next().await {
|
||||||
}
|
if let Some(this) = this.upgrade(&cx) {
|
||||||
|
this.update(&mut cx, |this, cx| {
|
||||||
|
this.surface = surface;
|
||||||
|
cx.notify();
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.detach();
|
||||||
|
|
||||||
struct ScreenCaptureView {
|
Self { surface: None }
|
||||||
surface: io_surface::IOSurface,
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl gpui::Entity for ScreenCaptureView {
|
|
||||||
type Event = ();
|
|
||||||
}
|
|
||||||
|
|
||||||
// impl ScreenCaptureView {
|
|
||||||
// pub fn new() -> Self {}
|
|
||||||
// }
|
|
||||||
|
|
||||||
impl gpui::View for ScreenCaptureView {
|
impl gpui::View for ScreenCaptureView {
|
||||||
fn ui_name() -> &'static str {
|
fn ui_name() -> &'static str {
|
||||||
"View"
|
"View"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(&mut self, _: &mut gpui::RenderContext<Self>) -> gpui::ElementBox {
|
fn render(&mut self, _: &mut gpui::RenderContext<Self>) -> gpui::ElementBox {
|
||||||
Canvas::new(|bounds, _, cx| {
|
let surface = self.surface.clone();
|
||||||
|
Canvas::new(move |bounds, _, cx| {
|
||||||
// cx.scene.push_surface(surface)
|
if let Some(native_surface) = surface.clone() {
|
||||||
|
dbg!("!!!!");
|
||||||
|
cx.scene.push_surface(Surface {
|
||||||
|
bounds,
|
||||||
|
native_surface,
|
||||||
|
});
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.boxed()
|
.boxed()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue