From 5999bb1b458ebd70e920385b1de5532c72c4a068 Mon Sep 17 00:00:00 2001 From: Fabio Lenherr / DashieTM Date: Mon, 13 Nov 2023 18:12:36 +0100 Subject: [PATCH] feat: Add initial Sound Mapping --- src/components/input/sourceBoxImpl.rs | 14 ++- src/components/output/audioBox.rs | 129 +++++++++++++++++++- src/components/output/audioBoxImpl.rs | 32 +++-- src/components/output/audioSource.rs | 25 +++- src/components/output/audioSourceImpl.rs | 11 +- src/components/window/handleSidebarClick.rs | 18 ++- src/resources/resetAudio.ui | 19 +-- src/resources/resetUI.cmb | 10 +- 8 files changed, 206 insertions(+), 52 deletions(-) diff --git a/src/components/input/sourceBoxImpl.rs b/src/components/input/sourceBoxImpl.rs index 0189eac..a70bed5 100644 --- a/src/components/input/sourceBoxImpl.rs +++ b/src/components/input/sourceBoxImpl.rs @@ -1,9 +1,12 @@ -use gtk::{CompositeTemplate, DropDown, TemplateChild, glib}; -use gtk::prelude::*; -use gtk::subclass::prelude::*; +use std::sync::{Arc, Mutex}; + use crate::components::base::listEntry::ListEntry; use crate::components::input::inputStreamEntry::InputStreamEntry; use crate::components::input::sourceBox; +use gtk::prelude::*; +use gtk::subclass::prelude::*; +use gtk::{glib, CompositeTemplate, DropDown, TemplateChild}; +use ReSet_Lib::audio::audio::{OutputStream, Source}; #[allow(non_snake_case)] #[derive(Default, CompositeTemplate)] @@ -15,6 +18,8 @@ pub struct SourceBox { pub resetSourceRow: TemplateChild, #[template_child] pub resetInputStreamButton: TemplateChild, + pub resetSources: Arc>>, + pub resetOutputStreams: Arc>>, } #[glib::object_subclass] @@ -49,4 +54,5 @@ impl WidgetImpl for SourceBox {} impl WindowImpl for SourceBox {} -impl ApplicationWindowImpl for SourceBox {} \ No newline at end of file +impl ApplicationWindowImpl for SourceBox {} + diff --git a/src/components/output/audioBox.rs b/src/components/output/audioBox.rs index 6bd0d02..75d7e72 100644 --- a/src/components/output/audioBox.rs +++ b/src/components/output/audioBox.rs @@ -1,9 +1,21 @@ -use adw::glib; +use std::sync::Arc; +use std::time::Duration; + +use crate::components::base::listEntry::ListEntry; +use crate::components::base::utils::Listeners; +use crate::components::output::audioBoxImpl; use adw::glib::Object; +use adw::prelude::BoxExt; +use adw::{glib, prelude::ListBoxRowExt}; +use dbus::blocking::Connection; +use dbus::Error; use glib::subclass::prelude::ObjectSubclassIsExt; use glib::Variant; +use gtk::gio; use gtk::prelude::ActionableExt; -use crate::components::output::audioBoxImpl; +use ReSet_Lib::audio::audio::{InputStream, Sink}; + +use super::audioSource::{self, AudioSourceEntry}; glib::wrapper! { pub struct AudioBox(ObjectSubclass) @@ -11,6 +23,9 @@ glib::wrapper! { @implements gtk::Accessible, gtk::Buildable, gtk::ConstraintTarget, gtk::Orientable; } +unsafe impl Send for AudioBox {} +unsafe impl Sync for AudioBox {} + impl AudioBox { pub fn new() -> Self { Object::builder().build() @@ -18,9 +33,113 @@ impl AudioBox { pub fn setupCallbacks(&self) { let selfImp = self.imp(); - selfImp.resetSinksRow.set_action_name(Some("navigation.push")); - selfImp.resetSinksRow.set_action_target_value(Some(&Variant::from("outputDevices"))); + selfImp + .resetSinksRow + .set_action_name(Some("navigation.push")); + selfImp + .resetSinksRow + .set_action_target_value(Some(&Variant::from("outputDevices"))); - selfImp.resetOutputStreamButton.set_action_name(Some("navigation.pop")); + selfImp + .resetOutputStreamButton + .set_action_name(Some("navigation.pop")); } } + +pub fn populate_sinks(output_box: Arc) { + let output_box_ref = output_box.clone(); + gio::spawn_blocking(move || { + let output_box_imp = output_box.imp(); + let sinks = get_sinks(); + output_box_imp.resetDefaultSink.replace(get_default_sink()); + glib::spawn_future(async move { + glib::idle_add_once(move || { + let output_box_imp = output_box_ref.imp(); + // TODO handle default mapping + // output_box_imp.resetVolumePercentage.set_text(); + // output_box_imp.resetVolumeSlider.let + for stream in sinks { + let entry = ListEntry::new(&AudioSourceEntry::new( + stream.name, + stream.volume, + stream.muted, + stream.index, + )); + entry.set_activatable(false); + output_box_imp.resetSinks.append(&entry); + } + }); + }); + }); +} + +pub fn populate_streams(listeners: Arc, output_box: Arc) { + // TODO add listener + let output_box_ref = output_box.clone(); + // let output_box_ref_listener = output_box.clone(); + let output_box_imp = output_box.imp(); + // let sources = output_box_imp.resetSinks.clone(); + // let output_streams = output_box_imp.resetInputStreams.clone(); + + gio::spawn_blocking(move || { + let streams = get_input_streams(); + glib::spawn_future(async move { + glib::idle_add_once(move || { + let output_box_imp = output_box_ref.imp(); + for stream in streams { + let entry = ListEntry::new(&AudioSourceEntry::new( + stream.name, + stream.volume, + stream.muted, + stream.index, + )); + entry.set_activatable(false); + output_box_imp.resetOutputStreams.append(&entry); + } + }); + }); + }); +} + +fn get_input_streams() -> Vec { + let conn = Connection::new_session().unwrap(); + let proxy = conn.with_proxy( + "org.xetibo.ReSet", + "/org/xetibo/ReSet", + Duration::from_millis(1000), + ); + let res: Result<(Vec,), Error> = + proxy.method_call("org.xetibo.ReSet", "ListInputStreams", ()); + if res.is_err() { + return Vec::new(); + } + res.unwrap().0 +} + +fn get_sinks() -> Vec { + let conn = Connection::new_session().unwrap(); + let proxy = conn.with_proxy( + "org.xetibo.ReSet", + "/org/xetibo/ReSet", + Duration::from_millis(1000), + ); + let res: Result<(Vec,), Error> = proxy.method_call("org.xetibo.ReSet", "ListSinks", ()); + if res.is_err() { + return Vec::new(); + } + res.unwrap().0 +} + +fn get_default_sink() -> Option { + let conn = Connection::new_session().unwrap(); + let proxy = conn.with_proxy( + "org.xetibo.ReSet", + "/org/xetibo/ReSet", + Duration::from_millis(1000), + ); + let res: Result<(Sink,), Error> = proxy.method_call("org.xetibo.ReSet", "GetDefaultSink", ()); + if res.is_err() { + return None; + } + Some(res.unwrap().0) +} diff --git a/src/components/output/audioBoxImpl.rs b/src/components/output/audioBoxImpl.rs index af4f4e5..79185ae 100644 --- a/src/components/output/audioBoxImpl.rs +++ b/src/components/output/audioBoxImpl.rs @@ -1,23 +1,41 @@ -use gtk::{CompositeTemplate, DropDown, TemplateChild, glib}; -use gtk::prelude::*; -use gtk::subclass::prelude::*; +use std::cell::RefCell; +use std::sync::{Arc, Mutex}; + +use crate::components::base::listEntry::ListEntry; use crate::components::output::audioBox; use crate::components::output::audioSource::AudioSourceEntry; -use crate::components::base::listEntry::ListEntry; +use gtk::subclass::prelude::*; +use gtk::{glib, Box, Button, CompositeTemplate, DropDown, Label, TemplateChild}; +use gtk::{prelude::*, ProgressBar, Scale}; +use ReSet_Lib::audio::audio::{InputStream, Sink}; #[allow(non_snake_case)] #[derive(Default, CompositeTemplate)] #[template(resource = "/org/Xetibo/ReSet/resetAudio.ui")] pub struct AudioBox { - #[template_child] - pub resetOutputDevice: TemplateChild, #[template_child] pub resetSinksRow: TemplateChild, #[template_child] + pub resetOutputDevice: TemplateChild, + #[template_child] + pub resetSinkMute: TemplateChild