[fractal/fractal-next] qr-code-scanner: Use is_camera_present() and allow multiple starts
- From: Julian Sparber <jsparber src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [fractal/fractal-next] qr-code-scanner: Use is_camera_present() and allow multiple starts
- Date: Thu, 13 Jan 2022 14:34:41 +0000 (UTC)
commit 5bb7e52470d12ca7e87de5bab4791721d8857db4
Author: Julian Sparber <julian sparber net>
Date: Wed Jan 12 18:41:12 2022 +0100
qr-code-scanner: Use is_camera_present() and allow multiple starts
This now uses `is_camera_present()` to check whether we have a camera.
It also makes sure that a pipeline is closed before a new one is
started.
Cargo.lock | 5 +-
Cargo.toml | 2 +-
src/contrib/qr_code_scanner/camera_paintable.rs | 15 ++---
src/contrib/qr_code_scanner/mod.rs | 80 +++++++++++++------------
4 files changed, 49 insertions(+), 53 deletions(-)
---
diff --git a/Cargo.lock b/Cargo.lock
index 535c7716..e68590ea 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4090,11 +4090,10 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
[[package]]
name = "tokio"
-version = "1.12.0"
+version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c2c2416fdedca8443ae44b4527de1ea633af61d8f7169ffa6e72c5b53d24efcc"
+checksum = "fbbf1c778ec206785635ce8ad57fe52b3009ae9e0c9f574a728f3049d3e55838"
dependencies = [
- "autocfg",
"bytes",
"libc",
"memchr",
diff --git a/Cargo.toml b/Cargo.toml
index cd10e056..5da11da3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -21,7 +21,7 @@ gtk-macros = "0.3"
once_cell = "1.5"
serde = "1.0.130"
serde_json = "1.0"
-tokio = { version = "1.2", features = ["rt", "rt-multi-thread"] }
+tokio = { version = "1.15", features = ["rt", "rt-multi-thread", "sync"] }
url = "2.2"
secret-service = "2.0"
html2pango = "0.4"
diff --git a/src/contrib/qr_code_scanner/camera_paintable.rs b/src/contrib/qr_code_scanner/camera_paintable.rs
index e4d7c9b1..4279c68e 100644
--- a/src/contrib/qr_code_scanner/camera_paintable.rs
+++ b/src/contrib/qr_code_scanner/camera_paintable.rs
@@ -212,7 +212,6 @@ mod imp {
pub struct CameraPaintable {
pub sink: camera_sink::CameraSink,
- pub detector: QrCodeDetector,
pub pipeline: RefCell<Option<gst::Pipeline>>,
pub sender: Sender<Action>,
pub image: RefCell<Option<gdk::Texture>>,
@@ -227,7 +226,6 @@ mod imp {
Self {
pipeline: RefCell::default(),
sink: camera_sink::CameraSink::new(sender.clone()),
- detector: QrCodeDetector::new(sender.clone()),
image: RefCell::new(None),
sender,
receiver,
@@ -337,6 +335,7 @@ impl Default for CameraPaintable {
impl CameraPaintable {
pub fn set_pipewire_fd<F: AsRawFd>(&self, fd: F, node_id: u32) {
+ self.close_pipeline();
let pipewire_element = gst::ElementFactory::make("pipewiresrc", None).unwrap();
pipewire_element
.set_property("fd", &fd.as_raw_fd())
@@ -350,6 +349,7 @@ impl CameraPaintable {
fn init_pipeline(&self, pipewire_src: gst::Element) {
let self_ = imp::CameraPaintable::from_instance(self);
let pipeline = gst::Pipeline::new(None);
+ let detector = QrCodeDetector::new(self_.sender.clone()).upcast();
let tee = gst::ElementFactory::make("tee", None).unwrap();
let queue = gst::ElementFactory::make("queue", None).unwrap();
@@ -377,21 +377,14 @@ impl CameraPaintable {
&tee,
&queue,
&videoconvert1,
- self_.detector.upcast_ref(),
+ &detector,
&queue2,
&videoconvert2,
self_.sink.upcast_ref(),
])
.unwrap();
- gst::Element::link_many(&[
- &pipewire_src,
- &tee,
- &queue,
- &videoconvert1,
- self_.detector.upcast_ref(),
- ])
- .unwrap();
+ gst::Element::link_many(&[&pipewire_src, &tee, &queue, &videoconvert1, &detector]).unwrap();
tee.link_pads(None, &queue2, None).unwrap();
gst::Element::link_many(&[&queue2, &videoconvert2, self_.sink.upcast_ref()]).unwrap();
diff --git a/src/contrib/qr_code_scanner/mod.rs b/src/contrib/qr_code_scanner/mod.rs
index e5a646f3..3e484b5a 100644
--- a/src/contrib/qr_code_scanner/mod.rs
+++ b/src/contrib/qr_code_scanner/mod.rs
@@ -20,6 +20,7 @@ mod imp {
use gtk::CompositeTemplate;
use once_cell::sync::Lazy;
use std::cell::Cell;
+ use tokio::sync::OnceCell;
use super::*;
@@ -29,8 +30,8 @@ mod imp {
pub paintable: CameraPaintable,
#[template_child]
pub picture: TemplateChild<gtk::Picture>,
+ pub connection: OnceCell<zbus::Connection>,
pub has_camera: Cell<bool>,
- pub is_started: Cell<bool>,
}
#[glib::object_subclass]
@@ -116,47 +117,51 @@ impl QrCodeScanner {
glib::Object::new(&[]).expect("Failed to create a QrCodeScanner")
}
+ async fn connection(&self) -> Result<&zbus::Connection, ashpd::Error> {
+ let priv_ = imp::QrCodeScanner::from_instance(self);
+
+ Ok(priv_
+ .connection
+ .get_or_try_init(|| zbus::Connection::session())
+ .await?)
+ }
+
pub fn stop(&self) {
let self_ = imp::QrCodeScanner::from_instance(self);
self_.paintable.close_pipeline();
}
- async fn start_internal(&self) -> bool {
- let self_ = imp::QrCodeScanner::from_instance(self);
- if let Ok(Some(stream_fd)) = stream().await {
+ pub async fn start(&self) -> bool {
+ let priv_ = imp::QrCodeScanner::from_instance(self);
+ if let Ok(stream_fd) = self.stream().await {
if let Ok(node_id) = camera::pipewire_node_id(stream_fd).await {
- self_.paintable.set_pipewire_fd(stream_fd, node_id);
- self_.has_camera.set(true);
- self.notify("has-camera");
+ priv_.paintable.set_pipewire_fd(stream_fd, node_id);
+ self.set_has_camera(true);
return true;
}
}
- self_.has_camera.set(false);
- self.notify("has-camera");
- false
+
+ self.set_has_camera(false);
+ return false;
}
- pub async fn start(&self) -> bool {
- let priv_ = imp::QrCodeScanner::from_instance(self);
- let is_started = self.start_internal().await;
- priv_.is_started.set(is_started);
- is_started
+ async fn has_camera_internal(&self) -> Result<bool, ashpd::Error> {
+ let proxy = camera::CameraProxy::new(self.connection().await?).await?;
+
+ proxy.is_camera_present().await
+ }
+
+ async fn stream(&self) -> Result<RawFd, ashpd::Error> {
+ let proxy = camera::CameraProxy::new(self.connection().await?).await?;
+
+ proxy.access_camera().await?;
+ proxy.open_pipe_wire_remote().await
}
fn init_has_camera(&self) {
spawn!(clone!(@weak self as obj => async move {
- let priv_ = imp::QrCodeScanner::from_instance(&obj);
- let has_camera = if obj.start_internal().await {
- if !priv_.is_started.get() {
- obj.stop();
- }
- true
- } else {
- false
- };
- priv_.has_camera.set(has_camera);
- obj.notify("has-camera");
+ obj.set_has_camera(obj.has_camera_internal().await.unwrap_or_default());
}));
}
@@ -165,6 +170,17 @@ impl QrCodeScanner {
priv_.has_camera.get()
}
+ fn set_has_camera(&self, has_camera: bool) {
+ let priv_ = imp::QrCodeScanner::from_instance(self);
+
+ if has_camera == self.has_camera() {
+ return;
+ }
+
+ priv_.has_camera.set(has_camera);
+ self.notify("has-camera");
+ }
+
/// Connects the prepared signals to the function f given in input
pub fn connect_code_detected<F: Fn(&Self, QrVerificationData) + 'static>(
&self,
@@ -182,18 +198,6 @@ impl QrCodeScanner {
}
}
-async fn stream() -> Result<Option<RawFd>, ashpd::Error> {
- let connection = zbus::Connection::session().await?;
- let proxy = camera::CameraProxy::new(&connection).await?;
-
- if proxy.is_camera_present().await? {
- proxy.access_camera().await?;
- Ok(Some(proxy.open_pipe_wire_remote().await?))
- } else {
- Ok(None)
- }
-}
-
#[derive(Clone, Debug, PartialEq, glib::GBoxed)]
#[gboxed(type_name = "QrVerificationDataBoxed")]
struct QrVerificationDataBoxed(QrVerificationData);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]