mirror of
https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git
synced 2024-11-25 13:01:07 +00:00
gtk4: add custom widget automatically updating the window size
Use it in the example and debug window but let's not make it public yet. Plan is to have a proper bin on top of gtk4paintablesink at some point. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/1680>
This commit is contained in:
parent
17910dd532
commit
cfe9968a77
6 changed files with 146 additions and 38 deletions
|
@ -62,23 +62,8 @@ fn create_ui(app: >k::Application) {
|
|||
|
||||
let vbox = gtk::Box::new(gtk::Orientation::Vertical, 0);
|
||||
|
||||
let picture = gtk::Picture::new();
|
||||
picture.set_paintable(Some(&paintable));
|
||||
|
||||
#[cfg(feature = "gtk_v4_14")]
|
||||
{
|
||||
let offload = gtk::GraphicsOffload::new(Some(&picture));
|
||||
offload.set_enabled(gtk::GraphicsOffloadEnabled::Enabled);
|
||||
#[cfg(feature = "gtk_v4_16")]
|
||||
{
|
||||
offload.set_black_background(true);
|
||||
}
|
||||
vbox.append(&offload);
|
||||
}
|
||||
#[cfg(not(feature = "gtk_v4_14"))]
|
||||
{
|
||||
vbox.append(&picture);
|
||||
}
|
||||
let gst_widget = gstgtk4::RenderWidget::new(>ksink);
|
||||
vbox.append(&gst_widget);
|
||||
|
||||
let label = gtk::Label::new(Some("Position: 00:00:00"));
|
||||
vbox.append(&label);
|
||||
|
|
|
@ -21,6 +21,10 @@ mod sink;
|
|||
mod utils;
|
||||
pub use sink::frame::Orientation;
|
||||
pub use sink::paintable::Paintable;
|
||||
// The widget needs to be public so it can be used by the example and element debug window but
|
||||
// we don't want it be part of the official API for now.
|
||||
#[doc(hidden)]
|
||||
pub use sink::render_widget::RenderWidget;
|
||||
pub use sink::PaintableSink;
|
||||
|
||||
fn plugin_init(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
|
||||
|
|
|
@ -831,29 +831,11 @@ impl PaintableSink {
|
|||
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));
|
||||
|
||||
#[cfg(feature = "gtk_v4_14")]
|
||||
{
|
||||
let offload = gtk::GraphicsOffload::new(Some(&picture));
|
||||
offload.set_enabled(gtk::GraphicsOffloadEnabled::Enabled);
|
||||
#[cfg(feature = "gtk_v4_16")]
|
||||
{
|
||||
offload.set_black_background(true);
|
||||
}
|
||||
window.set_child(Some(&offload));
|
||||
}
|
||||
#[cfg(not(feature = "gtk_v4_14"))]
|
||||
{
|
||||
window.set_child(Some(&picture));
|
||||
}
|
||||
let gst_widget = crate::RenderWidget::new(self_.obj().as_ref().upcast_ref());
|
||||
window.set_child(Some(&gst_widget));
|
||||
|
||||
window.set_default_size(640, 480);
|
||||
if std::env::var("GST_GTK4_WINDOW_FULLSCREEN").as_deref() == Ok("1") {
|
||||
window.set_fullscreened(true);
|
||||
|
|
|
@ -41,6 +41,7 @@ use gtk::glib::prelude::*;
|
|||
pub(super) mod frame;
|
||||
pub(super) mod imp;
|
||||
pub(super) mod paintable;
|
||||
pub(super) mod render_widget;
|
||||
|
||||
enum SinkEvent {
|
||||
FrameChanged,
|
||||
|
|
113
video/gtk4/src/sink/render_widget/imp.rs
Normal file
113
video/gtk4/src/sink/render_widget/imp.rs
Normal file
|
@ -0,0 +1,113 @@
|
|||
//
|
||||
// Copyright (C) 2024 Guillaume Desmottes <guillaume@desmottes.be>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License, v2.0.
|
||||
// If a copy of the MPL was not distributed with this file, You can obtain one at
|
||||
// <https://mozilla.org/MPL/2.0/>.
|
||||
//
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use std::cell::{Cell, RefCell};
|
||||
|
||||
use gtk::{gdk, glib, prelude::*, subclass::prelude::*};
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct RenderWidget {
|
||||
element: RefCell<Option<crate::PaintableSink>>,
|
||||
window_size: Cell<(u32, u32)>,
|
||||
}
|
||||
|
||||
#[glib::object_subclass]
|
||||
impl ObjectSubclass for RenderWidget {
|
||||
const NAME: &'static str = "GstGtk4ExampleRenderWidget";
|
||||
type Type = super::RenderWidget;
|
||||
type ParentType = gtk::Widget;
|
||||
|
||||
fn class_init(klass: &mut Self::Class) {
|
||||
klass.set_layout_manager_type::<gtk::BinLayout>();
|
||||
}
|
||||
}
|
||||
|
||||
impl ObjectImpl for RenderWidget {
|
||||
fn properties() -> &'static [glib::ParamSpec] {
|
||||
static PROPERTIES: Lazy<Vec<glib::ParamSpec>> = Lazy::new(|| {
|
||||
vec![
|
||||
glib::ParamSpecObject::builder::<crate::PaintableSink>("element")
|
||||
.nick("Element")
|
||||
.blurb("The GTK4 Paintable Sink GStreamer element")
|
||||
.construct_only()
|
||||
.build(),
|
||||
]
|
||||
});
|
||||
|
||||
PROPERTIES.as_ref()
|
||||
}
|
||||
|
||||
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
|
||||
match pspec.name() {
|
||||
"element" => self.element.borrow().to_value(),
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
|
||||
match pspec.name() {
|
||||
"element" => {
|
||||
*self.element.borrow_mut() = value.get::<Option<crate::PaintableSink>>().unwrap();
|
||||
}
|
||||
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn constructed(&self) {
|
||||
self.parent_constructed();
|
||||
|
||||
let element = self.element.borrow();
|
||||
let element = element.as_ref().unwrap();
|
||||
let paintable = element.property::<gdk::Paintable>("paintable");
|
||||
|
||||
let picture = gtk::Picture::new();
|
||||
picture.set_paintable(Some(&paintable));
|
||||
|
||||
#[cfg(feature = "gtk_v4_14")]
|
||||
{
|
||||
let offload = gtk::GraphicsOffload::new(Some(&picture));
|
||||
offload.set_enabled(gtk::GraphicsOffloadEnabled::Enabled);
|
||||
#[cfg(feature = "gtk_v4_16")]
|
||||
{
|
||||
offload.set_black_background(true);
|
||||
}
|
||||
offload.set_parent(self.obj().as_ref());
|
||||
}
|
||||
#[cfg(not(feature = "gtk_v4_14"))]
|
||||
{
|
||||
picture.set_parent(self.obj().as_ref());
|
||||
}
|
||||
}
|
||||
|
||||
fn dispose(&self) {
|
||||
while let Some(child) = self.obj().first_child() {
|
||||
child.unparent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl WidgetImpl for RenderWidget {
|
||||
fn snapshot(&self, snapshot: >k::Snapshot) {
|
||||
let window_width = self.obj().width() as u32;
|
||||
let window_height = self.obj().height() as u32;
|
||||
let new_size = (window_width, window_height);
|
||||
let updated = self.window_size.replace(new_size) != new_size;
|
||||
|
||||
if updated {
|
||||
let element = self.element.borrow();
|
||||
let element = element.as_ref().unwrap();
|
||||
element.set_property("window-width", window_width);
|
||||
element.set_property("window-height", window_height);
|
||||
}
|
||||
|
||||
self.parent_snapshot(snapshot)
|
||||
}
|
||||
}
|
23
video/gtk4/src/sink/render_widget/mod.rs
Normal file
23
video/gtk4/src/sink/render_widget/mod.rs
Normal file
|
@ -0,0 +1,23 @@
|
|||
//
|
||||
// Copyright (C) 2024 Guillaume Desmottes <guillaume@desmottes.be>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License, v2.0.
|
||||
// If a copy of the MPL was not distributed with this file, You can obtain one at
|
||||
// <https://mozilla.org/MPL/2.0/>.
|
||||
//
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use gtk::glib;
|
||||
|
||||
mod imp;
|
||||
|
||||
/// Use a simple container widget to automatically pass the window size to gtk4paintablesink.
|
||||
glib::wrapper! {
|
||||
pub struct RenderWidget(ObjectSubclass<imp::RenderWidget>) @extends gtk::Widget;
|
||||
}
|
||||
|
||||
impl RenderWidget {
|
||||
pub fn new(element: &gst::Element) -> Self {
|
||||
glib::Object::builder().property("element", element).build()
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue