freya_camera/
use_camera.rs1use freya_core::{
4 elements::image::ImageHandle,
5 prelude::*,
6};
7use freya_engine::prelude::AlphaType;
8
9use crate::{
10 camera::{
11 CameraConfig,
12 CameraError,
13 StreamInfo,
14 },
15 capture::{
16 CameraFrame,
17 CaptureHandle,
18 CaptureState,
19 spawn_capture,
20 },
21};
22
23#[derive(Clone, Copy, PartialEq)]
25pub struct Camera {
26 pub frame: State<Option<ImageHandle>>,
28 pub info: State<Option<StreamInfo>>,
30 pub error: State<Option<CameraError>>,
32}
33
34impl Camera {
35 pub fn create(config: CameraConfig) -> Self {
37 let mut frame: State<Option<ImageHandle>> = State::create(None);
38 let mut info: State<Option<StreamInfo>> = State::create(None);
39 let mut error: State<Option<CameraError>> = State::create(None);
40
41 let CaptureHandle { state, wake } = spawn_capture(config);
42
43 spawn(async move {
44 loop {
45 wake.notified().await;
46
47 let CaptureState {
48 frame: latest_frame,
49 info: latest_info,
50 error: latest_error,
51 } = std::mem::take(&mut *state.lock().unwrap());
52
53 if let Some(stream_info) = latest_info {
54 *info.write() = Some(stream_info);
55 }
56 if let Some(capture_error) = latest_error {
57 tracing::warn!("freya-camera: {capture_error}");
58 *error.write() = Some(capture_error);
59 }
60 if let Some(camera_frame) = latest_frame {
61 match build_handle(camera_frame) {
62 Ok(handle) => *frame.write() = Some(handle),
63 Err(build_error) => {
64 tracing::warn!("freya-camera: {build_error}");
65 *error.write() = Some(build_error);
66 }
67 }
68 }
69 }
70 });
71
72 Self { frame, info, error }
73 }
74}
75
76pub fn use_camera(init: impl FnOnce() -> CameraConfig) -> Camera {
93 use_hook(|| Camera::create(init()))
94}
95
96fn build_handle(frame: CameraFrame) -> Result<ImageHandle, CameraError> {
98 let CameraFrame {
99 width,
100 height,
101 data,
102 } = frame;
103
104 ImageHandle::from_rgba(width, height, data, AlphaType::Opaque)
105 .ok_or_else(|| CameraError::GeneralError("failed to create raster image".to_string()))
106}