use super::*;
use std::ffi::CStr;
use std::os::raw::{c_char, c_int, c_void};
use day_spec::NodeId;
use day_toolkit_uikit::Uikit;
use objc2::rc::Retained;
use objc2_ui_kit::UIView;
type ReportFn = unsafe extern "C" fn(node: u64, num: f64, text: *const c_char);
unsafe extern "C" {
fn day_camera_new(node: u64, facing: c_int, active: bool, report: ReportFn) -> *mut c_void;
fn day_camera_command(view: *mut c_void, cmd: c_int, arg: c_int);
fn day_camera_release(view: *mut c_void);
}
const CMD_START: c_int = 0;
const CMD_STOP: c_int = 1;
const CMD_CAPTURE: c_int = 2;
const CMD_FACING: c_int = 3;
unsafe extern "C" fn report(node: u64, num: f64, text: *const c_char) {
day_spec::ffi_guard::contain((), || {
let text = if text.is_null() {
String::new()
} else {
unsafe { CStr::from_ptr(text) }.to_string_lossy().into_owned()
};
day_toolkit_uikit::emit(
NodeId(node),
Event::Custom {
tag: "",
num,
text,
},
);
});
}
fn make(_backend: &mut Uikit, p: &CameraProps, id: NodeId) -> Retained<UIView> {
let ptr = unsafe { day_camera_new(id.0, p.facing.code(), p.active, report) };
unsafe { Retained::from_raw(ptr.cast::<UIView>()) }.expect("DayCameraView")
}
fn update(_backend: &mut Uikit, h: &Retained<UIView>, patch: &CameraPatch) {
let ptr = (&**h as *const UIView) as *mut c_void;
let (cmd, arg) = match patch {
CameraPatch::Start => (CMD_START, 0),
CameraPatch::Stop => (CMD_STOP, 0),
CameraPatch::Capture => (CMD_CAPTURE, 0),
CameraPatch::Facing(f) => (CMD_FACING, f.code()),
CameraPatch::Surface(_) => return,
};
unsafe { day_camera_command(ptr, cmd, arg) };
}
fn release(_backend: &mut Uikit, h: &Retained<UIView>) {
let ptr = (&**h as *const UIView) as *mut c_void;
unsafe { day_camera_release(ptr) };
}
day_pieces::renderer!(day_toolkit_uikit::RENDERERS, Uikit,
kind: KIND, props: CameraProps, patch: CameraPatch, make: make, update: update,
measure: day_pieces::fill_measure, release: release);