mirror of
https://gitlab.freedesktop.org/dabrain34/GstPipelineStudio.git
synced 2024-11-24 18:10:59 +00:00
logger: implement a logger with treeview
Any log should be now visible in the logger tree view according to the level.
This commit is contained in:
parent
d291c93352
commit
3731a92d51
7 changed files with 172 additions and 21 deletions
6
TODO.md
6
TODO.md
|
@ -9,7 +9,7 @@ TODO:
|
|||
- [x] Create connection between element
|
||||
- [] Control the connection between element
|
||||
- [x] unable to connect in and in out and out
|
||||
- [] unable to connnec element with incompatible caps.
|
||||
- [] unable to connect element with incompatible caps.
|
||||
- [x] unable to connect a port which is already connected
|
||||
- [x] create contextual menu on pad or element
|
||||
- [] upclass the element
|
||||
|
@ -22,7 +22,7 @@ TODO:
|
|||
- [] check that a node accept to create a port on request (input/output)
|
||||
- [x] select nodes/links with a Trait Selectable
|
||||
- [x] be able to remove a link by selecting it
|
||||
- [] Connect the logs to the window
|
||||
- [x] Connect the logs to the window
|
||||
- [] Create a window for the video output
|
||||
- [] Add multiple graphviews with tabs.
|
||||
|
||||
|
@ -30,7 +30,7 @@ TODO:
|
|||
|
||||
- [x] crash with x11 on contextual menu
|
||||
- [] check that element exists before creating it on file load.
|
||||
- [] open multiple times dialog (About) prevent to close it.
|
||||
- [x] open multiple times dialog (About) prevent to close it.
|
||||
|
||||
## Code cleanup
|
||||
|
||||
|
|
70
src/app.rs
70
src/app.rs
|
@ -31,9 +31,11 @@ use std::collections::HashMap;
|
|||
use std::rc::{Rc, Weak};
|
||||
use std::{error, ops};
|
||||
|
||||
use crate::logger;
|
||||
use crate::pipeline::{Pipeline, PipelineState};
|
||||
use crate::plugindialogs;
|
||||
use crate::settings::Settings;
|
||||
use crate::{GPS_DEBUG, GPS_ERROR};
|
||||
|
||||
use crate::graphmanager::{GraphView, Node, PortDirection};
|
||||
|
||||
|
@ -189,6 +191,39 @@ impl GPSApp {
|
|||
dialog.set_resizable(false);
|
||||
dialog.show();
|
||||
}
|
||||
fn reset_logger_list(&self, logger_list: &TreeView) {
|
||||
let model = ListStore::new(&[String::static_type()]);
|
||||
logger_list.set_model(Some(&model));
|
||||
}
|
||||
|
||||
fn setup_logger_list(&self) {
|
||||
let logger_list: TreeView = self
|
||||
.builder
|
||||
.object("logger_list")
|
||||
.expect("Couldn't get window");
|
||||
let column = TreeViewColumn::new();
|
||||
let cell = CellRendererText::new();
|
||||
|
||||
column.pack_start(&cell, true);
|
||||
// Association of the view's column with the model's `id` column.
|
||||
column.add_attribute(&cell, "text", 0);
|
||||
column.set_title("");
|
||||
logger_list.append_column(&column);
|
||||
self.reset_logger_list(&logger_list);
|
||||
}
|
||||
|
||||
fn add_to_logger_list(&self, log_entry: String) {
|
||||
let logger_list: TreeView = self
|
||||
.builder
|
||||
.object("logger_list")
|
||||
.expect("Couldn't get window");
|
||||
if let Some(model) = logger_list.model() {
|
||||
let list_store = model
|
||||
.dynamic_cast::<ListStore>()
|
||||
.expect("Could not cast to ListStore");
|
||||
list_store.insert_with_values(None, &[(0, &log_entry)]);
|
||||
}
|
||||
}
|
||||
|
||||
fn reset_favorite_list(&self, favorite_list: &TreeView) {
|
||||
let model = ListStore::new(&[String::static_type()]);
|
||||
|
@ -222,7 +257,7 @@ impl GPSApp {
|
|||
.get(&iter, 0)
|
||||
.get::<String>()
|
||||
.expect("Treeview selection, column 1");
|
||||
println!("{}", element_name);
|
||||
GPS_DEBUG!("{}", element_name);
|
||||
app.add_new_element(&element_name);
|
||||
}
|
||||
});
|
||||
|
@ -239,7 +274,7 @@ impl GPSApp {
|
|||
.get(&iter, 0)
|
||||
.get::<String>()
|
||||
.expect("Treeview selection, column 1");
|
||||
println!("{}", element_name);
|
||||
GPS_DEBUG!("{}", element_name);
|
||||
let point = graphene::Point::new(x as f32,y as f32);
|
||||
|
||||
|
||||
|
@ -292,6 +327,7 @@ impl GPSApp {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn display_plugin_list(app: &GPSApp) {
|
||||
let elements = Pipeline::elements_list().expect("Unable to obtain element's list");
|
||||
plugindialogs::display_plugin_list(app, &elements);
|
||||
|
@ -321,7 +357,7 @@ impl GPSApp {
|
|||
let app = upgrade_weak!(app_weak);
|
||||
GPSApp::get_file_from_dialog(&app, false, move |app, filename|
|
||||
{
|
||||
println!("Open file {}", filename);
|
||||
//logger::print_log(format!("Open file {}", filename));
|
||||
app.load_graph(&filename).expect("Unable to open file");
|
||||
});
|
||||
}));
|
||||
|
@ -336,7 +372,7 @@ impl GPSApp {
|
|||
let app = upgrade_weak!(app_weak);
|
||||
GPSApp::get_file_from_dialog(&app, true, move |app, filename|
|
||||
{
|
||||
println!("Save file {}", filename);
|
||||
GPS_DEBUG!("Save file {}", filename);
|
||||
app.save_graph(&filename).expect("Unable to save file");
|
||||
});
|
||||
}));
|
||||
|
@ -373,6 +409,7 @@ impl GPSApp {
|
|||
move |_, _| {
|
||||
let app = upgrade_weak!(app_weak);
|
||||
app.clear_graph();
|
||||
GPS_ERROR!("clear graph");
|
||||
}
|
||||
});
|
||||
application.add_action(&action);
|
||||
|
@ -538,7 +575,7 @@ impl GPSApp {
|
|||
// add an action to delete link
|
||||
let action = gio::SimpleAction::new("port.delete-link", None);
|
||||
action.connect_activate(glib::clone!(@weak pop_menu => move |_,_| {
|
||||
println!("port.delete-link port {} node {}", port_id, node_id);
|
||||
GPS_DEBUG!("port.delete-link port {} node {}", port_id, node_id);
|
||||
pop_menu.unparent();
|
||||
}));
|
||||
application.add_action(&action);
|
||||
|
@ -580,7 +617,7 @@ impl GPSApp {
|
|||
let app_weak = app.downgrade();
|
||||
action.connect_activate(glib::clone!(@weak pop_menu => move |_,_| {
|
||||
let app = upgrade_weak!(app_weak);
|
||||
println!("node.delete {}", node_id);
|
||||
GPS_DEBUG!("node.delete {}", node_id);
|
||||
let node = app.graphview.borrow().node(&node_id).unwrap();
|
||||
app.add_to_favorite_list(node.name());
|
||||
pop_menu.unparent();
|
||||
|
@ -590,7 +627,7 @@ impl GPSApp {
|
|||
let app_weak = app.downgrade();
|
||||
action.connect_activate(glib::clone!(@weak pop_menu => move |_,_| {
|
||||
let app = upgrade_weak!(app_weak);
|
||||
println!("node.delete {}", node_id);
|
||||
GPS_DEBUG!("node.delete {}", node_id);
|
||||
app.graphview.borrow_mut().remove_node(node_id);
|
||||
pop_menu.unparent();
|
||||
}));
|
||||
|
@ -600,7 +637,7 @@ impl GPSApp {
|
|||
let app_weak = app.downgrade();
|
||||
action.connect_activate(glib::clone!(@weak pop_menu => move |_,_| {
|
||||
let app = upgrade_weak!(app_weak);
|
||||
println!("node.request-pad-input {}", node_id);
|
||||
GPS_DEBUG!("node.request-pad-input {}", node_id);
|
||||
let mut node = app.graphview.borrow_mut().node(&node_id).unwrap();
|
||||
let port_id = app.graphview.borrow().next_port_id();
|
||||
node.add_port(port_id, "in", PortDirection::Input);
|
||||
|
@ -612,7 +649,7 @@ impl GPSApp {
|
|||
let app_weak = app.downgrade();
|
||||
action.connect_activate(glib::clone!(@weak pop_menu => move |_,_| {
|
||||
let app = upgrade_weak!(app_weak);
|
||||
println!("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();
|
||||
node.add_port(port_id, "out", PortDirection::Output);
|
||||
|
@ -622,7 +659,7 @@ impl GPSApp {
|
|||
|
||||
let action = gio::SimpleAction::new("node.properties", None);
|
||||
action.connect_activate(glib::clone!(@weak pop_menu => move |_,_| {
|
||||
println!("node.properties {}", node_id);
|
||||
GPS_DEBUG!("node.properties {}", node_id);
|
||||
let node = app.graphview.borrow().node(&node_id).unwrap();
|
||||
plugindialogs::display_plugin_properties(&app, &node.name(), node_id);
|
||||
pop_menu.unparent();
|
||||
|
@ -638,6 +675,17 @@ impl GPSApp {
|
|||
|
||||
// Setup the favorite list
|
||||
self.setup_favorite_list();
|
||||
|
||||
// Setup the logger to get messages into the TreeView
|
||||
let (ready_tx, ready_rx) = glib::MainContext::channel(glib::PRIORITY_DEFAULT);
|
||||
let app_weak = self.downgrade();
|
||||
logger::init_logger(ready_tx, logger::LogLevel::Debug);
|
||||
self.setup_logger_list();
|
||||
let _ = ready_rx.attach(None, move |msg: String| {
|
||||
let app = upgrade_weak!(app_weak, glib::Continue(false));
|
||||
app.add_to_logger_list(msg);
|
||||
glib::Continue(true)
|
||||
});
|
||||
}
|
||||
|
||||
// Downgrade to a weak reference
|
||||
|
@ -654,7 +702,7 @@ impl GPSApp {
|
|||
let pads = Pipeline::pads(element_name, false);
|
||||
if Pipeline::element_is_uri_src_handler(element_name) {
|
||||
GPSApp::get_file_from_dialog(self, false, move |app, filename| {
|
||||
println!("Open file {}", filename);
|
||||
GPS_DEBUG!("Open file {}", filename);
|
||||
let node = app.graphview.borrow().node(&node_id).unwrap();
|
||||
let mut properties: HashMap<String, String> = HashMap::new();
|
||||
properties.insert(String::from("location"), filename);
|
||||
|
|
|
@ -270,7 +270,7 @@
|
|||
<object class="GtkScrolledWindow">
|
||||
<property name="valign">end</property>
|
||||
<property name="child">
|
||||
<object class="GtkTreeView"/>
|
||||
<object class="GtkTreeView" id="logger_list"/>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
|
|
97
src/logger.rs
Normal file
97
src/logger.rs
Normal file
|
@ -0,0 +1,97 @@
|
|||
use glib::Sender;
|
||||
use gtk::glib;
|
||||
use once_cell::sync::Lazy;
|
||||
use once_cell::sync::OnceCell;
|
||||
use std::cell::RefCell;
|
||||
use std::fmt;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
#[derive(Default)]
|
||||
struct Logger {
|
||||
pub log_sender: OnceCell<Arc<Mutex<RefCell<Sender<String>>>>>,
|
||||
pub log_level: OnceCell<LogLevel>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, Ord, PartialEq, PartialOrd)]
|
||||
pub enum LogLevel {
|
||||
Error,
|
||||
_Warning,
|
||||
Info,
|
||||
_Log,
|
||||
Debug,
|
||||
}
|
||||
impl fmt::Display for LogLevel {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! GPS_ERROR (
|
||||
() => ($crate::print!("\n"));
|
||||
($($arg:tt)*) => ({
|
||||
logger::print_log(logger::LogLevel::Error, format_args!($($arg)*).to_string());
|
||||
})
|
||||
);
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! GPS_WARN (
|
||||
() => ($crate::print!("\n"));
|
||||
($($arg:tt)*) => ({
|
||||
logger::print_log(logger::LogLevel::Warning, format_args!($($arg)*).to_string());
|
||||
})
|
||||
);
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! GPS_INFO (
|
||||
() => ($crate::print!("\n"));
|
||||
($($arg:tt)*) => ({
|
||||
logger::print_log(logger::LogLevel::Info, format_args!($($arg)*).to_string());
|
||||
})
|
||||
);
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! GPS_LOG (
|
||||
() => ($crate::print!("\n"));
|
||||
($($arg:tt)*) => ({
|
||||
logger::print_log(logger::LogLevel::Log, format_args!($($arg)*).to_string());
|
||||
})
|
||||
);
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! GPS_DEBUG (
|
||||
() => ($crate::print!("\n"));
|
||||
($($arg:tt)*) => ({
|
||||
logger::print_log(logger::LogLevel::Debug, format_args!($($arg)*).to_string());
|
||||
})
|
||||
);
|
||||
|
||||
static LOGGER: Lazy<Logger> = Lazy::new(Logger::default);
|
||||
|
||||
pub fn init_logger(sender: Sender<String>, log_level: LogLevel) {
|
||||
LOGGER
|
||||
.log_sender
|
||||
.set(Arc::new(Mutex::new(RefCell::new(sender))))
|
||||
.expect("init logger should be called once");
|
||||
let _ = LOGGER.log_level.set(log_level);
|
||||
}
|
||||
|
||||
pub fn print_log(log_level: LogLevel, msg: String) {
|
||||
if log_level
|
||||
<= *LOGGER
|
||||
.log_level
|
||||
.get()
|
||||
.expect("Logger should be initialized before calling print_log")
|
||||
{
|
||||
let mut sender = LOGGER
|
||||
.log_sender
|
||||
.get()
|
||||
.expect("Logger should be initialized before calling print_log")
|
||||
.lock()
|
||||
.expect("guarded");
|
||||
|
||||
if let Err(e) = sender.get_mut().send(format!("{}:{}", log_level, msg)) {
|
||||
println!("Error: {}", e)
|
||||
};
|
||||
}
|
||||
}
|
|
@ -22,6 +22,8 @@ mod macros;
|
|||
mod app;
|
||||
mod common;
|
||||
mod graphmanager;
|
||||
#[macro_use]
|
||||
mod logger;
|
||||
mod pipeline;
|
||||
mod plugindialogs;
|
||||
mod settings;
|
||||
|
|
|
@ -18,6 +18,9 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
use crate::app::GPSApp;
|
||||
use crate::graphmanager::{GraphView, Node, NodeType, PortDirection};
|
||||
use crate::logger;
|
||||
use crate::GPS_INFO;
|
||||
|
||||
use gst::prelude::*;
|
||||
use gstreamer as gst;
|
||||
use std::cell::{Cell, RefCell};
|
||||
|
@ -95,7 +98,7 @@ impl Pipeline {
|
|||
}
|
||||
|
||||
pub fn create_pipeline(&self, description: &str) -> Result<(), Box<dyn error::Error>> {
|
||||
println!("Creating pipeline {}", description);
|
||||
GPS_INFO!("Creating pipeline {}", description);
|
||||
|
||||
/* create playbin */
|
||||
|
||||
|
@ -335,7 +338,7 @@ impl Pipeline {
|
|||
let params = element.class().list_properties();
|
||||
|
||||
for param in params {
|
||||
println!("Property_name {}", param.name());
|
||||
GPS_INFO!("Property_name {}", param.name());
|
||||
if (param.flags() & glib::ParamFlags::READABLE) == glib::ParamFlags::READABLE
|
||||
|| (param.flags() & glib::ParamFlags::READWRITE) == glib::ParamFlags::READWRITE
|
||||
{
|
||||
|
@ -345,7 +348,7 @@ impl Pipeline {
|
|||
} else if let Some(value) = Pipeline::value_as_str(param.default_value()) {
|
||||
properties_list.insert(String::from(param.name()), value);
|
||||
} else {
|
||||
println!("Unable to add property_name {}", param.name());
|
||||
GPS_INFO!("Unable to add property_name {}", param.name());
|
||||
}
|
||||
}
|
||||
Ok(properties_list)
|
||||
|
|
|
@ -4,6 +4,7 @@ use std::path::PathBuf;
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::common;
|
||||
use crate::logger;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Default)]
|
||||
pub struct Settings {
|
||||
|
@ -18,7 +19,7 @@ impl Settings {
|
|||
if let Some(parent_dir) = s.parent() {
|
||||
if !parent_dir.exists() {
|
||||
if let Err(e) = create_dir_all(parent_dir) {
|
||||
println!(
|
||||
GPS_ERROR!(
|
||||
"Error while trying to build settings snapshot_directory '{}': {}",
|
||||
parent_dir.display(),
|
||||
e
|
||||
|
@ -64,7 +65,7 @@ impl Settings {
|
|||
Settings::settings_file_exist();
|
||||
let s = Settings::get_settings_file_path();
|
||||
if let Err(e) = serde_any::to_file(&s, settings) {
|
||||
println!("Error while trying to save file: {} {}", s.display(), e);
|
||||
GPS_ERROR!("Error while trying to save file: {} {}", s.display(), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,7 +76,7 @@ impl Settings {
|
|||
match serde_any::from_file::<Settings, _>(&s) {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
println!("Error while opening '{}': {}", s.display(), e);
|
||||
GPS_ERROR!("Error while opening '{}': {}", s.display(), e);
|
||||
Settings::default()
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue