mirror of
https://gitlab.freedesktop.org/dabrain34/GstPipelineStudio.git
synced 2024-12-18 22:16:33 +00:00
app: port support update
Connect the port to the element pad capabilities. Can now create a port only if the element supports the request pad Can only delete a port which is a "sometimes" port/pad. Introduce GPS module.
This commit is contained in:
parent
4bae12c011
commit
0f0f9d6fc0
11 changed files with 422 additions and 263 deletions
28
Cargo.lock
generated
28
Cargo.lock
generated
|
@ -287,9 +287,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gdk4"
|
name = "gdk4"
|
||||||
version = "0.4.1"
|
version = "0.4.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f1023950739cd692fbf559507cad031bf2b0369d68466121f8a1316bc5ae29f0"
|
checksum = "228384db1fd6539f51152c97e59fbf29b6293988ee89bc915ebff229eb5cda58"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
"cairo-rs",
|
"cairo-rs",
|
||||||
|
@ -303,9 +303,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gdk4-sys"
|
name = "gdk4-sys"
|
||||||
version = "0.4.1"
|
version = "0.4.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "401b6be19db1e0ad2978fde7b46989b82f7595affa09cb56fe6f1302bc4f19e3"
|
checksum = "48a39e34abe35ee2cf54a1e29dd983accecd113ad30bdead5050418fa92f2a1b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cairo-sys-rs",
|
"cairo-sys-rs",
|
||||||
"gdk-pixbuf-sys",
|
"gdk-pixbuf-sys",
|
||||||
|
@ -510,9 +510,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gsk4"
|
name = "gsk4"
|
||||||
version = "0.4.1"
|
version = "0.4.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d3dd7c79a864b8c4606d39fad3fd872688ea20ba8e833a9f38e905a458a29a8c"
|
checksum = "cc7de6ca62027aea1d3ab5d4a6bb2db24a296f56473d8a9a4d7ee33042745ff3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
"cairo-rs",
|
"cairo-rs",
|
||||||
|
@ -526,9 +526,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gsk4-sys"
|
name = "gsk4-sys"
|
||||||
version = "0.4.1"
|
version = "0.4.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6d25ee96f7d1bdb6fa9945425aea95ce60efedf60c994eceb671fd93ad11d541"
|
checksum = "e31d21d7ce02ba261bb24c50c4ab238a10b41a2c97c32afffae29471b7cca69b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cairo-sys-rs",
|
"cairo-sys-rs",
|
||||||
"gdk4-sys",
|
"gdk4-sys",
|
||||||
|
@ -594,9 +594,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gtk4"
|
name = "gtk4"
|
||||||
version = "0.4.1"
|
version = "0.4.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a6fda2b49a25eefc1116f15d06585d333c21fc3ce499ab0a86641fac2fbf40ac"
|
checksum = "8622c50f55cbe83e78335cf95850ccefa99e8eac3335ef7d17473312402d7e89"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
"cairo-rs",
|
"cairo-rs",
|
||||||
|
@ -617,9 +617,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gtk4-macros"
|
name = "gtk4-macros"
|
||||||
version = "0.4.1"
|
version = "0.4.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5b17860e493ada8a40577f0e92bce8249a97c831e39d7811ef21de6281d67f86"
|
checksum = "c666e9d310431da43cb9d24995b247e5e24d11972d19bcd8b40e1663d25d0f51"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"proc-macro-crate",
|
"proc-macro-crate",
|
||||||
|
@ -631,9 +631,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gtk4-sys"
|
name = "gtk4-sys"
|
||||||
version = "0.4.1"
|
version = "0.4.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ffc1047ea7a0ff2947fbfb703eecfcca6b58912171037a4c55b1577015f079d5"
|
checksum = "1544614a8d44f38719a2fdfd608d644d5f385beab33e5852688f48a983a2b583"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cairo-sys-rs",
|
"cairo-sys-rs",
|
||||||
"gdk-pixbuf-sys",
|
"gdk-pixbuf-sys",
|
||||||
|
|
7
TODO.md
7
TODO.md
|
@ -27,12 +27,13 @@
|
||||||
### Graphview
|
### Graphview
|
||||||
|
|
||||||
- [ ] create a crate for graphview/node/port
|
- [ ] create a crate for graphview/node/port
|
||||||
- [ ] Remove a port from a node
|
- [x] Remove a port from a node if possible
|
||||||
- [ ] Implement graphview unit test
|
- [ ] Implement graphview unit test
|
||||||
|
- [x] add a css class for pad (presence always or sometimes)
|
||||||
|
|
||||||
### app
|
### app
|
||||||
|
|
||||||
- [ ] check that a node accept to create a port on request (input/output)
|
- [x] check that a node accept to create a port on request (input/output)
|
||||||
- [ ] Control the connection between element
|
- [ ] Control the connection between element
|
||||||
- [x] unable to connect in and in out and out
|
- [x] unable to connect in and in out and out
|
||||||
- [ ] unable to connect element with incompatible caps.
|
- [ ] unable to connect element with incompatible caps.
|
||||||
|
@ -45,7 +46,7 @@
|
||||||
- [ ] Implement a command line parser to graph
|
- [ ] Implement a command line parser to graph
|
||||||
- [ ] Render the parse launch line in a message box
|
- [ ] Render the parse launch line in a message box
|
||||||
- [ ] Prevent to create a pad in an element without the template
|
- [ ] Prevent to create a pad in an element without the template
|
||||||
- [ ] Check the pîpeline live
|
- [ ] Check the pipeline validity
|
||||||
- [ ] Implement pipeline unit test
|
- [ ] Implement pipeline unit test
|
||||||
- [x] Save node position in XML
|
- [x] Save node position in XML
|
||||||
- [x] Autosave the graph
|
- [x] Autosave the graph
|
||||||
|
|
107
src/app.rs
107
src/app.rs
|
@ -35,13 +35,13 @@ use std::ops;
|
||||||
use std::rc::{Rc, Weak};
|
use std::rc::{Rc, Weak};
|
||||||
|
|
||||||
use crate::about;
|
use crate::about;
|
||||||
|
use crate::gps::{ElementInfo, PadInfo, Pipeline, PipelineState};
|
||||||
use crate::logger;
|
use crate::logger;
|
||||||
use crate::pipeline::{Pipeline, PipelineState};
|
|
||||||
use crate::plugindialogs;
|
use crate::plugindialogs;
|
||||||
use crate::settings::Settings;
|
use crate::settings::Settings;
|
||||||
use crate::{GPS_DEBUG, GPS_ERROR, GPS_TRACE, GPS_WARN};
|
use crate::{GPS_DEBUG, GPS_ERROR, GPS_TRACE, GPS_WARN};
|
||||||
|
|
||||||
use crate::graphmanager::{GraphView, Node, PortDirection};
|
use crate::graphmanager::{GraphView, Node, PortDirection, PortPresence};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct GPSAppInner {
|
pub struct GPSAppInner {
|
||||||
|
@ -192,7 +192,7 @@ impl GPSApp {
|
||||||
|
|
||||||
application.add_action(&gio::SimpleAction::new("graph.add-plugin", None));
|
application.add_action(&gio::SimpleAction::new("graph.add-plugin", None));
|
||||||
|
|
||||||
application.add_action(&gio::SimpleAction::new("port.delete-link", None));
|
application.add_action(&gio::SimpleAction::new("port.delete", None));
|
||||||
|
|
||||||
application.add_action(&gio::SimpleAction::new("node.add-to-favorite", None));
|
application.add_action(&gio::SimpleAction::new("node.add-to-favorite", None));
|
||||||
application.add_action(&gio::SimpleAction::new("node.delete", None));
|
application.add_action(&gio::SimpleAction::new("node.delete", None));
|
||||||
|
@ -224,6 +224,28 @@ impl GPSApp {
|
||||||
pop_menu
|
pop_menu
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn app_menu_action(&self, action_name: &str) -> SimpleAction {
|
||||||
|
let application = gio::Application::default()
|
||||||
|
.expect("No default application")
|
||||||
|
.downcast::<gtk::Application>()
|
||||||
|
.expect("Unable to downcast default application");
|
||||||
|
|
||||||
|
application
|
||||||
|
.lookup_action(action_name)
|
||||||
|
.unwrap_or_else(|| panic!("Unable to find action {}", action_name))
|
||||||
|
.dynamic_cast::<SimpleAction>()
|
||||||
|
.expect("Unable to dynamic cast to SimpleAction")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn disconnect_app_menu_action(&self, action_name: &str) {
|
||||||
|
let action = self.app_menu_action(action_name);
|
||||||
|
|
||||||
|
if let Some(signal_handler_id) = self.menu_signal_handlers.borrow_mut().remove(action_name)
|
||||||
|
{
|
||||||
|
action.disconnect(signal_handler_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn connect_app_menu_action<
|
fn connect_app_menu_action<
|
||||||
F: Fn(&SimpleAction, std::option::Option<&glib::Variant>) + 'static,
|
F: Fn(&SimpleAction, std::option::Option<&glib::Variant>) + 'static,
|
||||||
>(
|
>(
|
||||||
|
@ -231,20 +253,8 @@ impl GPSApp {
|
||||||
action_name: &str,
|
action_name: &str,
|
||||||
f: F,
|
f: F,
|
||||||
) {
|
) {
|
||||||
let application = gio::Application::default()
|
let action = self.app_menu_action(action_name);
|
||||||
.expect("No default application")
|
self.disconnect_app_menu_action(action_name);
|
||||||
.downcast::<gtk::Application>()
|
|
||||||
.expect("Unable to downcast default application");
|
|
||||||
let action = application
|
|
||||||
.lookup_action(action_name)
|
|
||||||
.unwrap_or_else(|| panic!("Unable to find action {}", action_name))
|
|
||||||
.dynamic_cast::<SimpleAction>()
|
|
||||||
.expect("Unable to dynamic cast to SimpleAction");
|
|
||||||
|
|
||||||
if let Some(signal_handler_id) = self.menu_signal_handlers.borrow_mut().remove(action_name)
|
|
||||||
{
|
|
||||||
action.disconnect(signal_handler_id);
|
|
||||||
}
|
|
||||||
let signal_handler_id = action.connect_activate(f);
|
let signal_handler_id = action.connect_activate(f);
|
||||||
self.menu_signal_handlers
|
self.menu_signal_handlers
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
|
@ -459,7 +469,7 @@ impl GPSApp {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn display_plugin_list(app: &GPSApp) {
|
pub fn display_plugin_list(app: &GPSApp) {
|
||||||
let elements = Pipeline::elements_list().expect("Unable to obtain element's list");
|
let elements = ElementInfo::elements_list().expect("Unable to obtain element's list");
|
||||||
plugindialogs::display_plugin_list(app, &elements);
|
plugindialogs::display_plugin_list(app, &elements);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -660,9 +670,18 @@ impl GPSApp {
|
||||||
.object("port_menu")
|
.object("port_menu")
|
||||||
.expect("Couldn't get menu model for port");
|
.expect("Couldn't get menu model for port");
|
||||||
pop_menu.set_menu_model(Some(&menu));
|
pop_menu.set_menu_model(Some(&menu));
|
||||||
app.connect_app_menu_action("port.delete-link", move |_, _| {
|
|
||||||
GPS_DEBUG!("port.delete-link port {} node {}", port_id, node_id);
|
if app.graphview.borrow().can_remove_port(node_id, port_id) {
|
||||||
});
|
let app_weak = app.downgrade();
|
||||||
|
app.connect_app_menu_action("port.delete", move |_, _| {
|
||||||
|
let app = upgrade_weak!(app_weak);
|
||||||
|
GPS_DEBUG!("port.delete-link port {} node {}", port_id, node_id);
|
||||||
|
app.graphview.borrow().remove_port(node_id, port_id);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
app.disconnect_app_menu_action("port.delete");
|
||||||
|
}
|
||||||
|
|
||||||
pop_menu.show();
|
pop_menu.show();
|
||||||
None
|
None
|
||||||
},
|
},
|
||||||
|
@ -679,6 +698,7 @@ impl GPSApp {
|
||||||
let app = upgrade_weak!(app_weak, None);
|
let app = upgrade_weak!(app_weak, None);
|
||||||
|
|
||||||
let node_id = values[1].get::<u32>().expect("node id args[1]");
|
let node_id = values[1].get::<u32>().expect("node id args[1]");
|
||||||
|
let node = app.graphview.borrow().node(node_id).expect("Unable to find node with this ID");
|
||||||
let point = values[2].get::<graphene::Point>().expect("point in args[2]");
|
let point = values[2].get::<graphene::Point>().expect("point in args[2]");
|
||||||
|
|
||||||
let pop_menu = app.app_pop_menu_at_position(&*app.graphview.borrow(), point.to_vec2().x() as f64, point.to_vec2().y() as f64);
|
let pop_menu = app.app_pop_menu_at_position(&*app.graphview.borrow(), point.to_vec2().x() as f64, point.to_vec2().y() as f64);
|
||||||
|
@ -708,28 +728,33 @@ impl GPSApp {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
let app_weak = app.downgrade();
|
if ElementInfo::element_supports_new_pad_request(&node.name(), PortDirection::Input) {
|
||||||
app.connect_app_menu_action("node.request-pad-input",
|
let app_weak = app.downgrade();
|
||||||
move |_,_| {
|
app.connect_app_menu_action("node.request-pad-input",
|
||||||
let app = upgrade_weak!(app_weak);
|
move |_,_| {
|
||||||
GPS_DEBUG!("node.request-pad-input {}", node_id);
|
let app = upgrade_weak!(app_weak);
|
||||||
let mut node = app.graphview.borrow().node(node_id).unwrap();
|
GPS_DEBUG!("node.request-pad-input {}", node_id);
|
||||||
let port_id = app.graphview.borrow().next_port_id();
|
let port_id = app.graphview.borrow().next_port_id();
|
||||||
node.add_port(port_id, "in", PortDirection::Input);
|
app.graphview.borrow().add_port(node_id, port_id, "in", PortDirection::Input, PortPresence::Sometimes);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
app.disconnect_app_menu_action("node.request-pad-input");
|
||||||
|
}
|
||||||
|
if ElementInfo::element_supports_new_pad_request(&node.name(), PortDirection::Output) {
|
||||||
let app_weak = app.downgrade();
|
let app_weak = app.downgrade();
|
||||||
app.connect_app_menu_action("node.request-pad-output",
|
app.connect_app_menu_action("node.request-pad-output",
|
||||||
move |_,_| {
|
move |_,_| {
|
||||||
let app = upgrade_weak!(app_weak);
|
let app = upgrade_weak!(app_weak);
|
||||||
GPS_DEBUG!("node.request-pad-output {}", node_id);
|
GPS_DEBUG!("node.request-pad-output {}", node_id);
|
||||||
let mut node = app.graphview.borrow_mut().node(node_id).unwrap();
|
|
||||||
let port_id = app.graphview.borrow_mut().next_port_id();
|
let port_id = app.graphview.borrow_mut().next_port_id();
|
||||||
node.add_port(port_id, "out", PortDirection::Output);
|
app.graphview.borrow().add_port(node_id, port_id, "out", PortDirection::Output, PortPresence::Sometimes);
|
||||||
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
app.disconnect_app_menu_action("node.request-pad-output");
|
||||||
|
}
|
||||||
|
|
||||||
let app_weak = app.downgrade();
|
let app_weak = app.downgrade();
|
||||||
app.connect_app_menu_action("node.properties",
|
app.connect_app_menu_action("node.properties",
|
||||||
|
@ -771,8 +796,8 @@ impl GPSApp {
|
||||||
pub fn add_new_element(&self, element_name: &str) {
|
pub fn add_new_element(&self, element_name: &str) {
|
||||||
let graph_view = self.graphview.borrow();
|
let graph_view = self.graphview.borrow();
|
||||||
let node_id = graph_view.next_node_id();
|
let node_id = graph_view.next_node_id();
|
||||||
let pads = Pipeline::pads(element_name, false);
|
let (inputs, outputs) = PadInfo::pads(element_name, false);
|
||||||
if Pipeline::element_is_uri_src_handler(element_name) {
|
if ElementInfo::element_is_uri_src_handler(element_name) {
|
||||||
GPSApp::get_file_from_dialog(self, false, move |app, filename| {
|
GPSApp::get_file_from_dialog(self, false, move |app, filename| {
|
||||||
GPS_DEBUG!("Open file {}", filename);
|
GPS_DEBUG!("Open file {}", filename);
|
||||||
let node = app.graphview.borrow().node(node_id).unwrap();
|
let node = app.graphview.borrow().node(node_id).unwrap();
|
||||||
|
@ -783,9 +808,13 @@ impl GPSApp {
|
||||||
}
|
}
|
||||||
graph_view.add_node_with_port(
|
graph_view.add_node_with_port(
|
||||||
node_id,
|
node_id,
|
||||||
Node::new(node_id, element_name, Pipeline::element_type(element_name)),
|
Node::new(
|
||||||
pads.0,
|
node_id,
|
||||||
pads.1,
|
element_name,
|
||||||
|
ElementInfo::element_type(element_name),
|
||||||
|
),
|
||||||
|
inputs.len() as u32,
|
||||||
|
outputs.len() as u32,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,8 +31,8 @@
|
||||||
<menu id="port_menu">
|
<menu id="port_menu">
|
||||||
<section>
|
<section>
|
||||||
<item>
|
<item>
|
||||||
<attribute name="label" translatable="yes" comments="port menu entry delete the link">_Delete link</attribute>
|
<attribute name="label" translatable="yes" comments="port menu entry delete the link">_Delete</attribute>
|
||||||
<attribute name="action">app.port.delete-link</attribute>
|
<attribute name="action">app.port.delete</attribute>
|
||||||
</item>
|
</item>
|
||||||
</section>
|
</section>
|
||||||
</menu>
|
</menu>
|
||||||
|
|
222
src/gps/element.rs
Normal file
222
src/gps/element.rs
Normal file
|
@ -0,0 +1,222 @@
|
||||||
|
// element.rs
|
||||||
|
//
|
||||||
|
// Copyright 2022 Stéphane Cerveau <scerveau@collabora.com>
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
|
use crate::gps::PadInfo;
|
||||||
|
use crate::graphmanager::{NodeType, PortDirection, PortPresence};
|
||||||
|
use crate::logger;
|
||||||
|
use crate::GPS_INFO;
|
||||||
|
|
||||||
|
use gst::glib;
|
||||||
|
use gst::prelude::*;
|
||||||
|
use gstreamer as gst;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
#[derive(Debug, Eq, Ord, PartialEq, PartialOrd)]
|
||||||
|
pub struct ElementInfo {
|
||||||
|
pub name: Option<String>,
|
||||||
|
plugin_name: Option<String>,
|
||||||
|
rank: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for ElementInfo {
|
||||||
|
fn default() -> ElementInfo {
|
||||||
|
ElementInfo {
|
||||||
|
name: None,
|
||||||
|
plugin_name: None,
|
||||||
|
rank: -1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl ElementInfo {
|
||||||
|
pub fn elements_list() -> anyhow::Result<Vec<ElementInfo>> {
|
||||||
|
let registry = gst::Registry::get();
|
||||||
|
let mut elements: Vec<ElementInfo> = Vec::new();
|
||||||
|
let plugins = gst::Registry::plugin_list(®istry);
|
||||||
|
for plugin in plugins {
|
||||||
|
let plugin_name = gst::Plugin::plugin_name(&plugin);
|
||||||
|
let features = gst::Registry::feature_list_by_plugin(®istry, &plugin_name);
|
||||||
|
for feature in features {
|
||||||
|
let mut element = ElementInfo::default();
|
||||||
|
if let Ok(factory) = feature.downcast::<gst::ElementFactory>() {
|
||||||
|
let feature = factory.upcast::<gst::PluginFeature>();
|
||||||
|
|
||||||
|
element.name = Some(gst::PluginFeature::name(&feature).as_str().to_owned());
|
||||||
|
element.plugin_name =
|
||||||
|
Some(gst::Plugin::plugin_name(&plugin).as_str().to_owned());
|
||||||
|
elements.push(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elements.sort();
|
||||||
|
Ok(elements)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn element_feature(element_name: &str) -> Option<gst::PluginFeature> {
|
||||||
|
let registry = gst::Registry::get();
|
||||||
|
gst::Registry::find_feature(®istry, element_name, gst::ElementFactory::static_type())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn element_description(element_name: &str) -> anyhow::Result<String> {
|
||||||
|
let mut desc = String::from("");
|
||||||
|
let feature = ElementInfo::element_feature(element_name)
|
||||||
|
.ok_or_else(|| glib::bool_error!("Failed get element feature"))?;
|
||||||
|
|
||||||
|
if let Ok(factory) = feature.downcast::<gst::ElementFactory>() {
|
||||||
|
desc.push_str("<b>Factory details:</b>\n");
|
||||||
|
desc.push_str("<b>Name:</b>");
|
||||||
|
desc.push_str(&factory.name());
|
||||||
|
desc.push('\n');
|
||||||
|
|
||||||
|
let element_keys = factory.metadata_keys();
|
||||||
|
for key in element_keys {
|
||||||
|
let val = factory.metadata(&key);
|
||||||
|
if let Some(val) = val {
|
||||||
|
desc.push_str("<b>");
|
||||||
|
desc.push_str(&key);
|
||||||
|
desc.push_str("</b>:");
|
||||||
|
desc.push_str(>k::glib::markup_escape_text(&val).to_string());
|
||||||
|
desc.push('\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let feature = factory.upcast::<gst::PluginFeature>();
|
||||||
|
let plugin = gst::PluginFeature::plugin(&feature);
|
||||||
|
if let Some(plugin) = plugin {
|
||||||
|
desc.push('\n');
|
||||||
|
desc.push_str("<b>Plugin details:</b>");
|
||||||
|
desc.push('\n');
|
||||||
|
desc.push_str("<b>Name:");
|
||||||
|
desc.push_str("</b>");
|
||||||
|
desc.push_str(gst::Plugin::plugin_name(&plugin).as_str());
|
||||||
|
desc.push('\n');
|
||||||
|
desc.push_str("<b>Description:");
|
||||||
|
desc.push_str("</b>");
|
||||||
|
desc.push_str(>k::glib::markup_escape_text(&plugin.description()).to_string());
|
||||||
|
desc.push('\n');
|
||||||
|
desc.push_str("<b>Filename:");
|
||||||
|
desc.push_str("</b>");
|
||||||
|
desc.push_str(
|
||||||
|
>k::glib::markup_escape_text(
|
||||||
|
&plugin.filename().unwrap().as_path().display().to_string(),
|
||||||
|
)
|
||||||
|
.to_string(),
|
||||||
|
);
|
||||||
|
desc.push('\n');
|
||||||
|
desc.push_str("<b>Version:");
|
||||||
|
desc.push_str("</b>");
|
||||||
|
desc.push_str(>k::glib::markup_escape_text(&plugin.version()).to_string());
|
||||||
|
desc.push('\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(desc)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn element_type(element_name: &str) -> NodeType {
|
||||||
|
let (inputs, outputs) = PadInfo::pads(element_name, true);
|
||||||
|
let mut element_type = NodeType::Source;
|
||||||
|
if !inputs.is_empty() {
|
||||||
|
if !outputs.is_empty() {
|
||||||
|
element_type = NodeType::Transform;
|
||||||
|
} else {
|
||||||
|
element_type = NodeType::Sink;
|
||||||
|
}
|
||||||
|
} else if !outputs.is_empty() {
|
||||||
|
element_type = NodeType::Source;
|
||||||
|
}
|
||||||
|
|
||||||
|
element_type
|
||||||
|
}
|
||||||
|
|
||||||
|
fn value_as_str(v: &glib::Value) -> Option<String> {
|
||||||
|
match v.type_() {
|
||||||
|
glib::Type::I8 => Some(str_some_value!(v, i8).to_string()),
|
||||||
|
glib::Type::U8 => Some(str_some_value!(v, u8).to_string()),
|
||||||
|
glib::Type::BOOL => Some(str_some_value!(v, bool).to_string()),
|
||||||
|
glib::Type::I32 => Some(str_some_value!(v, i32).to_string()),
|
||||||
|
glib::Type::U32 => Some(str_some_value!(v, u32).to_string()),
|
||||||
|
glib::Type::I64 => Some(str_some_value!(v, i64).to_string()),
|
||||||
|
glib::Type::U64 => Some(str_some_value!(v, u64).to_string()),
|
||||||
|
glib::Type::F32 => Some(str_some_value!(v, f32).to_string()),
|
||||||
|
glib::Type::F64 => Some(str_some_value!(v, f64).to_string()),
|
||||||
|
glib::Type::STRING => str_opt_value!(v, String),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn element_properties(element_name: &str) -> anyhow::Result<HashMap<String, String>> {
|
||||||
|
let mut properties_list = HashMap::new();
|
||||||
|
let feature = ElementInfo::element_feature(element_name).expect("Unable to get feature");
|
||||||
|
|
||||||
|
let factory = feature
|
||||||
|
.downcast::<gst::ElementFactory>()
|
||||||
|
.expect("Unable to get the factory from the feature");
|
||||||
|
let element = factory.create(None)?;
|
||||||
|
let params = element.class().list_properties();
|
||||||
|
|
||||||
|
for param in params {
|
||||||
|
GPS_INFO!("Property_name {}", param.name());
|
||||||
|
if (param.flags() & glib::ParamFlags::READABLE) == glib::ParamFlags::READABLE
|
||||||
|
|| (param.flags() & glib::ParamFlags::READWRITE) == glib::ParamFlags::READWRITE
|
||||||
|
{
|
||||||
|
let value = ElementInfo::value_as_str(&element.property(param.name()).unwrap())
|
||||||
|
.unwrap_or_else(|| String::from(""));
|
||||||
|
properties_list.insert(String::from(param.name()), value);
|
||||||
|
} else if let Some(value) = ElementInfo::value_as_str(param.default_value()) {
|
||||||
|
properties_list.insert(String::from(param.name()), value);
|
||||||
|
} else {
|
||||||
|
GPS_INFO!("Unable to add property_name {}", param.name());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(properties_list)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn element_is_uri_src_handler(element_name: &str) -> bool {
|
||||||
|
let feature = ElementInfo::element_feature(element_name).expect("Unable to get feature");
|
||||||
|
|
||||||
|
let factory = feature
|
||||||
|
.downcast::<gst::ElementFactory>()
|
||||||
|
.expect("Unable to get the factory from the feature");
|
||||||
|
let element = factory
|
||||||
|
.create(None)
|
||||||
|
.expect("Unable to create an element from the feature");
|
||||||
|
match element.dynamic_cast::<gst::URIHandler>() {
|
||||||
|
Ok(uri_handler) => uri_handler.uri_type() == gst::URIType::Src,
|
||||||
|
Err(_e) => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn element_supports_new_pad_request(element_name: &str, direction: PortDirection) -> bool {
|
||||||
|
let (inputs, outputs) = PadInfo::pads(element_name, true);
|
||||||
|
if direction == PortDirection::Input {
|
||||||
|
for input in inputs {
|
||||||
|
if input.presence() == PortPresence::Sometimes {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if direction == PortDirection::Output {
|
||||||
|
for output in outputs {
|
||||||
|
if output.presence() == PortPresence::Sometimes {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
GPS_ERROR!("Port direction unknown");
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
7
src/gps/mod.rs
Normal file
7
src/gps/mod.rs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
mod element;
|
||||||
|
mod pad;
|
||||||
|
mod pipeline;
|
||||||
|
|
||||||
|
pub use element::ElementInfo;
|
||||||
|
pub use pad::PadInfo;
|
||||||
|
pub use pipeline::{Pipeline, PipelineState};
|
97
src/gps/pad.rs
Normal file
97
src/gps/pad.rs
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
// pad.rs
|
||||||
|
//
|
||||||
|
// Copyright 2022 Stéphane Cerveau <scerveau@collabora.com>
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
|
use crate::logger;
|
||||||
|
use crate::GPS_INFO;
|
||||||
|
|
||||||
|
use crate::gps::ElementInfo;
|
||||||
|
use crate::graphmanager::{PortDirection, PortPresence};
|
||||||
|
|
||||||
|
use gst::prelude::*;
|
||||||
|
use gstreamer as gst;
|
||||||
|
|
||||||
|
#[derive(Debug, PartialOrd, PartialEq)]
|
||||||
|
pub struct PadInfo {
|
||||||
|
name: Option<String>,
|
||||||
|
element_name: Option<String>,
|
||||||
|
direction: PortDirection,
|
||||||
|
presence: PortPresence,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for PadInfo {
|
||||||
|
fn default() -> PadInfo {
|
||||||
|
PadInfo {
|
||||||
|
name: None,
|
||||||
|
element_name: None,
|
||||||
|
direction: PortDirection::Unknown,
|
||||||
|
presence: PortPresence::Unknown,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl PadInfo {
|
||||||
|
pub fn presence(&self) -> PortPresence {
|
||||||
|
self.presence
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pad_to_port_presence(presence: gst::PadPresence) -> PortPresence {
|
||||||
|
match presence {
|
||||||
|
gst::PadPresence::Always => PortPresence::Always,
|
||||||
|
gst::PadPresence::Sometimes => PortPresence::Sometimes,
|
||||||
|
gst::PadPresence::Request => PortPresence::Sometimes,
|
||||||
|
_ => PortPresence::Unknown,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pads(element_name: &str, include_on_request: bool) -> (Vec<PadInfo>, Vec<PadInfo>) {
|
||||||
|
let feature = ElementInfo::element_feature(element_name).expect("Unable to get feature");
|
||||||
|
let mut input = vec![];
|
||||||
|
let mut output = vec![];
|
||||||
|
|
||||||
|
if let Ok(factory) = feature.downcast::<gst::ElementFactory>() {
|
||||||
|
if factory.num_pad_templates() > 0 {
|
||||||
|
let pads = factory.static_pad_templates();
|
||||||
|
for pad in pads {
|
||||||
|
GPS_INFO!("Found a pad name {}", pad.name_template());
|
||||||
|
if pad.presence() == gst::PadPresence::Always
|
||||||
|
|| (include_on_request
|
||||||
|
&& (pad.presence() == gst::PadPresence::Request
|
||||||
|
|| pad.presence() == gst::PadPresence::Sometimes))
|
||||||
|
{
|
||||||
|
if pad.direction() == gst::PadDirection::Src {
|
||||||
|
output.push(PadInfo {
|
||||||
|
name: Some(pad.name_template().to_string()),
|
||||||
|
element_name: Some(element_name.to_string()),
|
||||||
|
direction: PortDirection::Output,
|
||||||
|
presence: PadInfo::pad_to_port_presence(pad.presence()),
|
||||||
|
});
|
||||||
|
} else if pad.direction() == gst::PadDirection::Sink {
|
||||||
|
input.push(PadInfo {
|
||||||
|
name: Some(pad.name_template().to_string()),
|
||||||
|
element_name: Some(element_name.to_string()),
|
||||||
|
direction: PortDirection::Input,
|
||||||
|
presence: PadInfo::pad_to_port_presence(pad.presence()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(input, output)
|
||||||
|
}
|
||||||
|
}
|
|
@ -30,23 +30,6 @@ use std::fmt;
|
||||||
use std::ops;
|
use std::ops;
|
||||||
use std::rc::{Rc, Weak};
|
use std::rc::{Rc, Weak};
|
||||||
|
|
||||||
#[derive(Debug, Eq, Ord, PartialEq, PartialOrd)]
|
|
||||||
pub struct ElementInfo {
|
|
||||||
pub name: Option<String>,
|
|
||||||
plugin_name: Option<String>,
|
|
||||||
rank: i32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for ElementInfo {
|
|
||||||
fn default() -> ElementInfo {
|
|
||||||
ElementInfo {
|
|
||||||
name: None,
|
|
||||||
plugin_name: None,
|
|
||||||
rank: -1,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
pub enum PipelineState {
|
pub enum PipelineState {
|
||||||
Playing,
|
Playing,
|
||||||
|
@ -197,188 +180,6 @@ impl Pipeline {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn elements_list() -> anyhow::Result<Vec<ElementInfo>> {
|
|
||||||
let registry = gst::Registry::get();
|
|
||||||
let mut elements: Vec<ElementInfo> = Vec::new();
|
|
||||||
let plugins = gst::Registry::plugin_list(®istry);
|
|
||||||
for plugin in plugins {
|
|
||||||
let plugin_name = gst::Plugin::plugin_name(&plugin);
|
|
||||||
let features = gst::Registry::feature_list_by_plugin(®istry, &plugin_name);
|
|
||||||
for feature in features {
|
|
||||||
let mut element = ElementInfo::default();
|
|
||||||
if let Ok(factory) = feature.downcast::<gst::ElementFactory>() {
|
|
||||||
let feature = factory.upcast::<gst::PluginFeature>();
|
|
||||||
|
|
||||||
element.name = Some(gst::PluginFeature::name(&feature).as_str().to_owned());
|
|
||||||
element.plugin_name =
|
|
||||||
Some(gst::Plugin::plugin_name(&plugin).as_str().to_owned());
|
|
||||||
elements.push(element);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
elements.sort();
|
|
||||||
Ok(elements)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn element_feature(element_name: &str) -> Option<gst::PluginFeature> {
|
|
||||||
let registry = gst::Registry::get();
|
|
||||||
gst::Registry::find_feature(®istry, element_name, gst::ElementFactory::static_type())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn element_description(element_name: &str) -> anyhow::Result<String> {
|
|
||||||
let mut desc = String::from("");
|
|
||||||
let feature = Pipeline::element_feature(element_name)
|
|
||||||
.ok_or_else(|| glib::bool_error!("Failed get element feature"))?;
|
|
||||||
|
|
||||||
if let Ok(factory) = feature.downcast::<gst::ElementFactory>() {
|
|
||||||
desc.push_str("<b>Factory details:</b>\n");
|
|
||||||
desc.push_str("<b>Name:</b>");
|
|
||||||
desc.push_str(&factory.name());
|
|
||||||
desc.push('\n');
|
|
||||||
|
|
||||||
let element_keys = factory.metadata_keys();
|
|
||||||
for key in element_keys {
|
|
||||||
let val = factory.metadata(&key);
|
|
||||||
if let Some(val) = val {
|
|
||||||
desc.push_str("<b>");
|
|
||||||
desc.push_str(&key);
|
|
||||||
desc.push_str("</b>:");
|
|
||||||
desc.push_str(>k::glib::markup_escape_text(&val).to_string());
|
|
||||||
desc.push('\n');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let feature = factory.upcast::<gst::PluginFeature>();
|
|
||||||
let plugin = gst::PluginFeature::plugin(&feature);
|
|
||||||
if let Some(plugin) = plugin {
|
|
||||||
desc.push('\n');
|
|
||||||
desc.push_str("<b>Plugin details:</b>");
|
|
||||||
desc.push('\n');
|
|
||||||
desc.push_str("<b>Name:");
|
|
||||||
desc.push_str("</b>");
|
|
||||||
desc.push_str(gst::Plugin::plugin_name(&plugin).as_str());
|
|
||||||
desc.push('\n');
|
|
||||||
desc.push_str("<b>Description:");
|
|
||||||
desc.push_str("</b>");
|
|
||||||
desc.push_str(>k::glib::markup_escape_text(&plugin.description()).to_string());
|
|
||||||
desc.push('\n');
|
|
||||||
desc.push_str("<b>Filename:");
|
|
||||||
desc.push_str("</b>");
|
|
||||||
desc.push_str(
|
|
||||||
>k::glib::markup_escape_text(
|
|
||||||
&plugin.filename().unwrap().as_path().display().to_string(),
|
|
||||||
)
|
|
||||||
.to_string(),
|
|
||||||
);
|
|
||||||
desc.push('\n');
|
|
||||||
desc.push_str("<b>Version:");
|
|
||||||
desc.push_str("</b>");
|
|
||||||
desc.push_str(>k::glib::markup_escape_text(&plugin.version()).to_string());
|
|
||||||
desc.push('\n');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(desc)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pads(element_name: &str, include_on_request: bool) -> (u32, u32) {
|
|
||||||
let feature = Pipeline::element_feature(element_name).expect("Unable to get feature");
|
|
||||||
let mut input = 0;
|
|
||||||
let mut output = 0;
|
|
||||||
|
|
||||||
if let Ok(factory) = feature.downcast::<gst::ElementFactory>() {
|
|
||||||
if factory.num_pad_templates() > 0 {
|
|
||||||
let pads = factory.static_pad_templates();
|
|
||||||
for pad in pads {
|
|
||||||
if pad.presence() == gst::PadPresence::Always
|
|
||||||
|| (include_on_request
|
|
||||||
&& (pad.presence() == gst::PadPresence::Request
|
|
||||||
|| pad.presence() == gst::PadPresence::Sometimes))
|
|
||||||
{
|
|
||||||
if pad.direction() == gst::PadDirection::Src {
|
|
||||||
output += 1;
|
|
||||||
} else if pad.direction() == gst::PadDirection::Sink {
|
|
||||||
input += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(input, output)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn element_type(element_name: &str) -> NodeType {
|
|
||||||
let pads = Pipeline::pads(element_name, true);
|
|
||||||
let mut element_type = NodeType::Source;
|
|
||||||
if pads.0 > 0 {
|
|
||||||
if pads.1 > 0 {
|
|
||||||
element_type = NodeType::Transform;
|
|
||||||
} else {
|
|
||||||
element_type = NodeType::Sink;
|
|
||||||
}
|
|
||||||
} else if pads.1 > 0 {
|
|
||||||
element_type = NodeType::Source;
|
|
||||||
}
|
|
||||||
|
|
||||||
element_type
|
|
||||||
}
|
|
||||||
|
|
||||||
fn value_as_str(v: &glib::Value) -> Option<String> {
|
|
||||||
match v.type_() {
|
|
||||||
glib::Type::I8 => Some(str_some_value!(v, i8).to_string()),
|
|
||||||
glib::Type::U8 => Some(str_some_value!(v, u8).to_string()),
|
|
||||||
glib::Type::BOOL => Some(str_some_value!(v, bool).to_string()),
|
|
||||||
glib::Type::I32 => Some(str_some_value!(v, i32).to_string()),
|
|
||||||
glib::Type::U32 => Some(str_some_value!(v, u32).to_string()),
|
|
||||||
glib::Type::I64 => Some(str_some_value!(v, i64).to_string()),
|
|
||||||
glib::Type::U64 => Some(str_some_value!(v, u64).to_string()),
|
|
||||||
glib::Type::F32 => Some(str_some_value!(v, f32).to_string()),
|
|
||||||
glib::Type::F64 => Some(str_some_value!(v, f64).to_string()),
|
|
||||||
glib::Type::STRING => str_opt_value!(v, String),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn element_properties(element_name: &str) -> anyhow::Result<HashMap<String, String>> {
|
|
||||||
let mut properties_list = HashMap::new();
|
|
||||||
let feature = Pipeline::element_feature(element_name).expect("Unable to get feature");
|
|
||||||
|
|
||||||
let factory = feature
|
|
||||||
.downcast::<gst::ElementFactory>()
|
|
||||||
.expect("Unable to get the factory from the feature");
|
|
||||||
let element = factory.create(None)?;
|
|
||||||
let params = element.class().list_properties();
|
|
||||||
|
|
||||||
for param in params {
|
|
||||||
GPS_INFO!("Property_name {}", param.name());
|
|
||||||
if (param.flags() & glib::ParamFlags::READABLE) == glib::ParamFlags::READABLE
|
|
||||||
|| (param.flags() & glib::ParamFlags::READWRITE) == glib::ParamFlags::READWRITE
|
|
||||||
{
|
|
||||||
let value = Pipeline::value_as_str(&element.property(param.name()).unwrap())
|
|
||||||
.unwrap_or_else(|| String::from(""));
|
|
||||||
properties_list.insert(String::from(param.name()), value);
|
|
||||||
} else if let Some(value) = Pipeline::value_as_str(param.default_value()) {
|
|
||||||
properties_list.insert(String::from(param.name()), value);
|
|
||||||
} else {
|
|
||||||
GPS_INFO!("Unable to add property_name {}", param.name());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(properties_list)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn element_is_uri_src_handler(element_name: &str) -> bool {
|
|
||||||
let feature = Pipeline::element_feature(element_name).expect("Unable to get feature");
|
|
||||||
|
|
||||||
let factory = feature
|
|
||||||
.downcast::<gst::ElementFactory>()
|
|
||||||
.expect("Unable to get the factory from the feature");
|
|
||||||
let element = factory
|
|
||||||
.create(None)
|
|
||||||
.expect("Unable to create an element from the feature");
|
|
||||||
match element.dynamic_cast::<gst::URIHandler>() {
|
|
||||||
Ok(uri_handler) => uri_handler.uri_type() == gst::URIType::Src,
|
|
||||||
Err(_e) => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Render graph methods
|
// Render graph methods
|
||||||
fn process_gst_node(
|
fn process_gst_node(
|
||||||
&self,
|
&self,
|
|
@ -26,7 +26,7 @@ mod config;
|
||||||
mod graphmanager;
|
mod graphmanager;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod logger;
|
mod logger;
|
||||||
mod pipeline;
|
mod gps;
|
||||||
mod plugindialogs;
|
mod plugindialogs;
|
||||||
mod settings;
|
mod settings;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
|
|
|
@ -28,7 +28,10 @@ rust_sources = files(
|
||||||
'logger.rs',
|
'logger.rs',
|
||||||
'macros.rs',
|
'macros.rs',
|
||||||
'main.rs',
|
'main.rs',
|
||||||
'pipeline.rs',
|
'gps/pipeline.rs',
|
||||||
|
'gps/element.rs',
|
||||||
|
'gps/pad.rs',
|
||||||
|
'gps/mod.rs',
|
||||||
'plugindialogs.rs',
|
'plugindialogs.rs',
|
||||||
'settings.rs',
|
'settings.rs',
|
||||||
|
|
||||||
|
|
|
@ -17,9 +17,8 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
use crate::app::GPSApp;
|
use crate::app::GPSApp;
|
||||||
|
use crate::gps::ElementInfo;
|
||||||
use crate::logger;
|
use crate::logger;
|
||||||
use crate::pipeline::ElementInfo;
|
|
||||||
use crate::pipeline::Pipeline;
|
|
||||||
use gtk::glib;
|
use gtk::glib;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::TextBuffer;
|
use gtk::TextBuffer;
|
||||||
|
@ -93,7 +92,7 @@ pub fn display_plugin_list(app: &GPSApp, elements: &[ElementInfo]) {
|
||||||
if let Some((model, iter)) = selection.selected() {
|
if let Some((model, iter)) = selection.selected() {
|
||||||
let element_name = model
|
let element_name = model
|
||||||
.get::<String>(&iter, 1);
|
.get::<String>(&iter, 1);
|
||||||
let description = Pipeline::element_description(&element_name).expect("Unable to get element description from GStreamer");
|
let description = ElementInfo::element_description(&element_name).expect("Unable to get element description from GStreamer");
|
||||||
text_buffer.set_text("");
|
text_buffer.set_text("");
|
||||||
text_buffer.insert_markup(&mut text_buffer.end_iter(), &description);
|
text_buffer.insert_markup(&mut text_buffer.end_iter(), &description);
|
||||||
}
|
}
|
||||||
|
@ -133,7 +132,7 @@ pub fn display_plugin_properties(app: &GPSApp, element_name: &str, node_id: u32)
|
||||||
.expect("Couldn't get box-plugin-properties");
|
.expect("Couldn't get box-plugin-properties");
|
||||||
let update_properties: Rc<RefCell<HashMap<String, String>>> =
|
let update_properties: Rc<RefCell<HashMap<String, String>>> =
|
||||||
Rc::new(RefCell::new(HashMap::new()));
|
Rc::new(RefCell::new(HashMap::new()));
|
||||||
let properties = Pipeline::element_properties(element_name).unwrap();
|
let properties = ElementInfo::element_properties(element_name).unwrap();
|
||||||
for (name, value) in properties {
|
for (name, value) in properties {
|
||||||
let entry_box = Box::new(gtk::Orientation::Horizontal, 6);
|
let entry_box = Box::new(gtk::Orientation::Horizontal, 6);
|
||||||
let label = Label::new(Some(&name));
|
let label = Label::new(Some(&name));
|
||||||
|
|
Loading…
Reference in a new issue