mirror of
https://gitlab.freedesktop.org/dabrain34/GstPipelineStudio.git
synced 2024-11-22 00:50:59 +00:00
graphbook: introduce element_factory_exists
This method helps to tell if a factory exists when loading a graph. If the factory does not exists, use light mode to display it and prevent some menu item and change its description.
This commit is contained in:
parent
111750a33b
commit
f4be2299b9
5 changed files with 155 additions and 117 deletions
|
@ -100,3 +100,7 @@
|
||||||
### app
|
### app
|
||||||
- [x] Add multiple graphviews with tabs.
|
- [x] Add multiple graphviews with tabs.
|
||||||
- [x] handle the caps setter element
|
- [x] handle the caps setter element
|
||||||
|
|
||||||
|
## 0.3.2
|
||||||
|
### app
|
||||||
|
- [x] check that element exists before creating it on file load.
|
2
TODO.md
2
TODO.md
|
@ -15,7 +15,6 @@
|
||||||
- [ ] unable to connect element with incompatible caps.
|
- [ ] unable to connect element with incompatible caps.
|
||||||
- [ ] Implement graph dot render/load
|
- [ ] Implement graph dot render/load
|
||||||
|
|
||||||
|
|
||||||
- [ ] Add probes on each pad to monitor the pipeline
|
- [ ] Add probes on each pad to monitor the pipeline
|
||||||
- [ ] Render a media file
|
- [ ] Render a media file
|
||||||
- [ ] Offer compatible element to a pad (autorender)
|
- [ ] Offer compatible element to a pad (autorender)
|
||||||
|
@ -32,7 +31,6 @@
|
||||||
|
|
||||||
## bugs
|
## bugs
|
||||||
|
|
||||||
- [ ] check that element exists before creating it on file load.
|
|
||||||
- [ ] Combo box is not well selected if the value is not linear such as flags. See flags in playbin
|
- [ ] Combo box is not well selected if the value is not linear such as flags. See flags in playbin
|
||||||
- [ ] opening a graph file can lead a different behavior in the pipeline. See videomixer graph where the zorder
|
- [ ] opening a graph file can lead a different behavior in the pipeline. See videomixer graph where the zorder
|
||||||
on pads is not correctly set to right one.
|
on pads is not correctly set to right one.
|
||||||
|
|
|
@ -46,6 +46,19 @@ impl ElementInfo {
|
||||||
Ok(elements)
|
Ok(elements)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn element_factory_exists(element_name: &str) -> bool {
|
||||||
|
match ElementInfo::element_feature(element_name) {
|
||||||
|
Some(_feature) => {
|
||||||
|
GPS_DEBUG!("Found element factory name {}", element_name);
|
||||||
|
true
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
GPS_ERROR!("Unable to find element factory name {}", element_name);
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn element_feature(element_name: &str) -> Option<gst::PluginFeature> {
|
pub fn element_feature(element_name: &str) -> Option<gst::PluginFeature> {
|
||||||
let registry = gst::Registry::get();
|
let registry = gst::Registry::get();
|
||||||
gst::Registry::find_feature(®istry, element_name, gst::ElementFactory::static_type())
|
gst::Registry::find_feature(®istry, element_name, gst::ElementFactory::static_type())
|
||||||
|
@ -60,59 +73,68 @@ impl ElementInfo {
|
||||||
|
|
||||||
pub fn element_description(element_name: &str) -> anyhow::Result<String> {
|
pub fn element_description(element_name: &str) -> anyhow::Result<String> {
|
||||||
let mut desc = String::from("");
|
let mut desc = String::from("");
|
||||||
let feature = ElementInfo::element_feature(element_name)
|
if !ElementInfo::element_factory_exists(element_name) {
|
||||||
.ok_or_else(|| glib::bool_error!("Failed get element feature"))?;
|
|
||||||
let rank = feature.rank();
|
|
||||||
if let Ok(factory) = feature.downcast::<gst::ElementFactory>() {
|
|
||||||
desc.push_str("<b>Factory details:</b>\n");
|
desc.push_str("<b>Factory details:</b>\n");
|
||||||
desc.push_str("<b>Rank:</b>");
|
|
||||||
let _ = write!(desc, "{rank:?}",);
|
|
||||||
desc.push('\n');
|
|
||||||
desc.push_str("<b>Name:</b>");
|
desc.push_str("<b>Name:</b>");
|
||||||
desc.push_str(&factory.name());
|
desc.push_str(element_name);
|
||||||
desc.push('\n');
|
desc.push('\n');
|
||||||
|
desc.push('\n');
|
||||||
|
desc.push_str("Factory unavailable.");
|
||||||
|
} else {
|
||||||
|
let feature = ElementInfo::element_feature(element_name)
|
||||||
|
.ok_or_else(|| glib::bool_error!("Failed get element feature"))?;
|
||||||
|
let rank = feature.rank();
|
||||||
|
if let Ok(factory) = feature.downcast::<gst::ElementFactory>() {
|
||||||
|
desc.push_str("<b>Factory details:</b>\n");
|
||||||
|
desc.push_str("<b>Rank:</b>");
|
||||||
|
let _ = write!(desc, "{rank:?}",);
|
||||||
|
desc.push('\n');
|
||||||
|
desc.push_str("<b>Name:</b>");
|
||||||
|
desc.push_str(&factory.name());
|
||||||
|
desc.push('\n');
|
||||||
|
|
||||||
let element_keys = factory.metadata_keys();
|
let element_keys = factory.metadata_keys();
|
||||||
for key in element_keys {
|
for key in element_keys {
|
||||||
let val = factory.metadata(&key);
|
let val = factory.metadata(&key);
|
||||||
if let Some(val) = val {
|
if let Some(val) = val {
|
||||||
desc.push_str("<b>");
|
desc.push_str("<b>");
|
||||||
desc.push_str(&key);
|
desc.push_str(&key);
|
||||||
desc.push_str("</b>:");
|
desc.push_str("</b>:");
|
||||||
desc.push_str(>k::glib::markup_escape_text(val));
|
desc.push_str(>k::glib::markup_escape_text(val));
|
||||||
|
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()));
|
||||||
|
desc.push('\n');
|
||||||
|
desc.push_str("<b>Filename:");
|
||||||
|
desc.push_str("</b>");
|
||||||
|
desc.push_str(>k::glib::markup_escape_text(
|
||||||
|
&plugin
|
||||||
|
.filename()
|
||||||
|
.unwrap_or_default()
|
||||||
|
.as_path()
|
||||||
|
.display()
|
||||||
|
.to_string(),
|
||||||
|
));
|
||||||
|
desc.push('\n');
|
||||||
|
desc.push_str("<b>Version:");
|
||||||
|
desc.push_str("</b>");
|
||||||
|
desc.push_str(>k::glib::markup_escape_text(&plugin.version()));
|
||||||
desc.push('\n');
|
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()));
|
|
||||||
desc.push('\n');
|
|
||||||
desc.push_str("<b>Filename:");
|
|
||||||
desc.push_str("</b>");
|
|
||||||
desc.push_str(>k::glib::markup_escape_text(
|
|
||||||
&plugin
|
|
||||||
.filename()
|
|
||||||
.unwrap_or_default()
|
|
||||||
.as_path()
|
|
||||||
.display()
|
|
||||||
.to_string(),
|
|
||||||
));
|
|
||||||
desc.push('\n');
|
|
||||||
desc.push_str("<b>Version:");
|
|
||||||
desc.push_str("</b>");
|
|
||||||
desc.push_str(>k::glib::markup_escape_text(&plugin.version()));
|
|
||||||
desc.push('\n');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Ok(desc)
|
Ok(desc)
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,41 +51,43 @@ impl PadInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pads(element_name: &str, include_on_request: bool) -> (Vec<PadInfo>, Vec<PadInfo>) {
|
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 input = vec![];
|
||||||
let mut output = vec![];
|
let mut output = vec![];
|
||||||
|
if let Some(feature) = ElementInfo::element_feature(element_name) {
|
||||||
if let Ok(factory) = feature.downcast::<gst::ElementFactory>() {
|
if let Ok(factory) = feature.downcast::<gst::ElementFactory>() {
|
||||||
if factory.num_pad_templates() > 0 {
|
if factory.num_pad_templates() > 0 {
|
||||||
let pads = factory.static_pad_templates();
|
let pads = factory.static_pad_templates();
|
||||||
for pad in pads {
|
for pad in pads {
|
||||||
GPS_TRACE!("Found a pad name {}", pad.name_template());
|
GPS_TRACE!("Found a pad name {}", pad.name_template());
|
||||||
if pad.presence() == gst::PadPresence::Always
|
if pad.presence() == gst::PadPresence::Always
|
||||||
|| (include_on_request
|
|| (include_on_request
|
||||||
&& (pad.presence() == gst::PadPresence::Request
|
&& (pad.presence() == gst::PadPresence::Request
|
||||||
|| pad.presence() == gst::PadPresence::Sometimes))
|
|| pad.presence() == gst::PadPresence::Sometimes))
|
||||||
{
|
{
|
||||||
if pad.direction() == gst::PadDirection::Src {
|
if pad.direction() == gst::PadDirection::Src {
|
||||||
output.push(PadInfo {
|
output.push(PadInfo {
|
||||||
name: Some(pad.name_template().to_string()),
|
name: Some(pad.name_template().to_string()),
|
||||||
element_name: Some(element_name.to_string()),
|
element_name: Some(element_name.to_string()),
|
||||||
direction: PortDirection::Output,
|
direction: PortDirection::Output,
|
||||||
presence: PadInfo::pad_to_port_presence(pad.presence()),
|
presence: PadInfo::pad_to_port_presence(pad.presence()),
|
||||||
caps: Some(pad.caps().to_string()),
|
caps: Some(pad.caps().to_string()),
|
||||||
});
|
});
|
||||||
} else if pad.direction() == gst::PadDirection::Sink {
|
} else if pad.direction() == gst::PadDirection::Sink {
|
||||||
input.push(PadInfo {
|
input.push(PadInfo {
|
||||||
name: Some(pad.name_template().to_string()),
|
name: Some(pad.name_template().to_string()),
|
||||||
element_name: Some(element_name.to_string()),
|
element_name: Some(element_name.to_string()),
|
||||||
direction: PortDirection::Input,
|
direction: PortDirection::Input,
|
||||||
presence: PadInfo::pad_to_port_presence(pad.presence()),
|
presence: PadInfo::pad_to_port_presence(pad.presence()),
|
||||||
caps: Some(pad.caps().to_string()),
|
caps: Some(pad.caps().to_string()),
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
(input, output)
|
||||||
|
} else {
|
||||||
|
(input, output)
|
||||||
}
|
}
|
||||||
(input, output)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -242,6 +242,10 @@ pub fn create_graphtab(app: &GPSApp, id: u32, name: Option<&str>) {
|
||||||
if let Some(node) = current_graphtab(&app).graphview().node(node_id) {
|
if let Some(node) = current_graphtab(&app).graphview().node(node_id) {
|
||||||
let description = GPS::ElementInfo::element_description(&node.name()).ok();
|
let description = GPS::ElementInfo::element_description(&node.name()).ok();
|
||||||
node.set_tooltip_markup(description.as_deref());
|
node.set_tooltip_markup(description.as_deref());
|
||||||
|
if !GPS::ElementInfo::element_factory_exists(&node.name()) {
|
||||||
|
node.set_light(true);
|
||||||
|
node.set_tooltip_markup(description.as_deref());
|
||||||
|
}
|
||||||
for port in node.all_ports(GM::PortDirection::All) {
|
for port in node.all_ports(GM::PortDirection::All) {
|
||||||
let caps = PropertyExt::property(&port,"_caps");
|
let caps = PropertyExt::property(&port,"_caps");
|
||||||
GPS_DEBUG!("caps={} for port id {}", caps.clone().unwrap_or_else(|| "caps unknown".to_string()), port.id());
|
GPS_DEBUG!("caps={} for port id {}", caps.clone().unwrap_or_else(|| "caps unknown".to_string()), port.id());
|
||||||
|
@ -382,6 +386,8 @@ pub fn create_graphtab(app: &GPSApp, id: u32, name: Option<&str>) {
|
||||||
glib::clone!(@weak graphbook => @default-return None, move |values: &[Value]| {
|
glib::clone!(@weak graphbook => @default-return None, move |values: &[Value]| {
|
||||||
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 = current_graphtab(&app).graphview().node(node_id).unwrap();
|
||||||
|
let element_exists = GPS::ElementInfo::element_factory_exists(&node.name());
|
||||||
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(&*current_graphtab(&app).graphview(), point.to_vec2().x() as f64, point.to_vec2().y() as f64);
|
let pop_menu = app.app_pop_menu_at_position(&*current_graphtab(&app).graphview(), point.to_vec2().x() as f64, point.to_vec2().y() as f64);
|
||||||
let menu: gio::MenuModel = app
|
let menu: gio::MenuModel = app
|
||||||
|
@ -390,16 +396,6 @@ pub fn create_graphtab(app: &GPSApp, id: u32, name: Option<&str>) {
|
||||||
.expect("Couldn't get menu model for node");
|
.expect("Couldn't get menu model for node");
|
||||||
pop_menu.set_menu_model(Some(&menu));
|
pop_menu.set_menu_model(Some(&menu));
|
||||||
|
|
||||||
let app_weak = app.downgrade();
|
|
||||||
app.connect_app_menu_action("node.add-to-favorite",
|
|
||||||
move |_,_| {
|
|
||||||
let app = upgrade_weak!(app_weak);
|
|
||||||
GPS_DEBUG!("node.add-to-favorite id: {}", node_id);
|
|
||||||
if let Some(node) = current_graphtab(&app).graphview().node(node_id) {
|
|
||||||
GPSUI::elements::add_to_favorite_list(&app, node.name());
|
|
||||||
};
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
let app_weak = app.downgrade();
|
let app_weak = app.downgrade();
|
||||||
app.connect_app_menu_action("node.delete",
|
app.connect_app_menu_action("node.delete",
|
||||||
|
@ -409,42 +405,56 @@ pub fn create_graphtab(app: &GPSApp, id: u32, name: Option<&str>) {
|
||||||
current_graphtab(&app).graphview().remove_node(node_id);
|
current_graphtab(&app).graphview().remove_node(node_id);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
let node = app.node(node_id);
|
if element_exists {
|
||||||
if let Some(input) = GPS::ElementInfo::element_supports_new_pad_request(&node.name(), GM::PortDirection::Input) {
|
|
||||||
let app_weak = app.downgrade();
|
let app_weak = app.downgrade();
|
||||||
app.connect_app_menu_action("node.request-pad-input",
|
app.connect_app_menu_action("node.add-to-favorite",
|
||||||
move |_,_| {
|
move |_,_| {
|
||||||
let app = upgrade_weak!(app_weak);
|
let app = upgrade_weak!(app_weak);
|
||||||
GPS_DEBUG!("node.request-pad-input id: {}", node_id);
|
GPS_DEBUG!("node.add-to-favorite id: {}", node_id);
|
||||||
app.create_port_with_caps(node_id, GM::PortDirection::Input, GM::PortPresence::Sometimes, input.caps().to_string());
|
if let Some(node) = current_graphtab(&app).graphview().node(node_id) {
|
||||||
|
GPSUI::elements::add_to_favorite_list(&app, node.name());
|
||||||
|
};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} else {
|
|
||||||
app.disconnect_app_menu_action("node.request-pad-input");
|
|
||||||
}
|
|
||||||
let node = app.node(node_id);
|
|
||||||
if let Some(output) = GPS::ElementInfo::element_supports_new_pad_request(&node.name(), GM::PortDirection::Output) {
|
|
||||||
let app_weak = app.downgrade();
|
|
||||||
app.connect_app_menu_action("node.request-pad-output",
|
|
||||||
move |_,_| {
|
|
||||||
let app = upgrade_weak!(app_weak);
|
|
||||||
GPS_DEBUG!("node.request-pad-output id: {}", node_id);
|
|
||||||
app.create_port_with_caps(node_id, GM::PortDirection::Output, GM::PortPresence::Sometimes, output.caps().to_string());
|
|
||||||
}
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
app.disconnect_app_menu_action("node.request-pad-output");
|
|
||||||
}
|
|
||||||
|
|
||||||
let app_weak = app.downgrade();
|
|
||||||
app.connect_app_menu_action("node.properties",
|
let node = app.node(node_id);
|
||||||
move |_,_| {
|
if let Some(input) = GPS::ElementInfo::element_supports_new_pad_request(&node.name(), GM::PortDirection::Input) {
|
||||||
let app = upgrade_weak!(app_weak);
|
let app_weak = app.downgrade();
|
||||||
GPS_DEBUG!("node.properties id {}", node_id);
|
app.connect_app_menu_action("node.request-pad-input",
|
||||||
let node = current_graphtab(&app).graphview().node(node_id).unwrap();
|
move |_,_| {
|
||||||
GPSUI::properties::display_plugin_properties(&app, &node.name(), node_id);
|
let app = upgrade_weak!(app_weak);
|
||||||
|
GPS_DEBUG!("node.request-pad-input id: {}", node_id);
|
||||||
|
app.create_port_with_caps(node_id, GM::PortDirection::Input, GM::PortPresence::Sometimes, input.caps().to_string());
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
app.disconnect_app_menu_action("node.request-pad-input");
|
||||||
}
|
}
|
||||||
);
|
let node = app.node(node_id);
|
||||||
|
if let Some(output) = GPS::ElementInfo::element_supports_new_pad_request(&node.name(), GM::PortDirection::Output) {
|
||||||
|
let app_weak = app.downgrade();
|
||||||
|
app.connect_app_menu_action("node.request-pad-output",
|
||||||
|
move |_,_| {
|
||||||
|
let app = upgrade_weak!(app_weak);
|
||||||
|
GPS_DEBUG!("node.request-pad-output id: {}", node_id);
|
||||||
|
app.create_port_with_caps(node_id, GM::PortDirection::Output, GM::PortPresence::Sometimes, output.caps().to_string());
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
app.disconnect_app_menu_action("node.request-pad-output");
|
||||||
|
}
|
||||||
|
|
||||||
|
let app_weak = app.downgrade();
|
||||||
|
app.connect_app_menu_action("node.properties",
|
||||||
|
move |_,_| {
|
||||||
|
let app = upgrade_weak!(app_weak);
|
||||||
|
GPS_DEBUG!("node.properties id {}", node_id);
|
||||||
|
let node = current_graphtab(&app).graphview().node(node_id).unwrap();
|
||||||
|
GPSUI::properties::display_plugin_properties(&app, &node.name(), node_id);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
pop_menu.show();
|
pop_menu.show();
|
||||||
None
|
None
|
||||||
}),
|
}),
|
||||||
|
@ -459,7 +469,9 @@ pub fn create_graphtab(app: &GPSApp, id: u32, name: Option<&str>) {
|
||||||
let node_id = values[1].get::<u32>().expect("node id args[1]");
|
let node_id = values[1].get::<u32>().expect("node id args[1]");
|
||||||
GPS_TRACE!("Node double clicked id={}", node_id);
|
GPS_TRACE!("Node double clicked id={}", node_id);
|
||||||
let node = current_graphtab(&app).graphview().node(node_id).unwrap();
|
let node = current_graphtab(&app).graphview().node(node_id).unwrap();
|
||||||
GPSUI::properties::display_plugin_properties(&app, &node.name(), node_id);
|
if GPS::ElementInfo::element_factory_exists(&node.name()) {
|
||||||
|
GPSUI::properties::display_plugin_properties(&app, &node.name(), node_id);
|
||||||
|
}
|
||||||
None
|
None
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in a new issue