fractal/contrib/qr_code_scanner/camera/
mod.rs

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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
//! Camera API.

use futures_util::{future::LocalBoxFuture, FutureExt};
use gtk::{glib, prelude::*, subclass::prelude::*};
use once_cell::sync::Lazy;
use tracing::error;

mod camera_paintable;
#[cfg(target_os = "linux")]
mod linux;

pub use self::camera_paintable::Action;
use self::camera_paintable::CameraPaintable;

mod imp {

    use super::*;

    #[repr(C)]
    pub struct CameraClass {
        pub parent_class: glib::object::Class<glib::Object>,
        pub has_cameras: fn(&super::Camera) -> LocalBoxFuture<bool>,
        pub paintable: fn(&super::Camera) -> LocalBoxFuture<Option<CameraPaintable>>,
    }

    unsafe impl ClassStruct for CameraClass {
        type Type = Camera;
    }

    pub(super) async fn camera_has_cameras(this: &super::Camera) -> bool {
        let klass = this.class();
        (klass.as_ref().has_cameras)(this).await
    }

    pub(super) async fn camera_paintable(this: &super::Camera) -> Option<CameraPaintable> {
        let klass = this.class();
        (klass.as_ref().paintable)(this).await
    }

    #[derive(Debug, Default)]
    pub struct Camera;

    #[glib::object_subclass]
    impl ObjectSubclass for Camera {
        const NAME: &'static str = "Camera";
        type Type = super::Camera;
        type Class = CameraClass;
    }

    impl ObjectImpl for Camera {}
}

glib::wrapper! {
    /// Subclassable Camera API.
    ///
    /// The default implementation, for unsupported platforms, makes sure the camera support is disabled.
    pub struct Camera(ObjectSubclass<imp::Camera>);
}

impl Camera {
    /// Create a new `Camera`.
    ///
    /// Use `Camera::default()` to get a shared GObject.
    fn new() -> Self {
        #[cfg(target_os = "linux")]
        let obj = linux::LinuxCamera::new().upcast();

        #[cfg(not(target_os = "linux"))]
        let obj = glib::Object::new();

        obj
    }
}

impl Default for Camera {
    fn default() -> Self {
        static CAMERA: Lazy<Camera> = Lazy::new(Camera::new);

        CAMERA.to_owned()
    }
}

unsafe impl Send for Camera {}
unsafe impl Sync for Camera {}

pub trait CameraExt: 'static {
    /// Whether any cameras are available.
    async fn has_cameras(&self) -> bool;

    /// The paintable displaying the camera.
    async fn paintable(&self) -> Option<CameraPaintable>;
}

impl<O: IsA<Camera>> CameraExt for O {
    async fn has_cameras(&self) -> bool {
        imp::camera_has_cameras(self.upcast_ref()).await
    }

    async fn paintable(&self) -> Option<CameraPaintable> {
        imp::camera_paintable(self.upcast_ref()).await
    }
}

/// Public trait that must be implemented for everything that derives from
/// `Camera`.
///
/// Overriding a method from this Trait overrides also its behavior in
/// `CameraExt`.
#[allow(async_fn_in_trait)]
pub trait CameraImpl: ObjectImpl {
    /// Whether any cameras are available.
    async fn has_cameras(&self) -> bool {
        false
    }

    /// The paintable displaying the camera.
    async fn paintable(&self) -> Option<CameraPaintable> {
        error!("The camera API is not supported on this platform");
        None
    }
}

unsafe impl<T> IsSubclassable<T> for Camera
where
    T: CameraImpl,
    T::Type: IsA<Camera>,
{
    fn class_init(class: &mut glib::Class<Self>) {
        Self::parent_class_init::<T>(class.upcast_ref_mut());

        let klass = class.as_mut();

        klass.has_cameras = has_cameras_trampoline::<T>;
        klass.paintable = paintable_trampoline::<T>;
    }
}

// Virtual method implementation trampolines.
fn has_cameras_trampoline<T>(this: &Camera) -> LocalBoxFuture<bool>
where
    T: ObjectSubclass + CameraImpl,
    T::Type: IsA<Camera>,
{
    let this = this.downcast_ref::<T::Type>().unwrap();
    this.imp().has_cameras().boxed_local()
}

fn paintable_trampoline<T>(this: &Camera) -> LocalBoxFuture<Option<CameraPaintable>>
where
    T: ObjectSubclass + CameraImpl,
    T::Type: IsA<Camera>,
{
    let this = this.downcast_ref::<T::Type>().unwrap();
    this.imp().paintable().boxed_local()
}