mirror of
https://github.com/Xetibo/ReSet.git
synced 2025-04-08 14:42:02 +02:00
feat: Implement error popup for bluetooth and network
This commit is contained in:
parent
16a30a7bdd
commit
75050c840a
|
@ -58,6 +58,7 @@ pub fn show_error<T: ReSetErrorImpl + Send + Sync + 'static>(
|
|||
parent: Arc<T>,
|
||||
message: &'static str,
|
||||
) {
|
||||
// TODO: Add error to log
|
||||
glib::spawn_future(async move {
|
||||
glib::idle_add_once(move || {
|
||||
let mut error = parent.error();
|
||||
|
|
|
@ -16,6 +16,7 @@ use gtk::{gio, StringObject};
|
|||
use re_set_lib::bluetooth::bluetooth_structures::{BluetoothAdapter, BluetoothDevice};
|
||||
use re_set_lib::signals::{BluetoothDeviceAdded, BluetoothDeviceChanged, BluetoothDeviceRemoved};
|
||||
|
||||
use crate::components::base::error_impl::{show_error, ReSetErrorImpl};
|
||||
use crate::components::base::utils::Listeners;
|
||||
use crate::components::bluetooth::bluetooth_box_impl;
|
||||
use crate::components::bluetooth::bluetooth_entry::BluetoothEntry;
|
||||
|
@ -30,6 +31,14 @@ glib::wrapper! {
|
|||
unsafe impl Send for BluetoothBox {}
|
||||
unsafe impl Sync for BluetoothBox {}
|
||||
|
||||
impl ReSetErrorImpl for BluetoothBox {
|
||||
fn error(
|
||||
&self,
|
||||
) -> >k::subclass::prelude::TemplateChild<crate::components::base::error::ReSetError> {
|
||||
&self.imp().error
|
||||
}
|
||||
}
|
||||
|
||||
impl BluetoothBox {
|
||||
pub fn new(listeners: Arc<Listeners>) -> Arc<Self> {
|
||||
let obj: Arc<Self> = Arc::new(Object::builder().build());
|
||||
|
@ -68,14 +77,24 @@ fn setup_callbacks(
|
|||
.store(true, Ordering::SeqCst);
|
||||
});
|
||||
|
||||
let bluetooth_box_discover = bluetooth_box.clone();
|
||||
imp.reset_bluetooth_discoverable_switch
|
||||
.connect_active_notify(clone!(@weak imp => move |state| {
|
||||
set_bluetooth_adapter_visibility(imp.reset_current_bluetooth_adapter.borrow().path.clone(), state.is_active());
|
||||
set_bluetooth_adapter_visibility(
|
||||
imp.reset_current_bluetooth_adapter.borrow().path.clone(),
|
||||
state.is_active(),
|
||||
bluetooth_box_discover.clone()
|
||||
);
|
||||
}));
|
||||
|
||||
let bluetooth_box_pairable = bluetooth_box.clone();
|
||||
imp.reset_bluetooth_pairable_switch
|
||||
.connect_active_notify(clone!(@weak imp => move |state| {
|
||||
set_bluetooth_adapter_pairability(imp.reset_current_bluetooth_adapter.borrow().path.clone(), state.is_active());
|
||||
set_bluetooth_adapter_pairability(
|
||||
imp.reset_current_bluetooth_adapter.borrow().path.clone(),
|
||||
state.is_active(),
|
||||
bluetooth_box_pairable.clone()
|
||||
);
|
||||
}));
|
||||
|
||||
imp.reset_bluetooth_switch.connect_state_set(
|
||||
|
@ -110,6 +129,7 @@ fn setup_callbacks(
|
|||
let res = set_adapter_enabled(
|
||||
current_adapter.path.clone(),
|
||||
false,
|
||||
bluetooth_box_ref.clone()
|
||||
);
|
||||
if res {
|
||||
current_adapter.powered = false;
|
||||
|
@ -129,6 +149,7 @@ fn setup_callbacks(
|
|||
.path
|
||||
.clone(),
|
||||
true,
|
||||
restart_ref.clone()
|
||||
) {
|
||||
current_adapter.powered = true;
|
||||
start_bluetooth_listener(restart_listener_ref.clone(), restart_ref.clone());
|
||||
|
@ -145,8 +166,8 @@ pub fn populate_conntected_bluetooth_devices(bluetooth_box: Arc<BluetoothBox>) {
|
|||
// TODO handle saved devices -> they also exist
|
||||
gio::spawn_blocking(move || {
|
||||
let ref_box = bluetooth_box.clone();
|
||||
let devices = get_connected_devices();
|
||||
let adapters = get_bluetooth_adapters();
|
||||
let devices = get_connected_devices(ref_box.clone());
|
||||
let adapters = get_bluetooth_adapters(ref_box.clone());
|
||||
{
|
||||
let imp = bluetooth_box.imp();
|
||||
let list = imp.reset_model_list.write().unwrap();
|
||||
|
@ -165,6 +186,7 @@ pub fn populate_conntected_bluetooth_devices(bluetooth_box: Arc<BluetoothBox>) {
|
|||
}
|
||||
glib::spawn_future(async move {
|
||||
glib::idle_add_once(move || {
|
||||
let new_adapter_ref = ref_box.clone();
|
||||
let imp = ref_box.imp();
|
||||
|
||||
let list = imp.reset_model_list.read().unwrap();
|
||||
|
@ -202,14 +224,14 @@ pub fn populate_conntected_bluetooth_devices(bluetooth_box: Arc<BluetoothBox>) {
|
|||
if device.is_none() {
|
||||
return;
|
||||
}
|
||||
set_bluetooth_adapter(device.unwrap().0.path.clone());
|
||||
set_bluetooth_adapter(device.unwrap().0.path.clone(), new_adapter_ref.clone());
|
||||
}),
|
||||
);
|
||||
|
||||
for device in devices {
|
||||
let path = device.path.clone();
|
||||
let connected = device.connected;
|
||||
let bluetooth_entry = BluetoothEntry::new(device);
|
||||
let bluetooth_entry = BluetoothEntry::new(device, ref_box.clone());
|
||||
imp.available_devices
|
||||
.borrow_mut()
|
||||
.insert(path, bluetooth_entry.clone());
|
||||
|
@ -242,7 +264,10 @@ pub fn start_bluetooth_listener(listeners: Arc<Listeners>, bluetooth_box: Arc<Bl
|
|||
|
||||
let conn = Connection::new_session().unwrap();
|
||||
let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000));
|
||||
let _: Result<(), Error> = proxy.method_call(BLUETOOTH, "StartBluetoothListener", ());
|
||||
let res: Result<(), Error> = proxy.method_call(BLUETOOTH, "StartBluetoothListener", ());
|
||||
if res.is_err() {
|
||||
show_error::<BluetoothBox>(bluetooth_box.clone(), "Failed to start bluetooth listener");
|
||||
}
|
||||
imp.reset_bluetooth_available_devices
|
||||
.set_description(Some("Scanning..."));
|
||||
let device_added =
|
||||
|
@ -262,7 +287,8 @@ pub fn start_bluetooth_listener(listeners: Arc<Listeners>, bluetooth_box: Arc<Bl
|
|||
let imp = bluetooth_box.imp();
|
||||
let path = ir.bluetooth_device.path.clone();
|
||||
let connected = ir.bluetooth_device.connected;
|
||||
let bluetooth_entry = BluetoothEntry::new(ir.bluetooth_device);
|
||||
let bluetooth_entry =
|
||||
BluetoothEntry::new(ir.bluetooth_device, bluetooth_box.clone());
|
||||
imp.available_devices
|
||||
.borrow_mut()
|
||||
.insert(path, bluetooth_entry.clone());
|
||||
|
@ -353,8 +379,14 @@ pub fn start_bluetooth_listener(listeners: Arc<Listeners>, bluetooth_box: Arc<Bl
|
|||
loop {
|
||||
let _ = conn.process(Duration::from_millis(1000));
|
||||
if !listeners.bluetooth_listener.load(Ordering::SeqCst) {
|
||||
let _: Result<(), Error> =
|
||||
let res: Result<(), Error> =
|
||||
proxy.method_call(BLUETOOTH, "StopBluetoothListener", ());
|
||||
if res.is_err() {
|
||||
show_error::<BluetoothBox>(
|
||||
bluetooth_box.clone(),
|
||||
"Failed to stop bluetooth listener",
|
||||
);
|
||||
}
|
||||
loop_box
|
||||
.imp()
|
||||
.reset_bluetooth_available_devices
|
||||
|
@ -372,7 +404,13 @@ pub fn start_bluetooth_listener(listeners: Arc<Listeners>, bluetooth_box: Arc<Bl
|
|||
.set_sensitive(true);
|
||||
});
|
||||
});
|
||||
let _: Result<(), Error> = proxy.method_call(BLUETOOTH, "StopBluetoothScan", ());
|
||||
let res: Result<(), Error> = proxy.method_call(BLUETOOTH, "StopBluetoothScan", ());
|
||||
if res.is_err() {
|
||||
show_error::<BluetoothBox>(
|
||||
bluetooth_box.clone(),
|
||||
"Failed to stop bluetooth listener",
|
||||
);
|
||||
}
|
||||
loop_box
|
||||
.imp()
|
||||
.reset_bluetooth_available_devices
|
||||
|
@ -383,8 +421,14 @@ pub fn start_bluetooth_listener(listeners: Arc<Listeners>, bluetooth_box: Arc<Bl
|
|||
.bluetooth_scan_requested
|
||||
.store(false, Ordering::SeqCst);
|
||||
listener_active = true;
|
||||
let _: Result<(), Error> =
|
||||
let res: Result<(), Error> =
|
||||
proxy.method_call(BLUETOOTH, "StartBluetoothListener", ());
|
||||
if res.is_err() {
|
||||
show_error::<BluetoothBox>(
|
||||
bluetooth_box.clone(),
|
||||
"Failed to start bluetooth listener",
|
||||
);
|
||||
}
|
||||
loop_box
|
||||
.imp()
|
||||
.reset_bluetooth_available_devices
|
||||
|
@ -395,58 +439,91 @@ pub fn start_bluetooth_listener(listeners: Arc<Listeners>, bluetooth_box: Arc<Bl
|
|||
});
|
||||
}
|
||||
|
||||
fn get_connected_devices() -> Vec<BluetoothDevice> {
|
||||
fn get_connected_devices(bluetooth_box: Arc<BluetoothBox>) -> Vec<BluetoothDevice> {
|
||||
let conn = Connection::new_session().unwrap();
|
||||
let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000));
|
||||
let res: Result<(Vec<BluetoothDevice>,), Error> =
|
||||
proxy.method_call(BLUETOOTH, "GetConnectedBluetoothDevices", ());
|
||||
if res.is_err() {
|
||||
show_error::<BluetoothBox>(
|
||||
bluetooth_box.clone(),
|
||||
"Failed to get connected bluetooth devices",
|
||||
);
|
||||
return Vec::new();
|
||||
}
|
||||
res.unwrap().0
|
||||
}
|
||||
|
||||
fn get_bluetooth_adapters() -> Vec<BluetoothAdapter> {
|
||||
fn get_bluetooth_adapters(bluetooth_box: Arc<BluetoothBox>) -> Vec<BluetoothAdapter> {
|
||||
let conn = Connection::new_session().unwrap();
|
||||
let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000));
|
||||
let res: Result<(Vec<BluetoothAdapter>,), Error> =
|
||||
proxy.method_call(BLUETOOTH, "GetBluetoothAdapters", ());
|
||||
if res.is_err() {
|
||||
show_error::<BluetoothBox>(bluetooth_box.clone(), "Failed to get bluetooth adapters");
|
||||
return Vec::new();
|
||||
}
|
||||
res.unwrap().0
|
||||
}
|
||||
|
||||
fn set_bluetooth_adapter(path: Path<'static>) {
|
||||
fn set_bluetooth_adapter(path: Path<'static>, bluetooth_box: Arc<BluetoothBox>) {
|
||||
let conn = Connection::new_session().unwrap();
|
||||
let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000));
|
||||
let _: Result<(Path<'static>,), Error> =
|
||||
let res: Result<(Path<'static>,), Error> =
|
||||
proxy.method_call(BLUETOOTH, "SetBluetoothAdapter", (path,));
|
||||
if res.is_err() {
|
||||
show_error::<BluetoothBox>(bluetooth_box.clone(), "Failed to set bluetooth adapter");
|
||||
}
|
||||
}
|
||||
|
||||
fn set_bluetooth_adapter_visibility(path: Path<'static>, visible: bool) {
|
||||
fn set_bluetooth_adapter_visibility(
|
||||
path: Path<'static>,
|
||||
visible: bool,
|
||||
bluetooth_box: Arc<BluetoothBox>,
|
||||
) {
|
||||
let conn = Connection::new_session().unwrap();
|
||||
let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000));
|
||||
let _: Result<(bool,), Error> = proxy.method_call(
|
||||
let res: Result<(bool,), Error> = proxy.method_call(
|
||||
BLUETOOTH,
|
||||
"SetBluetoothAdapterDiscoverability",
|
||||
(path, visible),
|
||||
);
|
||||
if res.is_err() {
|
||||
show_error::<BluetoothBox>(
|
||||
bluetooth_box.clone(),
|
||||
"Failed to set bluetooth adapter visibility",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn set_bluetooth_adapter_pairability(path: Path<'static>, visible: bool) {
|
||||
fn set_bluetooth_adapter_pairability(
|
||||
path: Path<'static>,
|
||||
visible: bool,
|
||||
bluetooth_box: Arc<BluetoothBox>,
|
||||
) {
|
||||
let conn = Connection::new_session().unwrap();
|
||||
let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000));
|
||||
let _: Result<(bool,), Error> =
|
||||
let res: Result<(bool,), Error> =
|
||||
proxy.method_call(BLUETOOTH, "SetBluetoothAdapterPairability", (path, visible));
|
||||
if res.is_err() {
|
||||
show_error::<BluetoothBox>(
|
||||
bluetooth_box.clone(),
|
||||
"Failed to set bluetooth adapter pairability",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn set_adapter_enabled(path: Path<'static>, enabled: bool) -> bool {
|
||||
fn set_adapter_enabled(
|
||||
path: Path<'static>,
|
||||
enabled: bool,
|
||||
bluetooth_box: Arc<BluetoothBox>,
|
||||
) -> bool {
|
||||
let conn = Connection::new_session().unwrap();
|
||||
let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000));
|
||||
let result: Result<(bool,), Error> =
|
||||
proxy.method_call(BLUETOOTH, "SetBluetoothAdapterEnabled", (path, enabled));
|
||||
if result.is_err() {
|
||||
show_error::<BluetoothBox>(bluetooth_box.clone(), "Failed to enable bluetooth adapter");
|
||||
return false;
|
||||
}
|
||||
result.unwrap().0
|
||||
|
|
|
@ -9,6 +9,7 @@ use std::collections::HashMap;
|
|||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
||||
use crate::components::base::error::ReSetError;
|
||||
use crate::components::base::list_entry::ListEntry;
|
||||
use crate::components::bluetooth::bluetooth_box;
|
||||
use crate::components::bluetooth::bluetooth_entry::BluetoothEntry;
|
||||
|
@ -36,6 +37,8 @@ pub struct BluetoothBox {
|
|||
pub reset_bluetooth_discoverable_switch: TemplateChild<SwitchRow>,
|
||||
#[template_child]
|
||||
pub reset_bluetooth_pairable_switch: TemplateChild<SwitchRow>,
|
||||
#[template_child]
|
||||
pub error: TemplateChild<ReSetError>,
|
||||
pub available_devices: BluetoothMap,
|
||||
pub connected_devices: BluetoothMap,
|
||||
pub reset_bluetooth_adapters: Arc<RwLock<HashMap<String, (BluetoothAdapter, u32)>>>,
|
||||
|
|
|
@ -2,8 +2,10 @@ use std::ops::Deref;
|
|||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use crate::components::base::error_impl::show_error;
|
||||
use crate::components::bluetooth::bluetooth_entry_impl;
|
||||
use crate::components::utils::{BASE, BLUETOOTH, DBUS_PATH};
|
||||
use crate::components::wifi::wifi_box_impl::WifiBox;
|
||||
use adw::glib::Object;
|
||||
use adw::prelude::{ActionRowExt, PreferencesRowExt};
|
||||
use adw::{glib, ActionRow};
|
||||
|
@ -14,6 +16,8 @@ use gtk::prelude::{ButtonExt, ListBoxRowExt, WidgetExt};
|
|||
use gtk::{gio, Align, Button, GestureClick, Image, Label};
|
||||
use re_set_lib::bluetooth::bluetooth_structures::BluetoothDevice;
|
||||
|
||||
use super::bluetooth_box::BluetoothBox;
|
||||
|
||||
glib::wrapper! {
|
||||
pub struct BluetoothEntry(ObjectSubclass<bluetooth_entry_impl::BluetoothEntry>)
|
||||
@extends ActionRow, gtk::Widget,
|
||||
|
@ -24,7 +28,7 @@ unsafe impl Send for BluetoothEntry {}
|
|||
unsafe impl Sync for BluetoothEntry {}
|
||||
|
||||
impl BluetoothEntry {
|
||||
pub fn new(device: BluetoothDevice) -> Arc<Self> {
|
||||
pub fn new(device: BluetoothDevice, bluetooth_box: Arc<BluetoothBox>) -> Arc<Self> {
|
||||
let entry: Arc<BluetoothEntry> = Arc::new(Object::builder().build());
|
||||
let entry_imp = entry.imp();
|
||||
let entry_ref = entry.clone();
|
||||
|
@ -60,7 +64,7 @@ impl BluetoothEntry {
|
|||
.borrow()
|
||||
.connect_clicked(move |_| {
|
||||
let imp = entry_ref_remove.imp();
|
||||
remove_device_pairing(imp.bluetooth_device.borrow().path.clone());
|
||||
remove_device_pairing(imp.bluetooth_device.borrow().path.clone(), bluetooth_box.clone());
|
||||
});
|
||||
let gesture = GestureClick::new();
|
||||
// paired is not what we think
|
||||
|
@ -147,11 +151,14 @@ fn disconnect_from_device(entry: Arc<BluetoothEntry>, path: Path<'static>) {
|
|||
});
|
||||
}
|
||||
|
||||
fn remove_device_pairing(path: Path<'static>) {
|
||||
fn remove_device_pairing(path: Path<'static>, wifi_box: Arc<BluetoothBox>) {
|
||||
gio::spawn_blocking(move || {
|
||||
let conn = Connection::new_session().unwrap();
|
||||
let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000));
|
||||
let _: Result<(bool,), Error> =
|
||||
let res: Result<(bool,), Error> =
|
||||
proxy.method_call(BLUETOOTH, "RemoveDevicePairing", (path,));
|
||||
if res.is_err() {
|
||||
show_error::<BluetoothBox>(wifi_box.clone(), "Failed to remove device pairing");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use std::sync::Arc;
|
||||
use std::time::{Duration, SystemTime};
|
||||
|
||||
use crate::components::base::error_impl::show_error;
|
||||
use crate::components::utils::{
|
||||
create_dropdown_label_factory, set_combo_row_ellipsis, AUDIO, BASE, DBUS_PATH,
|
||||
};
|
||||
|
@ -30,6 +31,9 @@ impl OutputStreamEntry {
|
|||
pub fn new(source_box: Arc<SourceBox>, stream: OutputStream) -> Self {
|
||||
let obj: Self = Object::builder().build();
|
||||
// TODO use event callback for progress bar -> this is the "im speaking" indicator
|
||||
let output_box_volume_ref = source_box.clone();
|
||||
let output_box_mute_ref = source_box.clone();
|
||||
let output_box_source_ref = source_box.clone();
|
||||
{
|
||||
let index = stream.index;
|
||||
let box_imp = source_box.imp();
|
||||
|
@ -66,7 +70,7 @@ impl OutputStreamEntry {
|
|||
}
|
||||
*time = Some(SystemTime::now());
|
||||
}
|
||||
set_outputstream_volume(value, index, channels);
|
||||
set_outputstream_volume(value, index, channels, output_box_volume_ref.clone());
|
||||
Propagation::Proceed
|
||||
}),
|
||||
);
|
||||
|
@ -118,7 +122,7 @@ impl OutputStreamEntry {
|
|||
}
|
||||
let stream = stream.unwrap();
|
||||
let source = source.unwrap().0;
|
||||
set_source_of_output_stream(stream.index, source);
|
||||
set_source_of_output_stream(stream.index, source, output_box_source_ref.clone());
|
||||
}),
|
||||
);
|
||||
imp.reset_source_mute
|
||||
|
@ -139,53 +143,56 @@ impl OutputStreamEntry {
|
|||
imp.reset_source_mute
|
||||
.set_icon_name("audio-input-microphone-symbolic");
|
||||
}
|
||||
toggle_output_stream_mute(index, muted);
|
||||
toggle_output_stream_mute(index, muted, output_box_mute_ref.clone());
|
||||
}));
|
||||
}
|
||||
obj
|
||||
}
|
||||
}
|
||||
|
||||
fn set_outputstream_volume(value: f64, index: u32, channels: u16) -> bool {
|
||||
fn set_outputstream_volume(
|
||||
value: f64,
|
||||
index: u32,
|
||||
channels: u16,
|
||||
input_box: Arc<SourceBox>,
|
||||
) -> bool {
|
||||
gio::spawn_blocking(move || {
|
||||
let conn = Connection::new_session().unwrap();
|
||||
let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000));
|
||||
let _: Result<(), Error> = proxy.method_call(
|
||||
let res: Result<(), Error> = proxy.method_call(
|
||||
AUDIO,
|
||||
"SetOutputStreamVolume",
|
||||
(index, channels, value as u32),
|
||||
);
|
||||
// if res.is_err() {
|
||||
// return false;
|
||||
// }
|
||||
// res.unwrap().0
|
||||
if res.is_err() {
|
||||
show_error::<SourceBox>(input_box.clone(), "Failed to set output stream volume");
|
||||
}
|
||||
});
|
||||
true
|
||||
}
|
||||
|
||||
fn toggle_output_stream_mute(index: u32, muted: bool) -> bool {
|
||||
fn toggle_output_stream_mute(index: u32, muted: bool, input_box: Arc<SourceBox>) -> bool {
|
||||
gio::spawn_blocking(move || {
|
||||
let conn = Connection::new_session().unwrap();
|
||||
let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000));
|
||||
let _: Result<(), Error> = proxy.method_call(AUDIO, "SetOutputStreamMute", (index, muted));
|
||||
// if res.is_err() {
|
||||
// return false;
|
||||
// }
|
||||
// res.unwrap().0
|
||||
let res: Result<(), Error> =
|
||||
proxy.method_call(AUDIO, "SetOutputStreamMute", (index, muted));
|
||||
if res.is_err() {
|
||||
show_error::<SourceBox>(input_box.clone(), "Failed to mute output stream");
|
||||
}
|
||||
});
|
||||
true
|
||||
}
|
||||
|
||||
fn set_source_of_output_stream(stream: u32, source: u32) -> bool {
|
||||
fn set_source_of_output_stream(stream: u32, source: u32, input_box: Arc<SourceBox>) -> bool {
|
||||
gio::spawn_blocking(move || {
|
||||
let conn = Connection::new_session().unwrap();
|
||||
let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000));
|
||||
let _: Result<(bool,), Error> =
|
||||
let res: Result<(bool,), Error> =
|
||||
proxy.method_call(AUDIO, "SetSourceOfOutputStream", (stream, source));
|
||||
// if res.is_err() {
|
||||
// return false;
|
||||
// }
|
||||
// res.unwrap().0
|
||||
if res.is_err() {
|
||||
show_error::<SourceBox>(input_box.clone(), "Failed to set source of output stream");
|
||||
}
|
||||
});
|
||||
true
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use std::sync::Arc;
|
||||
use std::time::{Duration, SystemTime};
|
||||
|
||||
use crate::components::base::error_impl::show_error;
|
||||
use crate::components::utils::{
|
||||
create_dropdown_label_factory, set_combo_row_ellipsis, AUDIO, BASE, DBUS_PATH,
|
||||
};
|
||||
|
@ -30,6 +31,9 @@ impl InputStreamEntry {
|
|||
pub fn new(sink_box: Arc<SinkBox>, stream: InputStream) -> Self {
|
||||
let obj: Self = Object::builder().build();
|
||||
// TODO use event callback for progress bar -> this is the "im speaking" indicator
|
||||
let output_box_mute_ref = sink_box.clone();
|
||||
let output_box_volume_ref = sink_box.clone();
|
||||
let output_box_sink_ref = sink_box.clone();
|
||||
{
|
||||
let index = stream.sink_index;
|
||||
let box_imp = sink_box.imp();
|
||||
|
@ -75,7 +79,7 @@ impl InputStreamEntry {
|
|||
}
|
||||
*time = Some(SystemTime::now());
|
||||
}
|
||||
set_inputstream_volume(value, index, channels);
|
||||
set_inputstream_volume(value, index, channels, output_box_volume_ref.clone());
|
||||
Propagation::Proceed
|
||||
}),
|
||||
);
|
||||
|
@ -131,7 +135,7 @@ impl InputStreamEntry {
|
|||
}
|
||||
let stream = stream.unwrap();
|
||||
let sink = sink.unwrap().0;
|
||||
set_sink_of_input_stream(stream.index, sink);
|
||||
set_sink_of_input_stream(stream.index, sink, output_box_sink_ref.clone());
|
||||
}),
|
||||
);
|
||||
imp.reset_sink_mute
|
||||
|
@ -152,54 +156,55 @@ impl InputStreamEntry {
|
|||
imp.reset_sink_mute
|
||||
.set_icon_name("audio-volume-high-symbolic");
|
||||
}
|
||||
toggle_input_stream_mute(index, muted);
|
||||
toggle_input_stream_mute(index, muted, output_box_mute_ref.clone());
|
||||
}));
|
||||
}
|
||||
obj
|
||||
}
|
||||
}
|
||||
|
||||
fn set_inputstream_volume(value: f64, index: u32, channels: u16) -> bool {
|
||||
fn set_inputstream_volume(
|
||||
value: f64,
|
||||
index: u32,
|
||||
channels: u16,
|
||||
output_box: Arc<SinkBox>,
|
||||
) -> bool {
|
||||
gio::spawn_blocking(move || {
|
||||
let conn = Connection::new_session().unwrap();
|
||||
let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000));
|
||||
let _: Result<(), Error> = proxy.method_call(
|
||||
let res: Result<(), Error> = proxy.method_call(
|
||||
AUDIO,
|
||||
"SetInputStreamVolume",
|
||||
(index, channels, value as u32),
|
||||
);
|
||||
// if res.is_err() {
|
||||
// return false;
|
||||
// }
|
||||
// res.unwrap().0
|
||||
if res.is_err() {
|
||||
show_error::<SinkBox>(output_box.clone(), "Failed to set input stream volume");
|
||||
}
|
||||
});
|
||||
true
|
||||
}
|
||||
|
||||
fn toggle_input_stream_mute(index: u32, muted: bool) -> bool {
|
||||
fn toggle_input_stream_mute(index: u32, muted: bool, output_box: Arc<SinkBox>) -> bool {
|
||||
gio::spawn_blocking(move || {
|
||||
let conn = Connection::new_session().unwrap();
|
||||
let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000));
|
||||
let _: Result<(), Error> = proxy.method_call(AUDIO, "SetInputStreamMute", (index, muted));
|
||||
// if res.is_err() {
|
||||
// return false;
|
||||
// }
|
||||
// res.unwrap().0
|
||||
let res: Result<(), Error> = proxy.method_call(AUDIO, "SetInputStreamMute", (index, muted));
|
||||
if res.is_err() {
|
||||
show_error::<SinkBox>(output_box.clone(), "Failed to mute input stream");
|
||||
}
|
||||
});
|
||||
true
|
||||
}
|
||||
|
||||
fn set_sink_of_input_stream(stream: u32, sink: u32) -> bool {
|
||||
fn set_sink_of_input_stream(stream: u32, sink: u32, output_box: Arc<SinkBox>) -> bool {
|
||||
gio::spawn_blocking(move || {
|
||||
let conn = Connection::new_session().unwrap();
|
||||
let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000));
|
||||
let _: Result<(), Error> = proxy.method_call(AUDIO, "SetSinkOfInputStream", (stream, sink));
|
||||
// if res.is_err() {
|
||||
// return false;
|
||||
// }
|
||||
// res.unwrap().0
|
||||
let res: Result<(), Error> =
|
||||
proxy.method_call(AUDIO, "SetSinkOfInputStream", (stream, sink));
|
||||
if res.is_err() {
|
||||
show_error::<SinkBox>(output_box.clone(), "Failed to set sink of input stream");
|
||||
}
|
||||
});
|
||||
true
|
||||
}
|
||||
|
||||
// TODO propagate error from dbus
|
||||
|
|
|
@ -4,6 +4,7 @@ use std::sync::Arc;
|
|||
|
||||
use std::time::Duration;
|
||||
|
||||
use crate::components::base::error_impl::{show_error, ReSetErrorImpl};
|
||||
use crate::components::base::utils::Listeners;
|
||||
use crate::components::utils::{set_combo_row_ellipsis, BASE, DBUS_PATH, WIRELESS};
|
||||
use adw::glib;
|
||||
|
@ -38,6 +39,14 @@ type ResultMap = Result<(Vec<(Path<'static>, Vec<u8>)>,), Error>;
|
|||
unsafe impl Send for WifiBox {}
|
||||
unsafe impl Sync for WifiBox {}
|
||||
|
||||
impl ReSetErrorImpl for WifiBox {
|
||||
fn error(
|
||||
&self,
|
||||
) -> >k::subclass::prelude::TemplateChild<crate::components::base::error::ReSetError> {
|
||||
&self.imp().error
|
||||
}
|
||||
}
|
||||
|
||||
impl WifiBox {
|
||||
pub fn new(listeners: Arc<Listeners>) -> Arc<Self> {
|
||||
let obj: Arc<WifiBox> = Arc::new(Object::builder().build());
|
||||
|
@ -50,6 +59,7 @@ impl WifiBox {
|
|||
fn setup_callbacks(listeners: Arc<Listeners>, wifi_box: Arc<WifiBox>) -> Arc<WifiBox> {
|
||||
let imp = wifi_box.imp();
|
||||
let wifibox_ref = wifi_box.clone();
|
||||
let wifibox_ref_switch = wifi_box.clone();
|
||||
imp.reset_switch_initial.set(true);
|
||||
imp.reset_saved_networks.set_activatable(true);
|
||||
imp.reset_saved_networks
|
||||
|
@ -66,7 +76,7 @@ fn setup_callbacks(listeners: Arc<Listeners>, wifi_box: Arc<WifiBox>) -> Arc<Wif
|
|||
if imp.reset_switch_initial.load(Ordering::SeqCst) {
|
||||
return glib::Propagation::Proceed;
|
||||
}
|
||||
set_wifi_enabled(value);
|
||||
set_wifi_enabled(value, wifibox_ref_switch.clone());
|
||||
if !value {
|
||||
imp.reset_wifi_devices.write().unwrap().clear();
|
||||
*imp.reset_model_list.write().unwrap() = StringList::new(&[]);
|
||||
|
@ -92,17 +102,16 @@ fn setup_callbacks(listeners: Arc<Listeners>, wifi_box: Arc<WifiBox>) -> Arc<Wif
|
|||
|
||||
pub fn scan_for_wifi(wifi_box: Arc<WifiBox>) {
|
||||
let wifibox_ref = wifi_box.clone();
|
||||
let _wifibox_ref_listener = wifi_box.clone();
|
||||
let wifi_entries = wifi_box.imp().wifi_entries.clone();
|
||||
let wifi_entries_path = wifi_box.imp().wifi_entries_path.clone();
|
||||
|
||||
gio::spawn_blocking(move || {
|
||||
let wifi_status = get_wifi_status();
|
||||
let devices = get_wifi_devices();
|
||||
let wifi_status = get_wifi_status(wifibox_ref.clone());
|
||||
let devices = get_wifi_devices(wifibox_ref.clone());
|
||||
if devices.is_empty() {
|
||||
return;
|
||||
}
|
||||
let access_points = get_access_points();
|
||||
let access_points = get_access_points(wifibox_ref.clone());
|
||||
{
|
||||
let imp = wifibox_ref.imp();
|
||||
let list = imp.reset_model_list.write().unwrap();
|
||||
|
@ -118,7 +127,7 @@ pub fn scan_for_wifi(wifi_box: Arc<WifiBox>) {
|
|||
}
|
||||
let wifi_entries = wifi_entries.clone();
|
||||
let wifi_entries_path = wifi_entries_path.clone();
|
||||
dbus_start_network_events();
|
||||
dbus_start_network_events(wifibox_ref.clone());
|
||||
glib::spawn_future(async move {
|
||||
glib::idle_add_once(move || {
|
||||
let mut wifi_entries = wifi_entries.write().unwrap();
|
||||
|
@ -139,6 +148,7 @@ pub fn scan_for_wifi(wifi_box: Arc<WifiBox>) {
|
|||
}
|
||||
}
|
||||
|
||||
let device_changed_ref = wifibox_ref.clone();
|
||||
imp.reset_wifi_device.connect_selected_notify(
|
||||
clone!(@weak imp => move |dropdown| {
|
||||
let selected = dropdown.selected_item();
|
||||
|
@ -154,7 +164,7 @@ pub fn scan_for_wifi(wifi_box: Arc<WifiBox>) {
|
|||
if device.is_none() {
|
||||
return;
|
||||
}
|
||||
set_wifi_device(device.unwrap().0.path.clone());
|
||||
set_wifi_device(device.unwrap().0.path.clone(), device_changed_ref.clone());
|
||||
}),
|
||||
);
|
||||
for access_point in access_points {
|
||||
|
@ -178,7 +188,7 @@ pub fn scan_for_wifi(wifi_box: Arc<WifiBox>) {
|
|||
pub fn show_stored_connections(wifi_box: Arc<WifiBox>) {
|
||||
let wifibox_ref = wifi_box.clone();
|
||||
gio::spawn_blocking(move || {
|
||||
let connections = get_stored_connections();
|
||||
let connections = get_stored_connections(wifi_box.clone());
|
||||
glib::spawn_future(async move {
|
||||
glib::idle_add_once(move || {
|
||||
let self_imp = wifibox_ref.imp();
|
||||
|
@ -194,67 +204,80 @@ pub fn show_stored_connections(wifi_box: Arc<WifiBox>) {
|
|||
});
|
||||
}
|
||||
|
||||
pub fn dbus_start_network_events() {
|
||||
pub fn dbus_start_network_events(wifi_box: Arc<WifiBox>) {
|
||||
let conn = Connection::new_session().unwrap();
|
||||
let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000));
|
||||
let _: Result<(), Error> = proxy.method_call(WIRELESS, "StartNetworkListener", ());
|
||||
let res: Result<(), Error> = proxy.method_call(WIRELESS, "StartNetworkListener", ());
|
||||
if res.is_err() {
|
||||
show_error::<WifiBox>(wifi_box.clone(), "Failed to start Network listener");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_access_points() -> Vec<AccessPoint> {
|
||||
pub fn get_access_points(wifi_box: Arc<WifiBox>) -> Vec<AccessPoint> {
|
||||
let conn = Connection::new_session().unwrap();
|
||||
let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000));
|
||||
let res: Result<(Vec<AccessPoint>,), Error> =
|
||||
proxy.method_call(WIRELESS, "ListAccessPoints", ());
|
||||
if res.is_err() {
|
||||
show_error::<WifiBox>(wifi_box.clone(), "Failed to list access points");
|
||||
return Vec::new();
|
||||
}
|
||||
let (access_points,) = res.unwrap();
|
||||
access_points
|
||||
}
|
||||
|
||||
pub fn set_wifi_device(path: Path<'static>) {
|
||||
pub fn set_wifi_device(path: Path<'static>, wifi_box: Arc<WifiBox>) {
|
||||
let conn = Connection::new_session().unwrap();
|
||||
let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000));
|
||||
let _: Result<(bool,), Error> = proxy.method_call(WIRELESS, "SetWifiDevice", (path,));
|
||||
let res: Result<(bool,), Error> = proxy.method_call(WIRELESS, "SetWifiDevice", (path,));
|
||||
if res.is_err() {
|
||||
show_error::<WifiBox>(wifi_box.clone(), "Failed to set WiFi devices");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_wifi_devices() -> Vec<WifiDevice> {
|
||||
pub fn get_wifi_devices(wifi_box: Arc<WifiBox>) -> Vec<WifiDevice> {
|
||||
let conn = Connection::new_session().unwrap();
|
||||
let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000));
|
||||
let res: Result<(Vec<WifiDevice>,), Error> =
|
||||
proxy.method_call(WIRELESS, "GetAllWifiDevices", ());
|
||||
if res.is_err() {
|
||||
show_error::<WifiBox>(wifi_box.clone(), "Failed to get WiFi devices");
|
||||
return Vec::new();
|
||||
}
|
||||
let (devices,) = res.unwrap();
|
||||
devices
|
||||
}
|
||||
|
||||
pub fn get_wifi_status() -> bool {
|
||||
pub fn get_wifi_status(wifi_box: Arc<WifiBox>) -> bool {
|
||||
let conn = Connection::new_session().unwrap();
|
||||
let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000));
|
||||
let res: Result<(bool,), Error> = proxy.method_call(WIRELESS, "GetWifiStatus", ());
|
||||
if res.is_err() {
|
||||
show_error::<WifiBox>(wifi_box.clone(), "Failed to get WiFi status");
|
||||
return false;
|
||||
}
|
||||
res.unwrap().0
|
||||
}
|
||||
|
||||
pub fn get_stored_connections() -> Vec<(Path<'static>, Vec<u8>)> {
|
||||
pub fn get_stored_connections(wifi_box: Arc<WifiBox>) -> Vec<(Path<'static>, Vec<u8>)> {
|
||||
let conn = Connection::new_session().unwrap();
|
||||
let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000));
|
||||
let res: ResultMap = proxy.method_call(WIRELESS, "ListStoredConnections", ());
|
||||
if res.is_err() {
|
||||
show_error::<WifiBox>(wifi_box.clone(), "Failed to list stored connections");
|
||||
return Vec::new();
|
||||
}
|
||||
let (connections,) = res.unwrap();
|
||||
connections
|
||||
}
|
||||
|
||||
pub fn set_wifi_enabled(enabled: bool) {
|
||||
pub fn set_wifi_enabled(enabled: bool, wifi_box: Arc<WifiBox>) {
|
||||
let conn = Connection::new_session().unwrap();
|
||||
let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000));
|
||||
let _: Result<(bool,), Error> = proxy.method_call(WIRELESS, "SetWifiEnabled", (enabled,));
|
||||
let res: Result<(bool,), Error> = proxy.method_call(WIRELESS, "SetWifiEnabled", (enabled,));
|
||||
if res.is_err() {
|
||||
show_error::<WifiBox>(wifi_box.clone(), "Failed to enable WiFi");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start_event_listener(listeners: Arc<Listeners>, wifi_box: Arc<WifiBox>) {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use crate::components::base::error::ReSetError;
|
||||
use crate::components::wifi::wifi_box;
|
||||
use adw::{ActionRow, ComboRow, NavigationView, PreferencesGroup};
|
||||
use dbus::Path;
|
||||
|
@ -32,6 +33,8 @@ pub struct WifiBox {
|
|||
pub reset_stored_wifi_list: TemplateChild<PreferencesGroup>,
|
||||
#[template_child]
|
||||
pub reset_available_networks: TemplateChild<ActionRow>,
|
||||
#[template_child]
|
||||
pub error: TemplateChild<ReSetError>,
|
||||
pub wifi_entries: Arc<RwLock<HashMap<Vec<u8>, Arc<WifiEntry>>>>,
|
||||
pub wifi_entries_path: Arc<RwLock<HashMap<Path<'static>, Arc<WifiEntry>>>>,
|
||||
pub reset_wifi_devices: Arc<RwLock<HashMap<String, (WifiDevice, u32)>>>,
|
||||
|
|
|
@ -144,5 +144,8 @@
|
|||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="resetError" id="error"/>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
||||
|
|
|
@ -77,6 +77,7 @@
|
|||
(4,206,"AdwActionRow","reset_available_networks",205,None,None,None,-1,None),
|
||||
(4,207,"GtkImage",None,206,None,None,None,None,None),
|
||||
(4,208,"AdwPreferencesGroup","reset_wifi_list",154,None,None,None,1,None),
|
||||
(4,209,"resetError","error",7,None,None,None,2,None),
|
||||
(5,12,"AdwActionRow","resetWifiEntry",None,None,None,None,-1,None),
|
||||
(5,13,"resetPopup","reset_wifi_popup",12,None,None,None,None,None),
|
||||
(6,1,"GtkListBoxRow","resetSidebarEntry",None,None,None,None,None,None),
|
||||
|
@ -150,6 +151,7 @@
|
|||
(10,211,"AdwSwitchRow","reset_bluetooth_discoverable_switch",209,None,None,None,-1,None),
|
||||
(10,212,"AdwActionRow","reset_bluetooth_main_tab",208,None,None,None,None,None),
|
||||
(10,213,"GtkImage",None,212,None,None,None,None,None),
|
||||
(10,214,"resetError","error",1,None,None,None,2,None),
|
||||
(11,1,"AdwActionRow","resetBluetoothEntry",None,None,None,None,None,None),
|
||||
(12,11,"GtkBox","resetAudioInput",None,None,None,None,None,None),
|
||||
(12,12,"GtkLabel",None,11,None,None,None,None,None),
|
||||
|
|
|
@ -120,5 +120,8 @@
|
|||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="resetError" id="error"/>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
||||
|
|
Loading…
Reference in a new issue