pipewire connection: Show banner if disconnected

This commit is contained in:
Denis Drakhnia
2023-09-28 08:22:45 +03:00
parent 7d6aae70c5
commit 20f64595ac
8 changed files with 46 additions and 4 deletions

View File

@@ -15,7 +15,7 @@ categories = ["gui", "multimedia"]
[dependencies] [dependencies]
pipewire = "0.7.1" pipewire = "0.7.1"
adw = { version = "0.5", package = "libadwaita", features = ["v1_2"] } adw = { version = "0.5", package = "libadwaita", features = ["v1_3"] }
glib = { version = "0.18", features = ["log"] } glib = { version = "0.18", features = ["log"] }
log = "0.4.11" log = "0.4.11"

View File

@@ -12,7 +12,7 @@ base_id = 'org.pipewire.Helvum'
dependency('glib-2.0', version: '>= 2.66') dependency('glib-2.0', version: '>= 2.66')
dependency('gtk4', version: '>= 4.4.0') dependency('gtk4', version: '>= 4.4.0')
dependency('libadwaita-1', version: '>= 1.2') dependency('libadwaita-1', version: '>= 1.3')
dependency('libpipewire-0.3') dependency('libpipewire-0.3')
desktop_file_validate = find_program('desktop-file-validate', required: false) desktop_file_validate = find_program('desktop-file-validate', required: false)

View File

@@ -152,6 +152,7 @@ impl Application {
imp.graph_manager imp.graph_manager
.set(GraphManager::new( .set(GraphManager::new(
&imp.window.graph(), &imp.window.graph(),
&imp.window.connection_banner(),
pw_sender, pw_sender,
gtk_receiver, gtk_receiver,
)) ))

View File

@@ -35,6 +35,9 @@ mod imp {
#[property(get, set, construct_only)] #[property(get, set, construct_only)]
pub graph: OnceCell<crate::ui::graph::GraphView>, pub graph: OnceCell<crate::ui::graph::GraphView>,
#[property(get, set, construct_only)]
pub connection_banner: OnceCell<adw::Banner>,
pub pw_sender: OnceCell<PwSender<crate::GtkMessage>>, pub pw_sender: OnceCell<PwSender<crate::GtkMessage>>,
pub items: RefCell<HashMap<u32, glib::Object>>, pub items: RefCell<HashMap<u32, glib::Object>>,
} }
@@ -66,7 +69,15 @@ mod imp {
PipewireMessage::NodeRemoved { id } => imp.remove_node(id), PipewireMessage::NodeRemoved { id } => imp.remove_node(id),
PipewireMessage::PortRemoved { id, node_id } => imp.remove_port(id, node_id), PipewireMessage::PortRemoved { id, node_id } => imp.remove_port(id, node_id),
PipewireMessage::LinkRemoved { id } => imp.remove_link(id), PipewireMessage::LinkRemoved { id } => imp.remove_link(id),
PipewireMessage::Disconnected => imp.clear(), PipewireMessage::Connecting => {
imp.obj().connection_banner().set_revealed(true);
}
PipewireMessage::Connected => {
imp.obj().connection_banner().set_revealed(false);
},
PipewireMessage::Disconnected => {
imp.clear();
},
}; };
glib::ControlFlow::Continue glib::ControlFlow::Continue
} }
@@ -296,10 +307,14 @@ glib::wrapper! {
impl GraphManager { impl GraphManager {
pub fn new( pub fn new(
graph: &GraphView, graph: &GraphView,
connection_banner: &adw::Banner,
sender: PwSender<GtkMessage>, sender: PwSender<GtkMessage>,
receiver: glib::Receiver<PipewireMessage>, receiver: glib::Receiver<PipewireMessage>,
) -> Self { ) -> Self {
let res: Self = glib::Object::builder().property("graph", graph).build(); let res: Self = glib::Object::builder()
.property("graph", graph)
.property("connection-banner", connection_banner)
.build();
res.imp().attach_receiver(receiver); res.imp().attach_receiver(receiver);
assert!( assert!(

View File

@@ -74,6 +74,8 @@ pub enum PipewireMessage {
LinkRemoved { LinkRemoved {
id: u32, id: u32,
}, },
Connecting,
Connected,
Disconnected, Disconnected,
} }

View File

@@ -61,12 +61,20 @@ pub(super) fn thread_main(
let mainloop = MainLoop::new().expect("Failed to create mainloop"); let mainloop = MainLoop::new().expect("Failed to create mainloop");
let context = Rc::new(Context::new(&mainloop).expect("Failed to create context")); let context = Rc::new(Context::new(&mainloop).expect("Failed to create context"));
let is_stopped = Rc::new(Cell::new(false)); let is_stopped = Rc::new(Cell::new(false));
let mut is_connecting = false;
while !is_stopped.get() { while !is_stopped.get() {
// Try to connect // Try to connect
let core = match context.connect(None) { let core = match context.connect(None) {
Ok(core) => Rc::new(core), Ok(core) => Rc::new(core),
Err(_) => { Err(_) => {
if !is_connecting {
is_connecting = true;
gtk_sender
.send(PipewireMessage::Connecting)
.expect("Failed to send message");
}
// If connection is failed, try to connect again in 200ms // If connection is failed, try to connect again in 200ms
let interval = Some(Duration::from_millis(200)); let interval = Some(Duration::from_millis(200));
@@ -93,6 +101,13 @@ pub(super) fn thread_main(
} }
}; };
if is_connecting {
is_connecting = false;
gtk_sender
.send(PipewireMessage::Connected)
.expect("Failed to send message");
}
let registry = Rc::new(core.get_registry().expect("Failed to get registry")); let registry = Rc::new(core.get_registry().expect("Failed to get registry"));
// Keep proxies and their listeners alive so that we can receive info events. // Keep proxies and their listeners alive so that we can receive info events.

View File

@@ -12,6 +12,9 @@ mod imp {
#[template_child] #[template_child]
pub header_bar: TemplateChild<adw::HeaderBar>, pub header_bar: TemplateChild<adw::HeaderBar>,
#[template_child] #[template_child]
#[property(type = adw::Banner, get = |_| self.connection_banner.clone())]
pub connection_banner: TemplateChild<adw::Banner>,
#[template_child]
#[property(type = graph::GraphView, get = |_| self.graph.clone())] #[property(type = graph::GraphView, get = |_| self.graph.clone())]
pub graph: TemplateChild<graph::GraphView>, pub graph: TemplateChild<graph::GraphView>,
} }

View File

@@ -39,6 +39,12 @@
</child> </child>
</object> </object>
</child> </child>
<child>
<object class="AdwBanner" id="connection_banner">
<property name="title" translatable="yes">Disconnected</property>
<property name="revealed">false</property>
</object>
</child>
<child> <child>
<object class="GtkScrolledWindow"> <object class="GtkScrolledWindow">
<child> <child>