app: support multiple preview in a Notebook

The preview is now a NoteBook and if multiple video
gtk4sink are available, a page is created for each of it.
This commit is contained in:
Stéphane Cerveau 2022-02-01 11:46:39 +01:00
parent 09f56de320
commit 4cdf2fd70b
4 changed files with 39 additions and 14 deletions

View file

@ -410,17 +410,30 @@ impl GPSApp {
status_bar.push(status_bar.context_id("Description"), &state.to_string());
}
pub fn set_app_preview(&self, paintable: &gdk::Paintable) {
pub fn set_app_preview(&self, paintable: &gdk::Paintable, n_sink: usize) {
let picture = gtk::Picture::new();
picture.set_paintable(Some(paintable));
let box_preview: gtk::Box = self
let notebook_preview: gtk::Notebook = self
.builder
.object("box-preview")
.object("notebook-preview")
.expect("Couldn't get box_preview");
while let Some(child) = box_preview.first_child() {
box_preview.remove(&child);
if n_sink == 0 {
loop {
let i = notebook_preview.n_pages();
if i == 0 {
break;
}
notebook_preview.remove_page(Some(i - 1));
}
}
let box_preview = gtk::Box::builder()
.orientation(gtk::Orientation::Vertical)
.halign(gtk::Align::Center)
.valign(gtk::Align::Center)
.build();
box_preview.append(&picture);
let label = gtk::Label::new(Some(&format!("Preview{}", n_sink)));
notebook_preview.insert_page(&box_preview, Some(&label), None);
}
pub fn build_ui(&self, application: &Application) {

View file

@ -223,26 +223,28 @@ impl ElementInfo {
None
}
pub fn search_fo_element(bin: &gst::Bin, element_name: &str) -> Option<gst::Element> {
pub fn search_fo_element(bin: &gst::Bin, element_name: &str) -> Vec<gst::Element> {
let mut iter = bin.iterate_elements();
let element = loop {
let mut elements: Vec<gst::Element> = Vec::new();
let elements = loop {
match iter.next() {
Ok(Some(element)) => {
if element.is::<gst::Bin>() {
let bin = element.dynamic_cast::<gst::Bin>().unwrap();
break ElementInfo::search_fo_element(&bin, element_name);
let mut bin_elements = ElementInfo::search_fo_element(&bin, element_name);
elements.append(&mut bin_elements);
} else {
GPS_INFO!("Found factory: {}", element.factory().unwrap().name());
if element.factory().unwrap().name() == element_name {
GPS_INFO!("Found {}", element_name);
break Some(element);
elements.push(element);
}
}
}
Err(gst::IteratorError::Resync) => iter.resync(),
_ => break None,
_ => break elements,
}
};
element
elements
}
}

View file

@ -113,16 +113,18 @@ impl Pipeline {
pub fn check_for_gtk4sink(&self, pipeline: &gst::Pipeline) {
let bin = pipeline.clone().dynamic_cast::<gst::Bin>().unwrap();
let gtksink = ElementInfo::search_fo_element(&bin, "gtk4paintablesink");
if let Some(gtksink) = gtksink {
let gtksinks = ElementInfo::search_fo_element(&bin, "gtk4paintablesink");
for (first_sink, gtksink) in gtksinks.into_iter().enumerate() {
let paintable = gtksink.property::<gdk::Paintable>("paintable");
self.app
.borrow()
.as_ref()
.expect("App should be available")
.set_app_preview(&paintable);
.set_app_preview(&paintable, first_sink);
}
}
pub fn start_pipeline(
&self,
graphview: &GraphView,

View file

@ -295,6 +295,10 @@
</object>
</child>
<child>
<object class="GtkNotebook" id="notebook-preview">
<child>
<object class="GtkNotebookPage">
<property name="child">
<object class="GtkScrolledWindow">
<property name="hexpand">True</property>
<property name="vexpand">True</property>
@ -309,6 +313,10 @@
</object>
</property>
</object>
</property>
</object>
</child>
</object>
</child>
</object>
</child>