feat: Add default Sink and Source Switching

This commit is contained in:
Fabio Lenherr / DashieTM 2023-11-15 02:35:20 +01:00
parent dbcf2ab635
commit c619284146
6 changed files with 83 additions and 12 deletions

View file

@ -72,7 +72,11 @@ pub fn populate_sources(output_box: Arc<SourceBox>) {
output_box_imp.resetVolumePercentage.set_text(&percentage);
output_box_imp.resetVolumeSlider.set_value(*volume as f64);
for stream in sinks {
let entry = ListEntry::new(&SourceEntry::new(stream));
let mut is_default = false;
if output_box_imp.resetDefaultSource.borrow().name == stream.name {
is_default = true;
}
let entry = ListEntry::new(&SourceEntry::new(is_default, output_box_imp.resetDefaultCheckButton.clone(), stream));
entry.set_activatable(false);
output_box_imp.resetSources.append(&entry);
}

View file

@ -4,7 +4,7 @@ use std::sync::{Arc, Mutex};
use crate::components::base::listEntry::ListEntry;
use crate::components::input::sourceBox;
use gtk::subclass::prelude::*;
use gtk::{glib, CompositeTemplate, DropDown, TemplateChild};
use gtk::{glib, CompositeTemplate, DropDown, TemplateChild, CheckButton};
use gtk::{prelude::*, Button, Label, ProgressBar, Scale};
use ReSet_Lib::audio::audio::{OutputStream, Source};
@ -33,6 +33,7 @@ pub struct SourceBox {
pub resetOutputStreamButton: TemplateChild<ListEntry>,
#[template_child]
pub resetOutputStreams: TemplateChild<gtk::Box>,
pub resetDefaultCheckButton: Arc<CheckButton>,
pub resetDefaultSource: Arc<RefCell<Source>>,
pub resetSourceList: Arc<Mutex<Vec<Source>>>,
pub resetOutputStreamList: Arc<Mutex<Vec<OutputStream>>>,

View file

@ -1,15 +1,17 @@
use std::cell::RefCell;
use std::sync::Arc;
use std::thread;
use std::time::Duration;
use adw::glib;
use adw::glib::Object;
use adw::prelude::{ButtonExt, RangeExt};
use adw::prelude::{ButtonExt, RangeExt, CheckButtonExt};
use dbus::blocking::Connection;
use dbus::Error;
use glib::subclass::types::ObjectSubclassIsExt;
use glib::{clone, Propagation};
use ReSet_Lib::audio::audio::Source;
use gtk::CheckButton;
use super::sourceEntryImpl;
@ -20,7 +22,7 @@ glib::wrapper! {
}
impl SourceEntry {
pub fn new(stream: Source) -> Self {
pub fn new(is_default: bool, check_group: Arc<CheckButton>, stream: Source) -> Self {
let obj: Self = Object::builder().build();
// TODO use event callback for progress bar -> this is the "im speaking" indicator
// TODO map the slider to volume
@ -30,6 +32,7 @@ impl SourceEntry {
{
let imp = obj.imp();
imp.resetSourceName.set_text(stream.name.clone().as_str());
let name = Arc::new(stream.name.clone());
let volume = stream.volume.first().unwrap_or_else(|| &(0 as u32));
let fraction = (*volume as f64 / 655.36).round();
let percentage = (fraction).to_string() + "%";
@ -49,6 +52,18 @@ impl SourceEntry {
Propagation::Proceed
}),
);
imp.resetSelectedSource.set_group(Some(&*check_group));
// check_group.set_group(Some(&*imp.resetSelectedSink));
if is_default {
imp.resetSelectedSource.set_active(true);
} else {
imp.resetSelectedSource.set_active(false);
}
imp.resetSelectedSource.connect_toggled(move |button| {
if button.is_active() {
set_default_source(name.clone());
}
});
imp.resetSourceMute
.connect_clicked(clone!(@weak imp => move |_| {
let stream = imp.stream.clone();
@ -102,3 +117,20 @@ pub fn toggle_source_mute(index: u32, muted: bool) -> bool {
}
res.unwrap().0
}
pub fn set_default_source(name: Arc<String>) {
thread::spawn(move || {
let conn = Connection::new_session().unwrap();
let proxy = conn.with_proxy(
"org.xetibo.ReSet",
"/org/xetibo/ReSet",
Duration::from_millis(1000),
);
let res: Result<(bool,), Error> =
proxy.method_call("org.xetibo.ReSet", "SetDefaultSink", (name.as_str(),));
if res.is_err() {
return;
}
// handle change
});
}

View file

@ -73,7 +73,11 @@ pub fn populate_sinks(output_box: Arc<SinkBox>) {
output_box_imp.resetVolumeSlider.set_value(*volume as f64);
for stream in sinks {
// TODO create sink handler -> currently only allows input streams
let entry = ListEntry::new(&SinkEntry::new(stream));
let mut is_default = false;
if output_box_imp.resetDefaultSink.borrow().name == stream.name {
is_default = true;
}
let entry = ListEntry::new(&SinkEntry::new(is_default, output_box_imp.resetDefaultCheckButton.clone(), stream));
entry.set_activatable(false);
output_box_imp.resetSinks.append(&entry);
}

View file

@ -4,7 +4,7 @@ use std::sync::{Arc, Mutex};
use crate::components::base::listEntry::ListEntry;
use crate::components::output::inputStreamEntry::InputStreamEntry;
use gtk::subclass::prelude::*;
use gtk::{glib, Box, Button, CompositeTemplate, DropDown, Label, TemplateChild};
use gtk::{glib, Box, Button, CompositeTemplate, DropDown, Label, TemplateChild, CheckButton};
use gtk::{prelude::*, ProgressBar, Scale};
use ReSet_Lib::audio::audio::{InputStream, Sink};
@ -33,6 +33,7 @@ pub struct SinkBox {
pub resetInputStreamButton: TemplateChild<ListEntry>,
#[template_child]
pub resetInputStreams: TemplateChild<Box>,
pub resetDefaultCheckButton: Arc<CheckButton>,
pub resetDefaultSink: Arc<RefCell<Sink>>,
pub resetSinkList: Arc<Mutex<Vec<Sink>>>,
pub resetInputStreamList: Arc<Mutex<Vec<InputStream>>>,

View file

@ -1,14 +1,15 @@
use std::cell::RefCell;
use std::sync::Arc;
use std::thread;
use std::time::Duration;
use adw::glib;
use adw::glib::Object;
use adw::prelude::{ButtonExt, RangeExt};
use adw::prelude::{ButtonExt, CheckButtonExt, RangeExt};
use dbus::blocking::Connection;
use dbus::Error;
use glib::subclass::types::ObjectSubclassIsExt;
use glib::{clone, Propagation};
use gtk::CheckButton;
use ReSet_Lib::audio::audio::Sink;
use super::sinkEntryImpl;
@ -20,16 +21,14 @@ glib::wrapper! {
}
impl SinkEntry {
pub fn new(stream: Sink) -> Self {
pub fn new(is_default: bool, check_group: Arc<CheckButton>, stream: Sink) -> Self {
let obj: Self = Object::builder().build();
// TODO use event callback for progress bar -> this is the "im speaking" indicator
// TODO map the slider to volume
// TODO properly use volume fraction
// TODO map mute to callback
// TODO map dropdown
{
let imp = obj.imp();
imp.resetSinkName.set_text(stream.name.clone().as_str());
let name = Arc::new(stream.name.clone());
let volume = stream.volume.first().unwrap_or_else(|| &(0 as u32));
let fraction = (*volume as f64 / 655.36).round();
let percentage = (fraction).to_string() + "%";
@ -49,6 +48,18 @@ impl SinkEntry {
Propagation::Proceed
}),
);
imp.resetSelectedSink.set_group(Some(&*check_group));
// check_group.set_group(Some(&*imp.resetSelectedSink));
if is_default {
imp.resetSelectedSink.set_active(true);
} else {
imp.resetSelectedSink.set_active(false);
}
imp.resetSelectedSink.connect_toggled(move |button| {
if button.is_active() {
set_default_sink(name.clone());
}
});
imp.resetSinkMute
.connect_clicked(clone!(@weak imp => move |_| {
let stream = imp.stream.clone();
@ -102,3 +113,21 @@ pub fn toggle_sink_mute(index: u32, muted: bool) -> bool {
}
res.unwrap().0
}
pub fn set_default_sink(name: Arc<String>) {
thread::spawn(move || {
dbg!(name.clone());
let conn = Connection::new_session().unwrap();
let proxy = conn.with_proxy(
"org.xetibo.ReSet",
"/org/xetibo/ReSet",
Duration::from_millis(1000),
);
let res: Result<(bool,), Error> =
proxy.method_call("org.xetibo.ReSet", "SetDefaultSink", (name.as_str(),));
if res.is_err() {
return;
}
// handle change
});
}