1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
//! Dioxus integration for the [`chimeras`] camera library.
//!
//! This crate owns only the Dioxus-specific glue, the HTTP preview server,
//! the [`Registry`] backing it, the `<canvas>`-side WebGL2 renderer, and the
//! hooks consumers plug into their components. Every other primitive
//! (single-frame capture, pause/resume pump, source abstraction) lives
//! upstream in [`chimeras`] itself so non-Dioxus callers can use it too.
//!
//! # What's here
//!
//! - [`PreviewServer`] + [`start_preview_server`] + [`register_with`], a
//! loopback HTTP server that publishes the latest [`Frame`](chimeras::Frame)
//! for each stream id over `/preview/{id}.bin`. The listener thread is torn
//! down when the last [`PreviewServer`] clone drops.
//! - [`Registry`] + [`LatestFrame`], shared map of stream id → latest frame.
//! The server reads from it; pumps publish to it. Cleaned up automatically
//! when the owning component unmounts.
//! - [`use_camera_stream`], high-level hook returning [`UseCameraStream`]:
//! a status signal, an active/paused toggle, and a single-frame `capture_frame`
//! callback. Wraps [`chimeras::pump`] under the hood.
//! - [`use_devices`] / [`use_streams`], hooks for the camera list and
//! multi-stream id management.
//! - [`PreviewScript`] + [`StreamPreview`], components that render live
//! frames into a `<canvas>` via WebGL2 (NV12, BGRA, or RGBA shaders).
//!
//! # Wiring a Dioxus app
//!
//! ```no_run
//! use chimeras::{CameraSource, PixelFormat, Resolution, StreamConfig};
//! use dioxus::prelude::*;
//! use dioxus_chimeras::{PreviewScript, StreamPreview, register_with, start_preview_server, use_camera_stream};
//!
//! fn main() {
//! let server = start_preview_server().expect("preview server");
//! register_with(&server, dioxus::LaunchBuilder::desktop()).launch(app);
//! }
//!
//! fn app() -> Element {
//! let source = use_signal::<Option<CameraSource>>(|| None);
//! let config = StreamConfig {
//! resolution: Resolution { width: 1280, height: 720 },
//! framerate: 30,
//! pixel_format: PixelFormat::Bgra8,
//! };
//! let stream = use_camera_stream(0, source, config);
//! rsx! {
//! StreamPreview { id: 0 }
//! p { "{stream.status}" }
//! button {
//! onclick: move |_| stream.active.clone().set(!*stream.active.read()),
//! "Toggle preview"
//! }
//! button {
//! onclick: move |_| { let _ = stream.capture_frame.call(()); },
//! "Take picture"
//! }
//! PreviewScript {}
//! }
//! }
//! ```
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
/// The JavaScript blob that drives the WebGL2 preview renderer.
///
/// Usually you want the [`PreviewScript`] component instead, it injects this
/// blob into a `<script>` tag with the right attributes. This raw constant is
/// exposed for users rendering outside a Dioxus component (for example, in a
/// custom server-rendered template).
///
/// The script scans the DOM for `canvas[data-stream-id]` elements and binds
/// each one to the URL in its `data-preview-url` attribute. The
/// [`StreamPreview`] component emits canvases that match this contract.
pub const PREVIEW_JS: &str = include_str!;