Merge pull request #58 from Xetibo/dashie

feat: Add audio events
This commit is contained in:
takotori 2023-11-16 10:23:07 +01:00 committed by GitHub
commit 70a8d3fdb8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 1208 additions and 273 deletions

View file

@ -5,7 +5,7 @@ edition = "2021"
description = "A wip universal Linux settings application." description = "A wip universal Linux settings application."
[dependencies] [dependencies]
reset_daemon = "0.1.3" reset_daemon = "0.1.7"
ReSet-Lib = "0.2.8" ReSet-Lib = "0.2.8"
adw = { version = "0.5.3", package = "libadwaita", features = ["v1_4"] } adw = { version = "0.5.3", package = "libadwaita", features = ["v1_4"] }
dbus = "0.9.7" dbus = "0.9.7"

View file

@ -10,3 +10,8 @@
### instructions for installation: ### instructions for installation:
`flatpak install --user reset.flatpak` `flatpak install --user reset.flatpak`
### permissions
currently ReSet uses permission on all devices, for some reason otherwise it can't access sound settings like volume changes etc.
This can likely be fixed by implementing portal integration later.

View file

@ -1042,14 +1042,14 @@
{ {
"type": "archive", "type": "archive",
"archive-type": "tar-gzip", "archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/reset_daemon/reset_daemon-0.1.3.crate", "url": "https://static.crates.io/crates/reset_daemon/reset_daemon-0.1.7.crate",
"sha256": "1d7b1c575b773eadd0fc8991de8abb883cfb7bce9c5e8c4f9e10b85cb142efee", "sha256": "f7b48ba0698bdb4ead119140a557346907b40ae17cac324687a032b4d6ea9851",
"dest": "cargo/vendor/reset_daemon-0.1.3" "dest": "cargo/vendor/reset_daemon-0.1.7"
}, },
{ {
"type": "inline", "type": "inline",
"contents": "{\"package\": \"1d7b1c575b773eadd0fc8991de8abb883cfb7bce9c5e8c4f9e10b85cb142efee\", \"files\": {}}", "contents": "{\"package\": \"f7b48ba0698bdb4ead119140a557346907b40ae17cac324687a032b4d6ea9851\", \"files\": {}}",
"dest": "cargo/vendor/reset_daemon-0.1.3", "dest": "cargo/vendor/reset_daemon-0.1.7",
"dest-filename": ".cargo-checksum.json" "dest-filename": ".cargo-checksum.json"
}, },
{ {

View file

@ -3,15 +3,20 @@
"runtime": "org.gnome.Platform", "runtime": "org.gnome.Platform",
"runtime-version": "45", "runtime-version": "45",
"sdk": "org.gnome.Sdk", "sdk": "org.gnome.Sdk",
"sdk-extensions": ["org.freedesktop.Sdk.Extension.rust-stable"], "sdk-extensions": [
"org.freedesktop.Sdk.Extension.rust-stable"
],
"command": "reset", "command": "reset",
"finish-args": [ "finish-args": [
"--socket=session-bus", "--socket=session-bus",
"--socket=system-bus",
"--socket=pulseaudio", "--socket=pulseaudio",
"--share=ipc", "--share=ipc",
"--socket=fallback-x11", "--socket=fallback-x11",
"--socket=wayland", "--socket=wayland",
"--device=dri" "--device=dri",
"--device=all",
"--allow=bluetooth"
], ],
"build-options": { "build-options": {
"append-path": "/usr/lib/sdk/rust-stable/bin" "append-path": "/usr/lib/sdk/rust-stable/bin"

View file

@ -1,10 +1,21 @@
use std::{ use std::{
sync::atomic::{AtomicBool, Ordering}, sync::{atomic::{AtomicBool, Ordering}, Arc},
thread, thread,
time::Duration, time::Duration,
}; };
use dbus::{blocking::Connection, Error}; use dbus::{
arg::{self, Append},
blocking::Connection,
Error,
};
use gtk::gio;
use ReSet_Lib::{
audio::audio::{InputStream, OutputStream, Sink, Source},
signals::GetVal,
};
use crate::components::{input::sourceBox::{SourceBox, start_input_box_listener}, output::sinkBox::{SinkBox, start_output_box_listener}};
#[derive(Default)] #[derive(Default)]
pub struct Listeners { pub struct Listeners {
@ -31,3 +42,350 @@ impl Listeners {
}); });
} }
} }
#[derive(Debug)]
pub struct SinkAdded {
pub sink: Sink,
}
impl arg::AppendAll for SinkAdded {
fn append(&self, i: &mut arg::IterAppend) {
self.sink.append_by_ref(i);
}
}
impl arg::ReadAll for SinkAdded {
fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> {
Ok(SinkAdded { sink: i.read()? })
}
}
impl dbus::message::SignalArgs for SinkAdded {
const NAME: &'static str = "SinkAdded";
const INTERFACE: &'static str = "org.xetibo.ReSet";
}
impl GetVal<(Sink,)> for SinkAdded {
fn get_value(&self) -> (Sink,) {
(self.sink.clone(),)
}
}
#[derive(Debug)]
pub struct SinkChanged {
pub sink: Sink,
}
impl arg::AppendAll for SinkChanged {
fn append(&self, i: &mut arg::IterAppend) {
self.sink.append_by_ref(i);
}
}
impl arg::ReadAll for SinkChanged {
fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> {
Ok(SinkChanged { sink: i.read()? })
}
}
impl dbus::message::SignalArgs for SinkChanged {
const NAME: &'static str = "SinkChanged";
const INTERFACE: &'static str = "org.xetibo.ReSet";
}
impl GetVal<(Sink,)> for SinkChanged {
fn get_value(&self) -> (Sink,) {
(self.sink.clone(),)
}
}
#[derive(Debug)]
pub struct SinkRemoved {
pub index: u32,
}
impl arg::AppendAll for SinkRemoved {
fn append(&self, i: &mut arg::IterAppend) {
self.index.append_by_ref(i);
}
}
impl arg::ReadAll for SinkRemoved {
fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> {
Ok(SinkRemoved { index: i.read()? })
}
}
impl dbus::message::SignalArgs for SinkRemoved {
const NAME: &'static str = "SinkRemoved";
const INTERFACE: &'static str = "org.xetibo.ReSet";
}
impl GetVal<(u32,)> for SinkRemoved {
fn get_value(&self) -> (u32,) {
(self.index.clone(),)
}
}
#[derive(Debug)]
pub struct InputStreamAdded {
pub stream: InputStream,
}
impl arg::AppendAll for InputStreamAdded {
fn append(&self, i: &mut arg::IterAppend) {
self.stream.append_by_ref(i);
}
}
impl arg::ReadAll for InputStreamAdded {
fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> {
Ok(InputStreamAdded { stream: i.read()? })
}
}
impl dbus::message::SignalArgs for InputStreamAdded {
const NAME: &'static str = "InputStreamAdded";
const INTERFACE: &'static str = "org.xetibo.ReSet";
}
impl GetVal<(InputStream,)> for InputStreamAdded {
fn get_value(&self) -> (InputStream,) {
(self.stream.clone(),)
}
}
#[derive(Debug)]
pub struct InputStreamChanged {
pub stream: InputStream,
}
impl arg::AppendAll for InputStreamChanged {
fn append(&self, i: &mut arg::IterAppend) {
self.stream.append_by_ref(i);
}
}
impl arg::ReadAll for InputStreamChanged {
fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> {
Ok(InputStreamChanged { stream: i.read()? })
}
}
impl dbus::message::SignalArgs for InputStreamChanged {
const NAME: &'static str = "InputStreamChanged";
const INTERFACE: &'static str = "org.xetibo.ReSet";
}
#[derive(Debug)]
pub struct InputStreamRemoved {
pub index: u32,
}
impl arg::AppendAll for InputStreamRemoved {
fn append(&self, i: &mut arg::IterAppend) {
self.index.append_by_ref(i);
}
}
impl arg::ReadAll for InputStreamRemoved {
fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> {
Ok(InputStreamRemoved { index: i.read()? })
}
}
impl dbus::message::SignalArgs for InputStreamRemoved {
const NAME: &'static str = "InputStreamRemoved";
const INTERFACE: &'static str = "org.xetibo.ReSet";
}
impl GetVal<(u32,)> for InputStreamRemoved {
fn get_value(&self) -> (u32,) {
(self.index.clone(),)
}
}
#[derive(Debug)]
pub struct SourceAdded {
pub source: Source,
}
impl arg::AppendAll for SourceAdded {
fn append(&self, i: &mut arg::IterAppend) {
self.source.append_by_ref(i);
}
}
impl arg::ReadAll for SourceAdded {
fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> {
Ok(SourceAdded { source: i.read()? })
}
}
impl dbus::message::SignalArgs for SourceAdded {
const NAME: &'static str = "SourceAdded";
const INTERFACE: &'static str = "org.xetibo.ReSet";
}
impl GetVal<(Source,)> for SourceAdded {
fn get_value(&self) -> (Source,) {
(self.source.clone(),)
}
}
#[derive(Debug)]
pub struct SourceChanged {
pub source: Source,
}
impl arg::AppendAll for SourceChanged {
fn append(&self, i: &mut arg::IterAppend) {
self.source.append_by_ref(i);
}
}
impl arg::ReadAll for SourceChanged {
fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> {
Ok(SourceChanged { source: i.read()? })
}
}
impl dbus::message::SignalArgs for SourceChanged {
const NAME: &'static str = "SourceChanged";
const INTERFACE: &'static str = "org.xetibo.ReSet";
}
impl GetVal<(Source,)> for SourceChanged {
fn get_value(&self) -> (Source,) {
(self.source.clone(),)
}
}
#[derive(Debug)]
pub struct SourceRemoved {
pub index: u32,
}
impl arg::AppendAll for SourceRemoved {
fn append(&self, i: &mut arg::IterAppend) {
self.index.append_by_ref(i);
}
}
impl arg::ReadAll for SourceRemoved {
fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> {
Ok(SourceRemoved { index: i.read()? })
}
}
impl dbus::message::SignalArgs for SourceRemoved {
const NAME: &'static str = "SourceRemoved";
const INTERFACE: &'static str = "org.xetibo.ReSet";
}
impl GetVal<(u32,)> for SourceRemoved {
fn get_value(&self) -> (u32,) {
(self.index.clone(),)
}
}
#[derive(Debug)]
pub struct OutputStreamAdded {
pub stream: OutputStream,
}
impl arg::AppendAll for OutputStreamAdded {
fn append(&self, i: &mut arg::IterAppend) {
self.stream.append_by_ref(i);
}
}
impl arg::ReadAll for OutputStreamAdded {
fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> {
Ok(OutputStreamAdded { stream: i.read()? })
}
}
impl dbus::message::SignalArgs for OutputStreamAdded {
const NAME: &'static str = "OutputStreamAdded";
const INTERFACE: &'static str = "org.xetibo.ReSet";
}
impl GetVal<(OutputStream,)> for OutputStreamAdded {
fn get_value(&self) -> (OutputStream,) {
(self.stream.clone(),)
}
}
#[derive(Debug)]
pub struct OutputStreamChanged {
pub stream: OutputStream,
}
impl arg::AppendAll for OutputStreamChanged {
fn append(&self, i: &mut arg::IterAppend) {
self.stream.append_by_ref(i);
}
}
impl arg::ReadAll for OutputStreamChanged {
fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> {
Ok(OutputStreamChanged { stream: i.read()? })
}
}
impl dbus::message::SignalArgs for OutputStreamChanged {
const NAME: &'static str = "OutputStreamChanged";
const INTERFACE: &'static str = "org.xetibo.ReSet";
}
#[derive(Debug)]
pub struct OutputStreamRemoved {
pub index: u32,
}
impl arg::AppendAll for OutputStreamRemoved {
fn append(&self, i: &mut arg::IterAppend) {
self.index.append_by_ref(i);
}
}
impl arg::ReadAll for OutputStreamRemoved {
fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> {
Ok(OutputStreamRemoved { index: i.read()? })
}
}
impl dbus::message::SignalArgs for OutputStreamRemoved {
const NAME: &'static str = "OutputStreamRemoved";
const INTERFACE: &'static str = "org.xetibo.ReSet";
}
impl GetVal<(u32,)> for OutputStreamRemoved {
fn get_value(&self) -> (u32,) {
(self.index.clone(),)
}
}
pub fn start_event_listener(listeners: Arc<Listeners>, sink_box: Option<Arc<SinkBox>>,source_box: Option<Arc<SourceBox>>) {
gio::spawn_blocking(move || {
let mut conn = Connection::new_session().unwrap();
if sink_box.is_some() {
conn = start_output_box_listener(conn, listeners.clone(), sink_box.unwrap());
}
if source_box.is_some() {
conn = start_input_box_listener(conn, listeners.clone(), source_box.unwrap());
}
loop {
let _ = conn.process(Duration::from_millis(1000));
if !listeners.network_listener.load(Ordering::SeqCst) {
println!("stopping audio listener");
break;
}
// thread::sleep(Duration::from_millis(1000));
// TODO is this really how we should do this?
}
});
}

View file

@ -8,7 +8,7 @@ use dbus::blocking::Connection;
use dbus::Error; use dbus::Error;
use glib::subclass::types::ObjectSubclassIsExt; use glib::subclass::types::ObjectSubclassIsExt;
use glib::{clone, Cast, Propagation}; use glib::{clone, Cast, Propagation};
use gtk::StringObject; use gtk::{gio, StringObject};
use ReSet_Lib::audio::audio::OutputStream; use ReSet_Lib::audio::audio::OutputStream;
use super::outputStreamEntryImpl; use super::outputStreamEntryImpl;
@ -24,8 +24,6 @@ impl OutputStreamEntry {
pub fn new(source_box: Arc<SourceBox>, stream: OutputStream) -> Self { pub fn new(source_box: Arc<SourceBox>, stream: OutputStream) -> Self {
let obj: Self = Object::builder().build(); let obj: Self = Object::builder().build();
// TODO use event callback for progress bar -> this is the "im speaking" indicator // TODO use event callback for progress bar -> this is the "im speaking" indicator
// TODO map mute to callback
// TODO map dropdown
{ {
let box_imp = source_box.imp(); let box_imp = source_box.imp();
let imp = obj.imp(); let imp = obj.imp();
@ -54,17 +52,17 @@ impl OutputStreamEntry {
}), }),
); );
{ {
let mut list = box_imp.resetModelList.try_borrow(); let list = box_imp.resetModelList.read().unwrap();
while list.is_err() { // while list.is_err() {
list = box_imp.resetModelList.try_borrow(); // list = box_imp.resetModelList.try_borrow();
} // }
let list = list.unwrap(); // let list = list.unwrap();
imp.resetSelectedSource.set_model(Some(&*list)); imp.resetSelectedSource.set_model(Some(&*list));
let mut map = box_imp.resetSourceMap.try_borrow(); let map = box_imp.resetSourceMap.write().unwrap();
while map.is_err() { // while map.is_err() {
map = box_imp.resetSourceMap.try_borrow(); // map = box_imp.resetSourceMap.try_borrow();
} // }
let map = map.unwrap(); // let map = map.unwrap();
let mut name = box_imp.resetDefaultSource.try_borrow(); let mut name = box_imp.resetDefaultSource.try_borrow();
while name.is_err() { while name.is_err() {
name = box_imp.resetDefaultSource.try_borrow(); name = box_imp.resetDefaultSource.try_borrow();
@ -85,11 +83,7 @@ impl OutputStreamEntry {
let selected = selected.unwrap(); let selected = selected.unwrap();
let selected = selected.downcast_ref::<StringObject>().unwrap(); let selected = selected.downcast_ref::<StringObject>().unwrap();
let selected = selected.string().to_string(); let selected = selected.string().to_string();
let mut source = box_imp.resetSourceMap.try_borrow(); let source = box_imp.resetSourceMap.write().unwrap();
while source.is_err() {
source = box_imp.resetSourceMap.try_borrow();
}
let source = source.unwrap();
let source = source.get(&selected); let source = source.get(&selected);
if source.is_none() { if source.is_none() {
return; return;
@ -116,10 +110,10 @@ impl OutputStreamEntry {
let index = stream.index; let index = stream.index;
if muted { if muted {
imp.resetSourceMute imp.resetSourceMute
.set_icon_name("audio-volume-muted-symbolic"); .set_icon_name("microphone-disabled-symbolic");
} else { } else {
imp.resetSourceMute imp.resetSourceMute
.set_icon_name("audio-volume-high-symbolic"); .set_icon_name("audio-input-microphone-symbolic");
} }
toggle_output_stream_mute(index, muted); toggle_output_stream_mute(index, muted);
})); }));
@ -129,52 +123,63 @@ impl OutputStreamEntry {
} }
fn set_outputstream_volume(value: f64, index: u32, channels: u16) -> bool { fn set_outputstream_volume(value: f64, index: u32, channels: u16) -> bool {
gio::spawn_blocking(move || {
let conn = Connection::new_session().unwrap(); let conn = Connection::new_session().unwrap();
let proxy = conn.with_proxy( let proxy = conn.with_proxy(
"org.xetibo.ReSet", "org.xetibo.ReSet",
"/org/xetibo/ReSet", "/org/xetibo/ReSet",
Duration::from_millis(1000), Duration::from_millis(1000),
); );
let res: Result<(bool,), Error> = proxy.method_call( let _: Result<(), Error> = proxy.method_call(
"org.xetibo.ReSet", "org.xetibo.ReSet",
"SetOutputStreamVolume", "SetOutputStreamVolume",
(index, channels, value as u32), (index, channels, value as u32),
); );
if res.is_err() { // if res.is_err() {
return false; // return false;
} // }
res.unwrap().0 // res.unwrap().0
});
true
} }
fn toggle_output_stream_mute(index: u32, muted: bool) -> bool { fn toggle_output_stream_mute(index: u32, muted: bool) -> bool {
gio::spawn_blocking(move || {
let conn = Connection::new_session().unwrap(); let conn = Connection::new_session().unwrap();
let proxy = conn.with_proxy( let proxy = conn.with_proxy(
"org.xetibo.ReSet", "org.xetibo.ReSet",
"/org/xetibo/ReSet", "/org/xetibo/ReSet",
Duration::from_millis(1000), Duration::from_millis(1000),
); );
let res: Result<(bool,), Error> = let _: Result<(), Error> =
proxy.method_call("org.xetibo.ReSet", "SetOutputStreamMute", (index, muted)); proxy.method_call("org.xetibo.ReSet", "SetOutputStreamMute", (index, muted));
if res.is_err() { // if res.is_err() {
return false; // return false;
} // }
res.unwrap().0 // res.unwrap().0
});
true
} }
fn set_source_of_output_stream(stream: u32, source: u32) -> bool { fn set_source_of_output_stream(stream: u32, source: u32) -> bool {
gio::spawn_blocking(move || {
let conn = Connection::new_session().unwrap(); let conn = Connection::new_session().unwrap();
let proxy = conn.with_proxy( let proxy = conn.with_proxy(
"org.xetibo.ReSet", "org.xetibo.ReSet",
"/org/xetibo/ReSet", "/org/xetibo/ReSet",
Duration::from_millis(1000), Duration::from_millis(1000),
); );
let res: Result<(bool,), Error> = proxy.method_call( let _: Result<(bool,), Error> = proxy.method_call(
"org.xetibo.ReSet", "org.xetibo.ReSet",
"SetSourceOfOutputStream", "SetSourceOfOutputStream",
(stream, source), (stream, source),
); );
if res.is_err() { // if res.is_err() {
return false; // return false;
} // }
res.unwrap().0 // res.unwrap().0
});
true
} }
// TODO propagate error from dbus

View file

@ -1,15 +1,20 @@
use std::sync::atomic::Ordering;
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
use crate::components::base::listEntry::ListEntry; use crate::components::base::listEntry::ListEntry;
use crate::components::base::utils::Listeners; use crate::components::base::utils::{
Listeners, OutputStreamAdded, OutputStreamChanged, OutputStreamRemoved, SourceAdded,
SourceChanged, SourceRemoved,
};
use crate::components::input::sourceBoxImpl; use crate::components::input::sourceBoxImpl;
use crate::components::input::sourceEntry::set_source_volume; use crate::components::input::sourceEntry::set_source_volume;
use adw::glib; use adw::glib;
use adw::glib::Object; use adw::glib::Object;
use adw::prelude::{BoxExt, ButtonExt, ListBoxRowExt, RangeExt}; use adw::prelude::{BoxExt, ButtonExt, CheckButtonExt, ListBoxRowExt, RangeExt};
use dbus::blocking::Connection; use dbus::blocking::Connection;
use dbus::Error; use dbus::message::SignalArgs;
use dbus::{Error, Path};
use glib::subclass::prelude::ObjectSubclassIsExt; use glib::subclass::prelude::ObjectSubclassIsExt;
use glib::{clone, Cast, Propagation, Variant}; use glib::{clone, Cast, Propagation, Variant};
use gtk::prelude::ActionableExt; use gtk::prelude::ActionableExt;
@ -48,55 +53,65 @@ impl SourceBox {
} }
} }
pub fn populate_sources(output_box: Arc<SourceBox>) { pub fn populate_sources(input_box: Arc<SourceBox>) {
gio::spawn_blocking(move || { gio::spawn_blocking(move || {
let output_box_imp = output_box.imp(); let output_box_imp = input_box.imp();
let sources = get_sources(); let sources = get_sources();
{ {
let list = output_box_imp.resetModelList.borrow_mut(); let list = output_box_imp.resetModelList.write().unwrap();
let mut map = output_box_imp.resetSourceMap.borrow_mut(); let mut map = output_box_imp.resetSourceMap.write().unwrap();
let mut model_index = output_box_imp.resetModelIndex.write().unwrap();
let mut i: u32 = 0; let mut i: u32 = 0;
for source in sources.iter() { for source in sources.iter() {
list.append(&source.alias); list.append(&source.alias);
map.insert(source.alias.clone(), (source.index, i, source.name.clone())); map.insert(source.alias.clone(), (source.index, i, source.name.clone()));
i += 1; i += 1;
*model_index += 1;
} }
} }
output_box_imp output_box_imp
.resetDefaultSource .resetDefaultSource
.replace(get_default_source()); .replace(get_default_source());
populate_outputstreams(input_box.clone());
glib::spawn_future(async move { glib::spawn_future(async move {
glib::idle_add_once(move || { glib::idle_add_once(move || {
// TODO handle events // TODO handle events
let output_box_ref_slider = output_box.clone(); let output_box_ref_slider = input_box.clone();
let output_box_ref_mute = output_box.clone(); let output_box_ref_mute = input_box.clone();
let output_box_ref = output_box.clone(); let output_box_ref = input_box.clone();
{ {
let output_box_imp = output_box_ref.imp(); let output_box_imp = output_box_ref.imp();
let default_sink = output_box_imp.resetDefaultSource.clone(); // Clone outside closure let default_sink = output_box_imp.resetDefaultSource.clone();
let source = default_sink.borrow(); // let source = default_sink.borrow();
let volume = source.volume.first().unwrap_or_else(|| &(0 as u32)); let volume = source.volume.first().unwrap_or_else(|| &(0 as u32));
let fraction = (*volume as f64 / 655.36).round(); let fraction = (*volume as f64 / 655.36).round();
let percentage = (fraction).to_string() + "%"; let percentage = (fraction).to_string() + "%";
output_box_imp.resetVolumePercentage.set_text(&percentage); output_box_imp.resetVolumePercentage.set_text(&percentage);
output_box_imp.resetVolumeSlider.set_value(*volume as f64); output_box_imp.resetVolumeSlider.set_value(*volume as f64);
let mut list = output_box_imp.resetSourceList.write().unwrap();
for stream in sources { for stream in sources {
let index = source.index;
let alias = source.alias.clone();
let mut is_default = false; let mut is_default = false;
if output_box_imp.resetDefaultSource.borrow().name == stream.name { if output_box_imp.resetDefaultSource.borrow().name == stream.name {
is_default = true; is_default = true;
} }
let entry = ListEntry::new(&SourceEntry::new( let source_entry = Arc::new(SourceEntry::new(
is_default, is_default,
output_box_imp.resetDefaultCheckButton.clone(), output_box_imp.resetDefaultCheckButton.clone(),
stream, stream,
)); ));
let source_clone = source_entry.clone();
let entry = Arc::new(ListEntry::new(&*source_entry));
entry.set_activatable(false); entry.set_activatable(false);
output_box_imp.resetSources.append(&entry); list.insert(index, (entry.clone(), source_clone, alias));
output_box_imp.resetSources.append(&*entry);
} }
let list = output_box_imp.resetModelList.borrow(); let list = output_box_imp.resetModelList.read().unwrap();
output_box_imp.resetSourceDropdown.set_model(Some(&*list)); output_box_imp.resetSourceDropdown.set_model(Some(&*list));
let map = output_box_imp.resetSourceMap.borrow(); let map = output_box_imp.resetSourceMap.read().unwrap();
let name = output_box_imp.resetDefaultSource.borrow(); let name = output_box_imp.resetDefaultSource.borrow();
let name = &name.alias; let name = &name.alias;
let index = map.get(name); let index = map.get(name);
@ -115,7 +130,7 @@ pub fn populate_sources(output_box: Arc<SourceBox>) {
let selected = selected.downcast_ref::<StringObject>().unwrap(); let selected = selected.downcast_ref::<StringObject>().unwrap();
let selected = selected.string().to_string(); let selected = selected.string().to_string();
let source = output_box_imp.resetSourceMap.borrow(); let source = output_box_imp.resetSourceMap.read().unwrap();
let source = source.get(&selected); let source = source.get(&selected);
if source.is_none() { if source.is_none() {
return; return;
@ -131,7 +146,6 @@ pub fn populate_sources(output_box: Arc<SourceBox>) {
.connect_change_value(move |_, _, value| { .connect_change_value(move |_, _, value| {
let imp = output_box_ref_slider.imp(); let imp = output_box_ref_slider.imp();
let fraction = (value / 655.36).round(); let fraction = (value / 655.36).round();
println!("{fraction}");
let percentage = (fraction).to_string() + "%"; let percentage = (fraction).to_string() + "%";
imp.resetVolumePercentage.set_text(&percentage); imp.resetVolumePercentage.set_text(&percentage);
let source = imp.resetDefaultSource.borrow(); let source = imp.resetDefaultSource.borrow();
@ -153,10 +167,10 @@ pub fn populate_sources(output_box: Arc<SourceBox>) {
let index = stream.index; let index = stream.index;
if muted { if muted {
imp.resetSourceMute imp.resetSourceMute
.set_icon_name("audio-volume-muted-symbolic"); .set_icon_name("microphone-disabled-symbolic");
} else { } else {
imp.resetSourceMute imp.resetSourceMute
.set_icon_name("audio-volume-high-symbolic"); .set_icon_name("audio-input-microphone-symbolic");
} }
toggle_source_mute(index, muted); toggle_source_mute(index, muted);
}); });
@ -165,19 +179,23 @@ pub fn populate_sources(output_box: Arc<SourceBox>) {
}); });
} }
pub fn populate_outputstreams(_listeners: Arc<Listeners>, output_box: Arc<SourceBox>) { pub fn populate_outputstreams(input_box: Arc<SourceBox>) {
// TODO add listener // TODO add listener
let output_box_ref = output_box.clone(); let input_box_ref = input_box.clone();
gio::spawn_blocking(move || { gio::spawn_blocking(move || {
let streams = get_output_streams(); let streams = get_output_streams();
glib::spawn_future(async move { glib::spawn_future(async move {
glib::idle_add_once(move || { glib::idle_add_once(move || {
let output_box_imp = output_box_ref.imp(); let input_box_imp = input_box_ref.imp();
let mut list = input_box_imp.resetOutputStreamList.write().unwrap();
for stream in streams { for stream in streams {
let entry = ListEntry::new(&OutputStreamEntry::new(output_box.clone(), stream)); let index = stream.index;
let input_stream = Arc::new(OutputStreamEntry::new(input_box.clone(), stream));
let entry = Arc::new(ListEntry::new(&*input_stream));
entry.set_activatable(false); entry.set_activatable(false);
output_box_imp.resetOutputStreams.append(&entry); list.insert(index, (entry.clone(), input_stream.clone()));
input_box_imp.resetOutputStreams.append(&*entry);
} }
}); });
}); });
@ -228,3 +246,262 @@ fn get_default_source() -> Source {
} }
res.unwrap().0 res.unwrap().0
} }
pub fn start_input_box_listener(
conn: Connection,
listeners: Arc<Listeners>,
source_box: Arc<SourceBox>,
) -> Connection {
if listeners.network_listener.load(Ordering::SeqCst) {
return conn;
}
listeners.network_listener.store(true, Ordering::SeqCst);
let source_added = SourceAdded::match_rule(
Some(&"org.xetibo.ReSet".into()),
Some(&Path::from("/org/xetibo/ReSet")),
)
.static_clone();
let source_removed = SourceRemoved::match_rule(
Some(&"org.xetibo.ReSet".into()),
Some(&Path::from("/org/xetibo/ReSet")),
)
.static_clone();
let source_changed = SourceChanged::match_rule(
Some(&"org.xetibo.ReSet".into()),
Some(&Path::from("/org/xetibo/ReSet")),
)
.static_clone();
let output_stream_added = OutputStreamAdded::match_rule(
Some(&"org.xetibo.ReSet".into()),
Some(&Path::from("/org/xetibo/ReSet")),
)
.static_clone();
let output_stream_removed = OutputStreamRemoved::match_rule(
Some(&"org.xetibo.ReSet".into()),
Some(&Path::from("/org/xetibo/ReSet")),
)
.static_clone();
let output_stream_changed = OutputStreamChanged::match_rule(
Some(&"org.xetibo.ReSet".into()),
Some(&Path::from("/org/xetibo/ReSet")),
)
.static_clone();
let source_added_box = source_box.clone();
let source_removed_box = source_box.clone();
let source_changed_box = source_box.clone();
let output_stream_added_box = source_box.clone();
let output_stream_removed_box = source_box.clone();
let output_stream_changed_box = source_box.clone();
let res = conn.add_match(source_added, move |ir: SourceAdded, _, _| {
let source_box = source_added_box.clone();
glib::spawn_future(async move {
glib::idle_add_once(move || {
let output_box = source_box.clone();
let output_box_imp = output_box.imp();
let mut list = output_box_imp.resetSourceList.write().unwrap();
let index = ir.source.index;
let alias = ir.source.alias.clone();
let name = ir.source.name.clone();
let mut is_default = false;
if output_box_imp.resetDefaultSource.borrow().name == ir.source.name {
is_default = true;
}
let source_entry = Arc::new(SourceEntry::new(
is_default,
output_box_imp.resetDefaultCheckButton.clone(),
ir.source,
));
let source_clone = source_entry.clone();
let entry = Arc::new(ListEntry::new(&*source_entry));
entry.set_activatable(false);
list.insert(index, (entry.clone(), source_clone, alias.clone()));
output_box_imp.resetSources.append(&*entry);
let mut map = output_box_imp.resetSourceMap.write().unwrap();
let mut index = output_box_imp.resetModelIndex.write().unwrap();
map.insert(alias, (*index, *index, name));
*index += 1;
});
});
true
});
if res.is_err() {
println!("fail on source add");
return conn;
}
let res = conn.add_match(source_removed, move |ir: SourceRemoved, _, _| {
let source_box = source_removed_box.clone();
glib::spawn_future(async move {
glib::idle_add_once(move || {
let output_box = source_box.clone();
let output_box_imp = output_box.imp();
let mut list = output_box_imp.resetSourceList.write().unwrap();
let entry = list.get(&ir.index);
if entry.is_none() {
return;
}
output_box_imp.resetSources.remove(&*entry.unwrap().0);
list.remove(&ir.index);
let alias = list.remove(&ir.index);
if alias.is_none() {
return;
}
let mut map = output_box_imp.resetSourceMap.write().unwrap();
map.remove(&alias.unwrap().2);
let mut index = output_box_imp.resetModelIndex.write().unwrap();
*index -= 1;
});
});
true
});
if res.is_err() {
println!("fail on source remove");
return conn;
}
let res = conn.add_match(source_changed, move |ir: SourceChanged, _, _| {
let source_box = source_changed_box.clone();
let default_source = get_default_source();
glib::spawn_future(async move {
glib::idle_add_once(move || {
let output_box = source_box.clone();
let output_box_imp = output_box.imp();
let list = output_box_imp.resetSourceList.read().unwrap();
let entry = list.get(&ir.source.index);
if entry.is_none() {
return;
}
let imp = entry.unwrap().1.imp();
let is_default = ir.source.name == default_source.name;
imp.resetSourceName
.set_text(ir.source.alias.clone().as_str());
let volume = ir.source.volume.first().unwrap_or_else(|| &(0 as u32));
let fraction = (*volume as f64 / 655.36).round();
let percentage = (fraction).to_string() + "%";
imp.resetVolumePercentage.set_text(&percentage);
imp.resetVolumeSlider.set_value(*volume as f64);
if is_default {
imp.resetSelectedSource.set_active(true);
} else {
imp.resetSelectedSource.set_active(false);
}
});
});
true
});
if res.is_err() {
println!("fail on source remove");
return conn;
}
let res = conn.add_match(output_stream_added, move |ir: OutputStreamAdded, _, _| {
let source_box = output_stream_added_box.clone();
glib::spawn_future(async move {
glib::idle_add_once(move || {
let output_box = source_box.clone();
let output_box_imp = output_box.imp();
let mut list = output_box_imp.resetOutputStreamList.write().unwrap();
let index = ir.stream.index;
let output_stream = Arc::new(OutputStreamEntry::new(output_box.clone(), ir.stream));
let entry = Arc::new(ListEntry::new(&*output_stream));
entry.set_activatable(false);
list.insert(index, (entry.clone(), output_stream.clone()));
output_box_imp.resetOutputStreams.append(&*entry);
});
});
true
});
if res.is_err() {
println!("fail on stream add");
return conn;
}
let res = conn.add_match(
output_stream_changed,
move |ir: OutputStreamChanged, _, _| {
let imp = output_stream_changed_box.imp();
let alias: String;
{
let source_list = imp.resetSourceList.read().unwrap();
let alias_opt = source_list.get(&ir.stream.source_index);
if alias_opt.is_some() {
alias = alias_opt.unwrap().2.clone();
} else {
alias = String::from("");
}
}
let source_box = output_stream_changed_box.clone();
glib::spawn_future(async move {
glib::idle_add_once(move || {
let output_box = source_box.clone();
let output_box_imp = output_box.imp();
let entry: Arc<OutputStreamEntry>;
{
let list = output_box_imp.resetOutputStreamList.read().unwrap();
let entry_opt = list.get(&ir.stream.index);
if entry_opt.is_none() {
return;
}
entry = entry_opt.unwrap().1.clone();
}
let imp = entry.imp();
if ir.stream.muted {
imp.resetSourceMute
.set_icon_name("microphone-disabled-symbolic");
} else {
imp.resetSourceMute
.set_icon_name("audio-input-microphone-symbolic");
}
let name = ir.stream.application_name.clone() + ": " + ir.stream.name.as_str();
imp.resetSourceName.set_text(name.as_str());
let volume = ir.stream.volume.first().unwrap_or_else(|| &(0 as u32));
let fraction = (*volume as f64 / 655.36).round();
let percentage = (fraction).to_string() + "%";
imp.resetVolumePercentage.set_text(&percentage);
imp.resetVolumeSlider.set_value(*volume as f64);
let map = output_box_imp.resetSourceMap.read().unwrap();
let index = map.get(&alias);
if index.is_some() {
imp.resetSelectedSource.set_selected(index.unwrap().1);
}
});
});
true
},
);
if res.is_err() {
println!("fail on stream change");
return conn;
}
let res = conn.add_match(
output_stream_removed,
move |ir: OutputStreamRemoved, _, _| {
let source_box = output_stream_removed_box.clone();
glib::spawn_future(async move {
glib::idle_add_once(move || {
let output_box = source_box.clone();
let output_box_imp = output_box.imp();
let mut list = output_box_imp.resetOutputStreamList.write().unwrap();
let entry = list.get(&ir.index);
if entry.is_none() {
return;
}
output_box_imp.resetOutputStreams.remove(&*entry.unwrap().0);
list.remove(&ir.index);
});
});
true
},
);
if res.is_err() {
println!("fail on stream remove");
return conn;
}
listeners.network_listener.store(true, Ordering::SeqCst);
conn
}

View file

@ -1,13 +1,13 @@
use std::cell::RefCell; use std::cell::RefCell;
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, RwLock};
use crate::components::base::listEntry::ListEntry; use crate::components::base::listEntry::ListEntry;
use crate::components::input::sourceBox; use crate::components::input::sourceBox;
use gtk::subclass::prelude::*; use gtk::subclass::prelude::*;
use gtk::{glib, CheckButton, CompositeTemplate, DropDown, StringList, TemplateChild}; use gtk::{glib, CheckButton, CompositeTemplate, DropDown, StringList, TemplateChild};
use gtk::{prelude::*, Button, Label, ProgressBar, Scale}; use gtk::{prelude::*, Button, Label, ProgressBar, Scale};
use ReSet_Lib::audio::audio::{OutputStream, Source}; use ReSet_Lib::audio::audio::Source;
use super::outputStreamEntry::OutputStreamEntry; use super::outputStreamEntry::OutputStreamEntry;
use super::sourceEntry::SourceEntry; use super::sourceEntry::SourceEntry;
@ -36,11 +36,13 @@ pub struct SourceBox {
pub resetOutputStreams: TemplateChild<gtk::Box>, pub resetOutputStreams: TemplateChild<gtk::Box>,
pub resetDefaultCheckButton: Arc<CheckButton>, pub resetDefaultCheckButton: Arc<CheckButton>,
pub resetDefaultSource: Arc<RefCell<Source>>, pub resetDefaultSource: Arc<RefCell<Source>>,
pub resetSourceList: Arc<Mutex<Vec<Source>>>, pub resetSourceList: Arc<RwLock<HashMap<u32, (Arc<ListEntry>, Arc<SourceEntry>, String)>>>,
pub resetOutputStreamList: Arc<Mutex<Vec<OutputStream>>>, pub resetOutputStreamList: Arc<RwLock<HashMap<u32, (Arc<ListEntry>, Arc<OutputStreamEntry>)>>>,
pub resetModelList: Arc<RefCell<StringList>>, pub resetModelList: Arc<RwLock<StringList>>,
// first u32 is the index of the source, the second the index in the model list pub resetModelIndex: Arc<RwLock<u32>>,
pub resetSourceMap: Arc<RefCell<HashMap<String, (u32, u32, String)>>>, // first u32 is the index of the source, the second the index in the model list and the third is
// the full name
pub resetSourceMap: Arc<RwLock<HashMap<String, (u32, u32, String)>>>,
} }
#[glib::object_subclass] #[glib::object_subclass]

View file

@ -1,16 +1,15 @@
use std::sync::Arc; use std::sync::Arc;
use std::thread;
use std::time::Duration; use std::time::Duration;
use adw::glib; use adw::glib;
use adw::glib::Object; use adw::glib::Object;
use adw::prelude::{ButtonExt, RangeExt, CheckButtonExt}; use adw::prelude::{ButtonExt, CheckButtonExt, RangeExt};
use dbus::blocking::Connection; use dbus::blocking::Connection;
use dbus::Error; use dbus::Error;
use glib::subclass::types::ObjectSubclassIsExt; use glib::subclass::types::ObjectSubclassIsExt;
use glib::{clone, Propagation}; use glib::{clone, Propagation};
use gtk::{gio, CheckButton};
use ReSet_Lib::audio::audio::Source; use ReSet_Lib::audio::audio::Source;
use gtk::CheckButton;
use super::sourceEntryImpl; use super::sourceEntryImpl;
@ -24,7 +23,6 @@ impl SourceEntry {
pub fn new(is_default: bool, check_group: Arc<CheckButton>, stream: Source) -> Self { pub fn new(is_default: bool, check_group: Arc<CheckButton>, stream: Source) -> Self {
let obj: Self = Object::builder().build(); let obj: Self = Object::builder().build();
// TODO use event callback for progress bar -> this is the "im speaking" indicator // TODO use event callback for progress bar -> this is the "im speaking" indicator
// TODO handle events
{ {
let imp = obj.imp(); let imp = obj.imp();
imp.resetSourceName.set_text(stream.alias.clone().as_str()); imp.resetSourceName.set_text(stream.alias.clone().as_str());
@ -38,7 +36,6 @@ impl SourceEntry {
imp.resetVolumeSlider.connect_change_value( imp.resetVolumeSlider.connect_change_value(
clone!(@weak imp => @default-return Propagation::Stop, move |_, _, value| { clone!(@weak imp => @default-return Propagation::Stop, move |_, _, value| {
let fraction = (value / 655.36).round(); let fraction = (value / 655.36).round();
println!("{fraction}");
let percentage = (fraction).to_string() + "%"; let percentage = (fraction).to_string() + "%";
imp.resetVolumePercentage.set_text(&percentage); imp.resetVolumePercentage.set_text(&percentage);
let source = imp.stream.borrow(); let source = imp.stream.borrow();
@ -69,10 +66,10 @@ impl SourceEntry {
let index = stream.index; let index = stream.index;
if muted { if muted {
imp.resetSourceMute imp.resetSourceMute
.set_icon_name("audio-volume-muted-symbolic"); .set_icon_name("microphone-disabled-symbolic");
} else { } else {
imp.resetSourceMute imp.resetSourceMute
.set_icon_name("audio-volume-high-symbolic"); .set_icon_name("audio-input-microphone-symbolic");
} }
toggle_source_mute(index, muted); toggle_source_mute(index, muted);
})); }));
@ -82,51 +79,60 @@ impl SourceEntry {
} }
pub fn set_source_volume(value: f64, index: u32, channels: u16) -> bool { pub fn set_source_volume(value: f64, index: u32, channels: u16) -> bool {
gio::spawn_blocking(move || {
let conn = Connection::new_session().unwrap(); let conn = Connection::new_session().unwrap();
let proxy = conn.with_proxy( let proxy = conn.with_proxy(
"org.xetibo.ReSet", "org.xetibo.ReSet",
"/org/xetibo/ReSet", "/org/xetibo/ReSet",
Duration::from_millis(1000), Duration::from_millis(1000),
); );
let res: Result<(bool,), Error> = proxy.method_call( let _: Result<(), Error> = proxy.method_call(
"org.xetibo.ReSet", "org.xetibo.ReSet",
"SetSourceVolume", "SetSourceVolume",
(index, channels, value as u32), (index, channels, value as u32),
); );
if res.is_err() { // if res.is_err() {
return false; // return false;
} // }
res.unwrap().0 // res.unwrap().0
});
true
} }
pub fn toggle_source_mute(index: u32, muted: bool) -> bool { pub fn toggle_source_mute(index: u32, muted: bool) -> bool {
gio::spawn_blocking(move || {
let conn = Connection::new_session().unwrap(); let conn = Connection::new_session().unwrap();
let proxy = conn.with_proxy( let proxy = conn.with_proxy(
"org.xetibo.ReSet", "org.xetibo.ReSet",
"/org/xetibo/ReSet", "/org/xetibo/ReSet",
Duration::from_millis(1000), Duration::from_millis(1000),
); );
let res: Result<(bool,), Error> = let _: Result<(), Error> =
proxy.method_call("org.xetibo.ReSet", "SetSourceMute", (index, muted)); proxy.method_call("org.xetibo.ReSet", "SetSourceMute", (index, muted));
if res.is_err() { // if res.is_err() {
return false; // return false;
} // }
res.unwrap().0 // res.unwrap().0
});
true
} }
pub fn set_default_source(name: Arc<String>) { pub fn set_default_source(name: Arc<String>) -> bool {
thread::spawn(move || { gio::spawn_blocking(move || {
let conn = Connection::new_session().unwrap(); let conn = Connection::new_session().unwrap();
let proxy = conn.with_proxy( let proxy = conn.with_proxy(
"org.xetibo.ReSet", "org.xetibo.ReSet",
"/org/xetibo/ReSet", "/org/xetibo/ReSet",
Duration::from_millis(1000), Duration::from_millis(1000),
); );
let res: Result<(bool,), Error> = let _: Result<(), Error> =
proxy.method_call("org.xetibo.ReSet", "SetDefaultSink", (name.as_str(),)); proxy.method_call("org.xetibo.ReSet", "SetDefaultSink", (name.as_str(),));
if res.is_err() { // if res.is_err() {
return; // return;
} // }
// handle change // handle change
}); });
true
} }
// TODO propagate error from dbus

View file

@ -8,7 +8,7 @@ use dbus::blocking::Connection;
use dbus::Error; use dbus::Error;
use glib::subclass::types::ObjectSubclassIsExt; use glib::subclass::types::ObjectSubclassIsExt;
use glib::{clone, Cast, Propagation}; use glib::{clone, Cast, Propagation};
use gtk::StringObject; use gtk::{gio, StringObject};
use ReSet_Lib::audio::audio::InputStream; use ReSet_Lib::audio::audio::InputStream;
use super::inputStreamEntryImpl; use super::inputStreamEntryImpl;
@ -24,8 +24,8 @@ impl InputStreamEntry {
pub fn new(sink_box: Arc<SinkBox>, stream: InputStream) -> Self { pub fn new(sink_box: Arc<SinkBox>, stream: InputStream) -> Self {
let obj: Self = Object::builder().build(); let obj: Self = Object::builder().build();
// TODO use event callback for progress bar -> this is the "im speaking" indicator // TODO use event callback for progress bar -> this is the "im speaking" indicator
// TODO handle events
{ {
let index = stream.sink_index;
let box_imp = sink_box.imp(); let box_imp = sink_box.imp();
let imp = obj.imp(); let imp = obj.imp();
if stream.muted { if stream.muted {
@ -64,28 +64,33 @@ impl InputStreamEntry {
}), }),
); );
{ {
let mut list = box_imp.resetModelList.try_borrow(); let list = box_imp.resetModelList.read().unwrap();
while list.is_err() { // while list.is_err() {
list = box_imp.resetModelList.try_borrow(); // list = box_imp.resetModelList.try_borrow();
} // }
let list = list.unwrap(); // let list = list.unwrap();
imp.resetSelectedSink.set_model(Some(&*list)); imp.resetSelectedSink.set_model(Some(&*list));
let mut map = box_imp.resetSinkMap.try_borrow(); let map = box_imp.resetSinkMap.read().unwrap();
while map.is_err() { let sink_list = box_imp.resetSinkList.read().unwrap();
map = box_imp.resetSinkMap.try_borrow(); let name = sink_list.get(&index);
if name.is_some() {
let name = &name.unwrap().2;
let index = map.get(name);
if index.is_some() {
imp.resetSelectedSink.set_selected(index.unwrap().1);
} }
let map = map.unwrap(); } else {
let mut name = box_imp.resetDefaultSink.try_borrow(); let mut name = box_imp.resetDefaultSink.try_borrow();
while name.is_err() { while name.is_err() {
name = box_imp.resetDefaultSink.try_borrow(); name = box_imp.resetDefaultSink.try_borrow();
} }
let name = name.unwrap(); let name = &name.unwrap().alias;
let name = &name.alias;
let index = map.get(name); let index = map.get(name);
if index.is_some() { if index.is_some() {
imp.resetSelectedSink.set_selected(index.unwrap().1); imp.resetSelectedSink.set_selected(index.unwrap().1);
} }
} }
}
imp.resetSelectedSink.connect_selected_notify( imp.resetSelectedSink.connect_selected_notify(
clone!(@weak imp, @weak box_imp => move |dropdown| { clone!(@weak imp, @weak box_imp => move |dropdown| {
let selected = dropdown.selected_item(); let selected = dropdown.selected_item();
@ -95,11 +100,11 @@ impl InputStreamEntry {
let selected = selected.unwrap(); let selected = selected.unwrap();
let selected = selected.downcast_ref::<StringObject>().unwrap(); let selected = selected.downcast_ref::<StringObject>().unwrap();
let selected = selected.string().to_string(); let selected = selected.string().to_string();
let mut sink = box_imp.resetSinkMap.try_borrow(); let sink = box_imp.resetSinkMap.read().unwrap();
while sink.is_err() { // if sink.is_err() {
sink = box_imp.resetSinkMap.try_borrow(); // return;
} // }
let sink = sink.unwrap(); // let sink = sink.unwrap();
let sink = sink.get(&selected); let sink = sink.get(&selected);
if sink.is_none() { if sink.is_none() {
return; return;
@ -139,49 +144,60 @@ impl InputStreamEntry {
} }
fn set_inputstream_volume(value: f64, index: u32, channels: u16) -> bool { fn set_inputstream_volume(value: f64, index: u32, channels: u16) -> bool {
gio::spawn_blocking(move || {
let conn = Connection::new_session().unwrap(); let conn = Connection::new_session().unwrap();
let proxy = conn.with_proxy( let proxy = conn.with_proxy(
"org.xetibo.ReSet", "org.xetibo.ReSet",
"/org/xetibo/ReSet", "/org/xetibo/ReSet",
Duration::from_millis(1000), Duration::from_millis(1000),
); );
let res: Result<(bool,), Error> = proxy.method_call( let _: Result<(), Error> = proxy.method_call(
"org.xetibo.ReSet", "org.xetibo.ReSet",
"SetInputStreamVolume", "SetInputStreamVolume",
(index, channels, value as u32), (index, channels, value as u32),
); );
if res.is_err() { // if res.is_err() {
return false; // return false;
} // }
res.unwrap().0 // res.unwrap().0
});
true
} }
fn toggle_input_stream_mute(index: u32, muted: bool) -> bool { fn toggle_input_stream_mute(index: u32, muted: bool) -> bool {
gio::spawn_blocking(move || {
let conn = Connection::new_session().unwrap(); let conn = Connection::new_session().unwrap();
let proxy = conn.with_proxy( let proxy = conn.with_proxy(
"org.xetibo.ReSet", "org.xetibo.ReSet",
"/org/xetibo/ReSet", "/org/xetibo/ReSet",
Duration::from_millis(1000), Duration::from_millis(1000),
); );
let res: Result<(bool,), Error> = let _: Result<(), Error> =
proxy.method_call("org.xetibo.ReSet", "SetInputStreamMute", (index, muted)); proxy.method_call("org.xetibo.ReSet", "SetInputStreamMute", (index, muted));
if res.is_err() { // if res.is_err() {
return false; // return false;
} // }
res.unwrap().0 // res.unwrap().0
});
true
} }
fn set_sink_of_input_stream(stream: u32, sink: u32) -> bool { fn set_sink_of_input_stream(stream: u32, sink: u32) -> bool {
gio::spawn_blocking(move || {
let conn = Connection::new_session().unwrap(); let conn = Connection::new_session().unwrap();
let proxy = conn.with_proxy( let proxy = conn.with_proxy(
"org.xetibo.ReSet", "org.xetibo.ReSet",
"/org/xetibo/ReSet", "/org/xetibo/ReSet",
Duration::from_millis(1000), Duration::from_millis(1000),
); );
let res: Result<(bool,), Error> = let _: Result<(), Error> =
proxy.method_call("org.xetibo.ReSet", "SetSinkOfInputStream", (stream, sink)); proxy.method_call("org.xetibo.ReSet", "SetSinkOfInputStream", (stream, sink));
if res.is_err() { // if res.is_err() {
return false; // return false;
} // }
res.unwrap().0 // res.unwrap().0
});
true
} }
// TODO propagate error from dbus

View file

@ -1,14 +1,19 @@
use std::sync::atomic::Ordering;
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
use crate::components::base::listEntry::ListEntry; use crate::components::base::listEntry::ListEntry;
use crate::components::base::utils::Listeners; use crate::components::base::utils::{
InputStreamAdded, InputStreamChanged, InputStreamRemoved, Listeners, SinkAdded, SinkChanged,
SinkRemoved,
};
use crate::components::output::sinkEntry::set_sink_volume; use crate::components::output::sinkEntry::set_sink_volume;
use adw::glib::Object; use adw::glib::Object;
use adw::prelude::{BoxExt, ButtonExt, RangeExt}; use adw::prelude::{BoxExt, ButtonExt, CheckButtonExt, RangeExt};
use adw::{glib, prelude::ListBoxRowExt}; use adw::{glib, prelude::ListBoxRowExt};
use dbus::blocking::Connection; use dbus::blocking::Connection;
use dbus::Error; use dbus::message::SignalArgs;
use dbus::{Error, Path};
use glib::subclass::prelude::ObjectSubclassIsExt; use glib::subclass::prelude::ObjectSubclassIsExt;
use glib::{clone, Cast, Propagation, Variant}; use glib::{clone, Cast, Propagation, Variant};
use gtk::prelude::ActionableExt; use gtk::prelude::ActionableExt;
@ -54,17 +59,19 @@ pub fn populate_sinks(output_box: Arc<SinkBox>) {
let sinks = get_sinks(); let sinks = get_sinks();
{ {
let output_box_imp = output_box.imp(); let output_box_imp = output_box.imp();
let mut map = output_box_imp.resetSinkMap.write().unwrap();
let list = output_box_imp.resetModelList.write().unwrap();
let mut model_index = output_box_imp.resetModelIndex.write().unwrap();
output_box_imp.resetDefaultSink.replace(get_default_sink()); output_box_imp.resetDefaultSink.replace(get_default_sink());
let list = output_box_imp.resetModelList.borrow_mut();
let mut map = output_box_imp.resetSinkMap.borrow_mut();
let mut i: u32 = 0; let mut i: u32 = 0;
for sink in sinks.iter() { for sink in sinks.iter() {
dbg!(sink.clone());
list.append(&sink.alias); list.append(&sink.alias);
map.insert(sink.alias.clone(), (sink.index, i, sink.name.clone())); map.insert(sink.alias.clone(), (sink.index, i, sink.name.clone()));
i += 1; i += 1;
*model_index += 1;
} }
} }
populate_inputstreams(output_box.clone());
glib::spawn_future(async move { glib::spawn_future(async move {
glib::idle_add_once(move || { glib::idle_add_once(move || {
let output_box_ref_slider = output_box.clone(); let output_box_ref_slider = output_box.clone();
@ -79,22 +86,28 @@ pub fn populate_sinks(output_box: Arc<SinkBox>) {
let percentage = (fraction).to_string() + "%"; let percentage = (fraction).to_string() + "%";
output_box_imp.resetVolumePercentage.set_text(&percentage); output_box_imp.resetVolumePercentage.set_text(&percentage);
output_box_imp.resetVolumeSlider.set_value(*volume as f64); output_box_imp.resetVolumeSlider.set_value(*volume as f64);
for stream in sinks { let mut list = output_box_imp.resetSinkList.write().unwrap();
for sink in sinks {
let index = sink.index;
let alias = sink.alias.clone();
let mut is_default = false; let mut is_default = false;
if output_box_imp.resetDefaultSink.borrow().name == stream.name { if output_box_imp.resetDefaultSink.borrow().name == sink.name {
is_default = true; is_default = true;
} }
let entry = ListEntry::new(&SinkEntry::new( let sink_entry = Arc::new(SinkEntry::new(
is_default, is_default,
output_box_imp.resetDefaultCheckButton.clone(), output_box_imp.resetDefaultCheckButton.clone(),
stream, sink,
)); ));
let sink_clone = sink_entry.clone();
let entry = Arc::new(ListEntry::new(&*sink_entry));
entry.set_activatable(false); entry.set_activatable(false);
output_box_imp.resetSinks.append(&entry); list.insert(index, (entry.clone(), sink_clone, alias));
output_box_imp.resetSinks.append(&*entry);
} }
let list = output_box_imp.resetModelList.borrow(); let list = output_box_imp.resetModelList.read().unwrap();
output_box_imp.resetSinkDropdown.set_model(Some(&*list)); output_box_imp.resetSinkDropdown.set_model(Some(&*list));
let map = output_box_imp.resetSinkMap.borrow(); let map = output_box_imp.resetSinkMap.read().unwrap();
let name = output_box_imp.resetDefaultSink.borrow(); let name = output_box_imp.resetDefaultSink.borrow();
let name = &name.alias; let name = &name.alias;
let index = map.get(name); let index = map.get(name);
@ -113,7 +126,7 @@ pub fn populate_sinks(output_box: Arc<SinkBox>) {
let selected = selected.downcast_ref::<StringObject>().unwrap(); let selected = selected.downcast_ref::<StringObject>().unwrap();
let selected = selected.string().to_string(); let selected = selected.string().to_string();
let sink = output_box_imp.resetSinkMap.borrow(); let sink = output_box_imp.resetSinkMap.read().unwrap();
let sink = sink.get(&selected); let sink = sink.get(&selected);
if sink.is_none() { if sink.is_none() {
return; return;
@ -129,7 +142,6 @@ pub fn populate_sinks(output_box: Arc<SinkBox>) {
.connect_change_value(move |_, _, value| { .connect_change_value(move |_, _, value| {
let imp = output_box_ref_slider.imp(); let imp = output_box_ref_slider.imp();
let fraction = (value / 655.36).round(); let fraction = (value / 655.36).round();
println!("{fraction}");
let percentage = (fraction).to_string() + "%"; let percentage = (fraction).to_string() + "%";
imp.resetVolumePercentage.set_text(&percentage); imp.resetVolumePercentage.set_text(&percentage);
let sink = imp.resetDefaultSink.borrow(); let sink = imp.resetDefaultSink.borrow();
@ -162,8 +174,7 @@ pub fn populate_sinks(output_box: Arc<SinkBox>) {
}); });
} }
pub fn populate_inputstreams(_listeners: Arc<Listeners>, output_box: Arc<SinkBox>) { pub fn populate_inputstreams(output_box: Arc<SinkBox>) {
// TODO add listener
let output_box_ref = output_box.clone(); let output_box_ref = output_box.clone();
gio::spawn_blocking(move || { gio::spawn_blocking(move || {
@ -171,10 +182,14 @@ pub fn populate_inputstreams(_listeners: Arc<Listeners>, output_box: Arc<SinkBox
glib::spawn_future(async move { glib::spawn_future(async move {
glib::idle_add_once(move || { glib::idle_add_once(move || {
let output_box_imp = output_box_ref.imp(); let output_box_imp = output_box_ref.imp();
let mut list = output_box_imp.resetInputStreamList.write().unwrap();
for stream in streams { for stream in streams {
let entry = ListEntry::new(&InputStreamEntry::new(output_box.clone(), stream)); let index = stream.index;
let input_stream = Arc::new(InputStreamEntry::new(output_box.clone(), stream));
let entry = Arc::new(ListEntry::new(&*input_stream));
entry.set_activatable(false); entry.set_activatable(false);
output_box_imp.resetInputStreams.append(&entry); list.insert(index, (entry.clone(), input_stream.clone()));
output_box_imp.resetInputStreams.append(&*entry);
} }
}); });
}); });
@ -223,3 +238,250 @@ fn get_default_sink() -> Sink {
} }
res.unwrap().0 res.unwrap().0
} }
pub fn start_output_box_listener(conn: Connection, listeners: Arc<Listeners>, sink_box: Arc<SinkBox>) -> Connection {
if listeners.network_listener.load(Ordering::SeqCst) {
return conn;
}
listeners.network_listener.store(true, Ordering::SeqCst);
let sink_added = SinkAdded::match_rule(
Some(&"org.xetibo.ReSet".into()),
Some(&Path::from("/org/xetibo/ReSet")),
)
.static_clone();
let sink_removed = SinkRemoved::match_rule(
Some(&"org.xetibo.ReSet".into()),
Some(&Path::from("/org/xetibo/ReSet")),
)
.static_clone();
let sink_changed = SinkChanged::match_rule(
Some(&"org.xetibo.ReSet".into()),
Some(&Path::from("/org/xetibo/ReSet")),
)
.static_clone();
let input_stream_added = InputStreamAdded::match_rule(
Some(&"org.xetibo.ReSet".into()),
Some(&Path::from("/org/xetibo/ReSet")),
)
.static_clone();
let input_stream_removed = InputStreamRemoved::match_rule(
Some(&"org.xetibo.ReSet".into()),
Some(&Path::from("/org/xetibo/ReSet")),
)
.static_clone();
let input_stream_changed = InputStreamChanged::match_rule(
Some(&"org.xetibo.ReSet".into()),
Some(&Path::from("/org/xetibo/ReSet")),
)
.static_clone();
let sink_added_box = sink_box.clone();
let sink_removed_box = sink_box.clone();
let sink_changed_box = sink_box.clone();
let input_stream_added_box = sink_box.clone();
let input_stream_removed_box = sink_box.clone();
let input_stream_changed_box = sink_box.clone();
let res = conn.add_match(sink_added, move |ir: SinkAdded, _, _| {
let sink_box = sink_added_box.clone();
glib::spawn_future(async move {
glib::idle_add_once(move || {
let output_box = sink_box.clone();
let output_box_imp = output_box.imp();
let mut list = output_box_imp.resetSinkList.write().unwrap();
let index = ir.sink.index;
let alias = ir.sink.alias.clone();
let name = ir.sink.name.clone();
let mut is_default = false;
if output_box_imp.resetDefaultSink.borrow().name == ir.sink.name {
is_default = true;
}
let sink_entry = Arc::new(SinkEntry::new(
is_default,
output_box_imp.resetDefaultCheckButton.clone(),
ir.sink,
));
let sink_clone = sink_entry.clone();
let entry = Arc::new(ListEntry::new(&*sink_entry));
entry.set_activatable(false);
list.insert(index, (entry.clone(), sink_clone, alias.clone()));
output_box_imp.resetSinks.append(&*entry);
let mut map = output_box_imp.resetSinkMap.write().unwrap();
let mut index = output_box_imp.resetModelIndex.write().unwrap();
map.insert(alias, (*index, *index, name));
*index += 1;
});
});
true
});
if res.is_err() {
println!("fail on sink add");
return conn;
}
let res = conn.add_match(sink_removed, move |ir: SinkRemoved, _, _| {
let sink_box = sink_removed_box.clone();
glib::spawn_future(async move {
glib::idle_add_once(move || {
let output_box = sink_box.clone();
let output_box_imp = output_box.imp();
let mut list = output_box_imp.resetSinkList.write().unwrap();
let entry = list.get(&ir.index);
if entry.is_none() {
return;
}
output_box_imp.resetSinks.remove(&*entry.unwrap().0);
let alias = list.remove(&ir.index);
if alias.is_none() {
return;
}
let mut map = output_box_imp.resetSinkMap.write().unwrap();
map.remove(&alias.unwrap().2);
let mut index = output_box_imp.resetModelIndex.write().unwrap();
*index -= 1;
});
});
true
});
if res.is_err() {
println!("fail on sink remove");
return conn;
}
let res = conn.add_match(sink_changed, move |ir: SinkChanged, _, _| {
let sink_box = sink_changed_box.clone();
let default_sink = get_default_sink();
glib::spawn_future(async move {
glib::idle_add_once(move || {
let output_box = sink_box.clone();
let output_box_imp = output_box.imp();
let list = output_box_imp.resetSinkList.read().unwrap();
let entry = list.get(&ir.sink.index);
if entry.is_none() {
return;
}
let imp = entry.unwrap().1.imp();
let is_default = ir.sink.name == default_sink.name;
imp.resetSinkName.set_text(ir.sink.alias.clone().as_str());
let volume = ir.sink.volume.first().unwrap_or_else(|| &(0 as u32));
let fraction = (*volume as f64 / 655.36).round();
let percentage = (fraction).to_string() + "%";
imp.resetVolumePercentage.set_text(&percentage);
imp.resetVolumeSlider.set_value(*volume as f64);
if is_default {
imp.resetSelectedSink.set_active(true);
} else {
imp.resetSelectedSink.set_active(false);
}
});
});
true
});
if res.is_err() {
println!("fail on sink remove");
return conn;
}
let res = conn.add_match(input_stream_added, move |ir: InputStreamAdded, _, _| {
let sink_box = input_stream_added_box.clone();
glib::spawn_future(async move {
glib::idle_add_once(move || {
let output_box = sink_box.clone();
let output_box_imp = output_box.imp();
let mut list = output_box_imp.resetInputStreamList.write().unwrap();
let index = ir.stream.index;
let input_stream = Arc::new(InputStreamEntry::new(output_box.clone(), ir.stream));
let entry = Arc::new(ListEntry::new(&*input_stream));
entry.set_activatable(false);
list.insert(index, (entry.clone(), input_stream.clone()));
output_box_imp.resetInputStreams.append(&*entry);
});
});
true
});
if res.is_err() {
println!("fail on stream add");
return conn;
}
let res = conn.add_match(input_stream_changed, move |ir: InputStreamChanged, _, _| {
let imp = input_stream_changed_box.imp();
let alias: String;
{
let sink_list = imp.resetSinkList.read().unwrap();
let alias_opt = sink_list.get(&ir.stream.sink_index);
if alias_opt.is_some() {
alias = alias_opt.unwrap().2.clone();
} else {
alias = String::from("");
}
}
let sink_box = input_stream_changed_box.clone();
glib::spawn_future(async move {
glib::idle_add_once(move || {
let output_box = sink_box.clone();
let output_box_imp = output_box.imp();
let entry: Arc<InputStreamEntry>;
{
let list = output_box_imp.resetInputStreamList.read().unwrap();
let entry_opt = list.get(&ir.stream.index);
if entry_opt.is_none() {
return;
}
entry = entry_opt.unwrap().1.clone();
}
let imp = entry.imp();
if ir.stream.muted {
imp.resetSinkMute
.set_icon_name("audio-volume-muted-symbolic");
} else {
imp.resetSinkMute
.set_icon_name("audio-volume-high-symbolic");
}
let name = ir.stream.application_name.clone() + ": " + ir.stream.name.as_str();
imp.resetSinkName.set_text(name.as_str());
let volume = ir.stream.volume.first().unwrap_or_else(|| &(0 as u32));
let fraction = (*volume as f64 / 655.36).round();
let percentage = (fraction).to_string() + "%";
imp.resetVolumePercentage.set_text(&percentage);
imp.resetVolumeSlider.set_value(*volume as f64);
let map = output_box_imp.resetSinkMap.read().unwrap();
let index = map.get(&alias);
if index.is_some() {
imp.resetSelectedSink.set_selected(index.unwrap().1);
}
});
});
true
});
if res.is_err() {
println!("fail on stream change");
return conn;
}
let res = conn.add_match(input_stream_removed, move |ir: InputStreamRemoved, _, _| {
let sink_box = input_stream_removed_box.clone();
glib::spawn_future(async move {
glib::idle_add_once(move || {
let output_box = sink_box.clone();
let output_box_imp = output_box.imp();
let mut list = output_box_imp.resetInputStreamList.write().unwrap();
let entry = list.get(&ir.index);
if entry.is_none() {
return;
}
output_box_imp.resetInputStreams.remove(&*entry.unwrap().0);
list.remove(&ir.index);
});
});
true
});
if res.is_err() {
println!("fail on stream remove");
return conn;
}
listeners.network_listener.store(true, Ordering::SeqCst);
conn
}

View file

@ -1,6 +1,6 @@
use std::cell::RefCell; use std::cell::RefCell;
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, RwLock};
use crate::components::base::listEntry::ListEntry; use crate::components::base::listEntry::ListEntry;
use crate::components::output::inputStreamEntry::InputStreamEntry; use crate::components::output::inputStreamEntry::InputStreamEntry;
@ -9,7 +9,7 @@ use gtk::{
glib, Box, Button, CheckButton, CompositeTemplate, DropDown, Label, StringList, TemplateChild, glib, Box, Button, CheckButton, CompositeTemplate, DropDown, Label, StringList, TemplateChild,
}; };
use gtk::{prelude::*, ProgressBar, Scale}; use gtk::{prelude::*, ProgressBar, Scale};
use ReSet_Lib::audio::audio::{InputStream, Sink}; use ReSet_Lib::audio::audio::Sink;
use super::sinkBox; use super::sinkBox;
use super::sinkEntry::SinkEntry; use super::sinkEntry::SinkEntry;
@ -38,11 +38,14 @@ pub struct SinkBox {
pub resetInputStreams: TemplateChild<Box>, pub resetInputStreams: TemplateChild<Box>,
pub resetDefaultCheckButton: Arc<CheckButton>, pub resetDefaultCheckButton: Arc<CheckButton>,
pub resetDefaultSink: Arc<RefCell<Sink>>, pub resetDefaultSink: Arc<RefCell<Sink>>,
pub resetSinkList: Arc<Mutex<Vec<Sink>>>, pub resetSinkList: Arc<RwLock<HashMap<u32, (Arc<ListEntry>, Arc<SinkEntry>, String)>>>,
pub resetInputStreamList: Arc<Mutex<Vec<InputStream>>>, pub resetInputStreamList: Arc<RwLock<HashMap<u32, (Arc<ListEntry>, Arc<InputStreamEntry>)>>>,
pub resetModelList: Arc<RefCell<StringList>>, pub resetModelList: Arc<RwLock<StringList>>,
// first u32 is the index of the sink, the second the index in the model list pub resetModelIndex: Arc<RwLock<u32>>,
pub resetSinkMap: Arc<RefCell<HashMap<String, (u32, u32, String)>>>, // first u32 is the index of the sink, the second the index in the model list and the third is
// the full name
pub resetSinkMap: Arc<RwLock<HashMap<String, (u32, u32, String)>>>,
// pub : Arc<Mutex<Vec<ListEntry>>>,
} }
#[glib::object_subclass] #[glib::object_subclass]

View file

@ -1,5 +1,4 @@
use std::sync::Arc; use std::sync::Arc;
use std::thread;
use std::time::Duration; use std::time::Duration;
use adw::glib; use adw::glib;
@ -9,7 +8,7 @@ use dbus::blocking::Connection;
use dbus::Error; use dbus::Error;
use glib::subclass::types::ObjectSubclassIsExt; use glib::subclass::types::ObjectSubclassIsExt;
use glib::{clone, Propagation}; use glib::{clone, Propagation};
use gtk::CheckButton; use gtk::{gio, CheckButton};
use ReSet_Lib::audio::audio::Sink; use ReSet_Lib::audio::audio::Sink;
use super::sinkEntryImpl; use super::sinkEntryImpl;
@ -38,7 +37,6 @@ impl SinkEntry {
imp.resetVolumeSlider.connect_change_value( imp.resetVolumeSlider.connect_change_value(
clone!(@weak imp => @default-return Propagation::Stop, move |_, _, value| { clone!(@weak imp => @default-return Propagation::Stop, move |_, _, value| {
let fraction = (value / 655.36).round(); let fraction = (value / 655.36).round();
println!("{fraction}");
let percentage = (fraction).to_string() + "%"; let percentage = (fraction).to_string() + "%";
imp.resetVolumePercentage.set_text(&percentage); imp.resetVolumePercentage.set_text(&percentage);
let sink = imp.stream.borrow(); let sink = imp.stream.borrow();
@ -81,52 +79,59 @@ impl SinkEntry {
} }
pub fn set_sink_volume(value: f64, index: u32, channels: u16) -> bool { pub fn set_sink_volume(value: f64, index: u32, channels: u16) -> bool {
gio::spawn_blocking(move || {
let conn = Connection::new_session().unwrap(); let conn = Connection::new_session().unwrap();
let proxy = conn.with_proxy( let proxy = conn.with_proxy(
"org.xetibo.ReSet", "org.xetibo.ReSet",
"/org/xetibo/ReSet", "/org/xetibo/ReSet",
Duration::from_millis(1000), Duration::from_millis(1000),
); );
let res: Result<(bool,), Error> = proxy.method_call( let _: Result<(), Error> = proxy.method_call(
"org.xetibo.ReSet", "org.xetibo.ReSet",
"SetSinkVolume", "SetSinkVolume",
(index, channels, value as u32), (index, channels, value as u32),
); );
if res.is_err() { // if res.is_err() {
return false; // return false;
} // }
res.unwrap().0 // res.unwrap().0
});
true
} }
pub fn toggle_sink_mute(index: u32, muted: bool) -> bool { pub fn toggle_sink_mute(index: u32, muted: bool) -> bool {
gio::spawn_blocking(move || {
let conn = Connection::new_session().unwrap(); let conn = Connection::new_session().unwrap();
let proxy = conn.with_proxy( let proxy = conn.with_proxy(
"org.xetibo.ReSet", "org.xetibo.ReSet",
"/org/xetibo/ReSet", "/org/xetibo/ReSet",
Duration::from_millis(1000), Duration::from_millis(1000),
); );
let res: Result<(bool,), Error> = let _: Result<(), Error> =
proxy.method_call("org.xetibo.ReSet", "SetSinkMute", (index, muted)); proxy.method_call("org.xetibo.ReSet", "SetSinkMute", (index, muted));
if res.is_err() { // if res.is_err() {
return false; // return false;
} // }
res.unwrap().0 // res.unwrap().0
});
true
} }
pub fn set_default_sink(name: Arc<String>) { pub fn set_default_sink(name: Arc<String>) {
thread::spawn(move || { gio::spawn_blocking(move || {
dbg!(name.clone());
let conn = Connection::new_session().unwrap(); let conn = Connection::new_session().unwrap();
let proxy = conn.with_proxy( let proxy = conn.with_proxy(
"org.xetibo.ReSet", "org.xetibo.ReSet",
"/org/xetibo/ReSet", "/org/xetibo/ReSet",
Duration::from_millis(1000), Duration::from_millis(1000),
); );
let res: Result<(bool,), Error> = let _: Result<(), Error> =
proxy.method_call("org.xetibo.ReSet", "SetDefaultSink", (name.as_str(),)); proxy.method_call("org.xetibo.ReSet", "SetDefaultSink", (name.as_str(),));
if res.is_err() { // if res.is_err() {
return; // return;
} // }
// handle change // handle change
}); });
} }
// TODO propagate error from dbus

View file

@ -32,10 +32,8 @@ impl SavedWifiEntry {
let res: Result<(bool,), Error> = proxy.method_call("org.xetibo.ReSet", "DeleteConnection", (entry.imp().resetConnectionPath.take(),)); let res: Result<(bool,), Error> = proxy.method_call("org.xetibo.ReSet", "DeleteConnection", (entry.imp().resetConnectionPath.take(),));
if res.is_err() || res.unwrap() == (false,) { if res.is_err() || res.unwrap() == (false,) {
// TODO handle error -> inform user // TODO handle error -> inform user
println!("no worky");
return; return;
} }
println!("worked, should be ded");
let parent = entry.parent().unwrap(); let parent = entry.parent().unwrap();
parent.set_visible(false); parent.set_visible(false);
parent.unparent(); parent.unparent();

View file

@ -108,7 +108,6 @@ pub fn scanForWifi(listeners: Arc<Listeners>, wifiBox: Arc<WifiBox>) {
{ {
break; break;
} }
println!("receiving!");
let res = receiver.recv(); let res = receiver.recv();
if res.is_ok() { if res.is_ok() {
let access_point = res.unwrap(); let access_point = res.unwrap();
@ -211,7 +210,6 @@ pub fn get_stored_connections() -> Vec<(Path<'static>, Vec<u8>)> {
return Vec::new(); return Vec::new();
} }
let (connections,) = res.unwrap(); let (connections,) = res.unwrap();
dbg!(connections.clone());
connections connections
} }
@ -227,13 +225,11 @@ pub fn getConnectionSettings(path: Path<'static>) -> Option<ResetConnection> {
Error, Error,
> = proxy.method_call("org.xetibo.ReSet", "GetConnectionSettings", (path,)); > = proxy.method_call("org.xetibo.ReSet", "GetConnectionSettings", (path,));
if res.is_err() { if res.is_err() {
println!("lol not work");
return None; return None;
} }
let (res,) = res.unwrap(); let (res,) = res.unwrap();
let res = ResetConnection::convert_from_propmap(res); let res = ResetConnection::convert_from_propmap(res);
if res.is_err() { if res.is_err() {
println!("lol none");
return None; return None;
} }
Some(res.unwrap()) Some(res.unwrap())

View file

@ -79,8 +79,7 @@ impl WifiEntry {
let selfImp = self.imp(); let selfImp = self.imp();
selfImp.resetWifiEditButton.connect_clicked(clone!(@ weak selfImp => move |_| { selfImp.resetWifiEditButton.connect_clicked(clone!(@ weak selfImp => move |_| {
// TODO open navigationpage // TODO open navigationpage
let option = getConnectionSettings(selfImp.accessPoint.borrow().associated_connection.clone()); let _option = getConnectionSettings(selfImp.accessPoint.borrow().associated_connection.clone());
dbg!(option);
})); }));
} }
} }
@ -120,7 +119,6 @@ pub fn click_stored_network(entry: Arc<WifiEntry>) {
} }
return; return;
} }
dbg!(access_point.clone());
let res: Result<(bool,), Error> = proxy.method_call( let res: Result<(bool,), Error> = proxy.method_call(
"org.xetibo.ReSet", "org.xetibo.ReSet",
"ConnectToKnownAccessPoint", "ConnectToKnownAccessPoint",
@ -214,8 +212,4 @@ pub fn click_new_network(entry: Arc<WifiEntry>) {
}), }),
); );
entryImp.resetWifiPopup.popup(); entryImp.resetWifiPopup.popup();
println!(
"result is {}",
result.load(std::sync::atomic::Ordering::SeqCst)
);
} }

View file

@ -3,10 +3,10 @@ use std::sync::atomic::Ordering;
use std::sync::Arc; use std::sync::Arc;
use crate::components::base::settingBox::SettingBox; use crate::components::base::settingBox::SettingBox;
use crate::components::base::utils::Listeners; use crate::components::base::utils::{start_event_listener, Listeners};
use crate::components::bluetooth::bluetoothBox::BluetoothBox; use crate::components::bluetooth::bluetoothBox::BluetoothBox;
use crate::components::input::sourceBox::{SourceBox, populate_outputstreams, populate_sources}; use crate::components::input::sourceBox::{populate_sources, SourceBox};
use crate::components::output::sinkBox::{SinkBox, populate_inputstreams, populate_sinks}; use crate::components::output::sinkBox::{populate_sinks, SinkBox};
use crate::components::wifi::wifiBox::{scanForWifi, show_stored_connections, WifiBox}; use crate::components::wifi::wifiBox::{scanForWifi, show_stored_connections, WifiBox};
use gtk::prelude::WidgetExt; use gtk::prelude::WidgetExt;
use gtk::{FlowBox, Frame, Label}; use gtk::{FlowBox, Frame, Label};
@ -64,12 +64,15 @@ pub const HANDLE_AUDIO_CLICK: fn(Arc<Listeners>, FlowBox) =
listeners.bluetooth_listener.store(false, Ordering::SeqCst); listeners.bluetooth_listener.store(false, Ordering::SeqCst);
listeners.pulse_listener.store(true, Ordering::SeqCst); listeners.pulse_listener.store(true, Ordering::SeqCst);
let audioOutput = Arc::new(SinkBox::new()); let audioOutput = Arc::new(SinkBox::new());
populate_inputstreams(listeners.clone(), audioOutput.clone());
populate_sinks(audioOutput.clone()); populate_sinks(audioOutput.clone());
let audioFrame = wrapInFrame(SettingBox::new(&*audioOutput)); let audioFrame = wrapInFrame(SettingBox::new(&*audioOutput));
let audioInput = Arc::new(SourceBox::new()); let audioInput = Arc::new(SourceBox::new());
populate_outputstreams(listeners.clone(), audioInput.clone());
populate_sources(audioInput.clone()); populate_sources(audioInput.clone());
start_event_listener(
listeners.clone(),
Some(audioOutput.clone()),
Some(audioInput.clone()),
);
let sourceFrame = wrapInFrame(SettingBox::new(&*audioInput)); let sourceFrame = wrapInFrame(SettingBox::new(&*audioInput));
resetMain.remove_all(); resetMain.remove_all();
resetMain.insert(&audioFrame, -1); resetMain.insert(&audioFrame, -1);
@ -83,8 +86,8 @@ pub const HANDLE_VOLUME_CLICK: fn(Arc<Listeners>, FlowBox) =
listeners.bluetooth_listener.store(false, Ordering::SeqCst); listeners.bluetooth_listener.store(false, Ordering::SeqCst);
listeners.pulse_listener.store(false, Ordering::SeqCst); listeners.pulse_listener.store(false, Ordering::SeqCst);
let audioOutput = Arc::new(SinkBox::new()); let audioOutput = Arc::new(SinkBox::new());
populate_inputstreams(listeners.clone(), audioOutput.clone());
populate_sinks(audioOutput.clone()); populate_sinks(audioOutput.clone());
start_event_listener(listeners.clone(), Some(audioOutput.clone()), None);
let audioFrame = wrapInFrame(SettingBox::new(&*audioOutput)); let audioFrame = wrapInFrame(SettingBox::new(&*audioOutput));
resetMain.remove_all(); resetMain.remove_all();
resetMain.insert(&audioFrame, -1); resetMain.insert(&audioFrame, -1);
@ -97,8 +100,8 @@ pub const HANDLE_MICROPHONE_CLICK: fn(Arc<Listeners>, FlowBox) =
listeners.bluetooth_listener.store(false, Ordering::SeqCst); listeners.bluetooth_listener.store(false, Ordering::SeqCst);
listeners.pulse_listener.store(false, Ordering::SeqCst); listeners.pulse_listener.store(false, Ordering::SeqCst);
let audioInput = Arc::new(SourceBox::new()); let audioInput = Arc::new(SourceBox::new());
populate_outputstreams(listeners.clone(), audioInput.clone());
populate_sources(audioInput.clone()); populate_sources(audioInput.clone());
start_event_listener(listeners.clone(), None, Some(audioInput.clone()));
let sourceFrame = wrapInFrame(SettingBox::new(&*audioInput)); let sourceFrame = wrapInFrame(SettingBox::new(&*audioInput));
resetMain.remove_all(); resetMain.remove_all();
resetMain.insert(&sourceFrame, -1); resetMain.insert(&sourceFrame, -1);