chalkydri/cameras/
providers.rs

1use tokio::sync::mpsc;
2
3use gstreamer::{
4    Bus, BusSyncReply, Device, DeviceProvider, DeviceProviderFactory, Message, MessageView,
5    Structure, prelude::*,
6};
7
8/// An event from a camera provider
9pub(crate) enum ProviderEvent {
10    Connected(String, Device),
11    Disconnected(String, Device),
12}
13
14pub trait CamProvider {
15    fn init() -> Self
16    where
17        Self: Sized;
18    /// Get a unique ID for the given device
19    fn get_id(dev: &Device) -> String;
20    fn inner(&self) -> &DeviceProvider;
21
22    fn register_handler(&self, tx: mpsc::Sender<ProviderEvent>) {
23        self.inner()
24            .bus()
25            .set_sync_handler(move |_bus: &Bus, msg: &Message| {
26                match msg.view() {
27                    MessageView::DeviceAdded(msg) => {
28                        let dev = msg.device();
29                        let id = Self::get_id(&dev);
30
31                        tx.blocking_send(ProviderEvent::Connected(id, dev)).unwrap();
32                    }
33                    MessageView::DeviceRemoved(msg) => {
34                        let dev = msg.device();
35                        let id = Self::get_id(&dev);
36
37                        tx.blocking_send(ProviderEvent::Disconnected(id, dev))
38                            .unwrap();
39                    }
40                    _ => unimplemented!(),
41                }
42
43                BusSyncReply::Pass
44            });
45    }
46
47    fn unregister_handler(&self) {
48        self.inner().bus().unset_sync_handler();
49    }
50
51    fn start(&self) {
52        if !self.inner().is_started() {
53            self.inner().start().unwrap();
54        }
55    }
56
57    fn stop(&self) {
58        self.inner().stop();
59    }
60}
61
62pub struct V4l2Provider {
63    inner: DeviceProvider,
64}
65impl CamProvider for V4l2Provider {
66    fn init() -> Self {
67        let inner = DeviceProviderFactory::find("v4l2deviceprovider")
68            .unwrap()
69            .load()
70            .unwrap()
71            .get()
72            .unwrap();
73
74        Self { inner }
75    }
76    fn get_id(dev: &Device) -> String {
77        dev.property::<Structure>("properties")
78            .get::<String>("device.serial")
79            .unwrap()
80    }
81    fn inner(&self) -> &DeviceProvider {
82        &self.inner
83    }
84}