diff --git a/src/components/input/mod.rs b/src/components/input/mod.rs index c26515f..9ee1b34 100644 --- a/src/components/input/mod.rs +++ b/src/components/input/mod.rs @@ -1,7 +1,8 @@ pub mod output_stream_entry; pub mod output_stream_entry_impl; pub mod source_box; -mod source_box_event_handlers; +mod source_box_handlers; pub mod source_box_impl; +mod source_box_utils; pub mod source_entry; pub mod source_entry_impl; diff --git a/src/components/input/source_box.rs b/src/components/input/source_box.rs index 18f6773..b055e83 100644 --- a/src/components/input/source_box.rs +++ b/src/components/input/source_box.rs @@ -1,39 +1,34 @@ -use re_set_lib::audio::audio_structures::{Card, OutputStream, Source}; use re_set_lib::signals::{ OutputStreamAdded, OutputStreamChanged, OutputStreamRemoved, SourceAdded, SourceChanged, SourceRemoved, }; use std::sync::Arc; -use std::time::{Duration, SystemTime}; use adw::glib::Object; -use adw::prelude::{ - BoxExt, ButtonExt, CheckButtonExt, ComboRowExt, ListBoxRowExt, PreferencesGroupExt, RangeExt, -}; +use adw::prelude::{ComboRowExt, ListBoxRowExt}; use dbus::blocking::Connection; use dbus::message::SignalArgs; -use dbus::{Error, Path}; +use dbus::Path; use glib::subclass::prelude::ObjectSubclassIsExt; -use glib::{Cast, ControlFlow, Propagation, Variant}; +use glib::Variant; +use gtk::gio; use gtk::prelude::ActionableExt; -use gtk::{gio, StringObject}; -use crate::components::base::card_entry::CardEntry; use crate::components::base::error::{self}; -use crate::components::base::error_impl::{show_error, ReSetErrorImpl}; -use crate::components::base::list_entry::ListEntry; +use crate::components::base::error_impl::ReSetErrorImpl; use crate::components::input::source_box_impl; -use crate::components::input::source_entry::set_source_volume; use crate::components::utils::{ - create_dropdown_label_factory, set_combo_row_ellipsis, AUDIO, BASE, DBUS_PATH, + create_dropdown_label_factory, set_combo_row_ellipsis, BASE, DBUS_PATH, }; -use super::output_stream_entry::OutputStreamEntry; -use super::source_box_event_handlers::{ +use super::source_box_handlers::{ output_stream_added_handler, output_stream_changed_handler, output_stream_removed_handler, source_added_handler, source_changed_handler, source_removed_handler, }; -use super::source_entry::{set_default_source, toggle_source_mute, SourceEntry}; +use super::source_box_utils::{ + get_default_source, get_sources, populate_cards, populate_outputstreams, + populate_source_information, +}; glib::wrapper! { pub struct SourceBox(ObjectSubclass) @@ -125,273 +120,6 @@ pub fn populate_sources(input_box: Arc) { }); } -fn populate_source_information(input_box: Arc, sources: Vec) { - glib::spawn_future(async move { - glib::idle_add_once(move || { - let input_box_ref_slider = input_box.clone(); - let input_box_ref_toggle = input_box.clone(); - let input_box_ref_mute = input_box.clone(); - let input_box_imp = input_box.imp(); - let default_sink = input_box_imp.reset_default_source.clone(); - let source = default_sink.borrow(); - - if source.muted { - input_box_imp - .reset_source_mute - .set_icon_name("microphone-disabled-symbolic"); - } else { - input_box_imp - .reset_source_mute - .set_icon_name("audio-input-microphone-symbolic"); - } - - let volume = source.volume.first().unwrap_or(&0_u32); - let fraction = (*volume as f64 / 655.36).round(); - let percentage = (fraction).to_string() + "%"; - input_box_imp.reset_volume_percentage.set_text(&percentage); - input_box_imp.reset_volume_slider.set_value(*volume as f64); - let mut list = input_box_imp.reset_source_list.write().unwrap(); - for source in sources { - let index = source.index; - let alias = source.alias.clone(); - let mut is_default = false; - if input_box_imp.reset_default_source.borrow().name == source.name { - is_default = true; - } - let source_entry = Arc::new(SourceEntry::new( - is_default, - input_box_imp.reset_default_check_button.clone(), - source, - input_box.clone(), - )); - 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)); - input_box_imp.reset_sources.append(&*entry); - } - let list = input_box_imp.reset_model_list.read().unwrap(); - input_box_imp.reset_source_dropdown.set_model(Some(&*list)); - let name = input_box_imp.reset_default_source.borrow(); - - let index = input_box_imp.reset_model_index.read().unwrap(); - let model_list = input_box_imp.reset_model_list.read().unwrap(); - for entry in 0..*index { - if model_list.string(entry) == Some(name.alias.clone().into()) { - input_box_imp.reset_source_dropdown.set_selected(entry); - break; - } - } - input_box_imp - .reset_source_dropdown - .connect_selected_notify(move |dropdown| { - dropdown_handler(input_box_ref_toggle.clone(), dropdown); - }); - input_box_imp - .reset_volume_slider - .connect_change_value(move |_, _, value| { - volume_slider_handler(input_box_ref_slider.clone(), value) - }); - - input_box_imp.reset_source_mute.connect_clicked(move |_| { - mute_clicked_handler(input_box_ref_mute.clone()); - }); - }); - }); -} - -fn dropdown_handler(input_box: Arc, dropdown: &adw::ComboRow) -> ControlFlow { - let input_box_imp = input_box.imp(); - let input_box_ref = input_box.clone(); - let selected = dropdown.selected_item(); - if selected.is_none() { - return ControlFlow::Break; - } - let selected = selected.unwrap(); - let selected = selected.downcast_ref::().unwrap(); - let selected = selected.string().to_string(); - let source = input_box_imp.reset_source_map.read().unwrap(); - let source = source.get(&selected); - if source.is_none() { - return ControlFlow::Break; - } - let source = Arc::new(source.unwrap().1.clone()); - gio::spawn_blocking(move || { - let result = set_default_source(source, input_box_ref.clone()); - if result.is_none() { - return ControlFlow::Break; - } - refresh_default_source(result.unwrap(), input_box_ref.clone(), false); - ControlFlow::Continue - }); - ControlFlow::Continue -} - -fn volume_slider_handler(input_box: Arc, value: f64) -> Propagation { - let imp = input_box.imp(); - let fraction = (value / 655.36).round(); - let percentage = (fraction).to_string() + "%"; - imp.reset_volume_percentage.set_text(&percentage); - let source = imp.reset_default_source.borrow(); - let index = source.index; - let channels = source.channels; - { - let mut time = imp.volume_time_stamp.borrow_mut(); - if time.is_some() && time.unwrap().elapsed().unwrap() < Duration::from_millis(50) { - return Propagation::Proceed; - } - *time = Some(SystemTime::now()); - } - set_source_volume(value, index, channels, input_box.clone()); - Propagation::Proceed -} - -fn mute_clicked_handler(input_box_ref_mute: Arc) { - let imp = input_box_ref_mute.imp(); - let mut source = imp.reset_default_source.borrow_mut(); - source.muted = !source.muted; - if source.muted { - imp.reset_source_mute - .set_icon_name("microphone-disabled-symbolic"); - } else { - imp.reset_source_mute - .set_icon_name("audio-input-microphone-symbolic"); - } - toggle_source_mute(source.index, source.muted, input_box_ref_mute.clone()); -} - -pub fn refresh_default_source(new_source: Source, input_box: Arc, entry: bool) { - let volume = *new_source.volume.first().unwrap_or(&0_u32); - let fraction = (volume as f64 / 655.36).round(); - let percentage = (fraction).to_string() + "%"; - glib::spawn_future(async move { - glib::idle_add_once(move || { - let imp = input_box.imp(); - if !entry { - let list = imp.reset_source_list.read().unwrap(); - let entry = list.get(&new_source.index); - if entry.is_none() { - return; - } - let entry_imp = entry.unwrap().1.imp(); - entry_imp.reset_selected_source.set_active(true); - } else { - let model_list = imp.reset_model_list.read().unwrap(); - for entry in 0..*imp.reset_model_index.read().unwrap() { - if model_list.string(entry) == Some(new_source.alias.clone().into()) { - imp.reset_source_dropdown.set_selected(entry); - break; - } - } - } - imp.reset_volume_percentage.set_text(&percentage); - imp.reset_volume_slider.set_value(volume as f64); - if new_source.muted { - imp.reset_source_mute - .set_icon_name("microphone-disabled-symbolic"); - } else { - imp.reset_source_mute - .set_icon_name("audio-input-microphone-symbolic"); - } - imp.reset_default_source.replace(new_source); - }); - }); -} - -pub fn populate_outputstreams(input_box: Arc) { - let input_box_ref = input_box.clone(); - - gio::spawn_blocking(move || { - let streams = get_output_streams(input_box.clone()); - glib::spawn_future(async move { - glib::idle_add_once(move || { - let input_box_imp = input_box_ref.imp(); - let mut list = input_box_imp.reset_output_stream_list.write().unwrap(); - for stream in streams { - let index = stream.index; - let input_stream = Arc::new(OutputStreamEntry::new(input_box.clone(), stream)); - let input_stream_clone = input_stream.clone(); - let entry = Arc::new(ListEntry::new(&*input_stream)); - entry.set_activatable(false); - list.insert(index, (entry.clone(), input_stream_clone)); - input_box_imp.reset_output_streams.append(&*entry); - } - }); - }); - }); -} - -pub fn populate_cards(input_box: Arc) { - gio::spawn_blocking(move || { - let input_box_ref = input_box.clone(); - let cards = get_cards(input_box.clone()); - glib::spawn_future(async move { - glib::idle_add_once(move || { - let imp = input_box_ref.imp(); - for card in cards { - imp.reset_cards.add(&CardEntry::new(card)); - } - }); - }); - }); -} - -fn get_output_streams(input_box: Arc) -> Vec { - let conn = Connection::new_session().unwrap(); - let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000)); - let res: Result<(Vec,), Error> = - proxy.method_call(AUDIO, "ListOutputStreams", ()); - if res.is_err() { - show_error::(input_box.clone(), "Failed to get output streams"); - return Vec::new(); - } - res.unwrap().0 -} - -fn get_sources(input_box: Arc) -> Vec { - let conn = Connection::new_session().unwrap(); - let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000)); - let res: Result<(Vec,), Error> = proxy.method_call(AUDIO, "ListSources", ()); - if res.is_err() { - show_error::(input_box.clone(), "Failed to get sources"); - return Vec::new(); - } - res.unwrap().0 -} - -fn get_cards(input_box: Arc) -> Vec { - let conn = Connection::new_session().unwrap(); - let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000)); - let res: Result<(Vec,), Error> = proxy.method_call(AUDIO, "ListCards", ()); - if res.is_err() { - show_error::(input_box.clone(), "Failed to get profiles"); - return Vec::new(); - } - res.unwrap().0 -} - -pub fn get_default_source_name(input_box: Arc) -> String { - let conn = Connection::new_session().unwrap(); - let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000)); - let res: Result<(String,), Error> = proxy.method_call(AUDIO, "GetDefaultSourceName", ()); - if res.is_err() { - show_error::(input_box.clone(), "Failed to get default source name"); - return String::from(""); - } - res.unwrap().0 -} - -fn get_default_source(input_box: Arc) -> Source { - let conn = Connection::new_session().unwrap(); - let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000)); - let res: Result<(Source,), Error> = proxy.method_call(AUDIO, "GetDefaultSource", ()); - if res.is_err() { - show_error::(input_box.clone(), "Failed to get default source"); - return Source::default(); - } - res.unwrap().0 -} - pub fn start_input_box_listener(conn: Connection, source_box: Arc) -> Connection { let source_added = SourceAdded::match_rule(Some(&BASE.into()), Some(&Path::from(DBUS_PATH))).static_clone(); diff --git a/src/components/input/source_box_event_handlers.rs b/src/components/input/source_box_handlers.rs similarity index 77% rename from src/components/input/source_box_event_handlers.rs rename to src/components/input/source_box_handlers.rs index 55cbc72..f4878b1 100644 --- a/src/components/input/source_box_event_handlers.rs +++ b/src/components/input/source_box_handlers.rs @@ -1,8 +1,15 @@ -use std::sync::Arc; +use std::{ + sync::Arc, + time::{Duration, SystemTime}, +}; use adw::prelude::{ComboRowExt, PreferencesRowExt}; -use glib::subclass::types::ObjectSubclassIsExt; -use gtk::prelude::{BoxExt, ButtonExt, CheckButtonExt, ListBoxRowExt, RangeExt}; +use glib::{subclass::types::ObjectSubclassIsExt, Cast, ControlFlow, Propagation}; +use gtk::{ + gio, + prelude::{BoxExt, ButtonExt, CheckButtonExt, ListBoxRowExt, RangeExt}, + StringObject, +}; use re_set_lib::signals::{ OutputStreamAdded, OutputStreamChanged, OutputStreamRemoved, SourceAdded, SourceChanged, SourceRemoved, @@ -12,8 +19,9 @@ use crate::components::base::list_entry::ListEntry; use super::{ output_stream_entry::OutputStreamEntry, - source_box::{get_default_source_name, SourceBox}, - source_entry::SourceEntry, + source_box::SourceBox, + source_box_utils::{get_default_source_name, refresh_default_source}, + source_entry::{set_default_source, set_source_volume, toggle_source_mute, SourceEntry}, }; pub fn source_added_handler(source_box: Arc, ir: SourceAdded) -> bool { @@ -238,3 +246,63 @@ pub fn output_stream_removed_handler(source_box: Arc, ir: OutputStrea }); true } + +pub fn dropdown_handler(input_box: Arc, dropdown: &adw::ComboRow) -> ControlFlow { + let input_box_imp = input_box.imp(); + let input_box_ref = input_box.clone(); + let selected = dropdown.selected_item(); + if selected.is_none() { + return ControlFlow::Break; + } + let selected = selected.unwrap(); + let selected = selected.downcast_ref::().unwrap(); + let selected = selected.string().to_string(); + let source = input_box_imp.reset_source_map.read().unwrap(); + let source = source.get(&selected); + if source.is_none() { + return ControlFlow::Break; + } + let source = Arc::new(source.unwrap().1.clone()); + gio::spawn_blocking(move || { + let result = set_default_source(source, input_box_ref.clone()); + if result.is_none() { + return ControlFlow::Break; + } + refresh_default_source(result.unwrap(), input_box_ref.clone(), false); + ControlFlow::Continue + }); + ControlFlow::Continue +} + +pub fn volume_slider_handler(input_box: Arc, value: f64) -> Propagation { + let imp = input_box.imp(); + let fraction = (value / 655.36).round(); + let percentage = (fraction).to_string() + "%"; + imp.reset_volume_percentage.set_text(&percentage); + let source = imp.reset_default_source.borrow(); + let index = source.index; + let channels = source.channels; + { + let mut time = imp.volume_time_stamp.borrow_mut(); + if time.is_some() && time.unwrap().elapsed().unwrap() < Duration::from_millis(50) { + return Propagation::Proceed; + } + *time = Some(SystemTime::now()); + } + set_source_volume(value, index, channels, input_box.clone()); + Propagation::Proceed +} + +pub fn mute_clicked_handler(input_box_ref_mute: Arc) { + let imp = input_box_ref_mute.imp(); + let mut source = imp.reset_default_source.borrow_mut(); + source.muted = !source.muted; + if source.muted { + imp.reset_source_mute + .set_icon_name("microphone-disabled-symbolic"); + } else { + imp.reset_source_mute + .set_icon_name("audio-input-microphone-symbolic"); + } + toggle_source_mute(source.index, source.muted, input_box_ref_mute.clone()); +} diff --git a/src/components/input/source_box_utils.rs b/src/components/input/source_box_utils.rs new file mode 100644 index 0000000..8e37d90 --- /dev/null +++ b/src/components/input/source_box_utils.rs @@ -0,0 +1,229 @@ +use std::{sync::Arc, time::Duration}; + +use adw::prelude::{ComboRowExt, PreferencesGroupExt}; +use dbus::{blocking::Connection, Error}; +use glib::subclass::types::ObjectSubclassIsExt; +use gtk::{ + gio, + prelude::{BoxExt, ButtonExt, CheckButtonExt, ListBoxRowExt, RangeExt}, +}; +use re_set_lib::audio::audio_structures::{Card, OutputStream, Source}; + +use crate::components::{ + base::{card_entry::CardEntry, error_impl::show_error, list_entry::ListEntry}, + utils::{AUDIO, BASE, DBUS_PATH}, +}; + +use super::{ + output_stream_entry::OutputStreamEntry, + source_box::SourceBox, + source_box_handlers::{dropdown_handler, mute_clicked_handler, volume_slider_handler}, + source_entry::SourceEntry, +}; + +pub fn populate_source_information(input_box: Arc, sources: Vec) { + glib::spawn_future(async move { + glib::idle_add_once(move || { + let input_box_ref_slider = input_box.clone(); + let input_box_ref_toggle = input_box.clone(); + let input_box_ref_mute = input_box.clone(); + let input_box_imp = input_box.imp(); + let default_sink = input_box_imp.reset_default_source.clone(); + let source = default_sink.borrow(); + + if source.muted { + input_box_imp + .reset_source_mute + .set_icon_name("microphone-disabled-symbolic"); + } else { + input_box_imp + .reset_source_mute + .set_icon_name("audio-input-microphone-symbolic"); + } + + let volume = source.volume.first().unwrap_or(&0_u32); + let fraction = (*volume as f64 / 655.36).round(); + let percentage = (fraction).to_string() + "%"; + input_box_imp.reset_volume_percentage.set_text(&percentage); + input_box_imp.reset_volume_slider.set_value(*volume as f64); + let mut list = input_box_imp.reset_source_list.write().unwrap(); + for source in sources { + let index = source.index; + let alias = source.alias.clone(); + let mut is_default = false; + if input_box_imp.reset_default_source.borrow().name == source.name { + is_default = true; + } + let source_entry = Arc::new(SourceEntry::new( + is_default, + input_box_imp.reset_default_check_button.clone(), + source, + input_box.clone(), + )); + 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)); + input_box_imp.reset_sources.append(&*entry); + } + let list = input_box_imp.reset_model_list.read().unwrap(); + input_box_imp.reset_source_dropdown.set_model(Some(&*list)); + let name = input_box_imp.reset_default_source.borrow(); + + let index = input_box_imp.reset_model_index.read().unwrap(); + let model_list = input_box_imp.reset_model_list.read().unwrap(); + for entry in 0..*index { + if model_list.string(entry) == Some(name.alias.clone().into()) { + input_box_imp.reset_source_dropdown.set_selected(entry); + break; + } + } + input_box_imp + .reset_source_dropdown + .connect_selected_notify(move |dropdown| { + dropdown_handler(input_box_ref_toggle.clone(), dropdown); + }); + input_box_imp + .reset_volume_slider + .connect_change_value(move |_, _, value| { + volume_slider_handler(input_box_ref_slider.clone(), value) + }); + + input_box_imp.reset_source_mute.connect_clicked(move |_| { + mute_clicked_handler(input_box_ref_mute.clone()); + }); + }); + }); +} + +pub fn refresh_default_source(new_source: Source, input_box: Arc, entry: bool) { + let volume = *new_source.volume.first().unwrap_or(&0_u32); + let fraction = (volume as f64 / 655.36).round(); + let percentage = (fraction).to_string() + "%"; + glib::spawn_future(async move { + glib::idle_add_once(move || { + let imp = input_box.imp(); + if !entry { + let list = imp.reset_source_list.read().unwrap(); + let entry = list.get(&new_source.index); + if entry.is_none() { + return; + } + let entry_imp = entry.unwrap().1.imp(); + entry_imp.reset_selected_source.set_active(true); + } else { + let model_list = imp.reset_model_list.read().unwrap(); + for entry in 0..*imp.reset_model_index.read().unwrap() { + if model_list.string(entry) == Some(new_source.alias.clone().into()) { + imp.reset_source_dropdown.set_selected(entry); + break; + } + } + } + imp.reset_volume_percentage.set_text(&percentage); + imp.reset_volume_slider.set_value(volume as f64); + if new_source.muted { + imp.reset_source_mute + .set_icon_name("microphone-disabled-symbolic"); + } else { + imp.reset_source_mute + .set_icon_name("audio-input-microphone-symbolic"); + } + imp.reset_default_source.replace(new_source); + }); + }); +} + +pub fn populate_outputstreams(input_box: Arc) { + let input_box_ref = input_box.clone(); + + gio::spawn_blocking(move || { + let streams = get_output_streams(input_box.clone()); + glib::spawn_future(async move { + glib::idle_add_once(move || { + let input_box_imp = input_box_ref.imp(); + let mut list = input_box_imp.reset_output_stream_list.write().unwrap(); + for stream in streams { + let index = stream.index; + let input_stream = Arc::new(OutputStreamEntry::new(input_box.clone(), stream)); + let input_stream_clone = input_stream.clone(); + let entry = Arc::new(ListEntry::new(&*input_stream)); + entry.set_activatable(false); + list.insert(index, (entry.clone(), input_stream_clone)); + input_box_imp.reset_output_streams.append(&*entry); + } + }); + }); + }); +} + +pub fn populate_cards(input_box: Arc) { + gio::spawn_blocking(move || { + let input_box_ref = input_box.clone(); + let cards = get_cards(input_box.clone()); + glib::spawn_future(async move { + glib::idle_add_once(move || { + let imp = input_box_ref.imp(); + for card in cards { + imp.reset_cards.add(&CardEntry::new(card)); + } + }); + }); + }); +} + +pub fn get_output_streams(input_box: Arc) -> Vec { + let conn = Connection::new_session().unwrap(); + let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000)); + let res: Result<(Vec,), Error> = + proxy.method_call(AUDIO, "ListOutputStreams", ()); + if res.is_err() { + show_error::(input_box.clone(), "Failed to get output streams"); + return Vec::new(); + } + res.unwrap().0 +} + +pub fn get_sources(input_box: Arc) -> Vec { + let conn = Connection::new_session().unwrap(); + let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000)); + let res: Result<(Vec,), Error> = proxy.method_call(AUDIO, "ListSources", ()); + if res.is_err() { + show_error::(input_box.clone(), "Failed to get sources"); + return Vec::new(); + } + res.unwrap().0 +} + +pub fn get_cards(input_box: Arc) -> Vec { + let conn = Connection::new_session().unwrap(); + let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000)); + let res: Result<(Vec,), Error> = proxy.method_call(AUDIO, "ListCards", ()); + if res.is_err() { + show_error::(input_box.clone(), "Failed to get profiles"); + return Vec::new(); + } + res.unwrap().0 +} + +pub fn get_default_source_name(input_box: Arc) -> String { + let conn = Connection::new_session().unwrap(); + let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000)); + let res: Result<(String,), Error> = proxy.method_call(AUDIO, "GetDefaultSourceName", ()); + if res.is_err() { + show_error::(input_box.clone(), "Failed to get default source name"); + return String::from(""); + } + res.unwrap().0 +} + +pub fn get_default_source(input_box: Arc) -> Source { + let conn = Connection::new_session().unwrap(); + let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000)); + let res: Result<(Source,), Error> = proxy.method_call(AUDIO, "GetDefaultSource", ()); + if res.is_err() { + show_error::(input_box.clone(), "Failed to get default source"); + return Source::default(); + } + res.unwrap().0 +} diff --git a/src/components/input/source_entry.rs b/src/components/input/source_entry.rs index 3763c34..9fe131e 100644 --- a/src/components/input/source_entry.rs +++ b/src/components/input/source_entry.rs @@ -14,7 +14,8 @@ use re_set_lib::audio::audio_structures::Source; use crate::components::utils::{AUDIO, BASE, DBUS_PATH}; -use super::source_box::{refresh_default_source, SourceBox}; +use super::source_box::SourceBox; +use super::source_box_utils::refresh_default_source; use super::source_entry_impl; glib::wrapper! { diff --git a/src/components/output/mod.rs b/src/components/output/mod.rs index 1d67696..5938435 100644 --- a/src/components/output/mod.rs +++ b/src/components/output/mod.rs @@ -1,7 +1,8 @@ pub mod input_stream_entry; pub mod input_stream_entry_impl; pub mod sink_box; -mod sink_box_event_handlers; +mod sink_box_handlers; pub mod sink_box_impl; +mod sink_box_utils; pub mod sink_entry; pub mod sink_entry_impl; diff --git a/src/components/output/sink_box.rs b/src/components/output/sink_box.rs index 692bbb7..810e0e3 100644 --- a/src/components/output/sink_box.rs +++ b/src/components/output/sink_box.rs @@ -1,8 +1,3 @@ -use adw::prelude::PreferencesGroupExt; -use adw::ComboRow; -use re_set_lib::audio::audio_structures::Card; -use re_set_lib::audio::audio_structures::InputStream; -use re_set_lib::audio::audio_structures::Sink; use re_set_lib::signals::InputStreamAdded; use re_set_lib::signals::InputStreamChanged; use re_set_lib::signals::InputStreamRemoved; @@ -10,38 +5,35 @@ use re_set_lib::signals::SinkAdded; use re_set_lib::signals::SinkChanged; use re_set_lib::signals::SinkRemoved; use std::sync::Arc; -use std::time::{Duration, SystemTime}; use adw::glib::Object; +use adw::prelude::ComboRowExt; use adw::prelude::ListBoxRowExt; -use adw::prelude::{BoxExt, ButtonExt, CheckButtonExt, ComboRowExt, RangeExt}; use dbus::blocking::Connection; use dbus::message::SignalArgs; -use dbus::{Error, Path}; +use dbus::Path; use glib::subclass::prelude::ObjectSubclassIsExt; -use glib::{Cast, Propagation, Variant}; +use glib::Variant; +use gtk::gio; use gtk::prelude::ActionableExt; -use gtk::{gio, StringObject}; -use crate::components::base::card_entry::CardEntry; -use crate::components::base::error_impl::show_error; use crate::components::base::error_impl::ReSetErrorImpl; -use crate::components::base::list_entry::ListEntry; -use crate::components::output::sink_entry::set_sink_volume; -use crate::components::utils::AUDIO; use crate::components::utils::BASE; use crate::components::utils::DBUS_PATH; use crate::components::utils::{create_dropdown_label_factory, set_combo_row_ellipsis}; -use super::input_stream_entry::InputStreamEntry; -use super::sink_box_event_handlers::input_stream_added_handler; -use super::sink_box_event_handlers::input_stream_changed_handler; -use super::sink_box_event_handlers::input_stream_removed_handler; -use super::sink_box_event_handlers::sink_added_handler; -use super::sink_box_event_handlers::sink_changed_handler; -use super::sink_box_event_handlers::sink_removed_handler; +use super::sink_box_handlers::input_stream_added_handler; +use super::sink_box_handlers::input_stream_changed_handler; +use super::sink_box_handlers::input_stream_removed_handler; +use super::sink_box_handlers::sink_added_handler; +use super::sink_box_handlers::sink_changed_handler; +use super::sink_box_handlers::sink_removed_handler; use super::sink_box_impl; -use super::sink_entry::{set_default_sink, toggle_sink_mute, SinkEntry}; +use super::sink_box_utils::get_default_sink; +use super::sink_box_utils::get_sinks; +use super::sink_box_utils::populate_cards; +use super::sink_box_utils::populate_inputstreams; +use super::sink_box_utils::populate_sink_information; glib::wrapper! { pub struct SinkBox(ObjectSubclass) @@ -134,278 +126,6 @@ pub fn populate_sinks(output_box: Arc) { }); } -fn drop_down_handler(output_box: Arc, dropdown: &ComboRow) { - let output_box_ref = output_box.clone(); - let output_box_imp = output_box.imp(); - let selected = dropdown.selected_item(); - if selected.is_none() { - return; - } - let selected = selected.unwrap(); - let selected = selected.downcast_ref::().unwrap(); - let selected = selected.string().to_string(); - - let sink = output_box_imp.reset_sink_map.read().unwrap(); - let sink = sink.get(&selected); - if sink.is_none() { - return; - } - let new_sink_name = Arc::new(sink.unwrap().1.clone()); - gio::spawn_blocking(move || { - let result = set_default_sink(new_sink_name, output_box_ref.clone()); - if result.is_none() { - return; - } - let new_sink = result.unwrap(); - refresh_default_sink(new_sink, output_box_ref, false); - }); -} - -fn volume_slider_handler(output_box: Arc, value: f64) -> glib::Propagation { - let imp = output_box.imp(); - let fraction = (value / 655.36).round(); - let percentage = (fraction).to_string() + "%"; - imp.reset_volume_percentage.set_text(&percentage); - let sink = imp.reset_default_sink.borrow(); - let index = sink.index; - let channels = sink.channels; - { - let mut time = imp.volume_time_stamp.borrow_mut(); - if time.is_some() && time.unwrap().elapsed().unwrap() < Duration::from_millis(50) { - return Propagation::Proceed; - } - *time = Some(SystemTime::now()); - } - set_sink_volume(value, index, channels, output_box.clone()); - Propagation::Proceed -} - -fn mute_handler(output_box: Arc) { - let imp = output_box.imp(); - let mut stream = imp.reset_default_sink.borrow_mut(); - stream.muted = !stream.muted; - if stream.muted { - imp.reset_sink_mute - .set_icon_name("audio-volume-muted-symbolic"); - } else { - imp.reset_sink_mute - .set_icon_name("audio-volume-high-symbolic"); - } - toggle_sink_mute(stream.index, stream.muted, output_box.clone()); -} - -fn populate_sink_information(output_box: Arc, sinks: Vec) { - glib::spawn_future(async move { - glib::idle_add_once(move || { - let output_box_ref_select = output_box.clone(); - let output_box_ref_slider = output_box.clone(); - let output_box_ref_mute = output_box.clone(); - let output_box_ref = output_box.clone(); - { - let output_box_imp = output_box_ref.imp(); - let default_sink = output_box_imp.reset_default_sink.clone(); - let sink = default_sink.borrow(); - - if sink.muted { - output_box_imp - .reset_sink_mute - .set_icon_name("audio-volume-muted-symbolic"); - } else { - output_box_imp - .reset_sink_mute - .set_icon_name("audio-volume-high-symbolic"); - } - - let volume = sink.volume.first().unwrap_or(&0); - let fraction = (*volume as f64 / 655.36).round(); - let percentage = (fraction).to_string() + "%"; - output_box_imp.reset_volume_percentage.set_text(&percentage); - output_box_imp.reset_volume_slider.set_value(*volume as f64); - let mut list = output_box_imp.reset_sink_list.write().unwrap(); - for sink in sinks { - let index = sink.index; - let alias = sink.alias.clone(); - let mut is_default = false; - if output_box_imp.reset_default_sink.borrow().name == sink.name { - is_default = true; - } - let sink_entry = Arc::new(SinkEntry::new( - is_default, - output_box_imp.reset_default_check_button.clone(), - sink, - output_box.clone(), - )); - 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)); - output_box_imp.reset_sinks.append(&*entry); - } - let list = output_box_imp.reset_model_list.read().unwrap(); - output_box_imp.reset_sink_dropdown.set_model(Some(&*list)); - let name = output_box_imp.reset_default_sink.borrow(); - - let index = output_box_imp.reset_model_index.read().unwrap(); - let model_list = output_box_imp.reset_model_list.read().unwrap(); - for entry in 0..*index { - if model_list.string(entry) == Some(name.alias.clone().into()) { - output_box_imp.reset_sink_dropdown.set_selected(entry); - break; - } - } - output_box_imp - .reset_sink_dropdown - .connect_selected_notify(move |dropdown| { - drop_down_handler(output_box_ref_select.clone(), dropdown); - }); - } - output_box_ref - .imp() - .reset_volume_slider - .connect_change_value(move |_, _, value| { - volume_slider_handler(output_box_ref_slider.clone(), value) - }); - output_box_ref - .imp() - .reset_sink_mute - .connect_clicked(move |_| { - mute_handler(output_box_ref_mute.clone()); - }); - }); - }); -} - -pub fn refresh_default_sink(new_sink: Sink, output_box: Arc, entry: bool) { - let volume = *new_sink.volume.first().unwrap_or(&0_u32); - let fraction = (volume as f64 / 655.36).round(); - let percentage = (fraction).to_string() + "%"; - glib::spawn_future(async move { - glib::idle_add_once(move || { - let imp = output_box.imp(); - if !entry { - let list = imp.reset_sink_list.read().unwrap(); - let entry = list.get(&new_sink.index); - if entry.is_none() { - return; - } - let entry_imp = entry.unwrap().1.imp(); - entry_imp.reset_selected_sink.set_active(true); - } else { - let index = imp.reset_model_index.read().unwrap(); - let model_list = imp.reset_model_list.read().unwrap(); - for entry in 0..*index { - if model_list.string(entry) == Some(new_sink.alias.clone().into()) { - imp.reset_sink_dropdown.set_selected(entry); - break; - } - } - } - imp.reset_volume_percentage.set_text(&percentage); - imp.reset_volume_slider.set_value(volume as f64); - if new_sink.muted { - imp.reset_sink_mute - .set_icon_name("audio-volume-muted-symbolic"); - } else { - imp.reset_sink_mute - .set_icon_name("audio-volume-high-symbolic"); - } - imp.reset_default_sink.replace(new_sink); - }); - }); -} - -pub fn populate_inputstreams(output_box: Arc) { - let output_box_ref = output_box.clone(); - - gio::spawn_blocking(move || { - let streams = get_input_streams(output_box.clone()); - glib::spawn_future(async move { - glib::idle_add_once(move || { - let output_box_imp = output_box_ref.imp(); - let mut list = output_box_imp.reset_input_stream_list.write().unwrap(); - for stream in streams { - 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); - list.insert(index, (entry.clone(), input_stream.clone())); - output_box_imp.reset_input_streams.append(&*entry); - } - }); - }); - }); -} - -pub fn populate_cards(output_box: Arc) { - gio::spawn_blocking(move || { - let output_box_ref = output_box.clone(); - let cards = get_cards(output_box.clone()); - glib::spawn_future(async move { - glib::idle_add_once(move || { - let imp = output_box_ref.imp(); - for card in cards { - imp.reset_cards.add(&CardEntry::new(card)); - } - }); - }); - }); -} - -fn get_input_streams(output_box: Arc) -> Vec { - let conn = Connection::new_session().unwrap(); - let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000)); - let res: Result<(Vec,), Error> = proxy.method_call(AUDIO, "ListInputStreams", ()); - if res.is_err() { - show_error::(output_box.clone(), "Failed to list input streams"); - return Vec::new(); - } - res.unwrap().0 -} - -fn get_sinks(output_box: Arc) -> Vec { - let conn = Connection::new_session().unwrap(); - let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000)); - let res: Result<(Vec,), Error> = proxy.method_call(AUDIO, "ListSinks", ()); - if res.is_err() { - show_error::(output_box.clone(), "Failed to list sinks"); - return Vec::new(); - } - res.unwrap().0 -} - -fn get_cards(output_box: Arc) -> Vec { - let conn = Connection::new_session().unwrap(); - let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000)); - let res: Result<(Vec,), Error> = proxy.method_call(AUDIO, "ListCards", ()); - if res.is_err() { - show_error::(output_box.clone(), "Failed to list profiles"); - return Vec::new(); - } - res.unwrap().0 -} - -pub fn get_default_sink_name(output_box: Arc) -> String { - let conn = Connection::new_session().unwrap(); - let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000)); - let res: Result<(String,), Error> = proxy.method_call(AUDIO, "GetDefaultSinkName", ()); - if res.is_err() { - show_error::(output_box.clone(), "Failed to get default sink name"); - return String::from(""); - } - res.unwrap().0 -} - -fn get_default_sink(output_box: Arc) -> Sink { - let conn = Connection::new_session().unwrap(); - let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000)); - let res: Result<(Sink,), Error> = proxy.method_call(AUDIO, "GetDefaultSink", ()); - if res.is_err() { - show_error::(output_box.clone(), "Failed to get default sink"); - return Sink::default(); - } - res.unwrap().0 -} - pub fn start_output_box_listener(conn: Connection, sink_box: Arc) -> Connection { let sink_added = SinkAdded::match_rule(Some(&BASE.into()), Some(&Path::from(DBUS_PATH))).static_clone(); diff --git a/src/components/output/sink_box_event_handlers.rs b/src/components/output/sink_box_handlers.rs similarity index 78% rename from src/components/output/sink_box_event_handlers.rs rename to src/components/output/sink_box_handlers.rs index 0dd2922..42c41ad 100644 --- a/src/components/output/sink_box_event_handlers.rs +++ b/src/components/output/sink_box_handlers.rs @@ -1,8 +1,18 @@ -use std::sync::Arc; +use std::{ + sync::Arc, + time::{Duration, SystemTime}, +}; -use adw::prelude::{ComboRowExt, PreferencesRowExt}; -use glib::subclass::types::ObjectSubclassIsExt; -use gtk::prelude::{BoxExt, ButtonExt, CheckButtonExt, ListBoxRowExt, RangeExt}; +use adw::{ + prelude::{ComboRowExt, PreferencesRowExt}, + ComboRow, +}; +use glib::{subclass::types::ObjectSubclassIsExt, Cast, Propagation}; +use gtk::{ + gio, + prelude::{BoxExt, ButtonExt, CheckButtonExt, ListBoxRowExt, RangeExt}, + StringObject, +}; use re_set_lib::signals::{ InputStreamAdded, InputStreamChanged, InputStreamRemoved, SinkAdded, SinkChanged, SinkRemoved, }; @@ -11,10 +21,71 @@ use crate::components::base::list_entry::ListEntry; use super::{ input_stream_entry::InputStreamEntry, - sink_box::{get_default_sink_name, SinkBox}, - sink_entry::SinkEntry, + sink_box::SinkBox, + sink_box_utils::{get_default_sink_name, refresh_default_sink}, + sink_entry::{set_default_sink, set_sink_volume, toggle_sink_mute, SinkEntry}, }; +pub fn drop_down_handler(output_box: Arc, dropdown: &ComboRow) { + let output_box_ref = output_box.clone(); + let output_box_imp = output_box.imp(); + let selected = dropdown.selected_item(); + if selected.is_none() { + return; + } + let selected = selected.unwrap(); + let selected = selected.downcast_ref::().unwrap(); + let selected = selected.string().to_string(); + + let sink = output_box_imp.reset_sink_map.read().unwrap(); + let sink = sink.get(&selected); + if sink.is_none() { + return; + } + let new_sink_name = Arc::new(sink.unwrap().1.clone()); + gio::spawn_blocking(move || { + let result = set_default_sink(new_sink_name, output_box_ref.clone()); + if result.is_none() { + return; + } + let new_sink = result.unwrap(); + refresh_default_sink(new_sink, output_box_ref, false); + }); +} + +pub fn volume_slider_handler(output_box: Arc, value: f64) -> glib::Propagation { + let imp = output_box.imp(); + let fraction = (value / 655.36).round(); + let percentage = (fraction).to_string() + "%"; + imp.reset_volume_percentage.set_text(&percentage); + let sink = imp.reset_default_sink.borrow(); + let index = sink.index; + let channels = sink.channels; + { + let mut time = imp.volume_time_stamp.borrow_mut(); + if time.is_some() && time.unwrap().elapsed().unwrap() < Duration::from_millis(50) { + return Propagation::Proceed; + } + *time = Some(SystemTime::now()); + } + set_sink_volume(value, index, channels, output_box.clone()); + Propagation::Proceed +} + +pub fn mute_handler(output_box: Arc) { + let imp = output_box.imp(); + let mut stream = imp.reset_default_sink.borrow_mut(); + stream.muted = !stream.muted; + if stream.muted { + imp.reset_sink_mute + .set_icon_name("audio-volume-muted-symbolic"); + } else { + imp.reset_sink_mute + .set_icon_name("audio-volume-high-symbolic"); + } + toggle_sink_mute(stream.index, stream.muted, output_box.clone()); +} + pub fn sink_added_handler(output_box: Arc, ir: SinkAdded) -> bool { glib::spawn_future(async move { glib::idle_add_once(move || { diff --git a/src/components/output/sink_box_utils.rs b/src/components/output/sink_box_utils.rs new file mode 100644 index 0000000..7a4bb7e --- /dev/null +++ b/src/components/output/sink_box_utils.rs @@ -0,0 +1,234 @@ +use std::{sync::Arc, time::Duration}; + +use adw::prelude::{ComboRowExt, PreferencesGroupExt}; +use dbus::{blocking::Connection, Error}; +use glib::subclass::types::ObjectSubclassIsExt; +use gtk::{ + gio, + prelude::{BoxExt, ButtonExt, CheckButtonExt, ListBoxRowExt, RangeExt}, +}; +use re_set_lib::audio::audio_structures::{Card, InputStream, Sink}; + +use crate::components::{ + base::{card_entry::CardEntry, error_impl::show_error, list_entry::ListEntry}, + utils::{AUDIO, BASE, DBUS_PATH}, +}; + +use super::{ + input_stream_entry::InputStreamEntry, + sink_box::SinkBox, + sink_box_handlers::{drop_down_handler, mute_handler, volume_slider_handler}, + sink_entry::SinkEntry, +}; + +pub fn populate_sink_information(output_box: Arc, sinks: Vec) { + glib::spawn_future(async move { + glib::idle_add_once(move || { + let output_box_ref_select = output_box.clone(); + let output_box_ref_slider = output_box.clone(); + let output_box_ref_mute = output_box.clone(); + let output_box_ref = output_box.clone(); + { + let output_box_imp = output_box_ref.imp(); + let default_sink = output_box_imp.reset_default_sink.clone(); + let sink = default_sink.borrow(); + + if sink.muted { + output_box_imp + .reset_sink_mute + .set_icon_name("audio-volume-muted-symbolic"); + } else { + output_box_imp + .reset_sink_mute + .set_icon_name("audio-volume-high-symbolic"); + } + + let volume = sink.volume.first().unwrap_or(&0); + let fraction = (*volume as f64 / 655.36).round(); + let percentage = (fraction).to_string() + "%"; + output_box_imp.reset_volume_percentage.set_text(&percentage); + output_box_imp.reset_volume_slider.set_value(*volume as f64); + let mut list = output_box_imp.reset_sink_list.write().unwrap(); + for sink in sinks { + let index = sink.index; + let alias = sink.alias.clone(); + let mut is_default = false; + if output_box_imp.reset_default_sink.borrow().name == sink.name { + is_default = true; + } + let sink_entry = Arc::new(SinkEntry::new( + is_default, + output_box_imp.reset_default_check_button.clone(), + sink, + output_box.clone(), + )); + 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)); + output_box_imp.reset_sinks.append(&*entry); + } + let list = output_box_imp.reset_model_list.read().unwrap(); + output_box_imp.reset_sink_dropdown.set_model(Some(&*list)); + let name = output_box_imp.reset_default_sink.borrow(); + + let index = output_box_imp.reset_model_index.read().unwrap(); + let model_list = output_box_imp.reset_model_list.read().unwrap(); + for entry in 0..*index { + if model_list.string(entry) == Some(name.alias.clone().into()) { + output_box_imp.reset_sink_dropdown.set_selected(entry); + break; + } + } + output_box_imp + .reset_sink_dropdown + .connect_selected_notify(move |dropdown| { + drop_down_handler(output_box_ref_select.clone(), dropdown); + }); + } + output_box_ref + .imp() + .reset_volume_slider + .connect_change_value(move |_, _, value| { + volume_slider_handler(output_box_ref_slider.clone(), value) + }); + output_box_ref + .imp() + .reset_sink_mute + .connect_clicked(move |_| { + mute_handler(output_box_ref_mute.clone()); + }); + }); + }); +} + +pub fn refresh_default_sink(new_sink: Sink, output_box: Arc, entry: bool) { + let volume = *new_sink.volume.first().unwrap_or(&0_u32); + let fraction = (volume as f64 / 655.36).round(); + let percentage = (fraction).to_string() + "%"; + glib::spawn_future(async move { + glib::idle_add_once(move || { + let imp = output_box.imp(); + if !entry { + let list = imp.reset_sink_list.read().unwrap(); + let entry = list.get(&new_sink.index); + if entry.is_none() { + return; + } + let entry_imp = entry.unwrap().1.imp(); + entry_imp.reset_selected_sink.set_active(true); + } else { + let index = imp.reset_model_index.read().unwrap(); + let model_list = imp.reset_model_list.read().unwrap(); + for entry in 0..*index { + if model_list.string(entry) == Some(new_sink.alias.clone().into()) { + imp.reset_sink_dropdown.set_selected(entry); + break; + } + } + } + imp.reset_volume_percentage.set_text(&percentage); + imp.reset_volume_slider.set_value(volume as f64); + if new_sink.muted { + imp.reset_sink_mute + .set_icon_name("audio-volume-muted-symbolic"); + } else { + imp.reset_sink_mute + .set_icon_name("audio-volume-high-symbolic"); + } + imp.reset_default_sink.replace(new_sink); + }); + }); +} + +pub fn populate_inputstreams(output_box: Arc) { + let output_box_ref = output_box.clone(); + + gio::spawn_blocking(move || { + let streams = get_input_streams(output_box.clone()); + glib::spawn_future(async move { + glib::idle_add_once(move || { + let output_box_imp = output_box_ref.imp(); + let mut list = output_box_imp.reset_input_stream_list.write().unwrap(); + for stream in streams { + 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); + list.insert(index, (entry.clone(), input_stream.clone())); + output_box_imp.reset_input_streams.append(&*entry); + } + }); + }); + }); +} + +pub fn populate_cards(output_box: Arc) { + gio::spawn_blocking(move || { + let output_box_ref = output_box.clone(); + let cards = get_cards(output_box.clone()); + glib::spawn_future(async move { + glib::idle_add_once(move || { + let imp = output_box_ref.imp(); + for card in cards { + imp.reset_cards.add(&CardEntry::new(card)); + } + }); + }); + }); +} + +pub fn get_input_streams(output_box: Arc) -> Vec { + let conn = Connection::new_session().unwrap(); + let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000)); + let res: Result<(Vec,), Error> = proxy.method_call(AUDIO, "ListInputStreams", ()); + if res.is_err() { + show_error::(output_box.clone(), "Failed to list input streams"); + return Vec::new(); + } + res.unwrap().0 +} + +pub fn get_sinks(output_box: Arc) -> Vec { + let conn = Connection::new_session().unwrap(); + let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000)); + let res: Result<(Vec,), Error> = proxy.method_call(AUDIO, "ListSinks", ()); + if res.is_err() { + show_error::(output_box.clone(), "Failed to list sinks"); + return Vec::new(); + } + res.unwrap().0 +} + +pub fn get_cards(output_box: Arc) -> Vec { + let conn = Connection::new_session().unwrap(); + let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000)); + let res: Result<(Vec,), Error> = proxy.method_call(AUDIO, "ListCards", ()); + if res.is_err() { + show_error::(output_box.clone(), "Failed to list profiles"); + return Vec::new(); + } + res.unwrap().0 +} + +pub fn get_default_sink_name(output_box: Arc) -> String { + let conn = Connection::new_session().unwrap(); + let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000)); + let res: Result<(String,), Error> = proxy.method_call(AUDIO, "GetDefaultSinkName", ()); + if res.is_err() { + show_error::(output_box.clone(), "Failed to get default sink name"); + return String::from(""); + } + res.unwrap().0 +} + +pub fn get_default_sink(output_box: Arc) -> Sink { + let conn = Connection::new_session().unwrap(); + let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000)); + let res: Result<(Sink,), Error> = proxy.method_call(AUDIO, "GetDefaultSink", ()); + if res.is_err() { + show_error::(output_box.clone(), "Failed to get default sink"); + return Sink::default(); + } + res.unwrap().0 +} diff --git a/src/components/output/sink_entry.rs b/src/components/output/sink_entry.rs index 0fea70f..c07ae72 100644 --- a/src/components/output/sink_entry.rs +++ b/src/components/output/sink_entry.rs @@ -14,7 +14,8 @@ use re_set_lib::audio::audio_structures::Sink; use crate::components::utils::{AUDIO, BASE, DBUS_PATH}; -use super::sink_box::{refresh_default_sink, SinkBox}; +use super::sink_box::SinkBox; +use super::sink_box_utils::refresh_default_sink; use super::sink_entry_impl; glib::wrapper! {