feat: Add conditional features based on daemon capabilities

This commit is contained in:
Fabio Lenherr / DashieTM 2024-04-05 12:54:05 +02:00
parent 9dbf4228fc
commit f8f23faece
7 changed files with 207 additions and 89 deletions

View file

@ -4,7 +4,7 @@ use std::sync::Arc;
use gtk::FlowBox; use gtk::FlowBox;
use crate::components::base::utils::{Listeners, Position}; use crate::components::{base::utils::{Listeners, Position}, utils::Capabilities};
// extern "C" { // extern "C" {
// pub fn startup() -> SidebarInfo; // pub fn startup() -> SidebarInfo;
@ -12,7 +12,7 @@ use crate::components::base::utils::{Listeners, Position};
// pub fn run_test(); // pub fn run_test();
// } // }
pub type RegularClickEvent = fn(Arc<Listeners>, FlowBox, Rc<RefCell<Position>>); pub type RegularClickEvent = fn(&Capabilities, Arc<Listeners>, FlowBox, Rc<RefCell<Position>>);
pub type PluginClickEvent = Rc<dyn Fn(FlowBox, Rc<RefCell<Position>>, Vec<gtk::Box>)>; pub type PluginClickEvent = Rc<dyn Fn(FlowBox, Rc<RefCell<Position>>, Vec<gtk::Box>)>;
pub trait TSideBarInfo { pub trait TSideBarInfo {
@ -28,7 +28,9 @@ pub struct ReSetSidebarInfo {
pub name: &'static str, pub name: &'static str,
pub icon_name: &'static str, pub icon_name: &'static str,
pub parent: Option<&'static str>, pub parent: Option<&'static str>,
// pub pre_click:
pub click_event: RegularClickEvent, pub click_event: RegularClickEvent,
// pub post_click:
} }
impl TSideBarInfo for ReSetSidebarInfo { impl TSideBarInfo for ReSetSidebarInfo {

View file

@ -1,6 +1,11 @@
use std::cell::Cell;
use std::time::Duration;
use adw::gdk::pango::EllipsizeMode; use adw::gdk::pango::EllipsizeMode;
use adw::prelude::ListModelExtManual; use adw::prelude::ListModelExtManual;
use adw::{ActionRow, ComboRow}; use adw::{ActionRow, ComboRow};
use dbus::blocking::Connection;
use dbus::Error;
use glib::prelude::Cast; use glib::prelude::Cast;
use glib::Object; use glib::Object;
use gtk::prelude::{GObjectPropertyExpressionExt, ListBoxRowExt, ListItemExt, WidgetExt}; use gtk::prelude::{GObjectPropertyExpressionExt, ListBoxRowExt, ListItemExt, WidgetExt};
@ -12,6 +17,21 @@ pub const BLUETOOTH: &str = "org.Xetibo.ReSet.Bluetooth";
pub const AUDIO: &str = "org.Xetibo.ReSet.Audio"; pub const AUDIO: &str = "org.Xetibo.ReSet.Audio";
pub const BASE: &str = "org.Xetibo.ReSet.Daemon"; pub const BASE: &str = "org.Xetibo.ReSet.Daemon";
#[derive(Default)]
pub struct Capabilities {
pub wifi: Cell<bool>,
pub bluetooth: Cell<bool>,
pub audio: Cell<bool>,
}
impl Capabilities {
pub fn set(&self, wifi: bool, bluetooth: bool, audio: bool) {
self.wifi.set(wifi);
self.bluetooth.set(bluetooth);
self.audio.set(audio);
}
}
pub fn create_dropdown_label_factory() -> SignalListItemFactory { pub fn create_dropdown_label_factory() -> SignalListItemFactory {
let factory = SignalListItemFactory::new(); let factory = SignalListItemFactory::new();
factory.connect_setup(|_, item| { factory.connect_setup(|_, item| {
@ -68,3 +88,10 @@ pub fn set_action_row_ellipsis(element: ActionRow) {
} }
} }
} }
pub fn get_capabilities() -> Vec<String> {
let conn = Connection::new_session().unwrap();
let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000));
let res: Result<(Vec<String>,), Error> = proxy.method_call(BASE, "GetCapabilities", ());
res.unwrap().0
}

View file

@ -0,0 +1,48 @@
use crate::components::plugin::function::ReSetSidebarInfo;
use super::handle_sidebar_click::{
HANDLE_AUDIO_CLICK, HANDLE_BLUETOOTH_CLICK, HANDLE_CONNECTIVITY_CLICK, HANDLE_MICROPHONE_CLICK,
HANDLE_VOLUME_CLICK, HANDLE_WIFI_CLICK,
};
pub const CONNECTIVITY_SIDEBAR: ReSetSidebarInfo = ReSetSidebarInfo {
name: "Connectivity",
icon_name: "network-wired-symbolic",
parent: None,
click_event: HANDLE_CONNECTIVITY_CLICK,
};
pub const WIFI_SIDEBAR: ReSetSidebarInfo = ReSetSidebarInfo {
name: "WiFi",
icon_name: "network-wireless-symbolic",
parent: Some("Connectivity"),
click_event: HANDLE_WIFI_CLICK,
};
pub const BLUETOOTH_SIDEBAR: ReSetSidebarInfo = ReSetSidebarInfo {
name: "Bluetooth",
icon_name: "bluetooth-symbolic",
parent: Some("Connectivity"),
click_event: HANDLE_BLUETOOTH_CLICK,
};
pub const AUDIO_SIDEBAR: ReSetSidebarInfo = ReSetSidebarInfo {
name: "Audio",
icon_name: "audio-headset-symbolic",
parent: None,
click_event: HANDLE_AUDIO_CLICK,
};
pub const SINK_SIDEBAR: ReSetSidebarInfo = ReSetSidebarInfo {
name: "Output",
icon_name: "audio-volume-high-symbolic",
parent: Some("Audio"),
click_event: HANDLE_VOLUME_CLICK,
};
pub const SOURCE_SIDEBAR: ReSetSidebarInfo = ReSetSidebarInfo {
name: "Input",
icon_name: "audio-input-microphone-symbolic",
parent: Some("Audio"),
click_event: HANDLE_MICROPHONE_CLICK,
};

View file

@ -12,63 +12,96 @@ use crate::components::base::utils::{start_audio_listener, Listeners, Position};
use crate::components::bluetooth::bluetooth_box::{ use crate::components::bluetooth::bluetooth_box::{
populate_connected_bluetooth_devices, BluetoothBox, populate_connected_bluetooth_devices, BluetoothBox,
}; };
use crate::components::utils::Capabilities;
use crate::components::wifi::wifi_box::{ use crate::components::wifi::wifi_box::{
scan_for_wifi, show_stored_connections, start_event_listener, WifiBox, scan_for_wifi, show_stored_connections, start_event_listener, WifiBox,
}; };
use gtk::prelude::WidgetExt; use gtk::prelude::WidgetExt;
use gtk::{Align, FlowBox, FlowBoxChild, Frame}; use gtk::{Align, FlowBox, FlowBoxChild, Frame};
pub const HANDLE_CONNECTIVITY_CLICK: fn(Arc<Listeners>, FlowBox, Rc<RefCell<Position>>) = pub const HANDLE_CONNECTIVITY_CLICK: fn(
|listeners: Arc<Listeners>, reset_main: FlowBox, position: Rc<RefCell<Position>>| { &Capabilities,
if handle_init(listeners.clone(), position, Position::Connectivity) { Arc<Listeners>,
return; FlowBox,
} Rc<RefCell<Position>>,
) = |capabilities: &Capabilities,
listeners: Arc<Listeners>,
reset_main: FlowBox,
position: Rc<RefCell<Position>>| {
if handle_init(listeners.clone(), position, Position::Connectivity) {
return;
}
reset_main.remove_all();
let mut count = 0;
if capabilities.wifi.get() {
let wifi_box = WifiBox::new(listeners.clone()); let wifi_box = WifiBox::new(listeners.clone());
start_event_listener(listeners.clone(), wifi_box.clone()); start_event_listener(listeners.clone(), wifi_box.clone());
show_stored_connections(wifi_box.clone()); show_stored_connections(wifi_box.clone());
scan_for_wifi(wifi_box.clone()); scan_for_wifi(wifi_box.clone());
let wifi_frame = wrap_in_flow_box_child(SettingBox::new(&*wifi_box)); let wifi_frame = wrap_in_flow_box_child(SettingBox::new(&*wifi_box));
reset_main.insert(&wifi_frame, -1);
count += 1;
}
if capabilities.bluetooth.get() {
let bluetooth_box = BluetoothBox::new(listeners.clone()); let bluetooth_box = BluetoothBox::new(listeners.clone());
populate_connected_bluetooth_devices(listeners, bluetooth_box.clone()); populate_connected_bluetooth_devices(listeners, bluetooth_box.clone());
// start_bluetooth_listener(listeners, bluetooth_box.clone());
let bluetooth_frame = wrap_in_flow_box_child(SettingBox::new(&*bluetooth_box)); let bluetooth_frame = wrap_in_flow_box_child(SettingBox::new(&*bluetooth_box));
reset_main.remove_all();
reset_main.insert(&wifi_frame, -1);
reset_main.insert(&bluetooth_frame, -1); reset_main.insert(&bluetooth_frame, -1);
reset_main.set_max_children_per_line(2); count += 1;
}; }
pub const HANDLE_WIFI_CLICK: fn(Arc<Listeners>, FlowBox, Rc<RefCell<Position>>) = reset_main.set_max_children_per_line(count);
|listeners: Arc<Listeners>, reset_main: FlowBox, position: Rc<RefCell<Position>>| { };
pub const HANDLE_WIFI_CLICK: fn(&Capabilities, Arc<Listeners>, FlowBox, Rc<RefCell<Position>>) =
|_: &Capabilities,
listeners: Arc<Listeners>,
reset_main: FlowBox,
position: Rc<RefCell<Position>>| {
if handle_init(listeners.clone(), position, Position::Wifi) { if handle_init(listeners.clone(), position, Position::Wifi) {
return; return;
} }
reset_main.remove_all();
let wifi_box = WifiBox::new(listeners.clone()); let wifi_box = WifiBox::new(listeners.clone());
start_event_listener(listeners, wifi_box.clone()); start_event_listener(listeners, wifi_box.clone());
show_stored_connections(wifi_box.clone()); show_stored_connections(wifi_box.clone());
scan_for_wifi(wifi_box.clone()); scan_for_wifi(wifi_box.clone());
let wifi_frame = wrap_in_flow_box_child(SettingBox::new(&*wifi_box)); let wifi_frame = wrap_in_flow_box_child(SettingBox::new(&*wifi_box));
reset_main.remove_all();
reset_main.insert(&wifi_frame, -1); reset_main.insert(&wifi_frame, -1);
reset_main.set_max_children_per_line(1); reset_main.set_max_children_per_line(1);
}; };
pub const HANDLE_BLUETOOTH_CLICK: fn(Arc<Listeners>, FlowBox, Rc<RefCell<Position>>) = pub const HANDLE_BLUETOOTH_CLICK: fn(
|listeners: Arc<Listeners>, reset_main: FlowBox, position: Rc<RefCell<Position>>| { &Capabilities,
if handle_init(listeners.clone(), position, Position::Bluetooth) { Arc<Listeners>,
return; FlowBox,
} Rc<RefCell<Position>>,
let bluetooth_box = BluetoothBox::new(listeners.clone()); ) = |_: &Capabilities,
populate_connected_bluetooth_devices(listeners, bluetooth_box.clone()); listeners: Arc<Listeners>,
// start_bluetooth_listener(listeners, bluetooth_box.clone()); reset_main: FlowBox,
let bluetooth_frame = wrap_in_flow_box_child(SettingBox::new(&*bluetooth_box)); position: Rc<RefCell<Position>>| {
reset_main.remove_all(); if handle_init(listeners.clone(), position, Position::Bluetooth) {
reset_main.insert(&bluetooth_frame, -1); return;
reset_main.set_max_children_per_line(1); }
}; let bluetooth_box = BluetoothBox::new(listeners.clone());
populate_connected_bluetooth_devices(listeners, bluetooth_box.clone());
// start_bluetooth_listener(listeners, bluetooth_box.clone());
let bluetooth_frame = wrap_in_flow_box_child(SettingBox::new(&*bluetooth_box));
reset_main.remove_all();
reset_main.insert(&bluetooth_frame, -1);
reset_main.set_max_children_per_line(1);
};
pub const HANDLE_AUDIO_CLICK: fn(Arc<Listeners>, FlowBox, Rc<RefCell<Position>>) = pub const HANDLE_AUDIO_CLICK: fn(&Capabilities, Arc<Listeners>, FlowBox, Rc<RefCell<Position>>) =
|listeners: Arc<Listeners>, reset_main: FlowBox, position: Rc<RefCell<Position>>| { |_: &Capabilities,
listeners: Arc<Listeners>,
reset_main: FlowBox,
position: Rc<RefCell<Position>>| {
if handle_init(listeners.clone(), position, Position::Audio) { if handle_init(listeners.clone(), position, Position::Audio) {
return; return;
} }
@ -92,8 +125,11 @@ pub const HANDLE_AUDIO_CLICK: fn(Arc<Listeners>, FlowBox, Rc<RefCell<Position>>)
reset_main.set_max_children_per_line(2); reset_main.set_max_children_per_line(2);
}; };
pub const HANDLE_VOLUME_CLICK: fn(Arc<Listeners>, FlowBox, Rc<RefCell<Position>>) = pub const HANDLE_VOLUME_CLICK: fn(&Capabilities, Arc<Listeners>, FlowBox, Rc<RefCell<Position>>) =
|listeners: Arc<Listeners>, reset_main: FlowBox, position: Rc<RefCell<Position>>| { |_: &Capabilities,
listeners: Arc<Listeners>,
reset_main: FlowBox,
position: Rc<RefCell<Position>>| {
if handle_init(listeners.clone(), position, Position::AudioOutput) { if handle_init(listeners.clone(), position, Position::AudioOutput) {
return; return;
} }
@ -109,25 +145,35 @@ pub const HANDLE_VOLUME_CLICK: fn(Arc<Listeners>, FlowBox, Rc<RefCell<Position>>
reset_main.set_max_children_per_line(1); reset_main.set_max_children_per_line(1);
}; };
pub const HANDLE_MICROPHONE_CLICK: fn(Arc<Listeners>, FlowBox, Rc<RefCell<Position>>) = pub const HANDLE_MICROPHONE_CLICK: fn(
|listeners: Arc<Listeners>, reset_main: FlowBox, position: Rc<RefCell<Position>>| { &Capabilities,
if handle_init(listeners.clone(), position, Position::AudioInput) { Arc<Listeners>,
return; FlowBox,
} Rc<RefCell<Position>>,
let audio_input = Arc::new(SourceBox::new()); ) = |_: &Capabilities,
start_audio_listener(listeners.clone(), None, Some(audio_input.clone())); listeners: Arc<Listeners>,
if !listeners.pulse_listener.load(Ordering::SeqCst) { reset_main: FlowBox,
spin_loop(); position: Rc<RefCell<Position>>| {
} if handle_init(listeners.clone(), position, Position::AudioInput) {
populate_sources(audio_input.clone()); return;
let source_frame = wrap_in_flow_box_child(SettingBox::new(&*audio_input)); }
reset_main.remove_all(); let audio_input = Arc::new(SourceBox::new());
reset_main.insert(&source_frame, -1); start_audio_listener(listeners.clone(), None, Some(audio_input.clone()));
reset_main.set_max_children_per_line(1); if !listeners.pulse_listener.load(Ordering::SeqCst) {
}; spin_loop();
}
populate_sources(audio_input.clone());
let source_frame = wrap_in_flow_box_child(SettingBox::new(&*audio_input));
reset_main.remove_all();
reset_main.insert(&source_frame, -1);
reset_main.set_max_children_per_line(1);
};
pub const HANDLE_HOME: fn(Arc<Listeners>, FlowBox, Rc<RefCell<Position>>) = pub const HANDLE_HOME: fn(&Capabilities, Arc<Listeners>, FlowBox, Rc<RefCell<Position>>) =
|listeners: Arc<Listeners>, reset_main: FlowBox, position: Rc<RefCell<Position>>| { |_: &Capabilities,
listeners: Arc<Listeners>,
reset_main: FlowBox,
position: Rc<RefCell<Position>>| {
if handle_init(listeners, position, Position::Home) { if handle_init(listeners, position, Position::Home) {
return; return;
} }

View file

@ -3,3 +3,4 @@ pub mod reset_window;
pub mod reset_window_impl; pub mod reset_window_impl;
pub mod sidebar_entry; pub mod sidebar_entry;
pub mod sidebar_entry_impl; pub mod sidebar_entry_impl;
pub mod consts;

View file

@ -16,11 +16,17 @@ use re_set_lib::utils::plugin_setup::FRONTEND_PLUGINS;
use crate::components::base::setting_box::SettingBox; use crate::components::base::setting_box::SettingBox;
use crate::components::base::utils::{Listeners, Position}; use crate::components::base::utils::{Listeners, Position};
use crate::components::plugin::function::{PluginSidebarInfo, ReSetSidebarInfo}; use crate::components::plugin::function::PluginSidebarInfo;
use crate::components::utils::get_capabilities;
use crate::components::window::handle_sidebar_click::*; use crate::components::window::handle_sidebar_click::*;
use crate::components::window::reset_window_impl; use crate::components::window::reset_window_impl;
use crate::components::window::sidebar_entry::SidebarEntry; use crate::components::window::sidebar_entry::SidebarEntry;
use super::consts::{
AUDIO_SIDEBAR, BLUETOOTH_SIDEBAR, CONNECTIVITY_SIDEBAR, SINK_SIDEBAR, SOURCE_SIDEBAR,
WIFI_SIDEBAR,
};
glib::wrapper! { glib::wrapper! {
pub struct ReSetWindow(ObjectSubclass<reset_window_impl::ReSetWindow>) pub struct ReSetWindow(ObjectSubclass<reset_window_impl::ReSetWindow>)
@extends adw::ApplicationWindow, gtk::Window, gtk::Widget, @extends adw::ApplicationWindow, gtk::Window, gtk::Widget,
@ -112,45 +118,29 @@ impl ReSetWindow {
pub fn setup_sidebar_entries(&self) { pub fn setup_sidebar_entries(&self) {
let self_imp = self.imp(); let self_imp = self.imp();
let capabilities = get_capabilities();
let wifi = capabilities.contains(&"WiFi".to_string());
let bluetooth = capabilities.contains(&"Bluetooth".to_string());
let audio = capabilities.contains(&"Audio".to_string());
self_imp.capabilities.set(wifi, bluetooth, audio);
let sidebar_list = vec![ // let sidebar_list = vec![CONNECTIVITY_SIDEBAR, WIFI_SIDEBAR, BLUETOOTH_SIDEBAR, AUDIO_SIDEBAR, SINK_SIDEBAR, SOURCE_SIDEBAR];
ReSetSidebarInfo { let mut sidebar_list = Vec::new();
name: "Connectivity",
icon_name: "network-wired-symbolic", if wifi || bluetooth {
parent: None, sidebar_list.push(CONNECTIVITY_SIDEBAR);
click_event: HANDLE_CONNECTIVITY_CLICK, }
}, if wifi {
ReSetSidebarInfo { sidebar_list.push(WIFI_SIDEBAR);
name: "WiFi", };
icon_name: "network-wireless-symbolic", if bluetooth {
parent: Some("Connectivity"), sidebar_list.push(BLUETOOTH_SIDEBAR);
click_event: HANDLE_WIFI_CLICK, };
}, if audio {
ReSetSidebarInfo { sidebar_list.push(AUDIO_SIDEBAR);
name: "Bluetooth", sidebar_list.push(SINK_SIDEBAR);
icon_name: "bluetooth-symbolic", sidebar_list.push(SOURCE_SIDEBAR);
parent: Some("Connectivity"), }
click_event: HANDLE_BLUETOOTH_CLICK,
},
ReSetSidebarInfo {
name: "Audio",
icon_name: "audio-headset-symbolic",
parent: None,
click_event: HANDLE_AUDIO_CLICK,
},
ReSetSidebarInfo {
name: "Output",
icon_name: "audio-volume-high-symbolic",
parent: Some("Audio"),
click_event: HANDLE_VOLUME_CLICK,
},
ReSetSidebarInfo {
name: "Input",
icon_name: "audio-input-microphone-symbolic",
parent: Some("Audio"),
click_event: HANDLE_MICROPHONE_CLICK,
},
];
let mut plugin_sidebar_list = vec![]; let mut plugin_sidebar_list = vec![];
unsafe { unsafe {
@ -191,6 +181,7 @@ impl ReSetWindow {
} }
HANDLE_VOLUME_CLICK( HANDLE_VOLUME_CLICK(
&self_imp.capabilities,
self_imp.listeners.clone(), self_imp.listeners.clone(),
self_imp.reset_main.clone(), self_imp.reset_main.clone(),
self_imp.position.clone(), self_imp.position.clone(),
@ -361,6 +352,7 @@ fn setup_callback(window: Rc<ReSetWindow>) -> Rc<ReSetWindow> {
let click_event = result.imp().on_click_event.borrow(); let click_event = result.imp().on_click_event.borrow();
if let Some(event) = click_event.on_click_event { if let Some(event) = click_event.on_click_event {
event( event(
&imp.capabilities,
imp.listeners.clone(), imp.listeners.clone(),
imp.reset_main.get(), imp.reset_main.get(),
imp.position.clone(), imp.position.clone(),

View file

@ -12,6 +12,7 @@ use gtk::{Button, CompositeTemplate, FlowBox, ListBox, SearchEntry};
use crate::components::base::error::ReSetError; use crate::components::base::error::ReSetError;
use crate::components::base::utils::{Listeners, Position}; use crate::components::base::utils::{Listeners, Position};
use crate::components::utils::Capabilities;
use crate::components::wifi::wifi_box::WifiBox; use crate::components::wifi::wifi_box::WifiBox;
use crate::components::window::reset_window; use crate::components::window::reset_window;
use crate::components::window::sidebar_entry::SidebarEntry; use crate::components::window::sidebar_entry::SidebarEntry;
@ -40,6 +41,7 @@ pub struct ReSetWindow {
pub listeners: Arc<Listeners>, pub listeners: Arc<Listeners>,
pub position: Rc<RefCell<Position>>, pub position: Rc<RefCell<Position>>,
pub error_popup: ReSetError, pub error_popup: ReSetError,
pub capabilities: Capabilities,
} }
unsafe impl Send for ReSetWindow {} unsafe impl Send for ReSetWindow {}