feat: Add dropdowns

This commit is contained in:
Fabio Lenherr / DashieTM 2023-11-15 14:50:00 +01:00
parent c619284146
commit 0c286af82c
13 changed files with 297 additions and 54 deletions

View file

@ -1,4 +1,3 @@
use std::cell::RefCell;
use std::sync::Arc;
use std::time::Duration;
@ -8,10 +7,12 @@ use adw::prelude::{ButtonExt, RangeExt};
use dbus::blocking::Connection;
use dbus::Error;
use glib::subclass::types::ObjectSubclassIsExt;
use glib::{clone, Propagation};
use glib::{clone, Cast, Propagation};
use gtk::StringObject;
use ReSet_Lib::audio::audio::OutputStream;
use super::outputStreamEntryImpl;
use super::sourceBox::SourceBox;
glib::wrapper! {
pub struct OutputStreamEntry(ObjectSubclass<outputStreamEntryImpl::OutputStreamEntry>)
@ -20,12 +21,13 @@ glib::wrapper! {
}
impl OutputStreamEntry {
pub fn new(stream: OutputStream) -> Self {
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
// TODO map mute to callback
// TODO map dropdown
{
let box_imp = source_box.imp();
let imp = obj.imp();
let name = stream.application_name.clone() + ": " + stream.name.as_str();
imp.resetSourceName.set_text(name.as_str());
@ -40,17 +42,75 @@ impl OutputStreamEntry {
let fraction = (value / 655.36).round();
let percentage = (fraction).to_string() + "%";
imp.resetVolumePercentage.set_text(&percentage);
let stream = imp.stream.borrow();
let mut stream = imp.stream.try_borrow();
while stream.is_err() {
stream = imp.stream.try_borrow();
}
let stream = stream.unwrap();
let index = stream.index;
let channels = stream.channels;
set_outputstream_volume(value, index, channels);
Propagation::Proceed
}),
);
{
let mut list = box_imp.resetModelList.try_borrow();
while list.is_err() {
list = box_imp.resetModelList.try_borrow();
}
let list = list.unwrap();
imp.resetSelectedSource.set_model(Some(&*list));
let mut map = box_imp.resetSourceMap.try_borrow();
while map.is_err() {
map = box_imp.resetSourceMap.try_borrow();
}
let map = map.unwrap();
let mut name = box_imp.resetDefaultSource.try_borrow();
while name.is_err() {
name = box_imp.resetDefaultSource.try_borrow();
}
let name = name.unwrap();
let name = &name.alias;
let index = map.get(name);
if index.is_some() {
imp.resetSelectedSource.set_selected(index.unwrap().1);
}
}
imp.resetSelectedSource.connect_selected_notify(
clone!(@weak imp, @weak box_imp => move |dropdown| {
let selected = dropdown.selected_item();
if selected.is_none() {
return;
}
let selected = selected.unwrap();
let selected = selected.downcast_ref::<StringObject>().unwrap();
let selected = selected.string().to_string();
let mut source = box_imp.resetSourceMap.try_borrow();
while source.is_err() {
source = box_imp.resetSourceMap.try_borrow();
}
let source = source.unwrap();
let source = source.get(&selected);
if source.is_none() {
return;
}
let mut stream = imp.stream.try_borrow();
while stream.is_err() {
stream = imp.stream.try_borrow();
}
let stream = stream.unwrap();
let source = source.unwrap().0;
set_source_of_output_stream(stream.index, source);
}),
);
imp.resetSourceMute
.connect_clicked(clone!(@weak imp => move |_| {
let stream = imp.stream.clone();
let mut stream = stream.borrow_mut();
let mut stream = stream.try_borrow_mut();
while stream.is_err() {
stream = imp.stream.try_borrow_mut();
}
let mut stream = stream.unwrap();
stream.muted = !stream.muted;
let muted = stream.muted;
let index = stream.index;
@ -100,3 +160,21 @@ fn toggle_output_stream_mute(index: u32, muted: bool) -> bool {
}
res.unwrap().0
}
fn set_source_of_output_stream(stream: u32, source: u32) -> bool {
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",
"SetSourceOfOutputStream",
(stream, source),
);
if res.is_err() {
return false;
}
res.unwrap().0
}

View file

@ -2,9 +2,9 @@ use std::cell::RefCell;
use std::sync::Arc;
use crate::components::input::outputStreamEntry;
use ReSet_Lib::audio::audio::OutputStream;
use gtk::subclass::prelude::*;
use gtk::{glib, Button, CompositeTemplate, Label, ProgressBar, Scale, DropDown};
use gtk::{glib, Button, CompositeTemplate, DropDown, Label, ProgressBar, Scale};
use ReSet_Lib::audio::audio::OutputStream;
#[allow(non_snake_case)]
#[derive(Default, CompositeTemplate)]
@ -23,6 +23,7 @@ pub struct OutputStreamEntry {
#[template_child]
pub resetVolumeMeter: TemplateChild<ProgressBar>,
pub stream: Arc<RefCell<OutputStream>>,
pub associatedSource: Arc<RefCell<(u32, String)>>,
}
#[glib::object_subclass]
@ -45,4 +46,3 @@ impl BoxImpl for OutputStreamEntry {}
impl ObjectImpl for OutputStreamEntry {}
impl WidgetImpl for OutputStreamEntry {}

View file

@ -11,13 +11,13 @@ use adw::prelude::{BoxExt, ButtonExt, ListBoxRowExt, RangeExt};
use dbus::blocking::Connection;
use dbus::Error;
use glib::subclass::prelude::ObjectSubclassIsExt;
use glib::{Propagation, Variant};
use gtk::gio;
use glib::{clone, Cast, Propagation, Variant};
use gtk::prelude::ActionableExt;
use gtk::{gio, StringObject};
use ReSet_Lib::audio::audio::{OutputStream, Source};
use super::outputStreamEntry::OutputStreamEntry;
use super::sourceEntry::{toggle_source_mute, SourceEntry};
use super::sourceEntry::{set_default_source, toggle_source_mute, SourceEntry};
glib::wrapper! {
pub struct SourceBox(ObjectSubclass<sourceBoxImpl::SourceBox>)
@ -51,13 +51,23 @@ impl SourceBox {
pub fn populate_sources(output_box: Arc<SourceBox>) {
gio::spawn_blocking(move || {
let output_box_imp = output_box.imp();
let sinks = get_sources();
let sources = get_sources();
{
let list = output_box_imp.resetModelList.borrow_mut();
let mut map = output_box_imp.resetSourceMap.borrow_mut();
let mut i: u32 = 0;
for source in sources.iter() {
list.append(&source.alias);
map.insert(source.alias.clone(), (source.index, i, source.name.clone()));
i += 1;
}
}
output_box_imp
.resetDefaultSource
.replace(get_default_source());
glib::spawn_future(async move {
glib::idle_add_once(move || {
// TODO handle default mapping
// TODO handle events
let output_box_ref_slider = output_box.clone();
let output_box_ref_mute = output_box.clone();
let output_box_ref = output_box.clone();
@ -71,15 +81,49 @@ pub fn populate_sources(output_box: Arc<SourceBox>) {
let percentage = (fraction).to_string() + "%";
output_box_imp.resetVolumePercentage.set_text(&percentage);
output_box_imp.resetVolumeSlider.set_value(*volume as f64);
for stream in sinks {
for stream in sources {
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));
let entry = ListEntry::new(&SourceEntry::new(
is_default,
output_box_imp.resetDefaultCheckButton.clone(),
stream,
));
entry.set_activatable(false);
output_box_imp.resetSources.append(&entry);
}
let list = output_box_imp.resetModelList.borrow();
output_box_imp.resetSourceDropdown.set_model(Some(&*list));
let map = output_box_imp.resetSourceMap.borrow();
let name = output_box_imp.resetDefaultSource.borrow();
let name = &name.alias;
let index = map.get(name);
if index.is_some() {
output_box_imp
.resetSourceDropdown
.set_selected(index.unwrap().1);
}
output_box_imp.resetSourceDropdown.connect_selected_notify(
clone!(@weak output_box_imp => move |dropdown| {
let selected = dropdown.selected_item();
if selected.is_none() {
return;
}
let selected = selected.unwrap();
let selected = selected.downcast_ref::<StringObject>().unwrap();
let selected = selected.string().to_string();
let source = output_box_imp.resetSourceMap.borrow();
let source = source.get(&selected);
if source.is_none() {
return;
}
let sink = Arc::new(source.unwrap().2.clone());
set_default_source(sink);
}),
);
}
output_box_ref
.imp()
@ -121,7 +165,7 @@ pub fn populate_sources(output_box: Arc<SourceBox>) {
});
}
pub fn populate_outputstreams(listeners: Arc<Listeners>, output_box: Arc<SourceBox>) {
pub fn populate_outputstreams(_listeners: Arc<Listeners>, output_box: Arc<SourceBox>) {
// TODO add listener
let output_box_ref = output_box.clone();
@ -131,7 +175,7 @@ pub fn populate_outputstreams(listeners: Arc<Listeners>, output_box: Arc<SourceB
glib::idle_add_once(move || {
let output_box_imp = output_box_ref.imp();
for stream in streams {
let entry = ListEntry::new(&OutputStreamEntry::new(stream));
let entry = ListEntry::new(&OutputStreamEntry::new(output_box.clone(), stream));
entry.set_activatable(false);
output_box_imp.resetOutputStreams.append(&entry);
}

View file

@ -1,10 +1,11 @@
use std::cell::RefCell;
use std::collections::HashMap;
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, CheckButton};
use gtk::{glib, CheckButton, CompositeTemplate, DropDown, StringList, TemplateChild};
use gtk::{prelude::*, Button, Label, ProgressBar, Scale};
use ReSet_Lib::audio::audio::{OutputStream, Source};
@ -37,6 +38,9 @@ pub struct SourceBox {
pub resetDefaultSource: Arc<RefCell<Source>>,
pub resetSourceList: Arc<Mutex<Vec<Source>>>,
pub resetOutputStreamList: Arc<Mutex<Vec<OutputStream>>>,
pub resetModelList: Arc<RefCell<StringList>>,
// first u32 is the index of the source, the second the index in the model list
pub resetSourceMap: Arc<RefCell<HashMap<String, (u32, u32, String)>>>,
}
#[glib::object_subclass]

View file

@ -1,4 +1,3 @@
use std::cell::RefCell;
use std::sync::Arc;
use std::thread;
use std::time::Duration;
@ -25,13 +24,10 @@ impl SourceEntry {
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
// TODO properly use volume fraction
// TODO map mute to callback
// TODO map dropdown
// TODO handle events
{
let imp = obj.imp();
imp.resetSourceName.set_text(stream.name.clone().as_str());
imp.resetSourceName.set_text(stream.alias.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();