From 7274c725a6f4696179aad0ae9be264d630406887 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Fri, 9 Feb 2024 12:34:28 +0200 Subject: [PATCH] gtk4: Create a window if running from gst-launch-1.0 or GST_GTK4_WINDOW=1 is set Fixes https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/issues/482 Part-of: --- video/gtk4/src/sink/imp.rs | 68 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/video/gtk4/src/sink/imp.rs b/video/gtk4/src/sink/imp.rs index 4701679f..dcad8d42 100644 --- a/video/gtk4/src/sink/imp.rs +++ b/video/gtk4/src/sink/imp.rs @@ -61,6 +61,7 @@ pub(crate) static CAT: Lazy = Lazy::new(|| { #[derive(Default)] pub struct PaintableSink { paintable: Mutex>>, + window: Mutex>>, info: Mutex>, sender: Mutex>>, pending_frame: Mutex>, @@ -231,6 +232,18 @@ impl ElementImpl for PaintableSink { ) -> Result { match transition { gst::StateChange::NullToReady => { + let create_window = glib::program_name().as_deref() == Some("gst-launch-1.0") + || std::env::var("GST_GTK4_WINDOW").as_deref() == Ok("1"); + + if create_window { + let res = utils::invoke_on_main_thread(gtk::init); + + if let Err(err) = res { + gst::error!(CAT, imp: self, "Failed to create initialize GTK: {err}"); + return Err(gst::StateChangeError); + } + } + let mut paintable = self.paintable.lock().unwrap(); if paintable.is_none() { @@ -273,6 +286,10 @@ impl ElementImpl for PaintableSink { ); } } + + if create_window { + self.create_window(); + } } _ => (), } @@ -294,6 +311,17 @@ impl ElementImpl for PaintableSink { } }); } + gst::StateChange::ReadyToNull => { + let mut window_guard = self.window.lock().unwrap(); + if let Some(window) = window_guard.take() { + drop(window_guard); + + glib::MainContext::default().invoke(move || { + let window = window.get_ref(); + window.close(); + }); + } + } _ => (), } @@ -520,6 +548,46 @@ impl PaintableSink { .replace(tmp_caps); } + fn create_window(&self) { + let self_ = self.to_owned(); + glib::MainContext::default().invoke(move || { + let mut window_guard = self_.window.lock().unwrap(); + if window_guard.is_some() { + return; + } + + let paintable = match &*self_.paintable.lock().unwrap() { + Some(paintable) => paintable.get_ref().clone(), + None => return, + }; + + let window = gtk::Window::new(); + let picture = gtk::Picture::new(); + picture.set_paintable(Some(&paintable)); + window.set_child(Some(&picture)); + window.set_default_size(640, 480); + + window.connect_close_request({ + let self_ = self_.clone(); + move |_window| { + if self_.window.lock().unwrap().is_some() { + gst::element_imp_error!( + self_, + gst::ResourceError::NotFound, + ("Output window was closed") + ); + } + + glib::Propagation::Proceed + } + }); + + window.show(); + + *window_guard = Some(ThreadGuard::new(window)); + }); + } + fn create_paintable(&self, paintable_storage: &mut MutexGuard>>) { #[cfg(any(target_os = "macos", target_os = "windows", feature = "gst-gl"))] {