Color ports depending on the type of data (audio,video,midi) they carry

This commit is contained in:
Tom A. Wagner
2021-02-09 12:51:35 +01:00
parent 926829de22
commit ec8de4a4a7
3 changed files with 89 additions and 7 deletions

View File

@@ -6,6 +6,24 @@ use gtk::prelude::*;
use std::{cell::RefCell, rc::Rc};
// FIXME: This should be in its own .css file.
static STYLE: &str = "
.audio {
background: rgb(50,100,240);
color: black;
}
.video {
background: rgb(200,200,0);
color: black;
}
.midi {
background: rgb(200,0,50);
color: black;
}
";
#[derive(Debug)]
pub struct PipewireLink {
pub node_from: u32,
@@ -36,6 +54,17 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let app = gtk::Application::new(Some("org.freedesktop.pipewire.graphui"), Default::default())
.expect("Application creation failed");
app.connect_startup(|_| {
// Load CSS from the STYLE variable.
let provider = gtk::CssProvider::new();
provider.load_from_data(STYLE.as_bytes());
gtk::StyleContext::add_provider_for_display(
&gtk::gdk::Display::get_default().expect("Error initializing gtk css provider."),
&provider,
gtk::STYLE_PROVIDER_PRIORITY_APPLICATION,
);
});
app.connect_activate(move |app| {
let scrollwindow = gtk::ScrolledWindowBuilder::new()
.child(&*graphview.borrow())

View File

@@ -1,6 +1,8 @@
use crate::{view, PipewireLink};
use gtk::WidgetExt;
use libspa::dict::ReadableDict;
use log::warn;
use pipewire::{
port::Direction,
registry::{GlobalObject, ObjectType},
@@ -8,9 +10,20 @@ use pipewire::{
use std::{cell::RefCell, collections::HashMap, rc::Rc};
enum MediaType {
Audio,
Video,
Midi,
}
enum Item {
Node(view::Node),
Port { node_id: u32 },
Node {
widget: view::Node,
media_type: Option<MediaType>,
},
Port {
node_id: u32,
},
Link,
}
@@ -56,6 +69,7 @@ impl PipewireState {
let node_widget = crate::view::Node::new(&format!(
"{}",
node.props
.as_ref()
.map(|dict| String::from(
dict.get("node.nick")
.or(dict.get("node.description"))
@@ -64,12 +78,38 @@ impl PipewireState {
))
.unwrap_or_default()
));
// FIXME: This relies on the node being passed to us by the pipwire server before its port.
let media_type = node
.props
.map(|props| {
props.get("media.class").map(|class| {
if class.contains("Audio") {
Some(MediaType::Audio)
} else if class.contains("Video") {
Some(MediaType::Video)
} else if class.contains("Midi") {
Some(MediaType::Midi)
} else {
None
}
})
})
.flatten()
.flatten();
self.graphview
.borrow_mut()
.add_node(node.id, node_widget.clone());
// Save the created widget so we can delete ports easier.
self.items.insert(node.id, Item::Node(node_widget));
self.items.insert(
node.id,
Item::Node {
widget: node_widget,
media_type,
},
);
}
fn add_port(&mut self, port: GlobalObject) {
@@ -91,6 +131,18 @@ impl PipewireState {
},
);
// Color the port accordingly to its media class.
if let Some(Item::Node { media_type, .. }) = self.items.get(&node_id) {
match media_type {
Some(MediaType::Audio) => new_port.widget.add_css_class("audio"),
Some(MediaType::Video) => new_port.widget.add_css_class("video"),
Some(MediaType::Midi) => new_port.widget.add_css_class("midi"),
None => {}
}
} else {
warn!("Node not found for Port {}", port.id);
}
self.graphview
.borrow_mut()
.add_port_to_node(node_id, new_port.id, new_port);
@@ -100,6 +152,7 @@ impl PipewireState {
}
fn add_link(&mut self, link: GlobalObject) {
// FIXME: Links should be colored depending on the data they carry (video, audio, midi) like ports are.
self.items.insert(link.id, Item::Link);
// Update graph to contain the new link.
@@ -139,7 +192,7 @@ impl PipewireState {
pub fn global_remove(&mut self, id: u32) {
if let Some(item) = self.items.get(&id) {
match item {
Item::Node(_) => self.remove_node(id),
Item::Node { .. } => self.remove_node(id),
Item::Port { node_id } => self.remove_port(id, *node_id),
Item::Link => self.remove_link(id),
}
@@ -158,8 +211,8 @@ impl PipewireState {
}
fn remove_port(&self, id: u32, node_id: u32) {
if let Some(Item::Node(node)) = self.items.get(&node_id) {
node.remove_port(id);
if let Some(Item::Node { widget, .. }) = self.items.get(&node_id) {
widget.remove_port(id);
}
}

View File

@@ -1,6 +1,6 @@
/// Graphical representation of a pipewire port.
pub struct Port {
pub(super) widget: gtk::Button,
pub widget: gtk::Button,
pub id: u32,
pub direction: pipewire::port::Direction,
}